Schriftwerkzeuge

In den Einreichungsrichtlinien steht „alle Schriften müssen eingebettet sein“, und niemand weiß, ob das eigene PDF das erfüllt. Eine kursiv gesetzte Passage will sich einfach nicht neigen. In fontspec steht Numbers=OldStyle, und nichts ändert sich. Solche Fälle klärt kein Raten, sondern die Werkzeuge zur Schriftanalyse. Diese Seite reiht die Prüfprogramme rund um LaTeX auf, jeweils mit tatsächlich mitgeschnittener Ausgabe: pdffonts, fc-list, otfinfo, \fontname\font, nfssfont zum Drucken einer Glyphentabelle und vftovp, das eine virtuelle Schrift (.vf) in lesbaren Text aufbricht. Nebenbei klärt sich, warum eine TeX-Schrift phvbc8t heißt.

Welche Schrift wird hier gesetzt? \fontname und \showthe\font

An jeder Stelle eines Dokuments antwortet \fontname\font mit dem echten Dateinamen und \showthe\font mit den fünf NFSS-Koordinaten. Ersteres liefert den Namen der Metrik, die TeX tatsächlich geladen hatcmr10, cmbx10, cmti10 –, Letzteres schreibt > \OT1/cmr/m/n/10 . ins Log. Beide widersprechen sich nie: Das zweite ist die Anforderung, das erste das Ergebnis. Wer beides betrachtet, erkennt sofort, ob die angeforderte Schrift kam oder unterwegs ersetzt wurde.

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.

Hier ist eine Korrektur fällig. \showfont ist kein LaTeX-Befehl. Er wird oft als Mittel genannt, die aktuelle Schrift auszugeben, existiert aber weder im LaTeX2e-Kernel noch in einem Paket; der Aufruf endet mit ! Undefined control sequence. (ConTeXt kennt einen Befehl dieses Namens). Wer dasselbe in LaTeX will, liest zusätzlich zu den beiden obigen Wegen die Interna direkt aus: Innerhalb von \makeatletter lassen sich mit \f@encoding, \f@family, \f@series, \f@shape und \f@size die fünf Koordinaten in beliebigem Format per \typeout ausgeben.

Um das Laden der Schriften selbst zu verfolgen, dient das Paket tracefnt. Mit \tracingfonts=2 hält das Log bei jedem Laden einer realen Schrift fest, welche externe Schrift unter welchem NFSS-Namen geladen wurde. Bei der Suche nach der Ursache einer Ersetzung ist das aufschlussreicher als die Warnung. Die Ausgabe ist allerdings umfangreich; praktikabel ist daher, den betroffenen \section zuerst in ein minimales Dokument herauszulösen.

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.

Die eingebetteten Schriften eines PDF prüfen — pdffonts

pdffonts (Bestandteil von Poppler und Xpdf) listet tabellarisch auf, welche Schriften in einem fertigen PDF stecken, in welchem Format und ob sie eingebettet sind – eine Zeile je Schrift. Drei Spalten zählen: emb für die Einbettung, sub für die Untermenge (nur die tatsächlich benutzten Glyphen wurden behalten) und uni für die Rückabbildung auf Unicode (ob sich Text aus dem PDF kopieren lässt). Die Prüfung vor der Einreichung besteht aus genau diesem Befehl; steht in emb überall yes, wird die Datei nicht wegen nicht eingebetteter Schriften zurückgewiesen.

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

Die Ausgabe taugt zugleich als Engine-Fingerabdruck. pdfLaTeX bettet Type-1-Schriften mit Custom- oder Builtin-Kodierung ein, während XeLaTeX und LuaLaTeX mit einer OpenType-Schrift über fontspec CID Type 0C und Identity-H erzeugen – genug, um zu erkennen, womit ein zugesandtes PDF gebaut wurde. Die sechs Buchstaben vor jedem Namen (OSZFFG+ und dergleichen) sind Subset-Kennungen; wird dieselbe Schrift zweimal untermengt, entstehen zwei verschiedene Präfixe. Steht dagegen in emb ein no, bleibt diese Schrift dem Rechner der Lesenden überlassen – bei den vierzehn PostScript-Standardschriften meist unkritisch, bei einer Einreichung aber ein Ablehnungsgrund.

