# Fake small caps with XeTeX/fontspec?

Using XeTeX and fontspec, I use the Liberation font family in of my documents. Unfortunately those fonts (esp. Liberation Serif) do not natively support small caps.

Is there a way to enable fake small caps in fontspec?

-

Here is a simple solution

\documentclass{article}
\usepackage{fontspec}
\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%
\uppercase{#1}%
\endgroup%
}
\makeatother

\begin{document}
\Huge

\fontspec{Minion Pro}
This is real \textsc{small caps} \par
This is fake \fakesc{small caps} \par
\medskip
\fontspec{Didot Lt Std}
This is real \textsc{small caps} \par
This is fake \fakesc{small caps} \par
\end{document}


The effect is here,

Clearly, this will not universally work. The \fakesc will resize the font to Cap size without changing the baselineskip. However, this will depend on the design of the font. With Minion Pro, set in \Huge and thus Minion Pro Disp is in use, setting the fake small caps will use Minion Pro Subh, and thus looks not too bad, since Subh is slightly heavier than Disp. But set in a non-optical size font, say Didot, the contrast of weights is even more observable. In addition, due to different x-height, the fake small caps will looks a little too large. So you would need to adjust the \fontsize accordingly.

-
Consider also this answer, if one uses fontspec and one's font, like Junicode, has native small-caps in normal shape, but lacks them in bold - then a remapping to fontspec's 'FakeBold' can be performed using \DeclareFontShape. Cheers! –  sdaau May 16 '12 at 15:53
My understanding is that small-caps is supposed to leave the real capital letters normal, and only the convert the lower case letters to be small capital letters. This script appears to eliminate the upper case-ness of characters, making all characters, upper and lower, appear the same. Try a test case with both upper and lower characters, please. –  AgilePro Jul 27 '14 at 3:59

The best – and IMHO only acceptable – way to get small caps is to use a font containing them every fake looks bad, since the stroke widths of faked small caps won’t match the real uppercase letter.

Take a look at these images showing Linux Libertine, and make your own decision …

real small caps

faked small caps

-
Correct answer, not to my question though. –  Michael May 13 '12 at 17:59
@Michael: Certainly it’s no answer showing how to get faked small caps but an advice showing why not to want small caps and for that worth to be mentioned here in my opinion ;-) –  Tobi May 13 '12 at 22:27

Yeah if your font does not provide native small caps you can try the following code to make fake caps. Works fine on my side...

\documentclass[]{article}
%\usepackage{fontspec}

\begin{document}

\makeatletter

\def\mycommand{\bgroup\obeyspaces\mycommandaux}
\def\mycommandaux#1{\mycommandauxii #1\relax\relax\egroup}
\def\mycommandauxii#1{%
\ifx\relax#1\else \ifcat#1\@sptoken{} \expandafter\expandafter\expandafter\mycommandauxii\else
\ifnum#1=\uccode#1 {\normalsize #1}\else {\footnotesize \uppercase{#1}}\fi \expandafter\expandafter\expandafter\mycommandauxii\expandafter\fi\fi}

\mycommand{All inside this are fake caps}

\end{document}


Hope it helps ++

-
I tried this and it almost worked. I seem to lose all the spaces in the string: all the words are smashed together. Any solution to that? –  AgilePro Jul 27 '14 at 4:05

You can also use FontForge to add automatically generated real small caps to the font. It's still not the same as real real small caps but it's way better than faked small caps: http://fontforge.sourceforge.net/Styles.html#Smallcaps

Edit: Just had an experience that makes me decidedly modify the above statement to: "It has the potential to be way better than faked small caps. The result can also be utterly useless, however."

-

Here I compare an alternative to Yan's approach. I label his method "fake" as he did and label this approach as "faux". I have found (see Good small caps font to use with arev?, for example) that an unequal scaling of horizontal and vertical dimension is better able to capture the proportions of small caps. For Minion Pro, shown in this example, I use 83% horizontal, and 72% vertical scaling to create faux small caps, with 100% horizontal scaling (no change) on the sc Caps. By comparison, I use 91% horizontal and 75% vertical scaling on Computer Modern, with 111% horizontal scaling on sc Caps, and on Palatino, 76% horizontal, 68% vertical scaling, with no change on the sc Caps.

In addition, my \fauxsc macro is able to automatically differentiate lower-case from upper-case arguments, and render them appropriately, which eases the input syntax.

In this MWE, I compare both "fake" and "faux" small caps to the real McCoy for Computer Modern, Minion Pro, and Palatino, respectively.

\documentclass{article}
\usepackage{fontspec}
\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%
\uppercase{#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}
\LARGE
{\def\Hscale{.91}\def\Vscale{.75}\def\Cscale{1.11}
\makebox[1.2in][l]{This is fake} S\fakesc{mall} C\fakesc{aps} $\leftarrow$ other answer\par
\makebox[1.2in][l]{This is real} \textsc{Small Caps}\par
\makebox[1.2in][l]{This is faux} \fauxsc{Small Caps} $\leftarrow$ this answer
\par}\smallskip
\fontspec{Minion Pro}
\makebox[1.2in][l]{This is fake} S\fakesc{mall} C\fakesc{aps} $\leftarrow$ other answer\par
\makebox[1.2in][l]{This is real} \textsc{Small Caps}\par
\makebox[1.2in][l]{This is faux} \fauxsc{Small Caps} $\leftarrow$ this answer
\par\smallskip
{\fontspec{Palatino Linotype}
\def\Hscale{.76}\def\Vscale{.68}\def\Cscale{1.0}
\makebox[1.2in][l]{This is fake} S\fakesc{mall} C\fakesc{aps} $\leftarrow$ other answer\par
\makebox[1.2in][l]{This is real} \textsc{Small Caps}\par
\makebox[1.2in][l]{This is faux} \fauxsc{Small Caps} $\leftarrow$ this answer
\par}

\end{document}


-
Thanks, brilliant. Still way worse than real small caps of course, but way better than anything else I’ve tried so far. –  Konrad Rudolph Mar 29 at 15:53

Here is a very simple solution which I use when I'm forced by editors to use the Times New Roman font, which have no Small Caps implemented. Since I want to leave the rest of my document intact, I simple redefine \textsc in the following way:

\renewcommand{\textsc}[1]{{\footnotesize \uppercase{#1}}}
`
-