Un document LaTeX contenant le seul mot « Hello » pèse 252 octets sous forme de DVI. La même page convertie en PDF par pdflatex en pèse 11 287. Ces onze kilo-octets supplémentaires ne sont presque pas du texte mais la police elle-même : un programme Type 1 réduit aux cinq glyphes réellement employés occupe à lui seul 9 002 octets. Produire un PDF avec LaTeX, c’est au fond enchaîner des décisions sur ce que le fichier emporte avec lui. Cette page suit cette chaîne — les deux voies vers le PDF, le réglage de la version et de la compression, la façon dont le format de papier est réellement inscrit, et la vérification de l’incorporation des polices avec pdffonts — chiffres mesurés à l’appui.
Deux voies vers le PDF : sortie directe et passage par DVI
Soit le moteur écrit le PDF lui-même, soit un programme distinct convertit un fichier DVI. Sur la voie directe, pdflatex (pdfTeX) et lualatex (LuaTeX) émettent des opérateurs PDF au fil de la composition. Sur la voie DVI, latex ou le (u)platex japonais écrivent d’abord un DVI, que dvipdfmx traduit. Le cas intéressant est xelatex : il n’a l’air que d’une seule commande mais relève en réalité de la seconde famille — XeTeX écrit un DVI étendu appelé .xdv et le confie à xdvipdfmx. L’installation réelle de TeX Live 2024 le montre sans ambiguïté : dvipdfmx est un lien symbolique vers xdvipdfmx, si bien que la voie DVI japonaise et la voie .xdv de XeTeX passent par un seul et même binaire. La trace subsiste dans la sortie : un PDF produit par xelatex annonce comme 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.dviFaites passer le même manuscrit par cinq voies : le résultat est chaque fois « une page A4 », mais l’intérieur diffère. La chaîne Producer change, bien sûr ; ce qui mérite attention, ce sont la version PDF par défaut et les valeurs de MediaBox. La largeur A4 de 210 mm vaut exactement 595,2755905… points, et chaque convertisseur arrondit à sa façon : pdfTeX et LuaTeX suivent \pdfdecimaldigits=3 et écrivent 595.276, dvipdfmx écrit 595.28, et Ghostscript (via ps2pdf) arrondit jusqu’à l’entier 595. Cela ne pose presque jamais problème en pratique, mais c’est la raison pour laquelle deux fichiers A4 supposés identiques refusent de se comparer.
| Commande | Programme qui écrit le PDF | Version PDF par défaut | Largeur MediaBox A4 |
|---|---|---|---|
pdflatex | pdfTeX lui-même | 1.5 | 595.276 |
lualatex | LuaTeX lui-même | 1.5 | 595.276 |
xelatex | xdvipdfmx, via un .xdv | 1.5 | 595.28 |
latex + dvipdfmx | dvipdfmx | 1.5 | 595.28 |
uplatex + dvipdfmx | dvipdfmx ; la voie japonaise habituelle | 1.5 | 595.28 |
latex + dvips + ps2pdf | Ghostscript | 1.4 | 595 |
« pdflatex ne sait pas lire l’EPS » : c’est dépassé
Sous TeX Live 2024, écrire \usepackage{graphicx} puis \includegraphics{fig.eps} et lancer pdflatex suffit à intégrer la figure, sans réglage supplémentaire. Ce n’est pas que pdfTeX ait appris à lire l’EPS : le fichier pilote pdftex.def charge epstopdf-base de lui-même, à condition que LaTeX tourne, que l’échappement shell soit actif (le mode restricted par défaut de TeX Live suffit) et que \DoNotLoadEpstopdf ne soit pas défini. À l’exécution, un fichier intermédiaire fig-eps-converted-to.pdf apparaît à côté de la source, et c’est lui qui est inclus. Il n’est plus nécessaire d’écrire soi-même \usepackage{epstopdf}. À l’inverse, avec -no-shell-escape la conversion n’a pas lieu et la figure disparaît purement et simplement, sans erreur ni avertissement. C’est cet échec silencieux qui est redoutable.
Cette conversion automatique a un piège, et le commentaire de pdftex.def le signale lui-même : « This can be wrong! » Si fig.pdf et fig.eps coexistent et que le PDF est le véritable original, il sera écrasé par une version régénérée depuis l’EPS. Le remède consiste à placer \newcommand{\DoNotLoadEpstopdf}{} avant même la ligne \documentclass. La voie DVI (dvipdfmx) traite l’EPS depuis toujours, en appelant Ghostscript en arrière-plan pour la conversion, et sans laisser de fichier intermédiaire. C’est pourquoi un ancien flux de travail riche en EPS reste à l’aise sur la voie DVI.
% 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}Le pilote de sortie est-il vraiment détecté tout seul ?
Pour graphicx et color, la réponse est oui. Tous deux doivent connaître le pilote de sortie (pdftex, luatex, xetex, dvipdfmx, dvips, dvisvgm) afin d’émettre les bonnes instructions de bas niveau, et le fichier de configuration graphics.cfg devine le moteur en sondant \pdfoutput, \XeTeXversion et \luatexversion, puis choisit entre pdftex.def, luatex.def, xetex.def et dvips.def. Il ne faut donc pas écrire d’option de pilote à la main : une valeur figée devient fausse dès que l’on change de manière de compiler.
Mais hyperref fait exception. Produisez du DVI avec (u)platex en n’écrivant que \usepackage{hyperref} et le journal indique Package hyperref Info: Driver (default): hdvips. : il émet des \special destinés à dvips. Confiez ce DVI à dvipdfmx et défilent des dvipdfmx:warning: Unknown token "SDict", pour un PDF sans liens ni signets. Sur cette voie, précisez-le : \usepackage[dvipdfmx]{hyperref}. « Ne jamais nommer le pilote » vaut pour graphicx et non pour hyperref sur la voie DVI — l’histoire complète est dans « Signets et métadonnées ».
Fixer la version du PDF : où \pdfminorversion fonctionne vraiment
\pdfminorversion appartient à pdfTeX seul. Sous LuaTeX, il produit ! Undefined control sequence. ; XeTeX donne la même erreur. LuaTeX a regroupé ses primitives dans un espace de noms : on y écrit \pdfvariable minorversion=4. XeTeX n’a aucune primitive équivalente — c’est xdvipdfmx qui écrit le PDF — on transmet donc la demande au pilote : -output-driver="xdvipdfmx -V 4". Sur la voie DVI, c’est le plus simple : dvipdfmx -V 4 paper.dvi. On peut même remonter à l’origine de la valeur par défaut : le fichier pdftexconfig.tex de TeX Live contient \pdfminorversion = 5, et c’est là toute l’explication du « par défaut, PDF 1.5 ».
En 2024, il est cependant bien moins nécessaire de retenir ces trois écritures. Placez le point d’entrée plus récent du noyau LaTeX, \DocumentMetadata{pdfversion=2.0}, avant \documentclass, et vous obtenez du PDF 2.0 avec pdflatex, lualatex et xelatex indifféremment — mesuré, les trois annoncent PDF version: 2.0. Là où \pdfminorversion ne touche que le numéro mineur, pdfversion fixe aussi le majeur : \pdfminorversion=0 ne donne que du PDF 1.0 et n’atteindra jamais 2.0.
| Moteur ou voie | Comment fixer la version PDF | Remarque |
|---|---|---|
\pdfminorversion=5 | pdfTeX (pdflatex) | LuaTeX/XeTeX renvoient ! Undefined control sequence. |
\pdfvariable minorversion=5 | LuaTeX (lualatex) | la même écriture donne accès à compresslevel et consorts |
dvipdfmx -V 4 | voie DVI et XeTeX | pour XeTeX : -output-driver="xdvipdfmx -V 4" |
\DocumentMetadata{pdfversion=2.0} | les trois moteurs | fixe aussi le numéro majeur ; se place avant \documentclass |
Compression du PDF : \pdfcompresslevel et \pdfobjcompresslevel, mesurés
Monter le niveau de compression jusqu’à 9 rapporte deux octets par rapport à 6. Mesuré sur un document de huit pages fait de \lipsum[1-40] : \pdfcompresslevel=0 donne 79 508 octets, =1 donne 45 730, =6 donne 43 323 et =9 donne 43 321. Seul le passage de 0 à 1 compte ; au-delà, c’est du bruit. L’autre réglage, \pdfobjcompresslevel, relève d’un mécanisme tout différent : il comprime non pas le contenu des pages mais les définitions d’objets du PDF lui-même, réunies en flux d’objets. Sur le même document, cela fait passer de 43 321 à 41 019 octets, soit environ cinq pour cent.
Voici le piège qui relie les deux. Les flux d’objets sont apparus avec PDF 1.5 : redescendre à \pdfminorversion=4 pour un vieux lecteur désactive donc silencieusement \pdfobjcompresslevel. Pas tout à fait silencieusement, du reste — le journal indique pdfTeX warning (Object streams): \pdfobjcompresslevel > 0 requires PDF-1.5 or greater. Object streams disabled now. La mesure le confirme : la sortie avec \pdfminorversion=4 coïncide à l’octet près avec celle obtenue à \pdfobjcompresslevel=0 (43 321 dans les deux cas). Si un fichier grossit légèrement après une baisse de version, c’est presque toujours la raison. dvipdfmx suit la même logique : ajouter -V 4 fait passer un PDF de 8 310 octets à 10 055. Sa force de compression se règle par -z 0 à -z 9, et là encore l’écart entre -z 6 et -z 9 s’est élevé à six octets.
% 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 = 2Pour lire de ses propres yeux le PDF produit, le plus rapide est de couper entièrement la compression. Plutôt que d’écrire des primitives propres à chaque moteur, une seule ligne suffit : \DocumentMetadata{uncompress} — mesuré, un PDF de 52 622 octets devient un fichier de 91 347 octets qui s’ouvre dans un éditeur de texte. À utiliser pour examiner les opérateurs produits par la compilation ou pour retrouver quel paquet a inséré quel objet.
Vous écrivez [letterpaper] et obtenez de l’A4 : où se décide vraiment le format
L’option de classe ne décide pas du format de papier du PDF. Sous TeX Live 2024, passez \documentclass[letterpaper]{article} dans pdflatex : pdfinfo annonce Page size: 595.276 x 841.89 pts (A4). La raison est simple : la MediaBox du PDF est écrite à partir de \pdfpagewidth et \pdfpageheight, et letterpaper n’y touche pas — il ne règle que la justification (\textwidth et consorts). Or le pdftexconfig.tex de TeX Live a déjà fixé au démarrage \pdfpageheight = 297 true mm et \pdfpagewidth = 210 true mm. La classe compose donc un bloc de texte au format letter sur une feuille A4.
Il existe trois correctifs fiables. Charger geometry (\usepackage[letterpaper]{geometry} s’occupe aussi de \pdfpagewidth) ; écrire soi-même la primitive (\pdfpagewidth=8.5in, que XeTeX accepte également) ; ou, sur la voie DVI, le préciser à la conversion (dvipdfmx -p letter paper.dvi). Les trois ont donné, à la mesure, 612 x 792 pts (letter). Il existe une quatrième réponse, la plus moderne : avec \DocumentMetadata{}, la MediaBox est écrite depuis \paperwidth et \paperheight et non plus depuis \pdfpagewidth — l’option de classe l’emporte enfin. Le même fichier source donne de l’A4 ou du letter selon la seule présence de cette ligne. Passer à côté lors d’une migration coûte plus qu’un numéro de page décalé.
# 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{} presentLes polices sont-elles incorporées ? Lire pdffonts
Si toutes les lignes de la colonne emb de pdffonts paper.pdf indiquent yes, les polices sont incorporées. Un second indice se lit dans les noms : une police incorporée s’appelle par exemple OREBYP+CMR10, avec un préfixe de six majuscules suivi d’un +. Cela signale un sous-ensemble — seuls les glyphes réellement employés ont été découpés ; à l’inverse, un CMR10 nu, sans préfixe, laisse fortement penser que la police n’est pas incorporée du tout. En ouvrant le PDF « Hello » du début, le descripteur de police incorporée indique /CharSet (/H/e/l/o/one) : H, e, l, o et le chiffre un du folio. Voilà ce qu’est le sous-ensemble.
$ 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 0La colonne type renseigne elle aussi. Sur la même page « Hello », la sortie de pdflatex indique Type 1 et celle de dvipdfmx Type 1C. Ce sont exactement le même sous-ensemble Computer Modern des mêmes cinq glyphes, et pourtant les programmes de police incorporés pèsent 9 002 octets contre 720 — plus de douze fois moins. dvipdfmx réencode le Type 1 en CFF (Compact Font Format, appelé Type 1C dans un PDF) avant de l’incorporer, et ce seul fait explique l’essentiel de l’écart de taille signalé en ouverture : 2 145 octets par la voie DVI contre 11 287 pour pdflatex. LuaTeX et XeTeX utilisent par défaut la version OpenType de Latin Modern, qui arrive en CID Type 0C. Toutes ces formes sont réellement incorporées et conviennent aussi bien à l’impression qu’à une soumission.
Ce qu’il faut vérifier avant d’envoyer le fichier à un imprimeur ou à une revue
Deux commandes suffisent. pdffonts confirme que toutes les polices sont incorporées, pdfinfo donne les dimensions de page et la version du PDF. La vérification s’arrête là. Les incidents sont prévisibles : un no égaré dans la colonne emb (le plus souvent introduit par une figure PDF produite ailleurs), un fichier en letter alors qu’on attendait de l’A4, ou une version de PDF plus récente que ne l’autorisent les consignes de soumission. Comme la ligne Page size de pdfinfo n’inspecte pas chaque page, on peut lui donner un intervalle — pdfinfo -f 1 -l 99 paper.pdf — pour vérifier que les dimensions ne changent pas en cours de route.
pdffonts paper.pdf— chaque ligne deembporte-t-elle unyes, et chaque nom un préfixeABCDEF+?pdfinfo paper.pdf—Page sizecorrespond-il à l’intention, etPDF versionreste-t-elle dans les limites des consignes de soumission ?- Surtout de l’anglais, et vite → voie directe (
pdflatex). Les réglages par défaut n’exigent aucune réflexion. - Polices système, texte riche en Unicode →
lualatexouxelatex(voie directe). - Japonais avec
(u)platex→ voie DVI (dvipdfmx) ; papier avec-p, version PDF avec-V. - Un gros stock d’EPS → la voie DVI l’intègre sans laisser de fichiers intermédiaires ; la voie directe convertit automatiquement mais parsème le répertoire de
*-eps-converted-to.pdf.