Von den drei modernen Engines schreibt allein XeTeX kein PDF. Nach dem Satz gibt es einen Bytestrom im Format .xdv (extended DVI) aus, den ein eigenes Programm, xdvipdfmx, in PDF verwandelt. Von außen erledigt ein einziges xelatex document.tex alles; innen sind es zwei Stufen. Wer das weiß, liest das Log anders, sobald ein Bild oder eine eingebettete Schrift Ärger macht. Diese Seite behandelt, was XeTeX LaTeX gebracht hat – UTF-8 unmittelbar zu lesen und die im Betriebssystem installierten Schriften über fontspec beim Namen zu nennen –, außerdem, was .xdv wirklich ist und was tatsächlich zerbricht, wenn ein pdfLaTeX-Manuskript nach XeLaTeX umzieht.
Wer XeTeX geschrieben hat, und wofür
Den Anfang machte Jonathan Kew im Rahmen seiner Arbeit bei SIL International; die erste öffentliche Fassung erschien im April 2004, ausschließlich für Mac OS X. SIL befasst sich mit den Schriften und Orthografien von Minderheitensprachen weltweit, und die Anforderung stand von Beginn an fest: Unicode setzen, mit den Schriften, die tatsächlich für diese Sprachen gemacht wurden. Frühes XeTeX baute daher auf der damaligen Mac-Satztechnik AAT (Apple Advanced Typography) auf. 2006 folgte eine Linux-Portierung, bald darauf Windows, und ab TeX Live 2007 war es auf allen Plattformen enthalten. Unter TeX Live 2024 nennt die Copyright-Zeile von xetex --version SIL International, Jonathan Kew and Khaled Hosny und listet anschließend die eingebundenen Bibliotheken: ICU 74.2, HarfBuzz 8.3.0, Graphite2 1.3.14, FreeType2 2.13.2 – unter macOS zusätzlich die Frameworks Core Text und Cocoa. XeTeX versteht man am besten als die Schicht, die TeX mit dem verbindet, was Betriebssystem und Schriftindustrie real ausliefern.
Auch die Versionsnummer erzählt eine kleine Geschichte. xetex --version liefert XeTeX 3.141592653-2.6-0.999996 (TeX Live 2024). Das führende 3.141592653 ist Knuths TeX: Er hängt bei jeder Fehlerkorrektur eine Ziffer an, sodass die Zahl gegen π strebt, und hat festgehalten, dass die absolut letzte Änderung – nach seinem Tod vorzunehmen – die Version auf genau π setzen wird, worauf jeder verbliebene Fehler zur Eigenschaft wird. pdfTeX und LuaTeX tragen dieselben Ziffern, alle drei Engines teilen also diesen Anfang. Das abschließende 0.999996 gehört XeTeX selbst; die mitgelieferte NEWS-Datei zeigt, wie es jedes Jahr im Februar einen Schritt weiterrückt, von 0.999991 im Jahr 2019 bis 0.999996 im Februar 2024 – immer neue Neunen, immer knapp unter 1. Eine erklärte Absicht, gegen 1 zu konvergieren, ist nirgends dokumentiert; das bleibt eine Beobachtung, keine Regel.
Eine Systemschrift beim Namen nennen: fontspec und \setmainfont
\usepackage{fontspec} laden, \setmainfont{Helvetica Neue} schreiben – mit dem Namen, den das Betriebssystem kennt –, und damit ist die Sache erledigt. Keine TFM-Datei zu bauen, keine Zeile in eine Map-Datei einzutragen. Kompiliert man das mit xelatex, bestätigt pdffonts, dass HelveticaNeue als CID TrueType eingebettet wurde. Brotschrift, Serifenlose und Nichtproportionale heißen \setmainfont, \setsansfont und \setmonofont; für eine eigene Familie in Überschriften dient \newfontfamily\headingfont{...}. Mit den in TeX Live mitgelieferten Schriften verhält es sich allerdings anders, und genau dort bleiben die meisten zuerst hängen. Davon handelt der nächste Abschnitt.
\documentclass{article}
\usepackage{fontspec} % no inputenc, no fontenc needed
% An OS font is named the way the system knows it, e.g.
% \setmainfont{Helvetica Neue}
% A font that ships with TeX Live is safest named by file name:
\setmainfont{texgyretermes-regular.otf}[
BoldFont = texgyretermes-bold.otf,
ItalicFont = texgyretermes-italic.otf,
BoldItalicFont = texgyretermes-bolditalic.otf,
]
\setsansfont{texgyreheros-regular.otf}
\setmonofont{texgyrecursor-regular.otf}
\newfontfamily\headingfont{texgyreadventor-regular.otf}
\begin{document}
Unicode goes in literally: naïve, Straße, ¿cómo?, œuvre.
\textbf{Bold} and \textit{italic} come from the files named above.
\[ E = mc^2 \]
\end{document}Entscheidend ist, was nicht dasteht: weder inputenc noch fontenc. UTF-8-Eingabe und Unicode-Schriften sind die Grundlage, sodass die Zeichenkodierungsformeln der pdfLaTeX-Ära vollständig entfallen. Lässt sich eine Schrift nicht finden, lautet die Meldung ! Package fontspec Error: The font "..." cannot be found. – und zuerst zu verdächtigen ist dann nicht TeX, sondern die Namensauflösung auf Seiten des Betriebssystems. Die feineren Stellschrauben – Ligatures, Numbers=OldStyle, SmallCapsFeatures, RawFeature zur Übergabe roher OpenType-Tags und Renderer zur Wahl des Shapers (HarfBuzz / AAT / Graphite) – gehören zu fontspec und werden auf dessen eigener Seite behandelt. Sollen auch die Formeln in Unicode-Schriften gesetzt werden, kommt unicode-math hinzu.
The font "..." cannot be found. – wenn eine mitgelieferte Schrift auf ihren Namen nicht reagiert
XeTeX fragt für einen Namen die Schriftdatenbank des Betriebssystems, nicht die Verzeichnisse von TeX Live. Genau hier bleiben die meisten zuerst hängen. Auf einem macOS-Rechner mit unverändert installiertem TeX Live 2024 funktioniert \setmainfont{Helvetica Neue}, während \setmainfont{TeX Gyre Termes}, \setmainfont{Latin Modern Roman} und \setmainfont{TeX Gyre Pagella} sämtlich mit ! Package fontspec Error: The font "..." cannot be found. scheitern – und alle drei unter LuaLaTeX anstandslos laufen. Der Unterschied liegt in der Suche: luaotfload von LuaTeX durchsucht den TeX-Verzeichnisbaum selbst und legt einen Index an, während XeTeX die Schriftmaschinerie des Betriebssystems befragt – unter macOS Core Text –, sodass eine von der Distribution gelieferte, nie beim System angemeldete Schrift über ihren Namen nicht auffindbar ist.
Die Abhilfe ist einfach: mitgelieferte Schriften über ihren Dateinamen ansprechen. \setmainfont{texgyretermes-regular.otf} funktioniert – und zwar mit Beachtung der Groß- und Kleinschreibung, TeXGyreTermes-Regular.otf also nicht. Wer so benennt, verliert die automatische Zuordnung von Fett und Kursiv und deklariert deshalb BoldFont, ItalicFont und BoldItalicFont ausdrücklich. Das obige Beispiel ist in dieser Form geschrieben und übersetzt sowohl unter xelatex als auch unter lualatex ohne Fehler und ohne fehlende Zeichen. Alternativ lassen sich die Schriften der Distribution beim System anmelden (etwa über die texlive-fontconfig-Einrichtung unter Linux), doch das unterscheidet sich von Rechner zu Rechner und lässt sich bei Mitarbeitenden nicht reproduzieren; für ein Manuskript sind Dateinamen daher das Verlässlichere. Meldet jemand, XeLaTeX finde eine Schrift nicht, sollte als Erstes der Dateiname ausprobiert werden.
An japanischen Schriften zeigt sich dieselbe Regel von der anderen Seite. Ein Name, den das Betriebssystem kennt, wird aufgelöst; ein Name, den nur TeX Live kennt, nicht. Auf diesem macOS-Rechner mit TeX Live 2024 übersetzen \setmainfont{Hiragino Mincho ProN}, \setmainfont{Hiragino Sans} und \setmainfont{YuMincho} allesamt unter XeLaTeX, denn genau so heißen sie in der Schriftenübersicht des Systems. \setmainfont{Noto Sans JP} dagegen scheitert mit cannot be found, solange die Schrift nicht auf Systemebene installiert ist. Die Prüfung ist also einfach: nachsehen, ob die Schrift in der Schriftenliste des Systems auftaucht. Taucht sie auf, findet XeTeX sie; taucht sie nicht auf, hilft auch ihr Vorhandensein in TeX Live dem Namen nicht. Für japanische Manuskripte mit Vertikalsatz oder strengen Umbruchregeln bleibt luatexja oder upLaTeX der bequemere Weg als xeCJK.
Was .xdv ist – und warum XeTeX das PDF nicht selbst schreibt
.xdv ist DVI mit Erweiterungen. Mit xelatex -no-pdf lässt sich eine solche Datei greifbar erzeugen: Ihre ersten Bytes lauten f7 07 – auf den DVI-Befehl pre folgt eine Format-Kennung 7 statt der 2 des Standard-DVI. Im Inneren steht nach einem Kommentar XeTeX output 2026.08.13:0452 die verwendete Schrift als Dateipfad (etwa lmroman10-regular.otf). Eine .xdv-Datei weiß also bereits, welche Glyphe welcher Schriftdatei an welche Koordinate gehört – die Schrift selbst ist aber noch nicht eingebettet. Übrig bleibt, diese Schriftdateien zu öffnen, zu subsetten und in ein PDF zu packen, und genau das erledigt xdvipdfmx.
Ein gewöhnlicher xelatex-Lauf hinterlässt keine .xdv-Datei, denn XeTeX leitet diese Bytes über eine Pipe an die Standardeingabe des Treibers. Mit -output-driver=CMD lässt sich der Treiber ersetzen; zeigt man auf ein Skript, das lediglich cat ausführt, fängt man den Strom im Vorbeiziehen ab – im Test 820 Byte, am Ende der traditionelle DVI-Abschluss df df df df. Daraus folgen zwei praktische Konsequenzen. Erstens: Fragt ein Paket wie graphicx nach dem Treiber, lautet die Antwort xetex, also xdvipdfmx. Zweitens: Man muss ermitteln, aus welcher der beiden Stufen ein Fehler stammt. Getippt wurde xelatex, doch ein Fehlschlag bei Bildern oder Schrifteinbettung erscheint als xdvipdfmx-Zeile. Am schnellsten liest man das Log in zwei Hälften: die erste TeX-Fehlerzeile und die letzte Treiberzeile.
# Stop after the first stage and keep the intermediate XDV file.
$ xelatex -no-pdf document.tex
Output written on document.xdv (1 page, 820 bytes).
# The second byte is the DVI format id: 7 for XDV, 2 for plain DVI.
$ xxd document.xdv | head -2
00000000: f707 0183 92c0 1c3b 0000 0000 03e8 1d20 .......;.......
00000010: 5865 5465 5820 6f75 7470 7574 2032 3032 XeTeX output 202
# Run the second stage by hand. xdvipdfmx has been the default
# driver on every platform since XeTeX 0.997.
$ xdvipdfmx document.xdv
document.xdv -> document.pdf
# The driver is a replaceable external command.
$ xelatex -output-driver="/path/to/save-stdin.sh" document.texWas beim Umzug eines Dokuments von pdfLaTeX zu XeLaTeX zerbricht
Gefährlich ist gerade der Fall, der keinen Fehler auslöst. Übergibt man eine alte Präambel unverändert an xelatex, übersetzt sie meist anstandslos. \usepackage[utf8]{inputenc} wird mit einer einzigen Warnung übergangen – Package inputenc Warning: inputenc package ignored with utf8 based engines. –, und für sich genommen richtet das keinen Schaden an. Heikel ist die Kombination aus \usepackage[T1]{fontenc} und \usepackage{lmodern}. Bleiben diese beiden Zeilen stehen, verharrt XeLaTeX auf dem 8-Bit-Pfad des NFSS: Eingebettet wird eine TFM-Schrift namens ec-lmr10, von pdffonts als Type 1C gemeldet. Das ist etwas anderes als das CID Type 0C, das über fontspec entsteht – der Wechsel der Engine hat also praktisch nichts gebracht.
Eine einzige Logzeile unterscheidet beide Fälle. Ist [T1]{fontenc} noch geladen, ergibt ein getipptes 日 die Meldung Missing character: There is no 日 ("65E5) in font ec-lmr10! – der Codepunkt in TeX's Hexadezimalschreibweise "65E5, dazu ein 8-Bit-Schriftname. Im selben Dokument, auf fontspec umgestellt, heißt es Missing character: There is no 日 (U+65E5) in font [lmroman10-regular]... – die Notation wird zu U+65E5, der Schriftname zu einer OpenType-Datei. Wer die erste Form sieht, ist auf den 8-Bit-Pfad zurückgefallen. Dasselbe gilt für kombinierende diakritische Zeichen (ec-lmr10 kennt kein U+0301, der OpenType-Weg setzt es klaglos). Die richtige Migration besteht darin, die ganze Familie alter Schriftdeklarationen auf einmal zu entfernen – inputenc, fontenc, lmodern, times und Verwandte – und fontspec zur einzigen Quelle der Schriftauswahl zu machen.
| Zeile in der alten Präambel | Verhalten unter XeLaTeX | Vorgehen |
|---|---|---|
\usepackage[utf8]{inputenc} | wird mit einer Warnzeile ignoriert | entfernen |
\usepackage[T1]{fontenc} | hält stillschweigend auf dem 8-Bit-NFSS-Pfad | durch fontspec ersetzen |
\usepackage{lmodern} | bettet ec-lmr10 ein (Type 1C) | \setmainfont{lmroman10-regular.otf} verwenden |
microtype | nur Randausgleich; keine Schriftdehnung | unverändert weiter laden |
babel | funktioniert, ist aber dünn bei RTL und komplexen Schriften | polyglossia erwägen |
Warum die Schriftdehnung unter XeLaTeX nicht funktioniert
Weil die Engine die Funktion nicht besitzt. Von den beiden Säulen von microtype setzt XeTeX allein den Randausgleich um. Prüft man die Primitive einzeln durch, so hat XeTeX zwar \lpcode und \rpcode, die den Überhang je Zeichen festlegen, aber kein \efcode, das bestimmt, wie weit ein Zeichen gedehnt werden darf. Selbst der Schalter für den Randausgleich heißt nicht wie in pdfTeX \pdfprotrudechars, sondern eigenständig \XeTeXprotrudechars. Lädt man \usepackage{microtype} unter XeLaTeX, zeigt das Log Character protrusion enabled (level 2)., während die Zeile Automatic font expansion enabled, die unter pdfLaTeX oder LuaLaTeX danebenstünde, stillschweigend verschwindet. Fordert man sie ausdrücklich an, folgt ein klarer Abbruch: ! Package microtype Error: Font expansion does not work with xetex.
Komplexe Schriften und Rechts-nach-links: HarfBuzz und die \XeTeX...-Primitive
Der Hauptgrund für die weite Verbreitung von XeTeX ist, dass es Schriften, deren Zeichen ihre Form je nach Kontext ändern – Arabisch, die indischen Schriften –, korrekt behandelt. Für die Formung (Shaping) sorgt HarfBuzz: Version 0.9999 (Mai 2013) wechselte von der älteren ICU LayoutEngine zu HarfBuzz, und der Build in TeX Live 2024 bindet HarfBuzz 8.3.0 ein. Auch die Engine selbst bringt eigene Primitive mit: \XeTeXinputencoding zum Umschalten der Eingabekodierung mitten im Dokument, \XeTeXcharclass und \XeTeXinterchartoks zur Klassifizierung von Zeichen und zur Reaktion auf ihre Nachbarn, \XeTeXlinebreaklocale zur sprachabhängigen Wahl der Umbruchregeln, \XeTeXgenerateactualtext zum Einschreiben echten Texts ins PDF für die Extraktion sowie \XeTeXpicfile und \XeTeXpdffile für Bilder. Den Sprachwechsel übernimmt polyglossia, den Rechts-nach-links-Satz bidi (von polyglossia bei Arabisch und Ähnlichem selbsttätig geladen), Chinesisch, Koreanisch und Japanisch xeCJK – für japanischen Vertikalsatz und anspruchsvolle Umbruchregeln sind luatexja oder upLaTeX allerdings der glattere Weg.
Wann XeLaTeX die Wahl ist – und wann nicht
- Wenn die vorhandenen Schriften genutzt werden sollen. Den OpenType- oder TrueType-Namen in
\setmainfonteintragen – fertig, keine Konfigurationsdatei anzufassen. - Wenn Unicode wörtlich geschrieben werden soll. UTF-8-Eingabe ist Voreinstellung, und die gesamte Kodierungspräambel entfällt.
- Für mehrsprachige und Rechts-nach-links-Dokumente.
polyglossiamitbidiist im Arabischen und Hebräischen erprobt, und HarfBuzz übernimmt die Formung. - Dagegen spricht erstens: Schriftdehnung wird gebraucht. XeTeX kennt kein
\efcode, die Dehnung vonmicrotypekann also gar nicht greifen. Steht die typografische Qualität obenan, sind pdfLaTeX oder LuaLaTeX richtig. - Dagegen spricht zweitens: Das Satzsystem soll programmiert werden. XeTeX bettet keine Skriptsprache ein. Wer tiefe Eingriffe braucht, geht zu LuaLaTeX.
- Dagegen spricht drittens: japanischer Vertikalsatz. Er übersteigt den Zweck von
xeCJK; ein früher Versuch mitluatexjaoder upLaTeX spart Zeit.
Die Faustregel in einem Satz: Wer die Schriften des Betriebssystems nur beim Namen nutzen will, nimmt XeLaTeX; wer in den Satz selbst eingreifen will, LuaLaTeX. Ein vollständiger Vergleich der drei steht auf der Seite „Die Wahl der Engine“. Zum Schluss ein Hinweis zur Zusammenarbeit: Schriftnamen unterscheiden sich von System zu System, und \setmainfont{Helvetica Neue} scheitert auf dem Linux-Rechner einer Kollegin schlicht. Für ein gemeinsam bearbeitetes Manuskript sorgt man zuerst für einen Build, der mit den in TeX Live mitgelieferten Schriften durchläuft – über den Dateinamen benannt wie oben – und tauscht danach nur das Nötige aus. Wird ausschließlich ein PDF eingereicht, sollte pdffonts vor dem Versand bestätigen, dass alle Schriften eingebettet sind.