5

I don't get it. Gill Sans MT supports Small Caps without any issue in Word and Powerpoint. Font recognition apps event identify it. And yet, there is no way I can get them.

\documentclass{article}

\usepackage{fontspec}

\setmainfont{Gill Sans MT}[
SmallCapsFeatures={Letters=SmallCaps},
SmallCapsFont={*},
]

\begin{document}
    \textsc{Small Caps.}
\end{document}
4
  • 1
    Maybe Microsoft Office makes a fake small case.
    – Clara
    Apr 12 at 3:12
  • 1
    Are you sure you are using the exact same font files? Either way, when I try to run your MWE I get a warning: OpenType feature 'Letters=SmallCaps' (smcp) not available for font 'GillSansMT' with script 'CustomDefault' and language 'Default'.
    – Ingmar
    Apr 12 at 5:55
  • @Ingmar Yes the fonts are in the windows font folder I only have this version. Is there a way to produce smallcaps as in Office ? Apr 12 at 6:25
  • It's certainly been tried before: tex.stackexchange.com/questions/55664 Not sure I'd bother, though. If you actually must have Small Caps, it'd probably be best to use a font that has them.
    – Ingmar
    Apr 12 at 7:12

5 Answers 5

5

Word processors often have the capability of faking fonts that aren't in the system; with TeX this is not possible, because we're doing fine typography, not just printing whatever.

With several limitations (only text, no commands), you can fake small caps. For your simple application it should do.

Here I use Gillius ADF as I don't have Gill Sans MT.

\documentclass{article}

\usepackage{fontspec}

\setmainfont{Gillius ADF}[% replacement for Gill Sans
  NFSSFamily=gilliusadf,
]
\newfontfamily{\scaledgillius}{Gillius ADF}[Scale=0.8,FakeBold=1.5,WordSpace=1.25]

