Schrift- und DB-Werkzeuge

Eine Schrift ist installiert, und LaTeX findet sie nicht. Für genau diesen Satz gibt es diese Seite. Das Unangenehme daran: Jede Engine sucht Schriften auf völlig andere Weise. pdflatex sieht die Systemschriften überhaupt nicht an, sondern vertraut allein den Font-Maps, die updmap erzeugt. XeTeX fragt die Schriftverwaltung des Betriebssystems. LuaTeX befragt eine eigene Lua-Datenbank, die luaotfload aufbaut. „Steht in fc-list, lässt sich aber nicht verwenden“ ist deshalb kein Widerspruch – man schaut lediglich in einen anderen der drei Mechanismen. Im Folgenden stehen fc-list, fc-cache, updmap, kanji-config-updmap, luaotfload-tool und fmtutil danach geordnet, welche Schicht sie jeweils reparieren.

Wie eine Engine eine Schrift findet: drei getrennte Mechanismen

Die Dreiteilung ist schlicht der unverändert erhaltene Altersunterschied der Engines. pdfTeX stammt vom TeX der 1980er Jahre ab, als das Betriebssystem noch gar keinen Begriff von einem Schriftverzeichnis kannte. Also wird die Zuordnung zwischen einem logischen TeX-Namen – einer Zeichenkette wie ptmr8r – und einer echten Datei in einer Tabelle namens Font-Map festgehalten, und updmap setzt sie zusammen. XeTeX, ab 2004, wurde so entworfen, dass es unmittelbar an der Schriftverwaltung des Systems hängt: Ein otool -L auf die xetex-Binärdatei des macOS-Builds von TeX Live 2024 zeigt CoreText als gelinkte Bibliothek. LuaTeX löst Namen in Lua auf und befragt die von luaotfload erzeugte Datenbank. Dasselbe \setmainfont{...} befragt unter den dreien also drei verschiedene Instanzen.

EngineWie sie eine Schrift suchtReparaturbefehl
pdftexIgnoriert Systemschriften völlig; löst logische .tfm-Namen über eine Font-Map zu Dateien aufupdmap-sys
xetexFragt das Betriebssystem; der macOS-Build ist gegen CoreText gelinktdie Schriftverwaltung des Systems
luatexLöst Namen in Lua auf und befragt die von luaotfload erzeugte Namensdatenbankluaotfload-tool --update
dvipdfmxNicht Satz, sondern Einbettung: Die Map entscheidet, welche Schriften ins PDF gelangenupdmap-sys / kanji-config-updmap-sys

fc-list und fc-cache sind keine TeX-Live-Befehle

Wer das verwechselt, trifft danach lauter falsche Entscheidungen. fc-list, fc-cache und fc-match gehören zu fontconfig, einem eigenständigen Projekt, und sind nicht Teil von TeX Live. Man kann das bin-Verzeichnis von TeX Live 2024 vollständig durchsuchen: Es gibt keine ausführbare Datei, die mit fc- beginnt; die Exemplare auf diesem Mac stammen von Homebrew als fontconfig 2.18.2. Nützlich sind sie trotzdem, denn sie beantworten, welche Schriften das System besitzt und wo die Dateien liegen. fc-list : family gibt nur die Familiennamen aus, fc-list -f ein gewähltes Format wie file, family und style. Auf diesem Rechner kamen 2.799 Einträge zurück.

terminal
fc-list : family | sort -u | wc -l         # how many families the system offers
fc-list -f '%{file}\n' :family=Menlo        # where the file actually is
fc-cache -fv ~/Library/Fonts               # rebuild the fontconfig cache

fc-match "NoSuchFontXYZ"
# Verdana.ttf: "Verdana" "Regular"          <- a substitute, not an error

