La commande pdftex --version renvoie trois nombres accolés : pdfTeX 3.141592653-2.6-1.40.26. Le premier n'appartient pas à pdfTeX : c'est le TeX de Knuth saisi à mi-chemin de sa convergence vers π, et XeTeX comme LuaTeX portent les mêmes chiffres. pdfTeX, c'est ce TeX augmenté d'une seule chose : il écrit directement du PDF. C'est bien lui qui s'exécute quand on tape pdflatex, et il reste le moteur par défaut de LaTeX. Cette page explique pourquoi il l'est resté, comment les polices sont résolues par des métriques TFM et des fichiers map — une conception ancienne — et en quoi consiste l'apport propre de pdfTeX : la microtypographie qu'active microtype, à savoir la protrusion des caractères et la dilatation des glyphes. Tout ce qui suit provient d'exécutions réelles sous TeX Live 2024.
La différence entre pdflatex, latex et pdftex
Les trois sont le même exécutable. Dans le répertoire bin de TeX Live 2024, pdflatex et latex sont des liens symboliques vers pdftex ; amstex et csplain aussi. Seul diffère le format chargé au démarrage. Un format est un fichier .fmt contenant un jeu de macros déjà développé et figé ; la ligne pdflatex pdftex ... *pdflatex.ini de fmtutil.cnf signifie : appelé sous le nom pdflatex, exécuter le moteur pdftex avec les macros de LaTeX. Moteur (le programme) et format (le système de commandes) sont donc deux axes distincts, et « pdfLaTeX » désigne simplement la combinaison moteur pdfTeX + format LaTeX.
$ readlink $(which pdflatex) latex amstex
pdftex
pdftex
pdftex
$ grep -E '^(latex|pdflatex|pdftex) ' $(kpsewhich fmtutil.cnf)
latex pdftex language.dat -translate-file=cp227.tcx *latex.ini
pdflatex pdftex language.dat -translate-file=cp227.tcx *pdflatex.ini
pdftex pdftex language.def -translate-file=cp227.tcx *pdfetex.iniDeux enseignements secondaires découlent de ce tableau. D'abord, la commande latex n'est nullement « l'ancien TeX » : c'est pdfTeX en mode DVI. À l'exécution, la bannière affiche This is pdfTeX, ... (preloaded format=latex) et le résultat est un fichier .dvi. Ensuite, le format pdftex est construit à partir de pdfetex.ini : le e désigne e-TeX, cet ensemble d'extensions — \protected, \unexpanded, l'espace de registres élargi, \middle — que LaTeX moderne présuppose sans le dire. En vérifiant sur les trois moteurs si \eTeXversion est défini, pdfTeX, XeTeX et LuaTeX répondent tous par l'affirmative. e-TeX n'est plus une option. \pdftexversion, en revanche, n'existe que sur pdfTeX : c'est à cela que les packages reconnaissent le moteur qui les exécute.
Écrire le PDF directement, et revenir au DVI avec \pdfoutput=0
Un seul paramètre entier décide du format de sortie : \pdfoutput. Une valeur positive donne du PDF, 0 donne le DVI classique. Le TeX originel de Knuth n'émettait que du DVI (device independent) et laissait la conversion vers PostScript ou PDF à un programme distinct ; pdfTeX a intégré cette étape juste après le constructeur de pages — sans jamais condamner la sortie DVI. Les packages qui reposent sur des \special PostScript, PSTricks en tête, ont parfois encore besoin du chemin DVI → PS → PDF, et c'est \pdfoutput=0 qui le maintient ouvert.
Le piège tient à l'emplacement. \pdfoutput doit être fixé avant l'expédition de la première page ; modifié plus tard, pdfTeX s'arrête sur ! pdfTeX error (setup): \pdfoutput can only be changed before anything is written to the output., puis ! ==> Fatal error occurred, no output PDF file produced!. Ni PDF ni DVI ne subsistent. Comme LaTeX effectue très tôt sa détection de pilote, l'endroit sûr est tout en haut du fichier, avant \documentclass.
% Force DVI output even when the file is compiled with pdflatex.
% This line must come before \documentclass.
\pdfoutput=0
\documentclass{article}
\begin{document}
This run writes a .dvi file, not a .pdf.
\end{document}Ce que fait vraiment microtype : protrusion et dilatation
Cette unique ligne \usepackage{microtype} active deux mécanismes indépendants. Le .log les montre côte à côte : Package microtype Info: Character protrusion enabled (level 2). et Package microtype Info: Automatic font expansion enabled (level 2), stretch: 20, shrink: 20, step: 1. Le premier est la protrusion, ou crénage de marge : les points et les traits d'union en fin de ligne débordent légèrement du bloc de texte, si bien qu'un bord mécaniquement aligné paraît optiquement droit — généralisation de la vieille ponctuation suspendue. Le second est la dilatation des glyphes : les formes peuvent être étirées ou resserrées horizontalement jusqu'à 2 % (20/1000), et ce jeu est intégré à la décision de coupure de ligne elle-même. Les espaces intermots s'égalisent, et les « rivières » blanches qui descendent le long du paragraphe s'amincissent.
Aucune de ces deux idées ne vient de TeX. Toutes deux remontent au hz-program, le moteur de composition que le créateur de caractères Hermann Zapf développa à partir de 1988 avec Peter Karow et d'autres chez URW à Hambourg, avec pour but une page d'un gris uniforme, sans trous ni rivières. URW le fit breveter (brevet européen EP 0466953 ; les droits ont expiré en juillet 2010), et les algorithmes passèrent finalement à Adobe, qui les intégra à InDesign. Mais la même idée emprunta une seconde route : le Vietnamien Hàn Thế Thành analysa hz et l'implémenta dans TeX au titre de sa thèse à la faculté d'informatique de l'université Masaryk de Brno — Micro-typographic extensions to the TeX typesetting system, octobre 2000, sous la direction de Jiří Zlatuška. Une idée, deux destinations : le sommet du marché commercial et une implémentation libre à la portée de tous. \usepackage{microtype} est la seconde.
\documentclass{article}
\usepackage{microtype} % protrusion + expansion, sensible defaults
\begin{document}
With microtype loaded, pdfTeX nudges punctuation into the margin
and flexes glyph widths by a hair, so justified text looks far
more even. Nothing else in the document has to change.
\end{document}On peut aussi piloter les deux depuis les primitives brutes. Côté protrusion : \pdfprotrudechars (0 désactivé, 1 activé, 2 également répercuté dans le calcul des largeurs), avec \lpcode et \rpcode qui fixent la quantité par caractère à gauche et à droite. Côté dilatation : \pdfadjustspacing (=2 intègre le jeu à la coupure de ligne), \efcode pour la propension de chaque caractère à s'étirer, et \pdffontexpand pour déclarer les instances dilatées d'une police. On n'y touche pour ainsi dire jamais : microtype fournit un fichier de configuration par caractère (mt-cmr.cfg pour Computer Modern) et choisit les valeurs. Connaître ces noms reste utile : les avertissements du journal deviennent lisibles.
| Primitive | Fonction | Ce qu'elle contrôle |
|---|---|---|
\pdfprotrudechars | protrusion | 0 désactivé, 1 activé, 2 agit aussi sur le calcul des largeurs |
\lpcode / \rpcode | protrusion | débord par caractère à gauche / à droite (pour mille) |
\pdfadjustspacing | expansion | =2 intègre le jeu à la décision de coupure |
\efcode | expansion | propension de chaque caractère à s'étirer ; absente de XeTeX |
\pdffontexpand | expansion | déclare les instances dilatées d'une police |
Les polices sont résolues par des métriques TFM et des fichiers map
pdfTeX tire les métriques et les formes de glyphes de deux endroits distincts. Les métriques viennent d'un .tfm (TeX Font Metric) : kpsewhich cmr10.tfm renvoie fonts/tfm/public/cm/cmr10.tfm, et ce fichier ne contient que la largeur, la hauteur, la profondeur de chaque caractère et une table de crénage — pas un seul contour. C'est seulement une fois la composition achevée, au moment d'assembler le PDF, que le fichier map est consulté et que la vraie police qui y est nommée (un .pfb Type 1, ou une TrueType) est lue. L'entrée de cmr10 tient en une ligne : cmr10 CMR10 <cmr10.pfb — nom TFM, nom PostScript, et < signifiant « incorporer ce fichier ». Le pdftex.map que updmap engendre sous TeX Live 2024 compte 45 443 lignes ; ce seul fichier texte est la table de correspondance de toutes les polices de la distribution.
$ kpsewhich cmr10.tfm cmr10.pfb
/usr/local/texlive/2024/texmf-dist/fonts/tfm/public/cm/cmr10.tfm
/usr/local/texlive/2024/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb
$ grep -m1 '^cmr10 ' $(kpsewhich pdftex.map)
cmr10 CMR10 <cmr10.pfb
# The same one-line document, compiled by three engines:
$ pdffonts min-pdflatex.pdf
INJFRF+CMR10 Type 1 Builtin yes yes yes
$ pdffonts min-xelatex.pdf
HOLJOD+LMRoman10-Regular-Identity-H CID Type 0C Identity-H yes yes yes
$ pdffonts min-lualatex.pdf
YIRABR+LMRoman10-Regular CID Type 0C Identity-H yes yes yesComposez le même document d'une ligne avec les trois moteurs, puis passez pdffonts : la différence de conception apparaît telle quelle dans la sortie. pdfLaTeX incorpore CMR10 en Type 1 ; XeLaTeX et LuaLaTeX incorporent LMRoman10-Regular en CID Type 0C. La page ressemble à du Computer Modern dans les deux cas, mais le chemin emprunté et le fichier incorporé n'ont rien de commun. Les fichiers map peuvent être complétés depuis le document avec \pdfmapfile et \pdfmapline — et, fait notable, ces deux primitives subsistent dans XeTeX. L'héritage de l'ère 8 bits survit plus largement qu'on ne l'imagine.
Le plafond 8 bits : ! Bad character code, et pourquoi fontspec refuse
256 caractères par police. C'est le plafond le plus dur de pdfTeX. Écrivez \font\x=cmr10 \x \char"1234 et il s'arrête sur ! Bad character code (4660).. Donnez la même entrée à LuaTeX : rien ne se passe, ses polices sont larges en interne. C'est ce mur de 256 emplacements qui oblige à reconditionner les lettres latines accentuées dans un codage de police comme T1, et qui repousse les lettres grecques et les symboles vers d'autres polices. Une fois le plafond identifié, on comprend enfin à quoi sert fontenc.
C'est du côté de l'entrée que se loge le malentendu. Une source UTF-8 se compile sous LaTeX moderne sans charger inputenc : c'est la valeur par défaut depuis 2018. Mais ne se compile que l'ensemble des caractères que LaTeX a déclarés. Un fichier .tex contenant → passe sans broncher dans pdflatex ; mettez-y 日 et vous obtenez ! LaTeX Error: Unicode character 日 (U+65E5) not set up for use with LaTeX.. La limite de pdfTeX n'est donc pas « il ne lit pas l'UTF-8 » mais « il ne compose que les caractères prévus ». Et aucun chemin ne permet de nommer une police OpenType installée sur le système : chargez fontspec et l'exécution meurt aussitôt sur ! Fatal Package fontspec Error: The fontspec package requires either XeTeX or LuaTeX.. Ces trois faits — 256 emplacements, caractères déclarés seulement, pas de polices système — expliquent presque toutes les migrations vers XeTeX ou LuaTeX.
- Raisons de rester : compatibilité avec les modèles existants, rapidité et trente ans d'épreuve du terrain. Pour un article principalement en anglais,
pdflatexréserve le moins de surprises. - Raisons de partir : Unicode multilingue, polices du système, composition japonaise, traitement piloté par Lua. Si l'un de ces besoins est réel, changer de moteur vaut mieux qu'empiler des contournements.
- L'accident classique : charger
fontspecen restant sous pdfLaTeX.fontspecappartient à XeLaTeX et LuaLaTeX. - L'autre accident : placer
\pdfoutputaprès\documentclass. L'exécution échoue sans laisser ni PDF ni DVI.
Images : PNG, JPEG et PDF directement, EPS converti pour vous
pdfTeX lit directement trois formats d'image — PNG, JPEG et PDF — par la primitive de bas niveau \pdfximage, sur laquelle repose au quotidien \includegraphics de graphicx. Seul l'EPS doit d'abord être converti en PDF, et cela même est désormais automatique : avec le shell escape restreint activé par défaut dans TeX Live, \includegraphics{fig.eps} appelle discrètement repstopdf, dépose un fig-eps-converted-to.pdf à côté du fichier et incorpore celui-ci. Voici le piège. Avec -no-shell-escape, aucune conversion n'a lieu — et il n'y a ni erreur ni avertissement. À la place, un cadre vide portant le nom du fichier est composé, et le PDF sort parfaitement valide. C'est ainsi que les figures disparaissent classiquement en intégration continue.
Puisqu'il écrit lui-même le PDF, pdfTeX expose aussi des primitives qui atteignent les fonctions du format. \pdfliteral injecte des opérateurs de dessin PDF bruts ; \pdfobj crée un objet PDF ; \pdfannot place une annotation — un lien, un champ de formulaire. Les liens et signets de hyperref reposent sur cette couche. Pour les réglages globaux, on dispose de \pdfinfo pour les métadonnées (titre, auteur), de \pdfcompresslevel pour la force de compression et de \pdfpageattr pour attacher des attributs à chaque page.
\pdfinfo{
/Title (My Report)
/Author (A. Author)
}
\pdfcompresslevel=9
% a thin rule drawn with a raw PDF operator
\pdfliteral{0 0 m 100 0 l 0.4 w S}| Primitive | Rôle dans pdfTeX | Écriture dans LuaTeX |
|---|---|---|
\pdfoutput | choisit la sortie PDF ou DVI | \outputmode |
\pdfliteral | injecte des opérateurs de dessin PDF bruts | \pdfextension literal |
\pdfobj / \pdfannot | crée un objet ou une annotation PDF | \pdfextension obj / annot |
\pdfinfo | écrit les métadonnées (titre, auteur) | \pdfextension info |
\pdfcompresslevel | niveau de compression du PDF (0–9) | \pdfvariable compresslevel |
\pdfximage | lit une image PNG / JPEG / PDF | \saveimageresource |
\pdfsavepos | enregistre la position courante sur la page | \savepos |
\pdfprotrudechars | active la protrusion | \protrudechars |
\pdfadjustspacing | active la dilatation des glyphes | \adjustspacing |
Ce que les primitives \pdf... de pdfTeX ont laissé aux moteurs suivants
LuaTeX a été bâti sur pdfTeX et en a hérité l'essentiel, mais l'espace de noms \pdf..., devenu tentaculaire, a été rangé. Une grande part passe désormais par trois guichets — \pdfextension, \pdfvariable et \pdffeedback — qui reçoivent un mot-clé et des arguments. \pdfliteral est devenu \pdfextension literal, \pdfoutput est devenu \outputmode, \pdfximage est devenu \saveimageresource, et \pdfprotrudechars / \pdfadjustspacing sont devenus \protrudechars / \adjustspacing. En revanche, \lpcode, \rpcode et \efcode ont conservé leur nom tel quel. Le savoir de l'ère pdfTeX se transpose presque intégralement ; seule l'orthographe change.
XeTeX n'en a hérité qu'en partie, et cet héritage partiel a des conséquences pratiques. En sondant les primitives une à une sous TeX Live 2024, on constate que XeTeX possède \lpcode et \rpcode mais pas \efcode ; son commutateur de protrusion ne s'appelle pas non plus \pdfprotrudechars mais \XeTeXprotrudechars. Sous XeLaTeX, la protrusion fonctionne donc, tandis que la dilatation ne peut tout simplement pas être mise en œuvre ; la réclamer explicitement par \usepackage[expansion=true]{microtype} arrête l'exécution : ! Package microtype Error: Font expansion does not work with xetex.. Chargé sans option, microtype fait simplement disparaître du journal la ligne relative à la dilatation, sans commentaire — d'où l'impression répandue qu'il « fait moins » sous XeLaTeX, sans qu'on sache pourquoi.
Quand pdflatex reste le bon choix
Si le document est majoritairement en anglais, si la revue ou les coauteurs ont déjà fixé le modèle et si l'échéance approche : pdfLaTeX. Sur un même document mathématique de 417 pages, chronométré sur cette machine, pdfLaTeX s'est révélé le plus rapide des trois moteurs — et c'est aussi celui qui bute le moins souvent sur un package existant. Il exige peu : une ligne \usepackage{microtype}, des figures en PNG / JPEG / PDF, et, si l'on dépend d'EPS, un shell escape qu'on ne coupe pas. À l'inverse, empiler les contournements sur pdfTeX pour un document exigeant du japonais ou des polices système est un mauvais calcul ; au-delà, la tâche revient à XeLaTeX ou LuaLaTeX. pdfTeX est aujourd'hui pour l'essentiel en mode maintenance, le développement s'étant déplacé vers LuaTeX — mais les 45 443 lignes de pdftex.map et trente ans de modèles accumulés ne bougeront pas de sitôt.