PDF no es un formato de documento en el sentido en que lo son Word o RTF. Esos formatos almacenan una secuencia de contenido que un renderizador interpreta en el momento de la visualización, por lo que la salida depende de las fuentes y el motor de diseño que estén disponibles en ese momento. PDF almacena el resultado de ese proceso: instrucciones de renderizado precisas, programas de fuente, flujos de imagen comprimidos y un grafo de objetos que los une en una descripción autónoma de cada página. El fichero lleva suficiente información para reproducir cada página de forma idéntica en cualquier renderizador conforme, lo cual es tanto su principal objetivo de diseño como la fuente de la mayor parte de la complejidad que se encuentra al intentar generarlo, analizarlo o modificarlo mediante programación.
El modelo de objetos
Todo PDF es una colección de objetos numerados. Un objeto puede ser un booleano, un entero, un número real, un nombre, una cadena, un array, un diccionario, un flujo o nulo. Casi todo lo interesante es un diccionario, que es un conjunto de pares clave-valor donde las claves son nombres y los valores son cualquier otro tipo de objeto, incluidas las referencias a otros objetos por número y recuento de generación. Un flujo es un diccionario seguido de una secuencia de bytes, típicamente comprimida.
El diccionario de catálogo es la raíz. Apunta al árbol de páginas, que organiza los diccionarios de página en una estructura de árbol equilibrado en lugar de una lista plana, de modo que navegar a la página 5.000 de un documento de 10.000 páginas no requiere recorrer todos los descriptores de página anteriores. Cada diccionario de página referencia sus flujos de contenido (una o más secuencias de operadores de descripción de página), su diccionario de recursos (que a su vez referencia descriptores de fuente, espacios de color y XObjects de imagen) y su media box (el espacio de coordenadas en el que vive la página). El origen de coordenadas está en la esquina inferior izquierda, con Y positivo apuntando hacia arriba, en unidades de 1/72 de pulgada.
Al final del fichero se encuentra la tabla de referencias cruzadas, que asigna cada número de objeto a su desplazamiento en bytes en el fichero. Esto es lo que permite el acceso aleatorio: un visualizador lee primero la tabla de referencias cruzadas y luego se desplaza directamente a los objetos que necesita. PDF 1.5 introdujo los flujos de referencias cruzadas, que comprimen la tabla en un objeto flujo y empaquetan objetos relacionados en flujos de objetos, reduciendo notablemente el tamaño del fichero en documentos con muchos objetos pequeños.
Flujos de contenido y el modelo de gráficos
El contenido visual de una página vive en uno o más flujos de contenido. Cada flujo es una secuencia de operadores PDF intercalados con sus operandos. El operador de texto BT inicia un objeto de texto, Tf selecciona una fuente y un tamaño del diccionario de recursos, Td posiciona el cursor de texto, Tj o TJ pinta una cadena y ET cierra el objeto de texto. Los gráficos vectoriales siguen un patrón similar: m establece el punto de inicio de un trazado, l añade un segmento de línea, c añade una curva Bezier y f o S rellena o traza el trazado.
El estado de gráficos rige todo lo que ocurre entre operadores: la matriz de transformación actual, el ancho de línea, el espacio de color, el color de relleno, el color de trazo y el trazado de recorte. Operadores como q y Q empujan y sacan el estado de gráficos de una pila, que es como PDF implementa transformaciones de coordenadas locales y anulaciones de estado temporales sin afectar al contexto que las rodea. Los form XObjects generalizan esto: un flujo de contenido autónomo con su propio diccionario de recursos que se puede pintar en una página en posiciones y escalas arbitrarias con un único operador Do.
Incrustación de fuentes y extracción de texto
PDF puede referenciar fuentes por nombre y dejar que el visualizador sustituya algo, pero en la práctica cualquier documento que se vaya a compartir debe incrustar los datos de la fuente. Una fuente Type 1 o TrueType/OpenType incrustada en un PDF lleva un diccionario descriptor de fuente que apunta a un flujo de fichero de fuente. Para las fuentes TrueType, ese flujo contiene el programa de fuente binario; para Type 1, son los datos PFB. La creación de subconjuntos, que es lo que hace todo generador de PDF serio, elimina los glifos no referenciados por el documento, manteniendo los tamaños de fichero manejables incluso para fuentes Unicode grandes.
La extracción de texto es donde la incrustación de fuentes se vuelve problemática. La representación visual de un carácter está determinada por un glifo en el programa de fuente incrustado. El valor Unicode de ese carácter está determinado por un flujo CMap ToUnicode adjunto al diccionario de fuente. Cuando el CMap ToUnicode falta o es incorrecto, un visualizador PDF puede renderizar el texto de forma legible pero no puede extraerlo como Unicode significativo, que es la razón por la que copiar y pegar desde algunos PDFs produce caracteres sin sentido. El PDF etiquetado (ISO 32000 §14.8) añade una segunda capa: un árbol de estructura lógica que asigna el contenido de la página a roles semánticos del documento como párrafos, encabezados y celdas de tabla. Los lectores de pantalla y los motores de reflujo utilizan el árbol de estructura en lugar del orden del flujo de contenido sin procesar, lo que explica por qué un PDF con un diseño visual impecable puede seguir siendo inaccesible si el etiquetado está ausente o es incorrecto.
Actualizaciones incrementales y firmas digitales
Cuando se guardan cambios en un PDF existente sin reescribirlo desde cero, los nuevos objetos se añaden después del cuerpo del fichero original junto con una nueva sección de referencias cruzadas y un nuevo diccionario de tráiler. El tráiler actualizado apunta a los nuevos datos de referencias cruzadas, y los objetos sustituidos permanecen en el fichero pero simplemente no están referenciados por la nueva cadena de referencias cruzadas. Esto es la actualización incremental y tiene dos consecuencias importantes.
Primera: el fichero crece con cada ciclo de guardado. Un documento editado y guardado repetidamente acumula capas de objetos obsoletos. Herramientas como QPDF pueden linealizar o comprimir y reescribir un fichero para recuperar ese espacio, pero la opción predeterminada es la acumulación. Segunda: las firmas digitales dependen de las actualizaciones incrementales para su modelo de integridad. Una firma ISO 32000 cubre un rango de bytes del fichero, normalmente todo excepto el marcador de posición para el propio valor de la firma. Cualquier cambio posterior a la firma que aparezca como actualizaciones incrementales adicionales es visible para un lector de validación como modificaciones realizadas después de firmar, que es exactamente el rastro de auditoría que se desea. Sin embargo, esto también significa que ciertas modificaciones, como añadir una firma de aprobación o rellenar campos de formulario, están explícitamente permitidas por el estándar sin invalidar la firma original, siempre que los cambios se ajusten a la configuración de permisos del documento (ISO 32000-2 §12.7.6). Una modificación que queda fuera de esos permisos se marca como no autorizada. Entender bien esta distinción importa cuando se generan documentos que serán contrafirmados posteriormente.
Niveles de conformidad y el linaje ISO 32000
PDF comenzó como un formato propietario de Adobe en 1993, absorbió el modelo de imágenes de PostScript y a lo largo de quince versiones fue acumulando características: cifrado en 1.1, formularios interactivos en 1.2, firmas digitales y estructura lógica en 1.3, transparencia en 1.4, flujos de objetos en 1.5, cifrado AES en 1.6. Adobe presentó PDF 1.7 a ISO en 2007 y el resultado fue ISO 32000-1:2008. ISO 32000-2:2020 cubre PDF 2.0, que ajustó varias áreas poco especificadas, revisó la derivación de clave AES-256 (revisión 6 sustituyendo a la revisión 5) y añadió soporte explícito para ficheros asociados y medios enriquecidos.
Los subestándares derivan de la misma base. PDF/A (ISO 19005) sacrifica características por estabilidad archivística: sin cifrado, sin dependencias de contenido externo, todas las fuentes incrustadas, espacios de color independientes del dispositivo, metadatos XMP obligatorios. PDF/A-1 se basa en PDF 1.4, PDF/A-2 en PDF 1.7 y PDF/A-3 permite ficheros incrustados de cualquier formato. PDF/X (ISO 15930) es el subconjunto de producción de impresión: output intents, cajas de sangrado y recorte, sin transparencia en los niveles de conformidad más antiguos. PDF/UA (ISO 14289) exige estructura etiquetada, mapeos Unicode y metadatos de idioma para la accesibilidad. No son formatos en competencia; son conjuntos de restricciones adicionales sobre el PDF básico, y un único fichero puede ajustarse a más de uno simultáneamente siempre que las restricciones no entren en conflicto.
Para cualquiera que escriba código que genere o procese PDF, la base práctica es ISO 32000-2 prestando especial atención a las secciones que cubren el modelo de referencias cruzadas (§7.5), el estado de gráficos (§8.4), los operadores de estado de texto (§9.3), los descriptores de fuente y ToUnicode (§9.6 y §9.10), los formularios interactivos (§12.7) y las firmas digitales (§12.8). El estándar es extenso, pero la mayor parte del trabajo programático con PDF toca repetidamente un subconjunto reducido. Entender el modelo de objetos y el mecanismo de referencias cruzadas es el punto de entrada; todo lo demás es especialización a partir de ahí.