Artículo técnico

Salida PDF/A, PDF/X y PDF/UA en Delphi: guía de HotPDF

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. Todos los ficheros se abrían perfectamente en todos los visores que el cliente probó; veraPDF los rechazó todos por un único motivo, la ausencia de un OutputIntent. Ese incidente resume la lección central del trabajo con PDF conforme a estándares: la corrección visual no prueba nada, porque PDF/A, PDF/X y PDF/UA son restricciones sobre la estructura interna del fichero, no sobre su aspecto. HotPDF, la biblioteca PDF VCL nativa de losLab, incorpora esas restricciones en la generación del documento para que la conformidad se configure antes de que exista la primera página, en lugar de parchearse después.

Tres estándares ISO, tres promesas distintas

PDF/A (ISO 19005) promete que un fichero seguirá renderizándose igual dentro de décadas, por eso exige autocontención completa: todas las fuentes embebidas, todo color independiente del dispositivo mediante un OutputIntent, metadatos XMP completos y prohibición de cualquier elemento cuyo comportamiento dependa del entorno, incluidos cifrado y JavaScript. PDF/X (ISO 15930) promete intercambio a ciegas entre un diseñador y una imprenta, así que sus reglas tratan sobre color y geometría: condiciones de impresión caracterizadas, una clave obligatoria /Trapped, geometría definida de corte y sangrado, y en la variante X-1a ausencia de transparencia viva. PDF/UA (ISO 14289) promete que la tecnología asistiva puede leer el documento, lo que lo convierte en un requisito sobre estructura lógica: un árbol de etiquetas completo, orden de lectura correcto, idioma declarado del documento y alternativas textuales para el contenido no textual.

Estas promesas tiran en direcciones distintas. Un formulario interactivo encaja en PDF/UA y es imposible de combinar con las restricciones del perfil de archivo sobre comportamiento dinámico; un máster de imprenta solo CMYK es justamente lo contrario de lo que necesitan usuarios de lector de pantalla que nunca ven el color. Decida por canal de salida qué estándar manda, en lugar de perseguir un único fichero que satisfaga todo.

PDF/A en HotPDF: el OutputIntent lo es todo

El rechazo de archivo anterior se redujo a una sola 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 se pasa o se falla. StandardFontEmulation debe estar desactivado, porque las fuentes Base-14 emuladas no están embebidas por definición, y el embebido no es negociable bajo ISO 19005. El cifrado debe permanecer desactivado; no combine PDFACompliance con ActivateProtection, ya que un fichero de archivo cifrado es una contradicción que el validador detectará. Y el recuento de componentes pasado a AddPDFAOutputIntent tiene que coincidir con el perfil, 3 para un perfil RGB como sRGB IEC61966-2.1. HotPDF rastrea durante la generación el uso de DeviceRGB y DeviceCMYK frente al 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.

Trate el propio perfil ICC como un artefacto de despliegue con versión, no como un fichero que alguien copió una vez en el servidor de compilación. Los bytes del perfil se embeben en cada documento generado, por lo que un perfil corrupto o truncado contamina de golpe todo un lote, y el fallo solo aparece en el momento de validar. Envíe el perfil con su instalador, registre su suma de comprobación en el log de ejecución y cárguelo mediante el patrón TFileStream anterior para que un fichero ausente falle de forma ruidosa durante la generación, no de forma silenciosa en la puerta del archivo.

PDF/X para imprenta: Trapped, CMYK y perfil de prensa

Los másteres de imprenta invierten la historia del color: la prensa quiere CMYK caracterizado, y el estándar exige que se indique si se ha aplicado trapping. La clave /Trapped es obligatoria incluso cuando la respuesta honesta es que no lo sabe:

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;

Observe que el recuento de componentes cambia a 4 para el perfil de prensa CMYK. X-1a además descarta la transparencia viva, así que revise 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 su imprenta le entrega una caracterización distinta, cambie el perfil y el identificador, pero mantenga idéntica la estructura.

PDF/UA: la estructura se genera, no se injerta después

