Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

(I actually came to a solution with this, which I've posted separately, but I thought it'd be good to document anyways - and of course, any comments to this are welcome)

This is the problem - I need to "style fonts" in a document, which I compile using xelatex and fontspec. And it seems each time I call \setmainfont or \fontspec or \addfontfeature (which I thought are for "styling"), a new "font family" gets created.

Below is an MWE, that generates the following output (compiled with xelatex test.tex):

test.png

Note that each call to abovementioned functions causes 'Junicode(X+1)' to be instantiated; thankfully, \fontsize{size}{skip} doesn't seem to increase the number of fonts.

Here is the code (inline links: 1, 2, 3, 4, 5 ):

\documentclass[letterpaper,12pt]{article}

% http://tex.loria.fr/ctan-doc/macros/latex/doc/html/fntguide/node36.html
% dumps to log
% \usepackage{tracefnt}

% \typeout{ == \the\paperwidth / \the\paperheight ==}
% \typeout{ == \the\pdfpagewidth / \the\pdfpageheight ==}
\pdfpagewidth=\paperwidth \pdfpageheight=\paperheight

% default font change:
% http://www.forkosh.com/pstex/latexcommands.htm
%   \fontencoding{T1}
%   \fontfamily{garamond}
%   \fontseries{m}
%   \fontshape{it}
%   \fontsize{12}{15}
%   \selectfont


\usepackage{fontspec}

\defaultfontfeatures{Ligatures=TeX}
\setmainfont{Junicode}


% trick for fake smallcaps, http://tex.stackexchange.com/a/56097/2595
% each \setmainfont / \fontspec / \addfontfeature command creates a new Junicode(X) font
% here we are at Junicode(0)
% create Junicode(1) with fake bold
\fontspec[FakeBold=2.5]{Junicode}

% map Junicode(0)/bx/sc (bold smallcaps) to Junicode(1)/m/sc (normal smallcaps of fake bold)
\DeclareFontShape{EU1}{Junicode(0)}{bx}{sc}{<->ssub * Junicode(1)/m/sc}{}

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

\usepackage{tikz}


% from: http://tex.stackexchange.com/a/10524/2595
% change this to get the formatting you want
\newcommand{\parnum}{\bfseries\arabic{parcount}}

\newcounter{parcount}
\newenvironment{parnumbers}{%
   \par%
%    \reversemarginpar%
%    \everypar{\stepcounter{parcount}\leavevmode\marginpar[\hfill\parnum]{\parnum}}%
   \everypar{\stepcounter{parcount}\leavevmode\reversemarginpar{\makebox[20pt][r]{\hfill\parnum.\space}}}%
}{}


\begin{document}

\begin{parnumbers}

  {\scshape \showfont Aa}

  {\fontspec[Letters=SmallCaps]{Junicode} \showfont Aa}

  {\bfseries\scshape \showfont Aa}

  \showfont Aa

  \normalsize \showfont Aa

  \fontspec[Scale=1.0] {Junicode} \showfont Aa

  \addfontfeature{Scale=1.0} \showfont Aa

  \fontsize{9}{10} \showfont Aa

  \fontsize{9}{10}\selectfont \showfont Aa

  \addfontfeature{Scale=0.9} \showfont Aa

  \fontsize{8}{10}\selectfont \showfont Aa

  \normalsize \showfont Aa

  \begin{tikzpicture} \node { \normalsize \showfont Aa }; \end{tikzpicture}

  \showfont Aa

\end{parnumbers}

\end{document}
share|improve this question
add comment

3 Answers

up vote 3 down vote accepted

Well yes, new font families are created. But why does it worry you? A font family is simply a label. fontspec has to sort all your font definitions in the existing nfss-system. Which axis of the nfss system (encoding, family, shape, series, sizes) should a change like Letters=SmallCaps or Ligatures=TeX use instead? If you would use the shape or series axis you would not be able to combine your font with commands like \bfseries or \itshape.

In an extended nfss-system with more axis fontspec could use one of them. But in this case you would get new values in this axis. It would be a bit more cleaner and logical, but not more.

share|improve this answer
    
Thanks for that @UlrikeFischer - that clarifies things up.. I was worried, because I didn't think of a "font family" as a label - but as something big instantiated in memory; and secondly, I was worried that when I used commands that I thought restore a previous font, instead "instantiated" a new one. I was clearly not thinking in terms of NFSS-axis (more like OOP mixed with CSS instead :)) So I'll accept this answer; otherwise code that clarifies that for me is in this post. Many thanks again - cheers! –  sdaau May 18 '12 at 11:06
add comment

Well, there are commands \newfontface and \newfontfamily in fontspec. What confused we is that when I see something with "new", I think of instantiating objects (+ more memory) - when I see something with "set" or "add", I think of changing properties; here it works somewhat the opposite :)

In the following example, note that \newfontface does create a new font family, but it also provides a command which allows one to switch back to that same font; but notably, it doesn't in itself switch the font formatting. On the other hand, \newfontfamily will not do any changes in formatting - and will seemingly refer to the earliest instance of a font (here "Junicode(0)") - and the command which gets defined by using it will also allow a reset back to this instance.

Here is the output of the MWE:

test.png

... and here is the code:

\documentclass[letterpaper,12pt]{article}

\pdfpagewidth=\paperwidth \pdfpageheight=\paperheight


\usepackage{fontspec}

\defaultfontfeatures{Ligatures=TeX}
\setmainfont{Junicode}


% each \setmainfont / \fontspec / \addfontfeature command creates a new Junicode(X) font
% here we are at Junicode(0)
% create Junicode(1) with fake bold
\fontspec[FakeBold=2.5]{Junicode}
% also possible with \newfontface (so we can reference it if we need to)?
% \newfontface\myfontfcFkBdA[Scale=1.1]{Junicode} % no

% map Junicode(0)/bx/sc (bold smallcaps) to Junicode(1)/m/sc (normal smallcaps of fake bold)
\DeclareFontShape{EU1}{Junicode(0)}{bx}{sc}{<->ssub * Junicode(1)/m/sc}{}

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

\usepackage{tikz}


% from: http://tex.stackexchange.com/a/10524/2595
% change this to get the formatting you want
\newcommand{\parnum}{\bfseries\arabic{parcount}}

\newcounter{parcount}
\newenvironment{parnumbers}{%
   \par%
%    \reversemarginpar%
%    \everypar{\stepcounter{parcount}\leavevmode\marginpar[\hfill\parnum]{\parnum}}%
   \everypar{\stepcounter{parcount}\leavevmode\reversemarginpar{\makebox[20pt][r]{\hfill\parnum.\space}}}%
}{}




\begin{document}

\begin{parnumbers}

  {\scshape \showfont Aa} % (0)

  {\fontspec[Letters=SmallCaps]{Junicode} \showfont Aa} % (2)

  {\bfseries\scshape \showfont Aa} % (0)

  \showfont Aa % (0)

  \normalsize \showfont Aa % (0)

  \newfontface\myfontfcScA[Scale=1.1]{Junicode} \showfont Aa % (0), but creates (3)?

  \newfontfamily\myfontfam{Junicode} \showfont Aa % (0)

  \fontspec[Scale=1.0] {Junicode} \showfont Aa % (4)

  \addfontfeature{Scale=1.0} \showfont Aa % (5)

  \fontsize{9}{10} \showfont Aa % (5)

  \fontsize{9}{10}\selectfont \showfont Aa % (5)

  \addfontfeature{Scale=0.9} \showfont Aa % (6)

  \fontsize{8}{10}\selectfont \showfont Aa % (6)

  \normalsize \showfont Aa % (6)

  \begin{tikzpicture} \node { \normalsize \showfont Aa }; \end{tikzpicture} % (6)

  \showfont Aa % (6)

  \myfontfam \showfont Aa % (0)

  \normalsize \showfont Aa % (0)

  \myfontfcScA \showfont Aa % (3)

  \showfont Aa % (3)

  \normalsize \showfont Aa % (3)

  \myfontfam \showfont Aa % (0)

\end{parnumbers}

\end{document}
share|improve this answer
    
It's quite hard to understand in what this differs from the "question" example; with this I get one more font. At the bottom of the .log file you find for this example 4218 words of font info for 50 fonts, out of 3000000 for 9000; the other example gives 4210 words of font info for 49 fonts, out of 3000000 for 9000. –  egreg May 17 '12 at 10:53
    
Sorry, @egreg - I didn't even think about the log file! I realize it is written a bit messy; but basically, I though at first that \setfont, \fontspec change an existing font setting - instead they instantiate a new font family. So, I was at loss at how to change, but not instantiate unnecessarily - and it turns out, one can instead use \newfontfamily and commands generated by it to switch to a style, which I think is now correct in this post. Many thanks for the comment - cheers! –  sdaau May 17 '12 at 11:06
add comment

I'll post this here, as I thought it is related, and somewhat unobvious - and the question being: how do you refer to a font set by setmainfont in the preamble ?!

The trick is basically, to use \newfontfamily right after - and with exactly the same parameters as - a call to \setmainfont in the preamble.

For example, this is a "proper" MWE:

\documentclass[letterpaper,12pt]{article}
\pdfpagewidth=\paperwidth \pdfpageheight=\paperheight


\usepackage{fontspec}
\defaultfontfeatures{Ligatures=TeX}


\setmainfont[Scale=1.0]{Junicode}                   % Junicode(0)
\newfontfamily\mfontfam[Scale=1.0]{Junicode}        % Junicode(0) !!

\newfontfamily\mfontFamFkBd[FakeBold=2.5]{Junicode} % Junicode(1)

% map Junicode(0)/bx/sc (bold smallcaps) to Junicode(1)/m/sc (normal smallcaps of fake bold)
\DeclareFontShape{EU1}{Junicode(0)}{bx}{sc}{<->ssub * Junicode(1)/m/sc}{}

