Un archivo gubernamental rechazó una vez un depósito completo de 1,400 facturas generadas por el sistema de facturación Delphi de un cliente. Cada archivo se abría perfectamente en todos los visores que el cliente probó; veraPDF los rechazó a todos por una única razón: faltaba un OutputIntent. Ese incidente resume la lección central del trabajo con PDF conforme a estándares: la corrección visual no demuestra nada, porque PDF/A, PDF/X y PDF/UA son restricciones sobre la estructura interna del archivo, no sobre su apariencia. HotPDF, la biblioteca PDF VCL nativa de losLab, integra estas restricciones en la generación del documento para que el cumplimiento se configure antes de que exista la primera página, no como un parche posterior.
Tres estándares ISO, tres promesas distintas
PDF/A (ISO 19005) promete que un archivo seguirá renderizándose de forma idéntica dentro de décadas; por eso exige autocontención completa: cada fuente embebida, cada color independiente del dispositivo mediante un OutputIntent, metadatos XMP completos y la prohibición de todo aquello cuyo comportamiento dependa del entorno, incluidos cifrado y JavaScript. PDF/X (ISO 15930) promete intercambio a ciegas entre un diseñador y una imprenta, de modo que sus reglas tratan sobre color y geometría: condiciones de impresión caracterizadas, una clave /Trapped obligatoria, geometría de corte y sangrado definida y, en la variante X-1a, ninguna transparencia viva. PDF/UA (ISO 14289) promete que la tecnología de asistencia puede leer el documento, lo que lo convierte en un requisito de estructura lógica: un árbol de etiquetas completo, orden de lectura correcto, idioma declarado del documento y alternativas de texto para contenido no textual.
Estas promesas tiran en direcciones distintas. Un formulario interactivo está bien en PDF/UA y es imposible combinarlo con las restricciones del perfil archivístico sobre comportamiento dinámico; un original de impresión sólo CMYK es exactamente lo equivocado para usuarios de lectores de pantalla que nunca ven el color. Decidan por canal de salida qué estándar gobierna, en vez de perseguir un solo archivo que satisfaga todo.
PDF/A en HotPDF: el OutputIntent es la pieza central
El rechazo del archivo anterior se redujo a una estructura ausente, y es la estructura que más olvidan los generadores porque nada visible depende de ella. ISO 19005 exige un OutputIntent: un perfil ICC embebido que da a los colores de dispositivo un significado inequívoco. HotPDF convierte el perfil en una entrada explícita:
var
Pdf: THotPDF;
ICC: TFileStream;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'invoice-archival.pdf';
Pdf.PDFACompliance := 'B'; // level B: visual fidelity
Pdf.Lang := 'en-US';
Pdf.StandardFontEmulation := False; // embed real fonts, no Base-14 emulation
ICC := TFileStream.Create('sRGB.icc', fmOpenRead);
try
Pdf.AddPDFAOutputIntent('sRGB IEC61966-2.1', '', ICC, 3, 'DeviceRGB');
finally
ICC.Free;
end;
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(50, 760, 0, 'Archival invoice body');
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Tres detalles de configuración deciden si pasa o falla. StandardFontEmulation debe estar desactivado, porque las fuentes Base-14 emuladas, por definición, no están embebidas, y embeber fuentes no es negociable bajo ISO 19005. El cifrado debe permanecer deshabilitado; no combinen PDFACompliance con ActivateProtection, porque un archivo archivístico cifrado es una contradicción que el validador detectará. Y el conteo de componentes pasado a AddPDFAOutputIntent debe coincidir con el perfil: 3 para un perfil RGB como sRGB IEC61966-2.1. HotPDF rastrea el uso de DeviceRGB y DeviceCMYK durante la generación contra el intent declarado, de modo que un relleno CMYK en un documento con intent RGB aparece como problema de validación en lugar de inconsistencia silenciosa.
Traten el perfil ICC como un artefacto de despliegue con versión, no como un archivo que alguien copió alguna vez al servidor de build. Los bytes del perfil se embeben en cada documento generado, así que un perfil corrupto o truncado contamina todo un lote a la vez, y la falla sólo aparece en tiempo de validación. Entreguen el perfil con su instalador, registren su checksum en el log de ejecución y cárguenlo mediante el patrón TFileStream anterior para que un archivo faltante falle ruidosamente durante la generación, no silenciosamente en la puerta del archivo.
PDF/X para impresión: Trapped, CMYK y el perfil de prensa
Los originales de impresión invierten la historia del color: la prensa quiere CMYK caracterizado, y el estándar exige declarar si se aplicó trapping. La clave /Trapped es obligatoria incluso cuando la respuesta honesta es que no lo saben:
Pdf.PDFXCompliance := 'X-1a';
Pdf.Trapped := 'Unknown'; // mandatory key under ISO 15930
ICC := TFileStream.Create('FOGRA39.icc', fmOpenRead);
try
Pdf.AddPDFXOutputIntent('FOGRA39 (ISO 12647-2:2004)', '', ICC, 4, 'DeviceCMYK');
finally
ICC.Free;
end;
Pdf.BeginDoc;
// draw with CMYK-safe colors, no transparency, no encryption
Pdf.EndDoc;
Noten que el conteo de componentes cambió a 4 para el perfil CMYK de prensa. X-1a además descarta transparencia viva, así que revisen cualquier código de dibujo que superponga elementos translúcidos; lo que un visor compone en pantalla es precisamente lo que un RIP se niega a adivinar. Si la imprenta les entrega otra caracterización, cambien el perfil y el identificador, pero mantengan la estructura idéntica.
PDF/UA: la estructura se genera, nunca se injerta después
La accesibilidad es el estándar que los equipos intentan agregar al final con más frecuencia, y es donde el injerto falla con más dureza, porque el árbol de etiquetas debe reflejar el orden lógico en que se creó el contenido. En HotPDF, configurar PDFUACompliance activa la salida etiquetada, y la API de estructura vincula cada llamada de dibujo con su rol semántico:
Pdf.PDFUACompliance := True; // auto-enables tagged PDF
Pdf.Lang := 'en-US'; // set explicitly; empty falls back to 'en'
Pdf.BeginDoc;
Root := Pdf.AddStructureElement(sstDocument, nil);
H1 := Pdf.EmitTaggedHeading(1, Root, 50, 700, 'Quarterly Report');
Para := Pdf.BeginTaggedContent('P', Root);
Pdf.CurrentPage.TextOut(50, 650, 0, 'Revenue grew in all regions.');
Pdf.EndTaggedContent;
Pdf.EndDoc;
El patrón de error que deben vigilar es contenido dibujado fuera de cualquier par BeginTaggedContent/EndTaggedContent: se renderiza normalmente y es invisible para un lector de pantalla, el peor tipo de falla porque ningún tester vidente la notará. Si sus plantillas usan nombres personalizados de roles de estructura, mapéenlos al conjunto estándar con AddStructRoleMap('MyHead', 'H1') para que los lectores conformes sepan cómo interpretarlos. ISO 14289 también exige un idioma declarado; HotPDF sustituye 'en' cuando Lang está vacío, lo que es una red de seguridad, no una excusa para omitir el idioma real del documento.
Verificación: confíen en el validador, no en el visor
La historia de la factura tiene una moraleja simple: integren la verificación en la ruta de release con herramientas que revisen estructura, no renderizado. Para PDF/A y PDF/UA, veraPDF es el validador abierto de referencia y reporta fallas por cláusula ISO, lo que vuelve su salida directamente accionable contra la configuración mostrada arriba. Para PDF/X, los perfiles de Preflight de Adobe Acrobat siguen siendo la comprobación práctica, porque las condiciones de prensa tratan tanto sobre intención de color como sobre sintaxis. Dentro del generador, HotPDF reconcilia los flags de características con la versión PDF configurada al guardar, degradando silenciosamente lo que la versión no puede expresar, como AES-256 por debajo de PDF 1.7, mientras que las puertas de cumplimiento en EndDoc fallan de forma explícita ante contradicciones duras como combinar PDFACompliance con cifrado. Ninguna comprobación reemplaza al validador externo; juntas impiden que configuraciones imposibles lleguen hasta él.
Versionen junta toda la configuración de cumplimiento: la versión de HotPDF, la revisión de plantilla, el checksum del perfil ICC y la versión del validador que aprobó. La conformidad deriva cuando cualquiera de ellos cambia por debajo de los otros, y las auditorías más dolorosas que hemos visto fueron aquellas donde nadie podía decir qué combinación produjo un archivo de hace cinco años. Un único registro de configuración por lote cierra esa pregunta de forma permanente.
Ejecuten el validador sobre salida real de producción, no sobre una muestra armada a mano. Las fallas importantes vienen de los datos: un logotipo de cliente que llega como CMYK cuando el intent dice RGB, una revisión de plantilla que introduce una fuente no embebida, una ruta nueva de código que dibuja texto sin etiquetar. Conserven un archivo conocido fallido por cada incidente pasado como entrada de regresión, y su puerta de cumplimiento se mantendrá honesta. Para el lado de renderizado de estas canalizaciones, vean nuestro artículo sobre salida de reportes, fuentes e imágenes con HotPDF, y para conectar validadores a un build, la pieza complementaria sobre automatización de comprobaciones preflight de PDF.
FAQ
¿Un PDF puede cumplir PDF/A y PDF/X al mismo tiempo?
A veces, pero rara vez vale la pena equilibrar tantas restricciones: el perfil archivístico quiere color independiente del dispositivo y metadatos completos; el perfil de impresión quiere CMYK caracterizado y declaraciones de trapping. Generen por canal desde los mismos datos de origen en lugar de forzar un archivo a servir ambos propósitos.
¿Por qué veraPDF rechaza un archivo que se abre bien en todos los visores?
Los visores son deliberadamente tolerantes; los validadores son deliberadamente estrictos. OutputIntents ausentes, fuentes no embebidas y metadatos XMP faltantes nunca afectan el renderizado, así que sólo un validador estructural los reportará.
¿Las facturas deben usar PDF/A nivel A o nivel B?
El nivel B garantiza la reproducción visual y es lo que la mayoría de los archivos exige para documentos empresariales escaneados o generados. El nivel A agrega los requisitos de estructura etiquetada, lo que en la práctica incorpora la carga de trabajo de PDF/UA, y es la elección correcta cuando las obligaciones de accesibilidad aplican al propio archivo.
Lecturas adicionales
Las propiedades de cumplimiento, output intents y API de etiquetado de este artículo forman parte de HotPDF Component para Delphi y C++Builder; la página del producto enlaza la referencia completa de cada llamada usada aquí.