Sistema de fuentes (NFSS / codificación)

La cadena OT1/cmr/m/n/10 que aparece en un aviso de LaTeX no es un código a descifrar: es una dirección. LaTeX nunca nombra una fuente directamente; la señala con cinco coordenadas: codificación, familia, serie, forma, tamaño. El mecanismo se llama NFSS. Esta página sigue esas cinco coordenadas hasta el código fuente y el archivo de registro: por qué \bfseries pide la serie bx y no b, si pedir negrita después de \fontseries{c} acaba realmente en bc, y qué está diciendo en realidad el aviso de sustitución Font shape ... undefined.

NFSS: una fuente son cinco coordenadas

La selección de fuentes en LaTeX2e funciona sobre el NFSS (New Font Selection Scheme), cuya tesis central es una sola: cualquier fuente de texto queda completamente determinada por cinco atributoscodificación, familia, serie, forma, tamaño—. NFSS lo diseñaron Frank Mittelbach y Rainer Schöpf; la línea de copyright del fuente del núcleo ltfssbas.dtx se remonta a 1989. Antes de él, en LaTeX 2.09, ni siquiera se podían combinar \bf e \it: nadie había separado todavía el peso y la forma de la letra en ejes independientes.

  • Codificación — el orden de los glifos dentro de la fuente, es decir, a qué ranura va cada carácter de entrada. Para texto, las dos principales son OT1 (TeX text) y T1 (TeX extended text, la llamada Cork). Se detalla más abajo.
  • Familia — un conjunto de fuentes que comparten forma de letra. Computer Modern Roman es cmr, su sans es cmss, su typewriter cmtt; entre las comerciales, Times es ptm, Helvetica phv, Courier pcr.
  • Serie — un único eje que fusiona peso y anchura: m (medium), b (bold), bx (bold extended), c (condensed), bc (bold condensed), sb (semibold), etc.
  • Forma — el dibujo de las letras: n (vertical), it (itálica), sl (inclinada), sc (versalitas). Rara vez, ui (una itálica sin inclinación).
  • Tamaño — el tamaño de diseño, una dimensión como 10pt; sin unidad se supone pt.

Lo único que despista es que la serie funde peso y anchura en un solo valor. En el esquema estándar los pesos van de ul a ub (ultra light a ultra bold) y las anchuras de uc a ux (ultra condensed a ultra expanded); ambos se concatenan y la m se elimina, salvo que sobrevive una m suelta cuando peso y anchura son medium. Así, «negrita, anchura normal» es b, «bold extended» es bx, «peso normal, estrecha» es c y «negrita estrecha» es bc. Los cinco valores escritos como encoding/family/series/shape/size son el nombre formal de una fuente dentro de LaTeX, y \showthe\font imprime el que esté vigente.

log
% \showthe\font in a default article, and what the log answers:
> \OT1/cmr/m/n/10 .

% the same five values head every overfull-box report:
Overfull \hbox (121.83368pt too wide) detected at line 3
\OT1/cmr/m/n/10 Supercalifragilisticexpialidocious

% and the first four of them name a shape that had to be substituted:
LaTeX Font Warning: Font shape `T1/cmss/bx/sc' undefined
(Font)              using `T1/cmss/bx/n' instead on input line 4.

Por qué \bfseries pide la serie bx y no b

La respuesta es que \bfseries no lee \bfdefault en absoluto. El \bfdefault del núcleo sí vale b, pero \bfseries comprueba antes si la familia actual coincide con \rmdefault, \sfdefault o \ttdefault, y si coincide usa en su lugar un valor por defecto dedicado: \bfseries@rm, \bfseries@sf o \bfseries@tt. Y latex.ltx inicializa los tres a bx. \bfdefault solo se consulta cuando la familia actual no es ninguna de esas tres; es decir, mientras escribas \bfseries en la fuente del cuerpo, \bfdefault queda sin usar.

latex.ltx
% TeX Live 2024, latex.ltx (the LaTeX2e kernel), abridged
\def\bfseries@rm{bx}
\def\bfseries@sf{bx}
\def\bfseries@tt{bx}

\DeclareRobustCommand\bfseries{%
  \not@math@alphabet\bfseries\mathbf
  \expand@font@defaults
  \maybe@update@bfseries@defaults
  \ifx\f@family\rmdef@ult      \fontseries\bfseries@rm
  \else\ifx\f@family\sfdef@ult \fontseries\bfseries@sf
  \else\ifx\f@family\ttdef@ult \fontseries\bfseries@tt
  \else                        \fontseries\bfdefault
  \fi\fi\fi
  \UseHook{bfseries}%
  \selectfont
}