Accesibilidad es el estándar que los equipos intentan atornillar con más frecuencia al final, y es precisamente donde el reajuste falla con más fuerza, porque el árbol de etiquetas debe reflejar el orden lógico en que se creó el contenido. En HotPDF, activar PDFUACompliance habilita la salida etiquetada, y la API de estructura vincula cada llamada de dibujo con su papel 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 debe vigilarse es contenido dibujado fuera de cualquier pareja BeginTaggedContent/EndTaggedContent: se renderiza con normalidad y es invisible para un lector de pantalla, que es el peor tipo de fallo porque ningún probador vidente lo notará. Si sus plantillas usan nombres de rol de estructura personalizados, asígnelos al conjunto estándar con AddStructRoleMap('MyHead', 'H1') para que los lectores conformes sepan 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: fíese del validador, no del visor

La historia de las facturas tiene una moraleja sencilla: incorpore la verificación a la ruta de publicación con herramientas que comprueban estructura, no renderizado. Para PDF/A y PDF/UA, veraPDF es el validador abierto de referencia y comunica fallos por cláusula ISO, lo que hace que su salida sea directamente accionable contra la configuración mostrada arriba. Para PDF/X, los perfiles Preflight de Adobe Acrobat siguen siendo la comprobación práctica, ya que las condiciones de imprenta tratan tanto sobre intención de color como sobre sintaxis. Dentro del generador, HotPDF reconcilia las marcas de función con la versión PDF configurada en el momento de 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 conformidad en EndDoc elevan error de plano ante contradicciones duras, como combinar PDFACompliance con cifrado. Ninguna comprobación sustituye al validador externo; juntas evitan que configuraciones imposibles lleguen siquiera hasta él.

Versione toda la configuración de conformidad como un conjunto: la versión de HotPDF, la revisión de la plantilla, la suma de comprobación del perfil ICC y la versión del validador que dio el visto bueno. La conformidad deriva cuando cualquiera de ellos cambia por debajo de los demás, y las auditorías más dolorosas que hemos visto fueron aquellas en las que nadie podía decir qué combinación produjo un fichero de archivo de cinco años. Un único registro de configuración por lote cierra esa pregunta para siempre.

Ejecute el validador sobre salida real de producción, no sobre una muestra fabricada a mano. Los fallos que importan 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 nueva ruta de código que dibuja texto sin etiquetar. Conserve un fichero de fallo conocido por cada incidente pasado como entrada de regresión, y su puerta de conformidad se mantendrá honesta. Para la parte de renderizado de estas canalizaciones, vea nuestro artículo sobre salida de informes, fuentes e imágenes con HotPDF, y para conectar validadores a una compilación, la pieza complementaria sobre automatización de comprobaciones preflight de PDF.

FAQ

¿Puede un PDF ser conforme con PDF/A y PDF/X a la vez?

A veces, pero rara vez merece la pena el malabarismo de restricciones: el perfil de archivo quiere color independiente del dispositivo y metadatos completos, el perfil de imprenta quiere CMYK caracterizado y declaraciones de trapping. Genere por canal desde los mismos datos de origen en lugar de obligar a un fichero a servir a ambos.

¿Por qué veraPDF rechaza un fichero que se abre bien en todos los visores?

Los visores son deliberadamente tolerantes; los validadores son deliberadamente estrictos. La ausencia de OutputIntents, fuentes no embebidas y metadatos XMP ausentes nunca afecta al renderizado, así que solo un validador estructural los notificará.

¿Las facturas deberían usar PDF/A nivel A o nivel B?

El nivel B garantiza reproducción visual y es lo que la mayoría de archivos exigen para documentos empresariales escaneados o generados. El nivel A añade los requisitos de estructura etiquetada, incorporando en la práctica la carga de trabajo de PDF/UA, y es la opción correcta cuando las obligaciones de accesibilidad se aplican al propio archivo.

Lectura adicional

Las propiedades de conformidad, los output intents y la 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 utilizada aquí.