0

I tend to use the IBM Plex font, which does not have small caps — hence I get this message when trying to use \textsc: Font shape T1/IBMPlexSerif-TLF/m/fscn' undefined (Font) usingT1/IBMPlexSerif-TLF/m/n' instead.

To get around this I use \fauxsc (Fake small caps with XeTeX/fontspec?), which seems to work in pdflatex.

What would be really snazzy though would be to extend the functionality of \textsc such that when the font does have small caps, it just uses that; then when it doesn't (e.g. as happens with IBM Plex) instead of giving an error, it automatically switches to using \fauxsc

Would such a thing be possible?

6
  • 4
    Using faked small caps will ruin your document.
    – egreg
    Jul 7 '19 at 21:08
  • I imagine by "ruin your document" you mean it won't be as good as true small caps?
    – tecosaur
    Jul 8 '19 at 1:03
  • Just look at the picture in my answer: the difference in stroke weight is apparent and ugly.
    – egreg
    Jul 8 '19 at 8:49
  • Yea. I know (and can clearly see) what you're talking about. What's nice with Plex though is it's got a good variety of different weights available. Now I just need a way to make the smaller letters be one weight higher.
    – tecosaur
    Jul 8 '19 at 9:35
  • @egreg if this is of interest, this is what I ended up with: i.postimg.cc/JzyVgKd7/image.png by using this pastebin.com/SDGfBZ3d
    – tecosaur
    Jul 8 '19 at 15:05
5

Here's a possible solution, but if you really need small caps, use a font that has them.

\documentclass{article}
\usepackage{graphicx}
\usepackage{plex-serif}
\usepackage{roboto}

\let\textsc\relax
\DeclareRobustCommand{\textsc}[1]{%
  \sbox0{x\xdef\testA{\the\font}}%
  \sbox0{\scshape x\xdef\testB{\the\font}}%
  \ifx\testA\testB\fauxsc{#1}\else{\scshape #1}\fi
}

\makeatletter
\newlength\fake@f
\newlength\fake@c
\def\fakesc#1{%
  \begingroup
  \xdef\fake@name{\csname\curr@fontshape/\f@size\endcsname}%
  \fontsize{\fontdimen8\fake@name}{\baselineskip}\selectfont
  \MakeUppercase{#1}%
  \endgroup
}
\makeatother
\newcommand\fauxsc[1]{\fauxschelper#1 \relax\relax}
\def\fauxschelper#1 #2\relax{%
  \fauxschelphelp#1\relax\relax
  \if\relax#2\relax\else\ \fauxschelper#2\relax\fi
}
\def\Hscale{.83}\def\Vscale{.72}\def\Cscale{1.00}
\def\fauxschelphelp#1#2\relax{%
  \ifnum`#1>``\ifnum`#1<`\{\scalebox{\Hscale}[\Vscale]{\uppercase{#1}}\else
    \scalebox{\Cscale}[1]{#1}\fi\else\scalebox{\Cscale}[1]{#1}\fi
  \ifx\relax#2\relax\else\fauxschelphelp#2\relax\fi}

\begin{document}

\textsc{Abc def}

\sffamily % this has true small caps

\textsc{Abc def}

\end{document}

The idea is to compare what font gets chosen if \scshape is applied. In case LaTeX performs a substitution, \testA and \testB will both point to the same font.

enter image description here

2
  • This does not seem to work for me. I'm using it with geschichtsfrkl bibliography, and I'm getting a few strange errors: document.tex:186: Improper alphabetic constant. <to be read again> \MakeLowercase l.186 ...rung bewältigen.\cite{2012SchIg} document.tex:186: Missing = inserted for \ifnum. <to be read again> \protect l.186 ...rung bewältigen.\cite{2012SchIg} document.tex:186: Missing number, treated as zero. <to be read again> \protect l.186 ...rung bewältigen.\cite{2012SchIg} (And some more every \cite)
    – nleanba
    Jul 31 '20 at 16:26
  • 1
    @nleanba Oh, the trick for emulating small caps has several limitations and you found one. Use a font that has real small caps and forget about this.
    – egreg
    Jul 31 '20 at 17:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.