De los tres motores modernos, XeTeX es el único que no escribe PDF. Terminada la composición emite un flujo de bytes en un formato llamado .xdv (extended DVI), y un programa aparte, xdvipdfmx, lo convierte en PDF. Desde fuera, un solo xelatex document.tex lo hace todo; por dentro hay dos etapas. Saberlo cambia la forma de leer el registro el día en que una imagen o una fuente incrustada falla. Esta página trata lo que XeTeX aportó a LaTeX —leer UTF-8 tal cual y nombrar mediante fontspec las fuentes ya instaladas en el sistema—, qué es realmente un .xdv y qué se rompe de verdad al llevar un manuscrito de pdfLaTeX a XeLaTeX.
Quién escribió XeTeX y para qué
Todo empieza con el trabajo de Jonathan Kew en SIL International; la primera versión pública apareció en abril de 2004, solo para Mac OS X. SIL se ocupa de las escrituras y ortografías de lenguas minoritarias de todo el mundo, así que el requisito estaba ahí desde el principio: componer Unicode con las fuentes realmente hechas para esas lenguas. El XeTeX primitivo se levantó, en consecuencia, sobre la tecnología de composición del Mac de entonces, AAT (Apple Advanced Typography). En 2006 llegó el port a Linux, poco después a Windows, y desde TeX Live 2007 se distribuye en todas las plataformas. En TeX Live 2024, xetex --version imprime una línea de copyright con SIL International, Jonathan Kew and Khaled Hosny y luego enumera las bibliotecas que enlaza: ICU 74.2, HarfBuzz 8.3.0, Graphite2 1.3.14, FreeType2 2.13.2 y, en macOS, los frameworks Core Text y Cocoa. La mejor forma de entender XeTeX es verlo como la capa que conecta TeX con lo que el sistema operativo y la industria tipográfica entregan de verdad.
El número de versión también cuenta una pequeña historia. xetex --version devuelve XeTeX 3.141592653-2.6-0.999996 (TeX Live 2024). El 3.141592653 inicial es el TeX de Knuth: en cada corrección de errores añade un dígito, de modo que el número tiende a π, y ha dejado escrito que el cambio absolutamente final, que se hará tras su muerte, fijará la versión en π exactamente, momento en que todos los fallos restantes pasarán a ser características. pdfTeX y LuaTeX arrastran las mismas cifras, así que los tres motores comparten ese prefijo. El 0.999996 final es el propio de XeTeX, y el fichero NEWS que lo acompaña muestra cómo avanza un paso cada febrero, de 0.999991 en 2019 a 0.999996 en febrero de 2024: siempre más nueves, siempre justo por debajo de 1. Ningún documento declara la intención de converger a 1, así que conviene tomarlo como observación y no como regla.
Nombrar una fuente del sistema: fontspec y \setmainfont
Cargue \usepackage{fontspec}, escriba \setmainfont{Helvetica Neue} con el nombre que el sistema operativo conoce, y ahí termina el procedimiento. No hay TFM que construir ni línea que añadir a un fichero map. Compile eso con xelatex y pdffonts confirma que HelveticaNeue queda incrustada como CID TrueType. Los tipos de texto, de palo seco y de ancho fijo son \setmainfont, \setsansfont y \setmonofont; para levantar una familia aparte destinada a los títulos, \newfontfamily\headingfont{...}. Las fuentes que vienen con TeX Live, en cambio, siguen otro régimen, y ahí es donde la mayoría se atasca la primera vez. La sección siguiente se ocupa de ellas.
\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}Lo esencial es lo que no se escribe: ni inputenc ni fontenc. La entrada en UTF-8 y las fuentes Unicode son la base, de modo que los conjuros de codificación de la era pdfLaTeX desaparecen por completo. Cuando una fuente no aparece, el mensaje es ! Package fontspec Error: The font "..." cannot be found., y el primer sospechoso no es TeX sino la resolución de nombres del lado del sistema operativo. Los controles finos —Ligatures, Numbers=OldStyle, SmallCapsFeatures, RawFeature para pasar etiquetas OpenType en crudo y Renderer para elegir el modelador (HarfBuzz / AAT / Graphite)— pertenecen a fontspec y se tratan en su propia página. Para llevar las fuentes Unicode también a las fórmulas, se combina con unicode-math.
The font "..." cannot be found. — cuando una fuente incluida no responde a su nombre
XeTeX pregunta por el nombre a la base de datos de fuentes del sistema operativo, no a los directorios de TeX Live. Ahí es donde la mayoría se atasca la primera vez. En una máquina macOS con TeX Live 2024 instalado tal cual, \setmainfont{Helvetica Neue} funciona, mientras que \setmainfont{TeX Gyre Termes}, \setmainfont{Latin Modern Roman} y \setmainfont{TeX Gyre Pagella} fallan todas con ! Package fontspec Error: The font "..." cannot be found., y las tres funcionan bajo LuaLaTeX. La diferencia está en cómo busca cada motor: el luaotfload de LuaTeX recorre el propio árbol de directorios de TeX y construye un índice, mientras que XeTeX consulta la maquinaria de fuentes del sistema —Core Text en macOS—, de modo que una fuente distribuida por TeX Live y nunca registrada en el sistema no puede encontrarse por su nombre.
La solución es sencilla: nombrar las fuentes incluidas por su nombre de fichero. \setmainfont{texgyretermes-regular.otf} funciona, y distingue mayúsculas de minúsculas, así que TeXGyreTermes-Regular.otf no. Nombrar así un fichero hace perder el emparejamiento automático de negrita y cursiva, de modo que hay que declarar explícitamente BoldFont, ItalicFont y BoldItalicFont. El ejemplo anterior está escrito en esa forma y compila tanto con xelatex como con lualatex sin un solo error ni un carácter faltante. También cabe registrar las fuentes de la distribución en el sistema (la configuración texlive-fontconfig en Linux, por ejemplo), pero eso varía de una máquina a otra y no se reproducirá en casa de un colaborador; para un manuscrito, los nombres de fichero son lo más fiable. Cuando alguien informe de que XeLaTeX no encuentra una fuente, hágale probar antes que nada el nombre del fichero.
Las fuentes japonesas muestran la misma regla desde el otro lado. Un nombre que el sistema operativo conoce se resuelve; un nombre que solo conoce TeX Live, no. En esta máquina macOS con TeX Live 2024, \setmainfont{Hiragino Mincho ProN}, \setmainfont{Hiragino Sans} y \setmainfont{YuMincho} compilan todos bajo XeLaTeX, porque esos son los nombres que muestra el panel de fuentes del sistema. \setmainfont{Noto Sans JP}, en cambio, falla con cannot be found mientras no se haya instalado a nivel de sistema. La prueba es sencilla: mirar si la fuente aparece en la lista de fuentes del sistema. Si aparece, XeTeX la encontrará; si no, de nada sirve que esté dentro de TeX Live. Para manuscritos japoneses que requieren escritura vertical o reglas de corte estrictas, luatexja o upLaTeX sigue siendo el camino más llevadero que xeCJK.
Qué es un .xdv y por qué XeTeX no escribe el PDF él mismo
Un .xdv es DVI con extensiones. Ejecute xelatex -no-pdf y podrá tener uno delante: sus primeros bytes son f7 07, la orden DVI pre seguida de un identificador de formato 7 en lugar del 2 del DVI estándar. Por dentro, tras un comentario que dice XeTeX output 2026.08.13:0452, las fuentes empleadas figuran como rutas de fichero (lmroman10-regular.otf y similares). Es decir: un .xdv ya sabe qué glifo de qué fichero de fuente va en qué coordenada, pero la fuente todavía no está incrustada. Queda abrir esos ficheros, subconjuntarlos y empaquetarlos en un PDF, y ese es justamente el trabajo de xdvipdfmx.
Una ejecución normal de xelatex no deja ningún .xdv en el disco, porque XeTeX canaliza esos bytes hacia la entrada estándar del controlador. La opción -output-driver=CMD permite sustituir el controlador, así que apuntándola a un guion que solo ejecute cat se atrapa el flujo al pasar: 820 bytes en la prueba anterior, terminados con la cola tradicional del DVI, df df df df. De ahí se siguen dos consecuencias prácticas. Primera: cuando un paquete como graphicx pregunta qué controlador se usa, la respuesta es xetex, es decir, xdvipdfmx. Segunda: hay que averiguar de cuál de las dos etapas procede un error. Usted tecleó xelatex, pero un fallo en el manejo de imágenes o en la incrustación de fuentes aflora como una línea de xdvipdfmx. Leer el registro en dos mitades —el primer error de TeX y la última línea del controlador— es lo más rápido.
# 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.texQué se rompe al pasar un documento de pdfLaTeX a XeLaTeX
El caso peligroso es justamente el que no produce ningún error. Entregue un preámbulo antiguo tal cual a xelatex y lo más probable es que compile. \usepackage[utf8]{inputenc} se omite con un único aviso, Package inputenc Warning: inputenc package ignored with utf8 based engines., y por sí solo no hace daño. El problema es la pareja \usepackage[T1]{fontenc} y \usepackage{lmodern}. Si esas dos líneas siguen ahí, XeLaTeX permanece en la ruta de 8 bits del NFSS: lo que se incrusta es una fuente TFM llamada ec-lmr10, que pdffonts declara como Type 1C. No es el mismo objeto que el CID Type 0C que se obtiene mediante fontspec, de modo que cambiar de motor no ha servido casi de nada.
Una sola línea del registro distingue ambos casos. Con [T1]{fontenc} todavía cargado, escribir 日 produce Missing character: There is no 日 ("65E5) in font ec-lmr10!: el punto de código en hexadecimal al modo de TeX, "65E5, y un nombre de fuente de 8 bits. En el mismo documento pasado a fontspec se lee Missing character: There is no 日 (U+65E5) in font [lmroman10-regular]...: la notación pasa a U+65E5 y el nombre de la fuente pasa a ser un fichero OpenType. Si aparece la primera forma, ha recaído en la ruta de 8 bits. Lo mismo ocurre con los diacríticos combinantes (ec-lmr10 no tiene U+0301; la vía OpenType lo compone sin quejarse). La migración correcta consiste en borrar de golpe toda la familia de declaraciones de fuente heredadas —inputenc, fontenc, lmodern, times y compañía— y dejar que fontspec sea la única fuente de selección tipográfica.
| Línea del antiguo preámbulo | Qué hace XeLaTeX con ella | Qué hacer |
|---|---|---|
\usepackage[utf8]{inputenc} | se ignora, con una línea de aviso | eliminarla |
\usepackage[T1]{fontenc} | mantiene en silencio la ruta de 8 bits del NFSS | sustituir por fontspec |
\usepackage{lmodern} | incrusta ec-lmr10 (Type 1C) | usar \setmainfont{lmroman10-regular.otf} |
microtype | solo protrusión; no hay dilatación | cargarlo tal cual |
babel | funciona, pero flojea con RTL y escrituras complejas | considerar polyglossia |
Por qué la dilatación de glifos no funciona bajo XeLaTeX
Porque el motor no tiene esa prestación. De los dos pilares de microtype, XeTeX solo implementa la protrusión. Al sondear las primitivas una a una resulta que XeTeX tiene \lpcode y \rpcode, que fijan el saliente por carácter, pero no \efcode, que fija cuánto puede estirarse un carácter. Incluso el interruptor de protrusión no es el \pdfprotrudechars de pdfTeX sino un \XeTeXprotrudechars con nombre propio. Cargue \usepackage{microtype} bajo XeLaTeX y el registro muestra Character protrusion enabled (level 2)., mientras que la línea Automatic font expansion enabled que la acompañaría bajo pdfLaTeX o LuaLaTeX desaparece sin decir nada. Pídala explícitamente y la parada es limpia: ! Package microtype Error: Font expansion does not work with xetex.
Escrituras complejas y de derecha a izquierda: HarfBuzz y las primitivas \XeTeX...
La razón principal del éxito de XeTeX es que maneja correctamente las escrituras cuyas letras cambian de forma según el contexto: el árabe, la familia índica. Del modelado (shaping) se encarga HarfBuzz: la versión 0.9999 (mayo de 2013) abandonó el antiguo ICU LayoutEngine en favor de HarfBuzz, y la compilación incluida en TeX Live 2024 enlaza HarfBuzz 8.3.0. El motor trae además sus propias primitivas: \XeTeXinputencoding para cambiar de codificación de entrada a mitad de documento, \XeTeXcharclass y \XeTeXinterchartoks para clasificar caracteres y reaccionar a sus vecinos, \XeTeXlinebreaklocale para elegir las reglas de corte según la lengua, \XeTeXgenerateactualtext para escribir el texto real en el PDF de cara a su extracción, y \XeTeXpicfile y \XeTeXpdffile para las imágenes. Del cambio de lengua se ocupa polyglossia; de la composición de derecha a izquierda, bidi (que polyglossia carga por su cuenta en cuanto se pide árabe o similares); y del chino, coreano y japonés, xeCJK, aunque para la escritura vertical japonesa y las reglas de corte exigentes luatexja o upLaTeX ofrecen un camino más llano.
Cuándo elegir XeLaTeX y cuándo no
- Cuando se quiere usar las fuentes que ya se tienen. Basta poner el nombre OpenType o TrueType en
\setmainfont; no hay ningún fichero de configuración que tocar. - Cuando se quiere escribir Unicode literalmente. La entrada en UTF-8 es lo predeterminado y todo el preámbulo de codificación desaparece.
- Para documentos multilingües y de derecha a izquierda.
polyglossiaconbiditiene un largo historial en árabe y hebreo, y HarfBuzz se ocupa del modelado. - Razón para abstenerse, una: hace falta dilatación de glifos. XeTeX no tiene
\efcode, así que la dilatación demicrotypeno puede funcionar. Si la calidad tipográfica manda, use pdfLaTeX o LuaLaTeX. - Razón para abstenerse, dos: se quiere programar el compositor. XeTeX no incorpora lenguaje de guiones. Para intervenir a bajo nivel, pase a LuaLaTeX.
- Razón para abstenerse, tres: la escritura vertical japonesa. Excede el propósito de
xeCJK; probar prontoluatexjao upLaTeX ahorra tiempo.
La regla en una frase: si solo se quiere usar las fuentes del sistema por su nombre, XeLaTeX; si se quiere entrar en la composición misma, LuaLaTeX. La comparación completa de los tres motores está en la página «Elegir un motor». Un último apunte sobre el trabajo compartido: los nombres de fuente difieren de un sistema a otro, y \setmainfont{Helvetica Neue} fallará sin más en la máquina Linux de un colega. Para un manuscrito compartido, consiga primero una compilación que funcione con las fuentes incluidas en TeX Live, nombradas por su fichero como arriba, y sustituya después solo las fuentes que de verdad necesite. Si entrega únicamente un PDF, pase pdffonts y confirme que todas las fuentes están incrustadas antes de enviarlo.