\ExplSyntaxOn
\NewDocumentCommand{\fakesc}{m}
 {
  \krebs_fakesc:n { #1 }
 }

\seq_new:N \l__krebs_fakesc_words_in_seq
\seq_new:N \l__krebs_fakesc_words_out_seq

\cs_new_protected:Nn \krebs_fakesc:n
 {
  \group_begin:
  \scaledgillius
  \seq_set_split:Nnn \l__krebs_fakesc_words_in_seq { ~ } { #1 }
  \seq_set_map:NNn \l__krebs_fakesc_words_out_seq \l__krebs_fakesc_words_in_seq
   {
    \__krebs_fakesc:n { ##1 }
   }
  \seq_use:Nn \l__krebs_fakesc_words_out_seq { ~ }
  \group_end:
 }

\cs_new_protected:Nn \__krebs_fakesc:n
 {
  \text_map_inline:nn { #1 } { \__krebs_fakesc_letter:n { ##1 } }
 }

\cs_new_protected:Nn \__krebs_fakesc_letter:n
 {
  \int_compare:nTF { \char_value_uccode:n { `#1 } = `#1 }
   {
    {\fontfamily{gilliusadf}\selectfont #1 }
   }
   {
    \char_uppercase:N #1
   }
 }

\ExplSyntaxOff

\begin{document}

\fakesc{Smáll Câps. Ii}

\textit{\fakesc{Smáll Câps. Ii}}

\end{document}

enter image description here

1
  • Thank you very much for helping. Apr 13 at 13:19
5

Just for comparison, what we can do in OpTeX:

\fontfam[dejavu]

\def\fakecaps#1{\def\tmp{#1}\replstring\tmp{ }{{ }}%
   {\ea\let \ea\fupper \the\font  \uccode`'=`'
    \setfontsize{mag.8}\setff{+upper;embolden=1.1}\setwordspace{1.25}\fontsel
    \ea\foreach\tmp\do{\ifnum\uccode`##1=`##1{\fupper##1}\else ##1\fi}}}

Normal text. 
\fakecaps{Aren't it. Šmudla, že.}

\bye

See also OpTeX trick 0107.

4

Here is a code based on egreg's answer, which automatically detects the current font before passing the value to the command.

EDIT:

I corrected the issue with WordSpace by using \newfontfamily instead of obsolete package option.

The apostrophe and comma not being rendered properly has been fixed thanks to user94293's answer.

\documentclass{article}
\usepackage{fontspec}

\setmainfont{Times New Roman}

\newfontfamily\gill{gill Sans MT}
\newfontfamily\hadriano[UprightFont={* Light},BoldFont={* Bold}]{AT Hadriano Std}
\newfontfamily\minion{Minion Pro Capt}
\newfontfamily\stix{STIX Two Math}[AutoFakeBold=2]
\newfontfamily\djvs[BoldFont={* Bold}]{DejaVu Sans}
\newfontfamily\arial{Arial Unicode MS}
\newfontfamily\free{Free Serif}
\newfontfamily\symbola{Symbola}[FakeBold=0.5]



\ExplSyntaxOn
\NewDocumentCommand{\smartsc}{m}
{
    \krebs_smartsc:n { #1 }
}

\seq_new:N \l__krebs_smartsc_words_in_seq
\seq_new:N \l__krebs_smartsc_words_out_seq

\cs_new_protected:Nn \krebs_smartsc:n
{
    \group_begin:
    \newfontfamily{\currentfont}{\csname f@family\endcsname}
    \newfontfamily{\currentfontSC}{\csname f@family\endcsname}[Scale=0.72,WordSpace=1.75,FakeBold=1.1]
    \currentfontSC
    \seq_set_split:Nnn \l__krebs_smartsc_words_in_seq { ~ } { #1 }
    \seq_set_map:NNn \l__krebs_smartsc_words_out_seq \l__krebs_smartsc_words_in_seq
    {
        \__krebs_smartsc:n { ##1 }
    }
    \seq_use:Nn \l__krebs_smartsc_words_out_seq { ~ }
    \group_end:
}

\cs_new_protected:Nn \__krebs_smartsc:n
{
    \text_map_inline:nn { #1 } { \__krebs_smartsc_letter:n { ##1 } }
}

\cs_new_protected:Nn \__krebs_smartsc_letter:n
{
    \int_compare:nTF { \char_value_lccode:n { `#1 } = `#1 }
    {
        \char_uppercase:N #1
    }
    {
        {\currentfont #1}
    }
}
\ExplSyntaxOff


\begin{document}
    
    \noindent
    
    \smartsc{Small Caps are Nice, Aren't They?} (Times fake)
    
    \textsc{Small Caps are Nice, Aren't They?} (Times real)
    
    \gill\smartsc{Small Caps are Nice, Aren't They?} (Gill fake)
    
    \textsc{Small Caps are Nice, Aren't They?} (Gill real - No support)
    
    \hadriano\smartsc{Small Caps are Nice, Aren't They?} (Hadriano fake)
    
    \textsc{Small Caps are Nice, Aren't They?} (Hadriano real - No support)
    
    \minion\smartsc{Small Caps are Nice, Aren't They?} (Minion Pro Capt fake)
    
    \textsc{Small Caps are Nice, Aren't They?} (Minion Pro Capt real)
    
    \stix\smartsc{Small Caps are Nice, Aren't They?} (Stix Two Math fake)
    
    \textsc{Small Caps are Nice, Aren't They?} (Stix Two Math real - No support)
    
    \djvs\smartsc{Small Caps are Nice, Aren't They?} (DejaVu Sans fake)
    
    \textsc{Small Caps are Nice, Aren't They?} (DejaVu Sans real - No support)
    
    \arial\smartsc{Small Caps are Nice, Aren't They?} (Arial fake)
    
    \textsc{Small Caps are Nice, Aren't They?} (Arial real - No support)
    
    \free\smartsc{Small Caps are Nice, Aren't They?} (Free Serif fake)
    
    \textsc{Small Caps are Nice, Aren't They?} (Free Serif real)
    
    \symbola\smartsc{Small Caps are Nice, Aren't They?} (Symbola fake)
    
    \textsc{Small Caps are Nice, Aren't They?} (Symbola real - No support)
    
\end{document}

enter image description here

0
3

As a follow-up to the accepted answer, the apostrophe issue can be addressed by defining instead

\cs_new_protected:Nn \__krebs_smartsc_letter:n
{
    \int_compare:nTF { \char_value_lccode:n { `#1 } = `#1 }
    {
        \char_uppercase:N #1
    }
    {
        {\currentfont #1}
    }
}

It checks whether lowercases match (instead of checking uppercases).

enter image description here

1
  • Using \char_value_lccode instead of ... uccode is a great idea for apostrophes and punctuation, it solves it, I'll update my answer thank you very much! Apr 22 at 16:22
1

Since you are using fontspec: If you need to fake small caps, you might wish to use the FakeStretch optional argument. See the fontspec manual. You might also wish to increase the letter spacing, but I believe that FakeStretch already helps you there.

If you downscale uppercase letters, to make fake small caps, then the weight (thickness) of the characters also decreases in proportion. You can compensate in the horizontal direction using FakeStretch. Compensation should not be exactly the inverse of the shrinkage, since small caps are normally slightly lighter than uppercase.

Fontspec also has FakeBold but I am reluctant to use it. I do not know its algorithm. At least in some font editors, using the equivalent of FakeBold runs the risk of generating self-crossing or ambiguous glyph outlines. But FakeStretch is merely a one-dimensional scale, so that should not cause any problems.

FakeStretch will leave the horizontal bars (and serifs) alone, so they will be too thin. But this may escape notice. Depends on the font.

On a related note, some folks like to put acronyms in "medium caps" between small caps and uppercase. If you do that, it is usually better to upscale true small caps (if available) and unstretch the widths, rather than downscale uppercase and stretch the widths.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .