Por qué el texto de un PDF no es realmente texto
De un vistazo
Sección titulada «De un vistazo»Cuando lees un PDF, ves palabras. El archivo no contiene palabras. Contiene instrucciones para pintar formas en unas coordenadas, y resulta que las formas parecen letras. La brecha entre lo que un PDF dibuja y lo que significa es la razón por la que una página puede verse impecable y aun así copiarse como disparates. Esta página trata sobre esa brecha y sobre el pequeño mapa aparte que la cierra.
Por qué esto importa
Sección titulada «Por qué esto importa»Todo lo que haces con un PDF como texto —seleccionarlo, copiarlo, buscarlo,
indexarlo para su recuperación, leerlo en voz alta con un lector de pantalla—
depende de recuperar caracteres que el archivo nunca almacenó directamente. Si
esa recuperación falla, el fallo es invisible. La página sigue representándose.
Nadie lo nota hasta que alguien copia un párrafo en un correo y obtiene □□□□,
o busca en un contrato de 400 páginas una cláusula que está claramente ahí y no
encuentra nada.
Esa es una clase de error cara precisamente porque sobrevive a toda revisión visual. No hay nada que ver. El documento parece autoritativo y es, para fines de máquina, mudo.
La versión breve
Sección titulada «La versión breve»- Un PDF dibuja glifos —formas visuales elegidas por códigos numéricos dentro de una fuente—, no caracteres Unicode.
- La misma forma puede significar caracteres distintos, y el mismo carácter puede dibujarse con glifos distintos. La apariencia y el significado están desacoplados por diseño.
- Para recuperar el texto, un lector ejecuta la ruta de representación a la
inversa: de código a carácter. La CMap
/ToUnicodede la fuente es la tabla de consulta para ese paso inverso (Spec: ISO 32000-2, §9.10ISO 32000-2 §9.10). - Sin
/ToUnicode, o con uno incorrecto, el copiar y pegar sale ilegible y la búsqueda falla, con la página aún en perfecta nitidez de píxeles. - Este es el problema del significado. Que el glifo se vea bien es el problema
aparte de la apariencia que se trata en
Las fuentes: la parte difícil. NextPDF
emite un
/ToUnicodecorrecto para que el viaje de ida y vuelta sea fiel.
Cómo lo aborda NextPDF
Sección titulada «Cómo lo aborda NextPDF»Empecemos por cómo el texto llega a la página siquiera. Un flujo de contenido no
dice «escribe la palabra file». Selecciona una fuente y luego entrega una
cadena de códigos a un operador de representación de texto
(Spec: ISO 32000-2, §9ISO 32000-2 §9). Cada código es un índice —una
posición en un programa de fuente— y la fuente convierte ese índice en un
contorno de glifo y lo pinta. El código 70 no es el carácter F. Es «la
posición 70 en esta fuente», y resulta que la posición 70 contiene una curva
con forma de F. Elige otra fuente y la posición 70 podría ser un copo de
nieve.
Así que un código solo significa algo en relación con la codificación de su fuente. Para una fuente simple, esa codificación es aproximadamente un byte por glifo. Para las escrituras que necesitan miles de glifos —CJK, o cualquier documento Unicode completo— eso no es espacio suficiente, y el PDF recurre a una fuente compuesta (Type 0) (Spec: ISO 32000-2, §9.7ISO 32000-2 §9.7). Una fuente compuesta lee códigos de varios bytes a través de una CMap, los convierte en CID (identificadores de carácter) y asigna los CID a glifos. Es una indirección elegante que permite que una sola fuente direccione un conjunto enorme de glifos. También es un lugar más donde el rastro desde «lo que se muestra» hasta «lo que significa» puede enfriarse.
Ahora ejecútalo al revés. Para extraer texto, un lector toma los códigos que encuentra en el flujo de contenido y tiene que recuperar caracteres (Spec: ISO 32000-2, §9.10ISO 32000-2 §9.10). La codificación que dibujó el glifo iba de carácter a glifo; la extracción necesita de código de glifo a carácter, y no se garantiza que esa dirección sea invertible. Una fuente subconjunto puede haber renumerado sus glifos. Los CID de una fuente compuesta pueden ser privados. La forma de la página no lleva ningún significado Unicode inherente.
La solución es enviar el mapa inverso junto con la fuente. Ese mapa es la CMap
/ToUnicode: para cada código que usa el documento, registra el valor (o
los valores) Unicode que ese código representa. Con él, la extracción es una
consulta limpia. Sin él, un lector se queda adivinando a partir de codificaciones
de fuente y heurísticas, y adivinar es exactamente donde fi se convierte en un
signo de interrogación.
- Your charactersThe Unicode text you set, for example the word 'file'.
- Encoding → codesThe font's encoding turns characters into numeric codes; a composite font routes them through a CMap to CIDs.
- Codes → glyphsEach code selects a glyph outline, which is painted to the page. This is the part you see.
- Extraction reverses itA reader reads the codes back and looks each one up in /ToUnicode to recover Unicode.
- Text againWith a correct /ToUnicode, copy, search, indexing, and screen readers all get the original characters back.
NextPDF escribe el mapa inverso por norma. Cuando incrusta una fuente compuesta
emite el descendiente CIDFontType2, el padre Type0 y una CMap /ToUnicode
para que los códigos se resuelvan de vuelta a Unicode: el trabajo de
codificación descrito en
Las fuentes: la parte difícil. Lo que vale
la pena separar aquí es por qué: el flujo /ToUnicode no tiene que ver con
hacer que la página se vea bien. Los glifos ya se ven bien sin él. Es el único
artefacto que mantiene el texto extraíble.
Ejemplo práctico
Sección titulada «Ejemplo práctico»El lugar más famoso donde esto aflora es la ligadura fi. Muchas fuentes
dibujan f e i como un solo glifo combinado, porque el punto de la i choca
con el gancho de la f. En la página es una sola forma, dibujada por un solo
código. La cuestión es qué ocurre cuando la copias.
% A /ToUnicode entry that maps the single ligature code to TWO characters,% so selecting the 'fi' glyph copies out as 'f' then 'i' — not one mystery box.1 beginbfchar<0085> <00660069> % code 0x85 -> U+0066 'f' U+0069 'i'endbfcharEsa única entrada es la diferencia entre que una búsqueda de «file» coincida y
que una búsqueda de «file» pase por alto en silencio cada aparición
representada con la ligadura. Asigna el código de ligadura a la secuencia de dos
caracteres f + i, y la palabra se puede buscar y copiar. Déjalo sin asignar,
y la página seguirá mostrando file a la perfección mientras el texto, en
silencio, no dice nada que una máquina pueda leer.
Por esto «fi» puede extraerse como uno o como dos caracteres, y por esto la
diferencia no es aleatoria: es lo que se le dijo al mapa /ToUnicode que dijera.
Un mapa correcto descompone la ligadura de vuelta en sus caracteres. NextPDF
emite exactamente ese tipo de entrada, para que una ligadura en la página sean
dos letras corrientes en el portapapeles.
Concepto erróneo habitual
Sección titulada «Concepto erróneo habitual»La trampa, con nombre: «el texto se representa, así que el texto está bien».
La representación y la extracción son mecanismos distintos que leen datos
distintos. La representación sigue la ruta de código a glifo y es lo que
comprueban tus ojos. La extracción sigue la ruta de código a carácter a través de
/ToUnicode y es lo que comprueba todo consumidor de máquina. Un documento puede
bordar lo primero y fallar lo segundo por completo, porque por construcción no
hay nada visual que lo revele.
Una segunda trampa, más sutil: suponer que un glifo «obviamente» sabe qué carácter es. No lo sabe. Un glifo es una forma con un índice. La correspondencia de vuelta a un carácter es información adicional que el productor tiene que aportar. Si el productor nunca la escribió, ningún lector puede recuperarla con fidelidad: solo puede adivinar.
Límites y fronteras
Sección titulada «Límites y fronteras»| Edition | Availability |
|---|---|
| Core | NextPDF emite una CMap /ToUnicode correcta para las fuentes que incrusta, incluidos los casos de ligaduras y de fuentes compuestas, de modo que los documentos que produce son buscables y copiables. |
| Pro | Not in this edition |
| Enterprise | Not in this edition |
Un mapa /ToUnicode solo puede llevar la información que la fuente de origen
realmente expone. Donde un glifo no tiene un carácter determinable —una marca
puramente decorativa, un símbolo de uso privado sin asignación Unicode— ningún
mapa puede inventar un significado que nunca estuvo ahí. NextPDF emite la
correspondencia veraz que puede derivar; no fabrica caracteres para rellenar un
hueco.
Esta página trata sobre los documentos que NextPDF escribe. No es una
herramienta de reparación para PDF entrantes arbitrarios cuyo /ToUnicode ya
está ausente o es incorrecto; recuperar texto de esos es un problema heurístico
aparte. Y la extracción fiel es necesaria para la accesibilidad, pero no es toda
ella: el orden de lectura, las etiquetas y el texto alternativo se tratan en
Qué hace accesible a un PDF.
Mini-FAQ
Sección titulada «Mini-FAQ»¿Por qué el mismo PDF se copia bien en un lector y mal en otro?
Distintos lectores recurren a alternativas distintas cuando falta /ToUnicode.
Algunos adivinan a partir de la codificación incorporada de la fuente y aciertan
con texto latino común; otros no. Un /ToUnicode correcto elimina la lotería:
todo lector conforme obtiene los mismos caracteres.
¿Es lo mismo que la fuente no esté incrustada?
No. La incrustación tiene que ver con la apariencia: si el glifo se pinta sin
la fuente instalada. /ToUnicode tiene que ver con el significado: si el
código se corresponde de vuelta con un carácter. Una fuente puede estar
perfectamente incrustada y aun así no tener un /ToUnicode utilizable, que es el
fallo de página bonita pero no buscable.
¿La extracción necesita alguna vez más de un carácter por código?
Sí: el caso de la ligadura es exactamente eso: un código se corresponde con dos
caracteres. Una entrada /ToUnicode puede asignar un solo código a una secuencia
corta, que es como las ligaduras, y algunas formas compuestas, vuelven como sus
letras constituyentes.
Documentos relacionados
Sección titulada «Documentos relacionados»- Las fuentes: la parte difícil: la pieza complementaria del lado de la apariencia: incrustación, subconjuntos y cómo se construye la codificación. Esta página es el lado del significado de la misma moneda.
- Qué hace accesible a un PDF: el texto fiel es un ingrediente; el orden de lectura, las etiquetas y el texto alternativo son el resto.
- Qué es realmente un PDF: el modelo de
objetos dentro del cual viven las fuentes, las codificaciones y los flujos
/ToUnicode.
Glosario
Sección titulada «Glosario»- Glifo: una forma visual en una fuente (un contorno). Lo que un PDF pinta en realidad. Un glifo tiene un índice, pero ningún significado de carácter inherente.
- Carácter: una unidad de lenguaje escrito, identificada por un punto de código Unicode. Lo que quieres decir, y lo que la extracción intenta recuperar.
- Código: el valor numérico en un flujo de contenido que selecciona un glifo de la fuente actual. No es un carácter Unicode; solo tiene significado en relación con la fuente.
- CID: un identificador de carácter que usa una fuente compuesta para direccionar un glifo dentro de un conjunto grande; un paso intermedio entre el código y el glifo.
- Fuente compuesta (Type 0): una fuente que lee códigos de varios bytes a través de una CMap para llegar a los CID y a los glifos, usada cuando una sola fuente debe direccionar miles de glifos.
/ToUnicode: el flujo de CMap que asigna los códigos que usa un documento de vuelta a valores Unicode; lo que hace que el texto de PDF sea buscable, copiable y accesible.- Ligadura: un solo glifo que dibuja dos o más letras como una sola forma
(por ejemplo
fi); su entrada/ToUnicodela descompone de vuelta en sus caracteres.