12

I would like to typeset a short, letter-like document using the Zapfino font, with the following twist: I'm OK using Zapfino's "standard" (i.e., Variant 0) glyphs for lowercase letters, but I'd like to use the Variant 1 glyphs for uppercase letters. (In case you're curious, they look more "swash-y" than the Variant 0 uppercase glyphs...) To use a concrete example, I'd like to get

enter image description here

instead of

enter image description here

Note the different appearance of the uppercase letters. As of now, I can only achieve this look using the brute-force approach, viz., by defining the command \newcommand{\varone}[1]{{\fontspec[Variant=1]{Zapfino}#1}} and then encasing each uppercase letter X inside \varone{X}.

I've perused the fontspec manual and found the \newfontfeature command on p. 55, but I can't seem to be able to figure out how to apply this method to my objective, which is to set the font variant separately for uppercase and lowercase letters. Anyone have an idea?

In case it matters, I'm running MacTeX2011 under MacOSX 10.6.8. The Zapfino font I have is the one that comes installed with the OS.

Answer, based on a minimally changed version of @AndreyVihrov's solution below:

    % !TEX TS-program = xelatex
% !TEX encoding = UTF-8
\documentclass[letterpaper]{article}

\usepackage{fontspec}
\setmainfont{Zapfino}

% Prepare a separate "font" for Latin uppercase letters
\newfontfamily\upfont[Ligatures=TeX,Variant=1]{Zapfino}

\XeTeXinterchartokenstate=1
\newXeTeXintercharclass \uppercaseclass

% Assign the new XeTeX character class to all Latin uppercase letters
\makeatletter
\@tempcnta=`\A
\loop\unless\ifnum\@tempcnta>`\Z
  \XeTeXcharclass \@tempcnta \uppercaseclass
  \advance \@tempcnta by 1
\repeat
\makeatother

% Implement the font change
\XeTeXinterchartoks 0 \uppercaseclass   = {\begingroup\upfont}
\XeTeXinterchartoks \uppercaseclass 0   = {\endgroup}
\XeTeXinterchartoks 255 \uppercaseclass = {\begingroup\upfont}
\XeTeXinterchartoks \uppercaseclass 255 = {\endgroup}

\begin{document}
Once Upon a Time, Prince Charming saw \ldots
\end{document}

enter image description here

4
  • 2
    I'd use \newcommand{\varone}[1]{{\addfontfeatures{Variant=1}#1}}or, for implementing Andrey's trick, \begingroup\addfontfeatures{Variant=1} instead of a whole \fontspec. You can also consider to define a new font face instead of a font family.
    – egreg
    Nov 6, 2011 at 17:13
  • @egreg: You're right. Nov 6, 2011 at 17:33
  • @egreg: Please feel free to add a new answer to illustrate how one would a new font face. :-)
    – Mico
    Nov 6, 2011 at 17:56
  • That's just the \newfontface command of fontspec, that doesn't do all the job of looking for italic and bold face variants.
    – egreg
    Nov 6, 2011 at 18:55

1 Answer 1

13

You can make use of the XeTeX character class mechanism, which allows to insert tokens into the input stream based on user-defined character classes. In this case, we define a new class for uppercase letters and prepare code to be inserted before and after these letters:

\documentclass{article}

\usepackage{fontspec}

% Our font for uppercase letters
\newfontfamily\upfont[Ligatures=TeX,Color=FF0000]{Latin Modern Roman}

\XeTeXinterchartokenstate=1
\newXeTeXintercharclass \uppercaseclass

% Assign the new class to all Latin capital letters
\makeatletter
\@tempcnta=`\A
\loop\unless\ifnum\@tempcnta>`\Z
  \XeTeXcharclass \@tempcnta \uppercaseclass
  \advance \@tempcnta by 1
\repeat
\makeatother

% Setup font change
\XeTeXinterchartoks 0 \uppercaseclass   = {\begingroup\upfont}
\XeTeXinterchartoks \uppercaseclass 0   = {\endgroup}
\XeTeXinterchartoks 255 \uppercaseclass = {\begingroup\upfont}
\XeTeXinterchartoks \uppercaseclass 255 = {\endgroup}

\begin{document}

Once Upon a Time, there was a Beautiful Princess\ldots

\end{document}

enter image description here

The mechanism is described in the XeTeX reference.

7
  • Thanks, this works beautifully! If I understand your code correctly, it operates on all uppercase letters in the entire document, correct? A follow-up question: Is there a way to limit the scope of the font family change-over command to only a part of a document?
    – Mico
    Nov 6, 2011 at 18:27
  • @Mico: Yes. The simplest way to do that would be to replace \addfontfeatures{Color=FF0000} with a macro that expands to this text, and let this macro to \relax in parts where this output is not desired. Another way would be to copy-paste the loop code and use 0 instead of \uppercaseclass — this would cancel the effect either. Nov 6, 2011 at 20:20
  • 2
    BTW, every time \addfontfeature is invoked, it creates a new font definition behind the scenes, and this would slow compilation greatly if used on long portions of text. A more efficient way would be to define a new family upfront using \newfontfamily (or even \newfontface) and use it instead. Nov 12, 2011 at 15:25
  • @KhaledHosny: And I changed it from \newfontfamily originally thinking that it would be better… Nov 12, 2011 at 16:13
  • 3
    Note that XeTeX version 0.99996 has increased the number of character classes to 4096, so the boundary class, here denoted by 255, should become 4095.
    – egreg
    Jun 12, 2016 at 16:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .