Font tools

The submission guidelines say “all fonts must be embedded,” and you have no idea whether yours are. A passage you set in italic refuses to lean. You wrote Numbers=OldStyle in fontspec and nothing changed. What settles cases like these is not guesswork but the inspection tools. This page lines up the font-checking utilities around LaTeX, each with output actually captured from a run: pdffonts, fc-list, otfinfo, \fontname\font, nfssfont for printing a glyph chart, and vftovp for cracking a virtual font (.vf) open into readable text. On the way, we decode why a TeX font is called something like phvbc8t.

Which font is this, exactly? \fontname and \showthe\font

At any point in a document, \fontname\font answers with the real file name and \showthe\font answers with the five NFSS coordinates. The first returns the name of the metric TeX actually loadedcmr10, cmbx10, cmti10 — and the second prints > \OT1/cmr/m/n/10 . into the log. The two never contradict each other: the second is the request, the first is the result. Look at both and you can see at a glance whether you got the font you asked for or something substituted along the way.

log
% \typeout{fontname = \fontname\font} in a default article
fontname = cmr10
bf fontname = cmbx10
it fontname = cmti10

% \showthe\font stops the run and prints the NFSS name
> \OT1/cmr/m/n/10 .

% \showfont is NOT a LaTeX command; it belongs to ConTeXt.
% In LaTeX it fails with:
! Undefined control sequence.

One correction is due here. \showfont is not a LaTeX command. It is often cited as the way to report the current font, but it exists in neither the LaTeX2e kernel nor any package, and running it gives ! Undefined control sequence. (ConTeXt has a command of that name). To do the same thing in LaTeX, add to the two above the option of reading the internals directly: inside \makeatletter, the macros \f@encoding, \f@family, \f@series, \f@shape and \f@size let you \typeout the five coordinates in any format you like.

To trace font loading itself, use the tracefnt package. Set \tracingfonts=2 and every time a real font is loaded the log records which external font was loaded under which NFSS name. When you are chasing down a substitution, this carries more information than the warning does. The output is voluminous, though, so in practice you cut the offending \section down to a minimal document first and run it there.

log
% \usepackage{tracefnt} + \tracingfonts=2, document set in T1
LaTeX Font Info:    External font `ecbx1000 at10.0pt' loaded as
(Font)              T1/cmr/bx/n/10  on input line 6.
LaTeX Font Info:    External font `ecti1000 at10.0pt' loaded as
(Font)              T1/cmr/m/it/10  on input line 6.

Checking the fonts embedded in a PDF — pdffonts

pdffonts (shipped with Poppler and Xpdf) tabulates which fonts are in a finished PDF, in what format, and whether they are embedded — one line per font. Three columns matter: emb for embedding, sub for subsetting (only the glyphs actually used were kept), and uni for a Unicode mapping back (whether text can be copied out of the PDF). Pre-submission checking is just this one command, and if every row says yes under emb, no editor will bounce the file for unembedded fonts.

terminal
# a document compiled with pdfLaTeX and \usepackage[T1]{fontenc}
$ pdffonts pf.pdf
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
OSZFFG+SFRM1000                      Type 1            Custom           yes yes yes      4  0
PCDLRW+SFBX1000                      Type 1            Custom           yes yes yes      5  0
IEKZWO+SFTI1000                      Type 1            Custom           yes yes yes      6  0
GFIBPT+CMMI10                        Type 1            Builtin          yes yes yes      8  0

# the same document via XeLaTeX + fontspec with an OpenType face
$ pdffonts pfx.pdf
PPMQXL+TeXGyrePagella-Regular-Identity-H CID Type 0C   Identity-H       yes yes yes      4  0
AXDTQU+TeXGyrePagella-Bold-Identity-H    CID Type 0C   Identity-H       yes yes yes      6  0

The output doubles as an engine fingerprint. pdfLaTeX embeds Type 1 fonts with Custom or Builtin encodings, whereas XeLaTeX and LuaLaTeX driving an OpenType face through fontspec produce CID Type 0C and Identity-H — enough to tell what a PDF someone sent you was built with. The six letters prefixed to each name (OSZFFG+ and friends) are subset tags; subset the same font twice and you get two different prefixes. Conversely, a row with emb set to no means that font is left to the reader’s machine — usually harmless for the standard fourteen PostScript faces, but rejected on submission.

Finding out what fonts the system has — fc-list and otfinfo

The name you hand to fontspec has to be the font’s own name; inventing one does not work. To list what is installed, with names matched to files, use fc-list (part of fontconfig). With no arguments it prints everything; fc-list : family prints just the family names; a pattern narrows it down. On the LuaTeX side the equivalent is luaotfload-tool, whose --find resolves a name and whose --update rebuilds the font-name database. Note that fontconfig is standard on Linux but is not installed by default on macOS — you add it separately, through Homebrew or similar.

terminal
# every installed font, one line each (this machine reports 2799 lines)
$ fc-list | wc -l
2799

# narrow to one family: file, then all its names, then the style
$ fc-list "Hiragino Mincho ProN" file family style
/System/Library/Fonts/HiraginoMinchoProN.ttc: Hiragino Mincho ProN,\
  Hiragino Mincho ProN W6:style=W6,Regular

# what would fontconfig pick for a generic request?
$ fc-match sans
Verdana.ttf: "Verdana" "Regular"

What a font can actually do is otfinfo’s department (part of lcdf-typetools, shipped with TeX Live). -i gives names, version and copyright; -f lists the OpenType feature tags; -s the supported scripts and languages; -t the tables. -f is the practically valuable one: check for onum or smcp here before writing Numbers=OldStyle or Letters=SmallCaps in fontspec, and you head off most of the “I wrote it and nothing happened” cases. Naming a feature a font does not have is simply ignored, silently.

terminal
$ otfinfo -i $(kpsewhich texgyrepagella-regular.otf)
Family:              TeX Gyre Pagella
Subfamily:           Regular
PostScript name:     TeXGyrePagella-Regular
Version:             Version 2.501;PS 2.501;ffdkm 0.1
Copyright:           Copyright 2006-2018 for TeX Gyre extensions by B. Jackowski,
                     J.M. Nowacki, et al. Vietnamese characters were added by Han The Thanh.

$ otfinfo -f $(kpsewhich texgyrepagella-regular.otf)
c2sc	Small Capitals From Capitals
dlig	Discretionary Ligatures
kern	Kerning
liga	Standard Ligatures
lnum	Lining Figures
onum	Oldstyle Figures
size	Optical Size
smcp	Small Capitals
ss01	Stylistic Set 1

That -i output preserves a small connection, too. The Vietnamese characters in TeX Gyre Pagella were added by Hàn Thế Thành — the author of pdfTeX, and the man whose doctoral thesis brought micro-typography to TeX, the subject of this site’s microtype page. Font copyright notices keep more history than you would expect.

Printing every glyph in a font — nfssfont.tex and fonttable

To see with your own eyes which glyphs a font carries, print a glyph chart. The interactive tool that has shipped with TeX for decades is nfssfont.tex: start it and it asks Input external font name, e.g., cmr10; answer cmr10, type \table for the chart and \bye to finish. One correction here — the widely repeated invocation tex nfssfont does not work. Line 48 of nfssfont.tex is \documentclass{article}; it is a LaTeX document, and launching it under plain TeX dies with ! Emergency stop. The right command is latex nfssfont or pdflatex nfssfont.

terminal
$ pdflatex nfssfont
Input external font name, e.g., cmr10
(or <enter> for NFSS classification of font): cmr10
Now type a test command or \help for help [ \table \bye ]: \table
...
Output written on nfssfont.pdf (1 page, 71803 bytes).

# \help lists the whole repertoire:
#   \init switches to another font;  \stop or \bye finishes the run;
#   \table prints the font layout in tabular format;
#   \text prints a sample text, assuming TeX text font conventions;
#   \sample combines \table and \text;
#   \lowers \uppers \digits \math \punct \names \bigtest ...

# Knuth's original is plain TeX and does start under tex:
$ tex testfont
Name of the font to test = cmr10
Now type a test command (\help for help): \table

If the dialogue feels fussy, the fonttable package does the same job from inside a document. \fonttable{cmr10} takes a font name (strictly, a .tfm name) and typesets a table of every glyph — \fonttable{pzdr} to peek inside Zapf Dingbats; \xfonttable{T1}{cmr}{m}{n} specifies it by the four NFSS attributes instead. \fontrange{<low>}{<high>} narrows the table to 16-glyph blocks, up to 256 glyphs. And if you want sample text set in the font rather than a grid of glyphs, that is \fonttext{cmr10}. Much of the package’s code is an edited nfssfont.tex, and its glyph-testing commands reimplement Knuth’s testfont.tex — three faces of one tool. Incidentally, pressing return at nfssfont’s first prompt without typing a name switches it to specifying the font by its five NFSS attributes instead.

Virtual fonts (.vf) — a layer that fabricates glyphs that do not exist

A virtual font (.vf) is a layer that translates the single logical font TeX sees into real glyphs and low-level typesetting operations. In the TeX FAQ’s words, virtual fonts are “a means of collecting bits and pieces together to make the glyphs of a font,” the pieces coming from other fonts, rules, and typesetting commands with positioning. That sounds abstract until you open one. Crack the T1-encoded Times (ptmr8t) with vftovp and the ff ligature slot reads: set an f, move back 0.025 em, set another f. The raw Times has no ff glyph, so the virtual font builds one on the spot.

terminal
$ vftovp $(kpsewhich ptmr8t.vf) $(kpsewhich ptmr8t.tfm) ptmr8t.vpl
$ head -5 ptmr8t.vpl
(VTITLE )
(FAMILY UNSPECIFIED)
(CODINGSCHEME EXTENDED TEX FONT ENCODING - LATIN)
(DESIGNSIZE R 10.0)
(MAPFONT D 0 (FONTNAME ptmr8r) ...)

# slot O 33 (octal) is the ff ligature of T1 - assembled from two f glyphs
(CHARACTER O 33
   (CHARWD R 0.640991)
   (CHARHT R 0.677991)
   (MAP
      (SETCHAR C f)
      (MOVERIGHT R -0.025)
      (SETCHAR C f)
      )
   )

The mechanism divides the labour. TeX itself needs only the dimensions — width, height, depth — which it reads from the companion .tfm (TeX Font Metric). How each glyph is actually drawn lives in the .vf, and the DVI driver reads that (dvips, dvipdfmx). A virtual font is therefore always a pair, a .tfm plus a .vf. Binary files are unreadable, so every distribution ships two programs that convert to and from the human-readable .vpl (Virtual Property List). Plain metrics have the same arrangement with the .pl (Property List) format: open one with tftopl and you can read the seven FONTDIMEN parameters and the LIGTABLE of ligatures and kerns.

  • vftovp.vf + .tfm (binary) → .vpl (text). Argument order: virtual font, metric, output. This is the one for taking an existing virtual font apart.
  • vptovf.vpl (text) → .vf + .tfm (binary). Argument order: description, virtual font, metric. Bakes an edited description back down.
  • tftopl / pltotf — the same round trip for a plain Western metric. Use these to read what is inside a .tfm (FONTDIMEN, LIGTABLE).
  • ppltotf / ptftopl — the Japanese counterparts of the previous pair, for the binary JFMs of the pTeX family.
  • In all of them the extension may be omitted; .vf, .tfm and .vpl are supplied for you.

Put the resulting .tfm under .../fonts/tfm/<supplier>/ and the .vf under .../fonts/vf/<supplier>/ in the texmf tree, refresh the filename database with mktexlsr, and kpsewhich ptmr8t.vf will find them. The tables that pair a TFM name with the actual font file — the font maps — are managed by updmap. In modern practice, though, nobody writes a .vpl by hand: generating TeX metrics and virtual fonts from PostScript or OpenType faces is fontinst’s job. A virtual font is not something you author from scratch so much as something you open, read, and nudge after a tool has produced it.