Herausfinden, welche Schriften das System hat — fc-list und otfinfo

Der Name, den man fontspec übergibt, muss der Name der Schrift selbst sein; ein erfundener funktioniert nicht. Um Installiertes samt Zuordnung von Namen zu Dateien aufzulisten, dient fc-list (Teil von fontconfig). Ohne Argumente gibt es alles aus, fc-list : family nur die Familiennamen, ein Muster grenzt ein. Auf der LuaTeX-Seite entspricht dem luaotfload-tool: --find löst einen Namen auf, --update baut die Schriftnamendatenbank neu. Fontconfig ist unter Linux Standard, unter macOS jedoch nicht vorinstalliert – dort installiert man es separat, etwa über Homebrew.

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"

Was eine Schrift tatsächlich kann, ist das Ressort von otfinfo (aus lcdf-typetools, in TeX Live enthalten). -i liefert Namen, Version und Copyright, -f listet die OpenType-Feature-Tags, -s die unterstützten Schriftsysteme und Sprachen, -t die Tabellen. -f hat den größten praktischen Wert: Prüft man hier auf onum oder smcp, bevor man Numbers=OldStyle oder Letters=SmallCaps in fontspec schreibt, erledigen sich die meisten Fälle von „geschrieben, aber nichts passiert“. Ein Feature, das die Schrift nicht besitzt, wird schlicht stillschweigend ignoriert.

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

In dieser -i-Ausgabe steckt zudem eine kleine Verbindung. Die vietnamesischen Zeichen in TeX Gyre Pagella stammen von Hàn Thế Thành – dem Autor von pdfTeX, dessen Dissertation die Mikrotypografie zu TeX brachte, Thema der microtype-Seite dieser Website. Copyright-Vermerke von Schriften bewahren mehr Geschichte, als man vermutet.

Alle Glyphen einer Schrift drucken — nfssfont.tex und fonttable

Um mit eigenen Augen zu sehen, welche Glyphen eine Schrift führt, druckt man eine Glyphentabelle. Das interaktive Werkzeug, das seit Jahrzehnten mit TeX ausgeliefert wird, ist nfssfont.tex: Beim Start fragt es Input external font name, e.g., cmr10; man antwortet cmr10, tippt \table für die Tabelle und \bye zum Beenden. Eine Korrektur dazu: Der vielzitierte Aufruf tex nfssfont funktioniert nicht. Zeile 48 von nfssfont.tex lautet \documentclass{article}; es ist ein LaTeX-Dokument, und unter plain TeX bricht es mit ! Emergency stop. ab. Richtig ist latex nfssfont oder 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

Ist der Dialog zu umständlich, erledigt das Paket fonttable dasselbe aus einem Dokument heraus. \fonttable{cmr10} nimmt einen Schriftnamen (genauer: einen .tfm-Namen) und setzt eine Tabelle sämtlicher Glyphen – \fonttable{pzdr} für einen Blick in Zapf Dingbats; \xfonttable{T1}{cmr}{m}{n} gibt sie stattdessen über die vier NFSS-Attribute an. \fontrange{<low>}{<high>} grenzt die Tabelle auf 16-Glyphen-Blöcke ein, bis zu 256 Glyphen. Und wer statt eines Rasters Beispieltext in der Schrift sehen will, nimmt \fonttext{cmr10}. Ein Großteil des Paketcodes ist ein bearbeitetes nfssfont.tex, und die Glyphentestbefehle implementieren Knuths testfont.tex neu – drei Gesichter eines Werkzeugs. Übrigens: Drückt man bei der ersten Eingabeaufforderung von nfssfont nur die Eingabetaste, wechselt es in den Modus, die Schrift über ihre fünf NFSS-Attribute anzugeben.

Virtuelle Schriften (.vf) – eine Schicht, die nicht vorhandene Glyphen erzeugt