\newfontfamily\mfontFamA[Scale=0.8]{Junicode}       % Junicode(2)
\newfontfamily\mfontFamB[Scale=1.5]{Junicode}       % Junicode(3)



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

\usepackage{tikz}


% from: http://tex.stackexchange.com/a/10524/2595
% change this to get the formatting you want
\newcommand{\parnum}{\bfseries\arabic{parcount}}

\newcounter{parcount}
\newenvironment{parnumbers}{%
   \par%
   \everypar{\stepcounter{parcount}\leavevmode\reversemarginpar{\makebox[20pt][r]{\hfill\parnum.\space}}}%
}{}


\begin{document}

\begin{parnumbers}

  \mfontfam \showfont
  \typeout{ == \showfont}

  \mfontFamFkBd \showfont
  \typeout{ == \showfont}

  \mfontFamA \showfont
  \typeout{ == \showfont}

  \mfontFamB \showfont
  \typeout{ == \showfont}

\end{parnumbers}

\end{document}

If you compile this with xelatex test.tex, you will get to stdout:

 == Encoding: EU1{}, Family: Junicode(0){}, Series: m{}, Shape: n{}, Size: 12{}
 == Encoding: EU1{}, Family: Junicode(1){}, Series: m{}, Shape: n{}, Size: 12{}
 == Encoding: EU1{}, Family: Junicode(2){}, Series: m{}, Shape: n{}, Size: 12{} 
 == Encoding: EU1{}, Family: Junicode(3){}, Series: m{}, Shape: n{}, Size: 12{}

and in the log file:

$ grep created test.log 
. Font family 'Junicode(0)' created for font 'Junicode' with options
. Font family 'Junicode(0)' created for font 'Junicode' with options
. Font family 'Junicode(1)' created for font 'Junicode' with options
. Font family 'Junicode(2)' created for font 'Junicode' with options
. Font family 'Junicode(3)' created for font 'Junicode' with options

... and it can be easily checked that \mfontfam refers to "Junicode(0)".

However, note that if, say, the "Scale" parameter is different - even if the font stays the same - as in:

\setmainfont[Scale=1.0]{Junicode}                   % Junicode(0)
\newfontfamily\mfontfam[Scale=1.5]{Junicode}        % Junicode(?) !!

... then there will be problems: stdout will note:

 == Encoding: EU1{}, Family: Junicode(1){}, Series: m{}, Shape: n{}, Size: 12{}
 == Encoding: EU1{}, Family: Junicode(2){}, Series: m{}, Shape: n{}, Size: 12{}
 == Encoding: EU1{}, Family: Junicode(3){}, Series: m{}, Shape: n{}, Size: 12{}
 == Encoding: EU1{}, Family: Junicode(1){}, Series: m{}, Shape: n{}, Size: 12{}

... - a completely wrong order of fonts; and so will the log file inform us that about something similar:

$ grep created test.log 
. Font family 'Junicode(0)' created for font 'Junicode' with options
. Font family 'Junicode(1)' created for font 'Junicode' with options
. Font family 'Junicode(2)' created for font 'Junicode' with options
. Font family 'Junicode(3)' created for font 'Junicode' with options
. Font family 'Junicode(1)' created for font 'Junicode' with options

... ( and obviously, in this case the font mapping trick (as in \mfontfam \bfseries\scshape \showfont...) for small caps doesn't work anymore, as the mapping references are now inaccurate ). And notably, now \mfontfam will restore "Junicode(1)" (instead of "Junicode(0)", as it did in the example initially).

Well, just thought I'd jot this down - hope this helps someone,
Cheers!


EDIT: And one more thing; note that if, instead of the abovenoted \newfontfamily:

\newfontfamily\mfontFamB[Scale=1.5]{Junicode}
...
  \mfontFamB \showfont

(... which generates the following in the log:

$ grep -A 1 created test.log
...
--
. Font family 'Junicode(3)' created for font 'Junicode' with options
. [Ligatures=TeX,Scale=1.5].

) ... you use \newfontface, as in:

\newfontface\mfontFacB[Scale=1.5]{Junicode}
...
  \mfontFacB \showfont

... then you will get warnings like:

LaTeX Font Warning: Font shape `EU1/Junicode(3)/bx/n' undefined
(Font)              using `EU1/Junicode(3)/m/n' instead on input line 60.

... which are explained by the fontspec entry in the log:

$ grep -A 1 created test.log
...
--
. Font family 'Junicode(3)' created for font 'Junicode' with options
. [Ligatures=TeX,BoldFont={},ItalicFont={},SmallCapsFont={},Scale=1.5].

That is:

  • newfontface causes: [Ligatures=TeX,BoldFont={},ItalicFont={},SmallCapsFont={},Scale=1.5]
  • \newfontfamily causes: [Ligatures=TeX,Scale=1.5]

... or, newfontface explicitly sets bold/italic/smallcaps options of fonts to null; while newfontfamily doesn't do that.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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