1

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?

Bernard
  • 271,350
tecosaur
  • 1,033
  • 4
    Using faked small caps will ruin your document. – egreg Jul 07 '19 at 21:08
  • I imagine by "ruin your document" you mean it won't be as good as true small caps? – tecosaur Jul 08 '19 at 01:03
  • Just look at the picture in my answer: the difference in stroke weight is apparent and ugly. – egreg Jul 08 '19 at 08: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 08 '19 at 09:35
  • @egreg if this is of interest, this is what I ended up with: https://i.postimg.cc/JzyVgKd7/image.png by using this https://pastebin.com/SDGfBZ3d – tecosaur Jul 08 '19 at 15:05
  • Seems a decent result. – egreg Jul 08 '19 at 15:08

1 Answers1

4

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

egreg
  • 1,121,712
  • This does not seem to work for me. I'm using it with geschichtsfrkl bibliography, and I'm getting a few strange errors:
    <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