Eine virtuelle Schrift (.vf) ist eine Schicht, die die eine logische Schrift, die TeX sieht, in echte Glyphen und Low-Level-Satzoperationen übersetzt. In den Worten der TeX FAQ sind virtuelle Schriften „a means of collecting bits and pieces together to make the glyphs of a font“, wobei die Teile aus anderen Schriften, Linien und Satzbefehlen mit Positionsangabe stammen. Das klingt abstrakt, bis man eine öffnet. Zerlegt man das T1-kodierte Times (ptmr8t) mit vftovp, steht an der Stelle der ff-Ligatur: ein f setzen, 0,025 em zurückgehen, noch ein f setzen. Das rohe Times besitzt keine ff-Glyphe, also baut die virtuelle Schrift sie an Ort und Stelle.

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)
      )
   )

Der Mechanismus teilt die Arbeit auf. TeX braucht nur die Abmessungen – Breite, Höhe, Tiefe –, die es aus der zugehörigen .tfm (TeX Font Metric) liest. Wie jede Glyphe tatsächlich gezeichnet wird, steht in der .vf, und die liest der DVI-Treiber (dvips, dvipdfmx). Eine virtuelle Schrift ist daher immer ein Paar: .tfm plus .vf. Binärdateien sind unlesbar, deshalb liefert jede Distribution zwei Programme mit, die in die menschenlesbare .vpl (Virtual Property List) und zurück konvertieren. Reine Metriken haben dieselbe Anordnung mit dem .pl-Format (Property List): Mit tftopl geöffnet, lassen sich die sieben FONTDIMEN-Parameter und die LIGTABLE mit Ligaturen und Unterschneidungen lesen.

  • vftovp.vf + .tfm (binär) → .vpl (Text). Argumentreihenfolge: virtuelle Schrift, Metrik, Ausgabe. Das Werkzeug, um eine vorhandene virtuelle Schrift zu zerlegen.
  • vptovf.vpl (Text) → .vf + .tfm (binär). Argumentreihenfolge: Beschreibung, virtuelle Schrift, Metrik. Backt eine bearbeitete Beschreibung zurück.
  • tftopl / pltotf — derselbe Hin- und Rückweg für eine reine westliche Metrik. Damit liest man den Inhalt einer .tfm (FONTDIMEN, LIGTABLE).
  • ppltotf / ptftopl — die japanischen Gegenstücke des vorigen Paars, für die binären JFMs der pTeX-Familie.
  • Bei allen darf die Erweiterung entfallen; .vf, .tfm und .vpl werden ergänzt.

Die erzeugte .tfm legt man im texmf-Baum unter .../fonts/tfm/<supplier>/ ab, die .vf unter .../fonts/vf/<supplier>/, frischt die Dateinamendatenbank mit mktexlsr auf, und kpsewhich ptmr8t.vf findet sie. Die Tabellen, die einen TFM-Namen mit der tatsächlichen Schriftdatei verbinden – die Font-Maps –, verwaltet updmap. In der heutigen Praxis schreibt allerdings niemand eine .vpl von Hand – TeX-Metriken und virtuelle Schriften aus PostScript- oder OpenType-Schnitten zu erzeugen, ist Sache von fontinst. Eine virtuelle Schrift verfasst man weniger von Grund auf, als dass man sie nach der Erzeugung durch ein Werkzeug öffnet, liest und nachjustiert.

Warum TeX-Schriftnamen wie Chiffren aussehen — texdoc fontname

Die Antwort lautet: Es standen nur acht Zeichen zur Verfügung. Das Schema Fontname, das texdoc fontname öffnet, verschweigt den Grund nicht: Es hält ausdrücklich fest, dass Namen aus Kompatibilität mit DOS-Dateisystemen und mit ISO 9660, dem Standard der CD-ROM-Verteilung, auf acht Zeichen begrenzt sind. Erlaubt sind nur Kleinbuchstaben a–z, Ziffern und der Unterstrich. Diese acht werden als S TT W [V...] [N] [E] [DD] aufgeteilt – Lieferant, Schriftbild, Stärke, Varianten, Kodierung, Breite, Entwurfsgröße –, und das ist bereits das ganze Schema.