Why TeX font names look like ciphers — texdoc fontname

The answer is that only eight characters were available. The Fontname scheme, which texdoc fontname opens, does not hide the reason: it states outright that names are limited to eight characters for compatibility with DOS filesystems and with ISO 9660, the standard used for CD-ROM distribution. The permitted characters are lowercase a–z, digits and the underscore. Those eight are divided as S TT W [V...] [N] [E] [DD] — supplier, typeface, weight, variants, encoding, width, design size — and that is the whole scheme.

Part of phvbc8tSlot in the schemeMeaning
psupplier (S)Adobe — the note in supplier.map says “p for PostScript”
hvtypeface (TT)Helvetica (hv helvetic in typeface.map)
bweight (W)bold (weight.map has b Bold)
cwidth (E)condensed — on the NFSS side this merges with b into bc
8tencoding (N)variant.map reads 8t ECEncoding CorkEncoding — that is, T1

Read that table once and the names in your .fd files and log suddenly start talking. ptmr8t is Adobe’s Times regular in T1, pcrr8t is Courier regular in T1, ptmb8c is Times bold in TS1 (8c being Text Companion). 7t is “TeX text encoding,” that is OT1, and 8r is TeX Base 1, the encoding that receives a raw Type 1 — the real font a T1 virtual font sits on top of. That is exactly what we saw in the previous section, where ptmr8t.vf had ptmr8r in its MAPFONT. Fontname acknowledges that eight characters are cramped, incidentally, and devotes a separate section of the scheme to long names.

Japanese metrics — the JFM and its character classes

Japanese typesetting needs something a Western .tfm cannot supply. Kanji and kana sit by default in a square (full-width) box, and the space between them is not inter-word space: gaps open and close only around punctuation — brackets and stops. The structure that carries this is the JFM (Japanese Font Metric). pTeX and upTeX use a binary JFM much like a .tfm; LuaTeX-ja expresses the same role as a Lua table. The former converts to and from text with ppltotf and ptftopl; the latter is text already and can simply be read.

The chief difference from a Western TFM is that a JFM groups characters into “character classes.” As the LuaTeX-ja manual specifies, every length in a JFM is a floating-point number in design-size units, anchored to zw (the full width) and zh (the full height, height + depth); each class then carries its own width, height, depth and italic (italic correction). Class 0 always exists and holds the great majority of Japanese characters — those in no other class. Punctuation goes into separate classes, and a table of glue and kern to insert between one class and another is what produces the spacing around stops and brackets.

jfm.lua
-- A LuaTeX-ja JFM (excerpt); all lengths are in design-size units
luatexja.jfont.define_jfm {
  version = 3,
  dir = 'yoko',            -- horizontal writing
  zw = 1.0, zh = 1.0,       -- full width, full height
  [0] = {                  -- class 0: most kanji and kana
    chars = { '漢' },
    width = 1.0, height = 0.88, depth = 0.12, italic = 0.0,
  },
  [1] = {                  -- a class for stops and commas
    chars = { '。', '、' },
    width = 0.5, height = 0.88, depth = 0.12, italic = 0.0,
  },
}

On the pTeX family, JAglue — the spacing inserted between two Japanese characters, and between a Japanese character and Western text — is added automatically at typeset time. The JFM fixes the gap between classes; between unclassed Japanese characters the default kanjiskip applies, and at a Japanese/Western boundary, xkanjiskip. Together with kinsoku, the rules barring certain characters from the start or end of a line, these carry the look of Japanese type. LuaTeX-ja ships standard JFMs for different needs: jfm-ujis.lua is the default, based on upnmlminr-h.tfm, a metric used in upTeX (most characters square); jfm-jis.lua corresponds to jis.tfm, widely used in pTeX; jfm-min.lua corresponds to pTeX’s default min10.tfm. In a font definition you pick one with jfm=, as in \jfont\F=HaranoAjiMincho-Regular:jfm=ujis.