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}

  • 1
    Maybe Microsoft Office makes a fake small case. – Clara Apr 12 '23 at 03: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 '23 at 05: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 ? – Vincent Krebs Apr 12 '23 at 06:25
  • It's certainly been tried before: https://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 '23 at 07:12

5 Answers5

6

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.

wipet
  • 74,238
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

egreg
  • 1,121,712
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

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

user94293
  • 4,254
  • 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! – Vincent Krebs Apr 22 '23 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.

rallg
  • 2,379