Teil von phvbc8tPosition im SchemaBedeutung
pLieferant (S)Adobe – die Notiz in supplier.map sagt „p für PostScript“
hvSchriftbild (TT)Helvetica (hv helvetic in typeface.map)
bStärke (W)fett (weight.map führt b Bold)
cBreite (E)schmal – auf NFSS-Seite verschmilzt das mit b zu bc
8tKodierung (N)In variant.map steht 8t ECEncoding CorkEncoding – also T1

Wer diese Tabelle einmal gelesen hat, dem beginnen die Namen in .fd-Dateien und Logs plötzlich zu sprechen. ptmr8t ist Adobes Times regular in T1, pcrr8t Courier regular in T1, ptmb8c Times fett in TS1 (8c steht für Text Companion). 7t bedeutet „TeX text encoding“, also OT1, und 8r ist TeX Base 1, die Kodierung, die ein rohes Type 1 aufnimmt – die reale Schrift, auf der eine virtuelle T1-Schrift aufsetzt. Genau das war im vorigen Abschnitt zu sehen, wo ptmr8t.vf in seinem MAPFONT ptmr8r führte. Übrigens räumt Fontname selbst ein, dass acht Zeichen eng sind, und widmet langen Namen einen eigenen Abschnitt.

Japanische Metriken – die JFM und ihre Zeichenklassen

Japanischer Satz braucht etwas, das eine westliche .tfm nicht liefern kann. Kanji und Kana sitzen standardmäßig in einem quadratischen (vollbreiten) Kasten, und der Abstand zwischen ihnen ist kein Wortzwischenraum: Lücken öffnen und schließen sich nur um die Interpunktion – Klammern und Satzzeichen. Diese Struktur ist die JFM (Japanese Font Metric). pTeX und upTeX verwenden eine binäre JFM ähnlich einer .tfm; LuaTeX-ja drückt dieselbe Rolle als Lua-Tabelle aus. Erstere lässt sich mit ppltotf und ptftopl in Text und zurück wandeln, Letztere ist bereits Text und einfach lesbar.

Der wichtigste Unterschied zu einer westlichen TFM ist, dass eine JFM Zeichen zu „character classes“ gruppiert. Wie das LuaTeX-ja-Handbuch festlegt, ist jede Länge in einer JFM eine Gleitkommazahl in Einheiten der Entwurfsgröße, bezogen auf zw (volle Breite) und zh (volle Höhe, height + depth); jede Klasse trägt dann eigene Werte für width, height, depth und italic (Kursivkorrektur). Klasse 0 existiert immer und enthält die große Mehrheit der japanischen Zeichen, die keiner anderen Klasse angehören. Interpunktion kommt in eigene Klassen, und eine Tabelle des zwischen zwei Klassen einzufügenden Glue bzw. Kerns erzeugt die Abstände um Satzzeichen und Klammern.

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,
  },
}

In der pTeX-Familie wird JAglue – der Abstand zwischen zwei japanischen Zeichen sowie zwischen einem japanischen Zeichen und westlichem Text – beim Satz automatisch eingefügt. Die JFM bestimmt den Abstand zwischen Klassen; zwischen nicht klassifizierten japanischen Zeichen gilt das voreingestellte kanjiskip, an einer japanisch/westlichen Grenze xkanjiskip. Zusammen mit kinsoku, den Regeln, die bestimmte Zeichen am Zeilenanfang oder -ende verbieten, tragen sie das Erscheinungsbild japanischen Satzes. LuaTeX-ja liefert Standard-JFMs für verschiedene Zwecke mit: jfm-ujis.lua ist die Vorgabe, gestützt auf upnmlminr-h.tfm, eine in upTeX verwendete Metrik (die meisten Zeichen quadratisch); jfm-jis.lua entspricht dem in pTeX verbreiteten jis.tfm; jfm-min.lua entspricht pTeX’ Standard min10.tfm. In einer Schriftdefinition wählt man mit jfm=, etwa \jfont\F=HaranoAjiMincho-Regular:jfm=ujis.