Ein LaTeX-Dokument, das nur das Wort „Hello“ enthält, ist als DVI-Datei 252 Byte groß. Dieselbe Seite, von pdflatex in ein PDF verwandelt, wiegt 11.287 Byte. Fast die gesamten elf zusätzlichen Kilobyte sind kein Text, sondern die Schrift selbst: ein auf die fünf tatsächlich benutzten Glyphen reduziertes Type-1-Programm belegt allein 9.002 Byte. PDF-Erzeugung in LaTeX ist im Kern eine Kette von Entscheidungen darüber, was in der Datei mitreist. Diese Seite verfolgt diese Kette – die zwei Wege zum PDF, das Einstellen von PDF-Version und Komprimierung, wie das Papierformat wirklich eingetragen wird und wie sich die Schrifteinbettung mit pdffonts prüfen lässt – durchgehend mit gemessenen Zahlen.
Zwei Wege zum PDF: direkte Ausgabe und über DVI
Entweder schreibt die Engine das PDF selbst, oder ein separates Programm wandelt eine DVI-Datei um. Auf der Direktroute geben pdflatex (pdfTeX) und lualatex (LuaTeX) beim Setzen der Seite unmittelbar PDF-Operatoren aus. Auf der DVI-Route schreiben latex oder das japanische (u)platex zuerst eine DVI-Datei, die dvipdfmx übersetzt. Der interessante Fall ist xelatex: Es sieht nach einem einzigen Befehl aus, gehört aber zur zweiten Familie – XeTeX schreibt ein erweitertes DVI namens .xdv und übergibt es an xdvipdfmx. Ein Blick in die tatsächliche TeX-Live-2024-Installation zeigt es deutlich: dvipdfmx ist ein symbolischer Link auf xdvipdfmx, die japanische DVI-Route und XeTeX’ .xdv-Route werden also von ein und derselben Binärdatei bedient. Der Beleg bleibt in der Ausgabe erhalten – ein mit xelatex erzeugtes PDF nennt als Producer xdvipdfmx (20240305).
# TeX Live 2024: one binary serves both DVI routes
$ ls -l $(which dvipdfmx)
lrwxr-xr-x 1 root wheel 9 May 4 2024 .../dvipdfmx -> xdvipdfmx
# direct
$ pdflatex paper.tex
# via DVI
$ latex paper.tex && dvipdfmx paper.dvi
# via DVI, the Japanese way
$ uplatex paper.tex && dvipdfmx paper.dviSchickt man dasselbe Manuskript über fünf Wege, ist jedes Ergebnis „eine A4-Seite“, das Innenleben unterscheidet sich dennoch. Dass die Producer-Zeichenkette abweicht, versteht sich; bemerkenswert sind die voreingestellte PDF-Version und die MediaBox-Werte. Die A4-Breite von 210 mm sind exakt 595,2755905… Punkt, und jeder Konverter rundet anders: pdfTeX und LuaTeX schreiben nach \pdfdecimaldigits=3 den Wert 595.276, dvipdfmx schreibt 595.28, und Ghostscript (über ps2pdf) rundet bis auf die ganze Zahl 595. Praktisch spielt das kaum je eine Rolle, erklärt aber, warum zwei angeblich identische A4-Dateien beim Vergleich auseinanderlaufen.
| Befehl | Programm, das das PDF schreibt | Voreingestellte PDF-Version | A4-MediaBox-Breite |
|---|---|---|---|
pdflatex | pdfTeX selbst | 1.5 | 595.276 |
lualatex | LuaTeX selbst | 1.5 | 595.276 |
xelatex | xdvipdfmx, über ein .xdv | 1.5 | 595.28 |
latex + dvipdfmx | dvipdfmx | 1.5 | 595.28 |
uplatex + dvipdfmx | dvipdfmx; die übliche japanische Route | 1.5 | 595.28 |
latex + dvips + ps2pdf | Ghostscript | 1.4 | 595 |
„pdflatex kann kein EPS“ ist überholt
Unter TeX Live 2024 genügt \usepackage{graphicx} mit \includegraphics{fig.eps} und ein Lauf von pdflatex, und die Abbildung ist drin – ohne weitere Einstellungen. Nicht etwa, weil pdfTeX EPS lesen gelernt hätte. Die Treiberdatei pdftex.def lädt epstopdf-base von sich aus, sofern LaTeX läuft, Shell-Escape aktiviert ist (der voreingestellte restricted-Modus von TeX Live reicht) und \DoNotLoadEpstopdf nicht definiert wurde. Bei einem echten Lauf erscheint neben der Quelle eine Zwischendatei fig-eps-converted-to.pdf, und genau die wird eingebunden. \usepackage{epstopdf} muss man nicht mehr selbst schreiben. Umgekehrt unterbleibt die Umwandlung mit -no-shell-escape, und die Abbildung verschwindet einfach, ohne Fehler und ohne Warnung. Dieses stille Scheitern ist das gefährlichere.
Die automatische Umwandlung hat eine Falle, und der Kommentar in pdftex.def benennt sie selbst: „This can be wrong!“ Liegen fig.pdf und fig.eps beide vor und ist das PDF die eigentliche Vorlage, wird es durch eine aus dem EPS neu erzeugte Fassung überschrieben. Abhilfe schafft ein \newcommand{\DoNotLoadEpstopdf}{} noch vor der \documentclass-Zeile. Die DVI-Route (dvipdfmx) verarbeitet EPS seit jeher, indem sie im Hintergrund Ghostscript zur Umwandlung aufruft, und hinterlässt dabei keine Zwischendatei. Deshalb fühlt sich ein alter, EPS-lastiger Workflow auf der DVI-Route weiterhin wohl.
% keep a hand-made fig.pdf from being overwritten by fig.eps
\newcommand{\DoNotLoadEpstopdf}{}
\documentclass{article}
\usepackage{graphicx}
\begin{document}
\includegraphics{fig} % extension omitted: pdf, png, jpg are tried first
\end{document}Wird der Ausgabetreiber wirklich automatisch erkannt?
Für graphicx und color lautet die Antwort ja. Beide müssen den Ausgabetreiber kennen (pdftex, luatex, xetex, dvipdfmx, dvips, dvisvgm), um die richtigen Low-Level-Anweisungen auszugeben, und die Konfigurationsdatei graphics.cfg ermittelt die Engine, indem sie auf \pdfoutput, \XeTeXversion und \luatexversion prüft, und entscheidet dann zwischen pdftex.def, luatex.def, xetex.def und dvips.def. Deshalb sollte keine Treiberoption von Hand geschrieben werden – eine fest eingetragene wird in dem Moment zur Unwahrheit, in dem sich die Kompilierweise ändert.
Doch hyperref ist die Ausnahme. Erzeugt man mit (u)platex DVI und schreibt nur \usepackage{hyperref}, meldet das Log Package hyperref Info: Driver (default): hdvips. – es gibt \specials für dvips aus. Reicht man dieses DVI an dvipdfmx weiter, folgt eine Reihe dvipdfmx:warning: Unknown token "SDict" und ein PDF ohne Verweise und ohne Lesezeichen. Auf dieser Route also ausdrücklich \usepackage[dvipdfmx]{hyperref} schreiben. „Nie den Treiber angeben“ gilt für graphicx und nicht für hyperref auf der DVI-Route – die ganze Geschichte steht unter „Lesezeichen und Metadaten“.
Die PDF-Version festlegen: wo \pdfminorversion tatsächlich wirkt
\pdfminorversion gehört allein zu pdfTeX. Unter LuaTeX führt es zu ! Undefined control sequence., unter XeTeX zum selben Fehler. LuaTeX hat seine Primitive in einen Namensraum umgruppiert, dort heißt es \pdfvariable minorversion=4. XeTeX besitzt überhaupt kein entsprechendes Primitiv – das PDF schreibt ja xdvipdfmx –, also reicht man den Wunsch an den Treiber weiter: -output-driver="xdvipdfmx -V 4". Auf der DVI-Route ist es am einfachsten: dvipdfmx -V 4 paper.dvi. Auch die Herkunft der Voreinstellung lässt sich nachverfolgen: In TeX Lives pdftexconfig.tex steht \pdfminorversion = 5, und mehr steckt hinter „Standard ist PDF 1.5“ nicht.
Seit 2024 muss man diese drei Schreibweisen allerdings kaum noch auseinanderhalten. Setzt man den neueren Einstiegspunkt des LaTeX-Kerns, \DocumentMetadata{pdfversion=2.0}, vor \documentclass, entsteht PDF 2.0 unter pdflatex, lualatex und xelatex gleichermaßen – gemessen melden alle drei PDF version: 2.0. Während \pdfminorversion nur die Unterversionsnummer betrifft, legt pdfversion auch die Hauptversion fest: \pdfminorversion=0 liefert lediglich PDF 1.0 und erreicht 2.0 nie.
| Engine bzw. Route | PDF-Version festlegen | Hinweis |
|---|---|---|
\pdfminorversion=5 | pdfTeX (pdflatex) | LuaTeX/XeTeX melden ! Undefined control sequence. |
\pdfvariable minorversion=5 | LuaTeX (lualatex) | dieselbe Schreibweise erreicht auch compresslevel und Verwandte |
dvipdfmx -V 4 | DVI-Route und XeTeX | für XeTeX: -output-driver="xdvipdfmx -V 4" |
\DocumentMetadata{pdfversion=2.0} | alle drei Engines | legt auch die Hauptversion fest; steht vor \documentclass |
PDF-Komprimierung: \pdfcompresslevel und \pdfobjcompresslevel, gemessen
Die Kompressionsstufe von 6 auf 9 zu heben, spart zwei Byte. Gemessen an einem achtseitigen \lipsum[1-40]-Dokument: \pdfcompresslevel=0 ergibt 79.508 Byte, =1 ergibt 45.730, =6 ergibt 43.323 und =9 ergibt 43.321. Nur der Schritt von 0 auf 1 zählt, alles darüber ist Rauschen. Der zweite Regler, \pdfobjcompresslevel, arbeitet ganz anders: Er komprimiert nicht den Seiteninhalt, sondern die Objektdefinitionen des PDF selbst, gebündelt in Objektströmen. Beim selben Dokument sinkt die Größe dadurch von 43.321 auf 41.019 Byte, also um etwa fünf Prozent.
Hier liegt die Falle, die beides verbindet. Objektströme kamen mit PDF 1.5, wer also für einen alten Viewer auf \pdfminorversion=4 heruntergeht, schaltet \pdfobjcompresslevel stillschweigend ab. Ganz still ist es nicht – im Log steht: pdfTeX warning (Object streams): \pdfobjcompresslevel > 0 requires PDF-1.5 or greater. Object streams disabled now. Die Messung bestätigt es: Die Ausgabe mit \pdfminorversion=4 stimmt byteweise mit der bei \pdfobjcompresslevel=0 überein (beide 43.321 Byte). Wächst eine Datei nach dem Herabsetzen der Version leicht an, ist fast immer das die Ursache. Bei dvipdfmx gilt dasselbe: Mit -V 4 wird aus einem 8.310-Byte-PDF eines mit 10.055 Byte. Die Kompressionsstärke steuert dort -z 0 bis -z 9, und auch hier betrug der Abstand zwischen -z 6 und -z 9 sechs Byte.
% pdfTeX defaults, as set by TeX Live in pdftexconfig.tex
\pdfminorversion = 5
\pdfcompresslevel = 9 % 0 = off; 1 already captures most of the gain
\pdfobjcompresslevel = 2 % object streams; needs PDF 1.5 or later
% LuaTeX spells the same knobs differently
\pdfvariable minorversion = 5
\pdfvariable compresslevel = 9
\pdfvariable objcompresslevel = 2Wer das erzeugte PDF mit eigenen Augen lesen will, schaltet die Komprimierung am besten ganz ab. Statt engine-spezifische Primitive zu schreiben, genügt eine Zeile: \DocumentMetadata{uncompress} – gemessen wird aus einem 52.622-Byte-PDF eines mit 91.347 Byte, das sich im Texteditor öffnen lässt. Nützlich, wenn die erzeugten Operatoren zu prüfen sind oder nachvollzogen werden soll, welches Paket welches Objekt eingefügt hat.
Sie schreiben [letterpaper] und erhalten A4: wo das Papierformat wirklich entschieden wird
Die Klassenoption entscheidet nicht über das Papierformat des PDF. Unter TeX Live 2024 durchläuft \documentclass[letterpaper]{article} den pdflatex, und pdfinfo meldet Page size: 595.276 x 841.89 pts (A4). Der Grund ist schlicht: Die MediaBox des PDF entsteht aus \pdfpagewidth und \pdfpageheight, und letterpaper rührt daran nicht – es legt nur den Satzspiegel fest (\textwidth und Verwandte). TeX Lives pdftexconfig.tex hat beim Start bereits \pdfpageheight = 297 true mm und \pdfpagewidth = 210 true mm gesetzt. Die Klasse setzt also einen Satzspiegel im Letter-Maß auf ein Blatt A4.
Es gibt drei verlässliche Abhilfen. geometry laden (\usepackage[letterpaper]{geometry} kümmert sich auch um \pdfpagewidth); das Primitiv selbst schreiben (\pdfpagewidth=8.5in, was auch XeTeX annimmt); oder auf der DVI-Route beim Umwandeln angeben (dvipdfmx -p letter paper.dvi). Alle drei ergaben gemessen 612 x 792 pts (letter). Und es gibt eine vierte, modernere Antwort: Mit \DocumentMetadata{} wird die MediaBox aus \paperwidth und \paperheight geschrieben statt aus \pdfpagewidth – die Klassenoption gewinnt also endlich. Dieselbe Quelldatei liefert A4 oder Letter, je nachdem, ob diese eine Zeile da ist. Wer das bei einer Umstellung übersieht, bekommt mehr als eine verschobene Seitenzahl.
# TeX Live 2024, same source, four ways of asking for US letter
$ pdflatex letter.tex && pdfinfo letter.pdf | grep "Page size"
Page size: 595.276 x 841.89 pts (A4) # [letterpaper] alone: ignored
$ pdflatex geom.tex && pdfinfo geom.pdf | grep "Page size"
Page size: 612 x 792 pts (letter) # \usepackage[letterpaper]{geometry}
$ latex letter.tex && dvipdfmx -p letter letter.dvi
Page size: 612 x 792 pts (letter) # decided by the converter
$ pdflatex dm.tex && pdfinfo dm.pdf | grep "Page size"
Page size: 612 x 792 pts (letter) # \DocumentMetadata{} presentSind die Schriften eingebettet? pdffonts lesen
Steht in der Spalte emb von pdffonts paper.pdf überall yes, sind die Schriften eingebettet. Ein zweites Erkennungszeichen liegt in den Namen selbst: Eine eingebettete Schrift heißt etwa OREBYP+CMR10, mit einem sechsbuchstabigen Großbuchstaben-Präfix und einem +. Das kennzeichnet eine Teilmenge – herausgeschnitten wurden nur die tatsächlich verwendeten Glyphen –, und ein nacktes CMR10 ohne Präfix deutet umgekehrt stark darauf hin, dass die Schrift gar nicht eingebettet ist. Ein Blick in das „Hello“-PDF vom Anfang zeigt im Schriftdeskriptor /CharSet (/H/e/l/o/one): H, e, l, o und die Ziffer eins aus der Seitenzahl. Genau das heißt Subsetting.
$ pdffonts paper.pdf
name type encoding emb sub uni object ID
----------------------------- ---------- --------- --- --- --- ---------
OREBYP+CMR10 Type 1 Builtin yes yes yes 4 0
PTKKKD+CMTI10 Type 1 Builtin yes yes yes 5 0
# the same source through latex + dvipdfmx: Type 1C instead of Type 1
$ pdffonts paper-dvipdfmx.pdf
FUYUFD+CMR10 Type 1C Builtin yes yes yes 4 0
# a font that was NOT embedded: bare name, emb = no
Helvetica Type 1 Standard no no no 7 0Auch die Spalte type sagt etwas. Vergleicht man dieselbe „Hello“-Seite, meldet die pdflatex-Ausgabe Type 1, die dvipdfmx-Ausgabe Type 1C. Beide enthalten denselben Computer-Modern-Teilsatz derselben fünf Glyphen, doch die eingebetteten Schriftprogramme messen 9.002 gegenüber 720 Byte – mehr als das Zwölffache. dvipdfmx kodiert Type 1 vor dem Einbetten in CFF um (Compact Font Format, im PDF Type 1C genannt), und genau daraus erklärt sich der eingangs genannte Größenunterschied: 2.145 Byte über DVI gegen 11.287 Byte von pdflatex. LuaTeX und XeTeX greifen standardmäßig zur OpenType-Fassung von Latin Modern, die als CID Type 0C landet. All das ist echte Einbettung und für Druck wie Einreichung gleichermaßen unbedenklich.
Was vor dem Versand an Druckerei oder Zeitschrift zu prüfen ist
Zwei Befehle genügen. pdffonts bestätigt, dass jede Schrift eingebettet ist, pdfinfo liefert Seitenmaße und PDF-Version. Mehr ist die Prüfung nicht. Die Pannen sind vorhersehbar: ein verirrtes no in der Spalte emb (am leichtesten durch eine extern erzeugte PDF-Abbildung eingeschleppt), eine Datei im Letter-Format, wo A4 erwartet wird, oder eine PDF-Version, die neuer ist als die Einreichungsregeln erlauben. Da die Zeile Page size von pdfinfo nicht jede Seite untersucht, lässt sich zusätzlich ein Bereich angeben – pdfinfo -f 1 -l 99 paper.pdf –, um zu prüfen, ob sich die Maße mittendrin ändern.
pdffonts paper.pdf– steht in jeder Zeile vonembeinyes, und trägt jeder Name einABCDEF+-Präfix?pdfinfo paper.pdf– entsprichtPage sizeder Absicht, und liegtPDF versionim Rahmen der Einreichungsregeln?- Überwiegend Englisch und schnell → Direktroute (
pdflatex). Die Voreinstellungen erfordern kein Nachdenken. - Systemschriften, Unicode-lastiger Text →
lualatexoderxelatex(Direktroute). - Japanisch mit
(u)platex→ DVI-Route (dvipdfmx); Papier über-p, PDF-Version über-V. - Großer EPS-Bestand → Die DVI-Route bindet ihn ein, ohne Zwischendateien zu hinterlassen; die Direktroute wandelt automatisch um, streut aber
*-eps-converted-to.pdfins Verzeichnis.