Hier lauert eine Falle, in die jeder einmal tappt. fc-match sagt nie „nicht gefunden“. Übergibt man einen Namen, den es nicht gibt, liefert fontconfig trotzdem etwas: Hier antwortete fc-match "NoSuchFontXYZ" mit Verdana.ttf: "Verdana" "Regular". Das ist ein Ersatz, keine Bestätigung. Wer mit fc-match prüfen will, ob eine Schrift installiert ist, bekommt immer ein Ja. Für eine echte Entscheidung vergleicht man den zurückgegebenen Familiennamen mit dem gefragten oder grenzt mit fc-list ein. Unter macOS kommt ein zweiter Hinweis hinzu: Wie der vorige Abschnitt zeigte, schaut xetex auf CoreText, ein Eintrag in fc-list garantiert also nicht, dass XeTeX die Schrift nutzen kann. Umgekehrt ist bei Builds, in denen XeTeX tatsächlich über fontconfig sucht – typischerweise TeX Live unter Linux –, ein fc-cache nach dem Ablegen einer Schrift im eigenen Schriftverzeichnis genau der richtige Schritt.

updmap – was eine einzelne Zeile einer Font-Map wirklich sagt

Eine Font-Map ist reiner Text, eine Zeile je Verbindung zwischen einem logischen TeX-Namen und einer echten Datei. updmap schreibt diese Zeilen nicht selbst; es verkettet die in updmap.cfg aufgeführten .map-Dateien zu psfonts.map für dvips und pdftex.map für pdftex und dvipdfmx. Ein Zählen von updmap-sys --listmaps ergibt auf diesem Rechner 389 Deklarationen – davon 332 Map, 46 MixedMap, 11 KanjiMap. Die verkettete psfonts.map ist eine einzige Textdatei mit 45.672 Zeilen, knapp 5,5 MB. Eine Zeile darin liest sich so: der Name auf TeX-Seite, der PostScript-Fontname, eine Umkodierungsanweisung und die tatsächlichen Dateien.

terminal
# one real line out of psfonts.map on this machine
ptmr8r NimbusRomNo9L-Regu " TeXBase1Encoding ReEncodeFont " <8r.enc <utmr8a.pfb

updmap-sys --listmaps            # every declared map, and which cfg declared it
sudo updmap-sys --enable Map myfont.map
sudo updmap-sys                  # rebuild psfonts.map and pdftex.map

Was in der Praxis stolpern lässt, ist selten der Befehl, sondern welche Konfiguration man anfasst. In TeX Live 2024 verweigert das nackte updmap den Dienst: Es antwortet updmap [ERROR]: Either -sys or -user mode is required. gefolgt von updmap [ERROR]: In nearly all cases you should use updmap -sys. Diese Weigerung ist eine Freundlichkeit, denn die eigentliche Falle liegt direkt dahinter. Die Ausgabe von updmap --help sagt es unverblümt: Sobald updmap-user auch nur ein einziges Mal gelaufen ist, hat ein Aufruf von updmap-sys keine Wirkung mehr. Es entsteht eine persönliche Konfigurationsdatei, die von da an Vorrang hat. Auf gemeinsam genutzten Rechnern und in CI standardisiert man auf updmap-sys und greift zu updmap-user nur, wenn man die Systemeinstellungen bewusst überschreiben will. Das sudo ist nötig, weil alles unter /usr/local/texlive/2024 root gehört.

kanji-config-updmap – die eingebettete japanische Schrift wählen

Dass die Wahl der japanischen Schrift einen eigenen Befehl hat, hat einen Grund. Auf dem Weg über pLaTeX und upLaTeX wird nicht beim Satz, sondern erst im Schritt dvipdfmx entschieden, welche japanische Schrift ins PDF eingebettet wird. Die eingebettete Schrift lässt sich also nachträglich austauschen, ohne das Manuskript anzufassen; kanji-config-updmap von texjporg ist dieser Schalter und setzt intern die updmap-Option jaEmbed, früher kanjiEmbed. Beginnen Sie mit status. Auf diesem Rechner kam CURRENT family for ja: haranoaji (variant: -04) zurück, gefolgt von ipa und ipaex als bereitstehenden Familien. Zum Wechseln übergibt man den Familiennamen direkt. Wie bei updmap gibt es eine -sys- und eine -user-Form; auf gemeinsam genutzten Rechnern ist kanji-config-updmap-sys die sichere Wahl.

terminal
kanji-config-updmap-sys status
# CURRENT family for ja: haranoaji (variant: -04)
# Standby family : ipa
# Standby family : ipaex

sudo kanji-config-updmap-sys ipaex   # embed the IPAex family instead
sudo kanji-config-updmap-sys auto    # let it pick from what is installed

luaotfload-tool – warum der erste LuaTeX-Lauf langsam ist

