Last step in moving to XeTeX: Font shape problems

The TeX Gyre fonts typically come with small caps. TeX Gyre Heros looks very similar to Helvetica (technically, it is based on URW Nimbus Sans L; so it has the same font metrics as Helvetica, but the characters might look slightly different­­­­). The fonts are probably already installed with your TeX distribution. To use them form there in XeLaTeX, you have to call them the following way:

\documentclass{article}
\usepackage{fontspec}

\setmainfont[
    Extension=.otf,
    UprightFont= *-regular,
    BoldFont=*-bold,
    ItalicFont=*-italic,
    BoldItalicFont=*-bolditalic,
]{texgyreheros}

\begin{document}
    CGRart \textsc{CGRart}
\end{document}

TeX Gyra Heros sample


As Caramdir mentions in his comment, Helvetica doesn't come with small caps, and it doesn't seem that many free fonts (and even many professional fonts) come with real small caps. Will Robertson recommended the following workaround on the XeTeX mailing list a couple of years ago.

In the past I've thought about this in fontspec, but it really becomes impossible if you want the fake small caps to behaviour like \textsc -- that is, to have uppercase come out as real uppercase but lowercase to come out as scaled uppercase.

So rather than using fontspec, it's probably easier to use the relsize package, like this:

\documentclass{article}
\usepackage{fontspec,relsize}
\begin{document}
\fontspec{Georgia}
THIS IS UPPERCASE and lowercase
{\smaller THIS IS FAKE SMALL CAPS}
\end{document}

You can always define a macro to make this more "semantic", as well:

\newcommand\fakesc[1]{{\smaller #1}}

Original message here.


Just wanted to post my results with this - it seems the biggest problem is font encoding; apparently neither \sffamily nor \sfdefault handle it - so while one can set "phv" as the helvetica font in diverse ways, that font seemingly only exists in T1 encoding. One sign of this is if I compile the below example with pdflatex (previously removing all fontspec-related stuff) - and I get upon loading of helvet.sty:

(/path/to/texlive/2011/texmf-dist/tex/latex/psnfss/ot1phv.fd
File: ot1phv.fd 2001/06/04 scalable font definitions for OT1/phv.

The problem is then, that fontspec will switch to a different encoding - EU1 if you build with xelatex, and EU2 if with lualatex (or at least that is how I've seen it so far). And so, \sffamily may tell fontspec to look for phv, but if the encoding is set to EU2, then fontspec looks for EU2/phv which doesn't exist (instead of T1/phv which does).

The solution seems to be to issue a command like this explicitly:

\fontencoding{T1}\fontfamily{phv}\selectfont

... and as the below MWE shows, I haven't found a way how to redefine \sffamily or \sfdefault to also switch to T1 encoding (like with explicit \fontencoding{T1}). Another way could - conceivably - be, to use something like:

\DeclareFontShape{EU2}{phv}{m}{n}{<->ssub * phv/bx/n}{} % nope 

... in the spirit of font "mapping" as in this post (where xelatex is used to generate a fake-bold smallcaps family; and the missing bold smallcaps from the original font is mapped to the fake-bold one); unfortunately, it seems \DeclareFontShape can only map between fonts of the same encoding - I cannot see a way to specify something line T1 on the right-hand side.

The output of the MWE is this (click for full res):

test.png

... and this is what pdffonts sees there:

$ pdffonts test.pdf 
name                                 type              emb sub uni object ID
------------------------------------ ----------------- --- --- --- ---------
UGSGGF+Junicode                      CID TrueType      yes yes yes      8  0
GEDPKS+LMRoman10-Regular             CID Type 0C       yes yes yes      9  0
ZRGIMP+NimbusSanL-Bold               Type 1            yes yes no      10  0
[none]                               Type 3            yes no  no      11  0
EURSKX+Junicode-Bold                 CID TrueType      yes yes yes     12  0

... and this is the code:

\documentclass[10pt]{article}

\usepackage{fontspec}
\defaultfontfeatures{Ligatures=TeX}
\setmainfont[Scale=1.0]{Junicode}

\usepackage[left=10pt,right=10pt]{geometry}
\usepackage{tikz}

\usepackage{helvet}

% for debugging fonts: https://tex.stackexchange.com/a/14382/2595
\makeatletter
\newcommand{\showfont}{Encoding: \f@encoding{},
  Family: \f@family{},
  Series: \f@series{},
  Shape: \f@shape{},
  Size: \f@size{},
  \edef\tmpfn{\font@name}
  font@name: \meaning\font@name \\
}
\makeatother

\begin{document}

  Testing 1 \showfont

    \sffamily\selectfont

  Testing 2 \showfont

    % texlive/2011/texmf-dist/tex/latex/psnfss/helvet.sty
    \renewcommand{\sfdefault}{phv}\sfdefault\selectfont

  Testing 3 \showfont

    \fontencoding{T1}\fontfamily{phv}\bfseries\selectfont

  Testing 4 \showfont % macro:->\T1/phv/bx/n/12

    \rmfamily\selectfont

  Testing 5 \showfont

    \fontencoding{EU2}\selectfont

  Testing 6 \showfont

    \sffamily\selectfont

  Testing 7 \showfont

    \fontencoding{T1}\selectfont

  Testing 8 \showfont

    \fontencoding{EU2}\rmfamily\selectfont

  Testing 9 \showfont

%     \DeclareFontShape{EU2}{phv}{m}{n}{<->ssub * phv/bx/n}{} % nope
%     \renewcommand{\sfdefault}{\T1/phv/bx/n/12} % nope
    \sffamily\selectfont

  Testing 10 \showfont

    \typeout{ .. \expandafter\meaning\csname sffamily \endcsname -- \meaning\sffamily} %  .. \long macro:->\not@math@alphabet \sffamily \mathsf \fontfamily \sfdefault \selectfont -- macro:->\protect \sffamily
    \typeout{ .. \expandafter\meaning\csname sfdefault \endcsname -- \meaning\sfdefault} % \relax-- \long macro:->phv
    \typeout{ .. \expandafter\meaning\csname fontfamily \endcsname -- \meaning\fontfamily} % \long macro:#1->\edef \f@family {#1}-- macro:->\protect \fontfamily
    \typeout{ .. \expandafter\meaning\csname selectfont \endcsname -- \meaning\selectfont} %

\end{document}

Well, hope this helps someone,
Cheers!