¿Y por qué el valor por defecto es bx? Por cuántas fuentes talló Knuth en realidad. Al contar las métricas de Computer Modern en TeX Live 2024 se ve que la negrita simple existe como un único archivo, cmb10.tfm. La bold extended, en cambio, viene como cmbx5, cmbx6, cmbx7, cmbx8, cmbx9, cmbx10 y cmbx12: siete tamaños de diseño. Solo cmbx puede componer negrita como es debido hasta las notas al pie y los subíndices, así que NFSS le pide bx a Computer Modern.

Hasta aquí es una peculiaridad de Computer Modern, pero el núcleo recoge después de sí mismo. En \begin{document} se ejecuta \init@series@setup, que rebaja \bfseries@rm a b salvo que \rmdefault sea uno de cmr, cmss, cmtt, lcmss, lcmtt, lmr, lmss, lmtt. Dicho de otro modo, bx es una herencia exclusiva de Computer Modern y Latin Modern: en cuanto se cambia a Times o a TeX Gyre, \bfseries pasa a pedir b sin decir nada. Medido, ocurre justo eso: con \renewcommand\rmdefault{ptm}, tanto \bfseries@rm como la serie resultante salen b.

Ajuste en el documentoSerie que pide \bfseriesRazón
article (default)bx\rmdefault es cmr, así que sobrevive el valor inicial de \bfseries@rm
\usepackage{lmodern}bxlmr también está en la lista Computer Modern del núcleo
\renewcommand\rmdefault{ptm}b\init@series@setup lo halla fuera de la lista y baja \bfseries@rm
\fontseries{b}\selectfontbun valor indicado a bajo nivel no pasa por las macros por defecto
\DeclareFontSeriesDefault[rm]{bf}{sb}sbla forma prevista de reorientar la negrita de una sola metafamilia

La conclusión práctica es clara: si quieres cambiar qué significa negrita, prefiere \DeclareFontSeriesDefault[rm]{bf}{b} antes que \renewcommand{\bfdefault}{b}. Lo segundo funciona —reescribir \bfdefault hace que \maybe@update@bfseries@defaults sobrescriba los tres valores dedicados—, pero no permite apuntar solo a la romana ni solo a la sans. Y ante el síntoma clásico de «pedí negrita y nada engordó», esta correspondencia es lo primero que hay que sospechar: quizá tu fuente sencillamente no tenga bx.

Las series se fusionan: c más b da bc

Desde la versión de LaTeX2e de 2020 (\IncludeInRelease{2020/02/02} en latexrelease.sty), una petición de serie se fusiona en lugar de sobrescribir. Pide negrita mientras compones en estrecha (c) y no obtendrás b, sino bc, negrita estrecha. La tabla que lo decide se construye con \DeclareFontSeriesChangeRule, y el núcleo alinea más de doscientas líneas de reglas así. {c}{b}{bc}{} se lee como «si la serie actual es c y se pide b, ve a bc; sin alternativa».

latex.ltx
% the rule table (latex.ltx, from ltfssaxes.dtx), a handful of the 200-odd entries
\def\DeclareFontSeriesChangeRule#1#2#3#4{%
  \@namedef{series@#1@#2}{{#3}{#4}}}
\DeclareFontSeriesChangeRule {c}{b}{bc}{}     % condensed + bold      -> bc
\DeclareFontSeriesChangeRule {b}{c}{bc}{b}    % bold + condensed      -> bc, else b
\DeclareFontSeriesChangeRule {bx}{c}{bc}{bx}  % bold extended + cond. -> bc, else bx
\DeclareFontSeriesChangeRule {m}{b}{b}{bx}    % medium + bold         -> b,  else bx

Las reglas no se disparan de forma incondicional. \selectfont fusiona primero sin sustitución y luego comprueba si el encoding/family/series/shape resultante existe realmente; si no, restaura los valores anteriores y repite la fusión en modo sustitución. Computer Modern no tiene ningún corte estrecho, de modo que \fontseries{c}\selectfont avisa y retrocede a m, y una negrita posterior solo llega a b: justo por eso se concluye que la fusión «no ocurre». Pruébalo con una familia que sí tenga estrecha y las reglas funcionan. Helvetica (phv) trae m, c, b y bc en T1, así que el ejemplo de abajo lo muestra de verdad.

document.tex
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{helvet}          % sets \sfdefault to phv
\begin{document}\makeatletter
\sffamily                    % -> phv/m   (Helvetica)
\fontseries{c}\selectfont    % -> phv/c   font file phvr8tn (Helvetica Narrow)
\bfseries                    % -> phv/bc  font file phvb8tn (Helvetica Bold Narrow)
\typeout{[series] \f@series\space -> \fontname\font}
\makeatother\end{document}

% [series] bc -> phvb8tn
%
% The same document with Computer Modern instead reports:
%   LaTeX Font Warning: Font shape `OT1/cmr/c/n' undefined
%   [series] m  (the condensed request was substituted away before bold arrived)

Selectores de bajo nivel y \selectfont

Los selectores de bajo nivel fijan un atributo cada vez: \fontencoding{T1}, \fontfamily{ptm}, \fontseries{b}, \fontshape{it}, \fontsize{12}{14}. Hay exactamente una regla —fijarlos no hace nada hasta llamar a \selectfont— y la sección anterior mostró el porqué. \fontseries no escribe el valor en ninguna parte: lo apila en una lista pendiente llamada \delayed@f@adjustment, y es \selectfont quien realiza de una vez la fusión, la comprobación de existencia y la sustitución. Olvida el \selectfont entre un ajuste y el texto, y ese texto saldrá en la fuente anterior.

document.tex
\documentclass{article}
\usepackage[T1]{fontenc}
\begin{document}
% Correct: set the attributes, commit with \selectfont, then the text
{\fontfamily{ptm}\fontseries{b}\selectfont Bold Times}

% Wrong: the words before \selectfont are still in the old font
{\fontfamily{ptm} Some \fontseries{b}\selectfont text.}

% \usefont gives four attributes at once and commits on the spot
{\usefont{T1}{ptm}{b}{it} Bold italic Times}

% Change only the size; reuse the current baselineskip
\makeatletter
{\fontsize{14}{\f@baselineskip}\selectfont Fourteen point}
\makeatother
\end{document}

El atajo que pasa cuatro de los cinco atributos a la vez es \usefont{codificación}{familia}{serie}{forma}: el tamaño se toma del valor actual y el cambio se confirma en el acto. Encerrado en un grupo { }, el efecto queda acotado. Pasar la macro interna \f@baselineskip como segundo argumento de \fontsize es el modismo habitual para cambiar el cuerpo sin tocar el interlineado (nunca reescribas macros internas, pero leer una para pasarla es inofensivo). Dicho esto, rara vez hace falta escribir nada de esto. \textbf solo llama a \fontseries y \sffamily solo a \fontfamily; se baja al nivel inferior únicamente para nombrar una fuente concreta o conectar una fuente nueva a una clase o paquete.

Las macros por defecto: \rmdefault y compañía

La familia que seleccionan \textrm o \rmfamily no está fijada en el código: vive en una macro. Son tres —\rmdefault (romana), \sfdefault (sans), \ttdefault (typewriter)— con valores por defecto cmr, cmss, cmtt en la clase article. Para cambiar la fuente del cuerpo se reescriben estas macros, no los comandos. Y, como mostró la sección anterior, esos tres valores deciden además qué pedirá la negrita, así que es más exacto verlos no como alias sino como la política tipográfica del documento.

preamble.tex
% Re-point the three meta-families for the whole document
\renewcommand{\rmdefault}{ptm}  % roman   -> Times
\renewcommand{\sfdefault}{phv}  % sans    -> Helvetica
\renewcommand{\ttdefault}{pcr}  % mono    -> Courier

% The body font itself is these four (defaults: OT1, \rmdefault, m, n)
%   \encodingdefault \familydefault \seriesdefault \shapedefault
% and \familydefault points at \rmdefault, so the line above changes the body.

% Retarget bold and medium per meta-family (LaTeX2e 2020-02-02 and later)
\DeclareFontSeriesDefault[rm]{bf}{b}
\DeclareFontSeriesDefault[sf]{md}{l}

Archivos .fd y \DeclareFontShape: donde las coordenadas encuentran archivos reales

Lo que ata las cinco coordenadas a archivos de fuente reales es el archivo de definición de fuente (.fd). Su nombre es la codificación en minúsculas seguida de la familia —ot1cmr.fd para cmr en OT1, t1phv.fd para phv en T1— y LaTeX lo carga automáticamente en cuanto lo necesita. kpsewhich ot1cmr.fd dice dónde está el tuyo. Dentro hay una línea \DeclareFontFamily y luego un \DeclareFontShape por cada combinación de serie y forma.

ot1cmr.fd
% TeX Live 2024, tex/latex/base/ot1cmr.fd (excerpt)
\DeclareFontFamily{OT1}{cmr}{\hyphenchar\font45 }
\DeclareFontShape{OT1}{cmr}{m}{n}%
     {<5><6><7><8><9><10><12>gen*cmr%
      <10.95>cmr10%
      <14.4>cmr12%
      <17.28><20.74><24.88>cmr17}{}
%%%%%%% bold series
\DeclareFontShape{OT1}{cmr}{b}{n}
     {%
      <5><6><7><8><9><10><10.95><12>%
      <14.4><17.28><20.74><24.88>cmb10%
      }{}
%%%%%%%% bold extended series
\DeclareFontShape{OT1}{cmr}{bx}{n}
   {%
      <5><6><7><8><9>gen*cmbx%
      <10><10.95>cmbx10%
      <12><14.4><17.28><20.74><24.88>cmbx12%
      }{}

Leer uno es simplemente seguir los rangos de tamaño entre ángulos. <5><6><7><8><9>gen*cmbx significa «de 5 a 9 puntos, usa la fuente real cuyo nombre es la raíz más el tamaño (cmbx5, cmbx6, …)»; <12><14.4>...cmbx12 significa «a partir de 12 puntos, escala cmbx12». El bloque b de arriba muestra la situación de un solo corte descrita antes: todos los tamaños, de 5 a 24,88 puntos, son cmb10 estirado. También existen ssub (sustitución silenciosa) y sub (sustitución con aviso); t1phv.fd, por ejemplo, incluye \DeclareFontShape{T1}{phv}{bx}{n}{<->ssub * phv/b/n}{}: Helvetica no tiene bx, así que entrega b sin decir nada.

Leer el aviso Font shape ... undefined

Este aviso es un informe que dice: esa combinación no estaba en el .fd, así que he tomado por mi cuenta la más cercana. Siempre aparece en dos líneas: las cuatro coordenadas pedidas en la primera y las cuatro realmente usadas más un número de línea en la segunda. No es un error, así que la compilación termina; el PDF resultante simplemente no es el que pediste. En los ejemplos anteriores, Computer Modern no tiene corte estrecho, así que c pasó a m, y T1/cmss no tiene versalitas, así que se usó la vertical n.

log
% a missing shape inside a family that does exist
LaTeX Font Warning: Font shape `T1/cmss/bx/sc' undefined
(Font)              using `T1/cmss/bx/n' instead on input line 4.

% a family that does not exist at all: \DeclareFontSubstitution kicks in
LaTeX Font Warning: Font shape `T1/nosuchfont/m/n' undefined
(Font)              using `T1/cmr/m/n' instead on input line 4.

% and at the end of the run, the summary line that is easy to miss
LaTeX Font Warning: Some font shapes were not available, defaults substituted.

Solo hay tres causas. (1) La fuente sencillamente no tiene ese trazado — Helvetica no tiene itálica, así que entra sl. No se puede invocar lo que no existe: elige otra fuente o acepta el sustituto. (2) El nombre de familia está mal escrito — si en la segunda línea aparece cmr, es el último recurso de \DeclareFontSubstitution disparándose, casi siempre por una errata o un paquete que olvidaste cargar. (3) Te equivocaste de codificación — pedir en T1 una familia que solo tiene .fd de OT1, por ejemplo. Y la línea resumen del final, Some font shapes were not available, defaults substituted., se pasa por alto fácilmente; pero si está ahí, algún pasaje del documento va compuesto en una letra que no elegiste.

Codificaciones de fuente: OT1, T1 y TU

Una codificación de fuente es el acuerdo sobre a qué ranura (glifo) de la fuente va cada carácter de entrada. Es el primero de los cinco atributos y el único sin comando de autor como \textbf: cambiarla es trabajo de un paquete, el de fontenc. OT1 es el «TeX text» original de 7 bits de Knuth (el valor por defecto). Con sitio para solo 128 caracteres, é y ñ se construyen componiendo una letra base con un acento (\accent), y esa composición es la razón de que las palabras acentuadas no se partan y de que se copien mal desde el PDF. T1 (TeX extended text, también codificación Cork por la reunión de TUG de 1990 en Cork) es una codificación de 8 bits y 256 glifos que lleva cada letra acentuada como un solo glifo, con lo que ambos problemas desaparecen a la vez.

Nada muestra mejor que una codificación es solo un acuerdo sobre el orden de las ranuras que el signo de libra en OT1. OT1 no tiene ranura para la libra esterlina, así que \textsterling, en ot1enc.def, echa mano de la ranura del signo de dólar de la fuente itálica (en Computer Modern esa ranura contiene £). Y si la fuente actual no tiene inclinación, cambia antes a \fontshape{ui}; de lo contrario solo la £ saldría torcida. Por eso la declaración ui de ot1cmr.fd lleva un comentario de aviso que dice que esa definición se usa para el \pounds de LaTeX y no debe eliminarse.

TU (TeX Unicode) permite direccionar por punto de código Unicode las fuentes OpenType instaladas en el sistema, y es el valor por defecto en XeLaTeX y LuaLaTeX. Sustituyó a los antiguos EU1 (para XeTeX) y EU2 (para LuaTeX): según el registro de cambios de fontspec, TU llegó en v2.5, el 30 de enero de 2016, y ascendió a valor por defecto en v2.5c, el 20 de enero de 2017. En TeX Live 2024 las cadenas EU1 y EU2 ya no aparecen en ninguna parte de fontspec.sty. Además existen T2A (cirílico), LGR (griego) y TS1 (la codificación Text Companion: moneda, copyright y otros símbolos de texto); para matemáticas, OML (itálica matemática), OMS (símbolos) y OMX (símbolos grandes). Ojo: los comandos de símbolos de TS1 pasaron al núcleo en 2020, de modo que el paquete textcomp actual no define ningún símbolo; esa historia está en la página de símbolos.

CodificaciónQué cubreAnchura / notas
OT1El TeX text original de Knuth (por defecto)7 bits; acentos compuestos, sin partición
T1TeX extended text (Cork); lenguas occidentales8 bits, 256 glifos; acentos únicos, la partición funciona
TUTeX Unicode; fuentes OpenType direccionadas directamentePor defecto en Xe/LuaLaTeX; sustituyó a EU1 / EU2
T2ACirílico8 bits (T2B / T2C son hermanos)
LGRGriegoLa codificación de 256 glifos hoy estándar para el griego
TS1Text Companion (símbolos de texto)Moneda, copyright, etc.; los comandos pasaron al núcleo en 2020
OML / OMS / OMXItálica matemática / símbolos / símbolos grandesSolo para matemáticas, nunca para texto corrido

inputenc frente a fontenc: la entrada y la salida

Separemos dos cosas que se confunden con facilidad. La codificación de entrada rige cómo se leen como caracteres los bytes del fuente .tex (UTF-8 y compañía), históricamente tarea del paquete inputenc. La codificación de fuente rige a qué glifo de la fuente de salida va cada uno de esos caracteres, y es tarea de fontenc. Recuérdalo como la entrada (inputenc) y la salida (fontenc) y no los mezclarás. El pdfLaTeX moderno lee el fuente como UTF-8 por defecto, así que casi nunca hace falta cargar inputenc de forma explícita. La codificación de fuente, en cambio, sigue mereciendo la pena. fontenc es un paquete para pdfLaTeX; en XeLaTeX y LuaLaTeX se usa fontspec, y como allí TU es el valor por defecto, el problema apenas surge.

Con pdfLaTeX, escribe \usepackage[T1]{fontenc}

Si compones con pdfLaTeX, la convención es poner \usepackage[T1]{fontenc} en el preámbulo. Cambia la codificación de fuente del documento a T1 y barre los inconvenientes del OT1 por defecto: palabras acentuadas que no se parten y texto que se corrompe al copiarlo del PDF. La documentación de fontenc dice justo eso: da soporte a lenguas occidentales extendidas como el francés, el alemán, el italiano y el polaco, y con ella LaTeX parte palabras con letras acentuadas mientras la salida se puede copiar y pegar. Cuando se listan varias codificaciones como opciones, la última de la lista pasa a ser la predeterminada (\encodingdefault se fija en ella): para un documento que mezcla griego, escribe \usepackage[LGR,T1]{fontenc}, dejando el cuerpo en T1 y cambiando a LGR solo donde haga falta.

document.tex
\documentclass{article}
\usepackage[T1]{fontenc}   % font encoding -> T1 (Cork)
% Input is UTF-8 by default on pdfLaTeX, so inputenc is usually unneeded.
\begin{document}
% With T1 these words hyphenate and survive copy-and-paste out of the PDF.
Na\"ive r\"esum\"e, \"uberfl\"ussig, Stra\ss{}e.
\end{document}