Was beim ersten LuaLaTeX-Lauf überrascht, ist die Wartezeit. Ursache ist die Namensdatenbank von luaotfload, die durch Absuchen der Schriftdateien im System eine Zuordnung von Namen zu Dateien aufbaut. Auf diesem Rechner liegt sie unter TEXMFVAR/luatex-cache/generic/names/luaotfload-names.luc.gz und misst etwa 390 KB. Interessant ist, dass eine fehlgeschlagene Suche von selbst einen Neuaufbau anstößt. Übergibt man \setmainfont einen nicht existierenden Namen, zeigt das Log luaotfload | db : Reload initiated (formats: otf,ttf,ttc); reason: Font "NoSuchFontXYZ" not found. und hält erst dann bei ! Package fontspec Error: The font "NoSuchFontXYZ" cannot be found. „LuaLaTeX sieht die eben installierte Schrift nicht“ heilt sich also meist mit einem weiteren Lauf. Erzwingen lässt es sich mit luaotfload-tool --update, das die Datenbank neu erzeugt und, wenn nichts vorhanden ist, Font names database not found, generating new one. sowie This can take several minutes; please be patient. ausgibt.

terminal
luaotfload-tool --update              # rebuild the LuaTeX names database
luaotfload-tool --diagnose=environment # what luaotfload thinks its world looks like
ls "$(kpsewhich --var-value=TEXMFVAR)/luatex-cache/generic/names/"

fmtutil – die .fmt neu bauen, die eine Engine beim Start lädt

Beim Aufruf von pdflatex lädt die Engine zuerst eine Formatdatei wie latex.fmt, bevor sie irgendetwas tut. Diese Datei ist ein Abbild des gesamten internen Zustands der Engine in dem Moment, in dem sie ganz LaTeX eingelesen hatte – der Kniff, mit dem sie startet, ohne jedes Mal Tausende Zeilen Makros erneut zu lesen. fmtutil erzeugt diese .fmt-Dateien neu. Gebraucht wird es selten: nur nach einer Aktualisierung, die ein Format betrifft, oder wenn eine .fmt beschädigt ist und die Engine schon vor dem Start abbricht. Nach jeder Paketinstallation läuft es nicht. Für ein einzelnes Format fmtutil-sys --byfmt pdflatex, für alle fmtutil-sys --all, was mehrere Minuten dauert. Die Unterscheidung -sys und -user funktioniert genau wie bei updmap; auf gemeinsam genutzten Rechnern gilt -sys.

terminal
sudo fmtutil-sys --byfmt pdflatex   # rebuild one format
sudo fmtutil-sys --all              # rebuild every format (several minutes)
kpsewhich --var-value=TEXMFVAR      # where the .fmt files end up

Welcher Befehl zu welchem Symptom

BefehlEinzusetzen, wenn
fc-list : familyZuerst klären, ob das System die Schrift wirklich besitzt und unter welchem Namen
luaotfload-tool --updateNur LuaLaTeX findet die Schrift nicht, und ein zweiter Lauf hilft nicht
updmap-sys --enable MapEin Paket mit lateinischer Schrift wurde von Hand installiert, das PDF zeigt aber die alte Schrift
kanji-config-updmap-sys statusNur der japanische Text im PDF stimmt nicht; zuerst das aktuelle jaEmbed prüfen
fmtutil-sys --byfmtDie Engine bricht vor dem Satz ab, weil sie ihr Format nicht laden kann
mktexlsrEine Datei liegt in TEXMFLOCAL und wird trotzdem nicht gefunden; siehe die Build-Tools-Seite

Zum Schluss noch ein kleines Werkzeug am Rand dieser Karte. TeX Live liefert einen Befehl namens albatross, den seine Manpage als Werkzeug zum Auffinden von Schriften mit einem bestimmten Unicode-Zeichen beschreibt – und intern stützt er sich auf fontconfig, eine weitere Stelle, an der ein Werkzeug der TeX-Welt fontconfig aufruft. Der Aufruf hier endete allerdings mit Unable to locate a Java Runtime. Es benötigt eine Java-Laufzeitumgebung; wer es nutzen will, installiert sie separat. mktexlsr und texhash sowie kpsewhich sind ausführlich auf der Build-Tools-Seite behandelt.