O HotPDF escreve documentos PDF 2.0 nativos a partir de Delphi e C++Builder, incluindo os três perfis arquiváveis PDF/A-4 e a saída acessível PDF/UA-2 com elementos de estrutura em namespaces. Selecioná-los é uma questão de duas propriedades, mas os padrões por trás dessas propriedades mudaram mais do que o número de versão sugere: PDF/A-4 derrubou as letras de conformidade que todo mundo aprendeu com PDF/A-2, e PDF/UA-2 introduziu namespaces de estrutura que um documento da parte 1 nunca teve
Este artigo cobre o que de fato muda no arquivo gerado, e quais erros o HotPDF transforma em uma exceção em EndDoc em vez de em um documento que falha na validação no site do cliente
Como a identificação do PDF/A-4 difere das partes 2 e 3
PDF/A-4 se identifica por número de parte e ano de revisão, sem letra de conformidade para a parte base. Defina PDFACompliance como '4' e o HotPDF emite pdfaid:part=4 com pdfaid:rev=2020 e nenhuma entrada pdfaid:conformance. A letra não se perdeu — a parte 4 não tem níveis A/B/U, porque os requisitos que costumavam separá-los foram incorporados à parte base
Duas extensões mantêm uma letra. '4E' seleciona PDF/A-4e para documentos de engenharia e emite conformidade E, que permite os caminhos de anotação 3D e RichMedia que os outros perfis proíbem. '4F' seleciona PDF/A-4f e emite conformidade F, que permite um arquivo embutido de qualquer formato. Todos os três forçam um cabeçalho PDF 2.0, exigem as verificações usuais de output intent e metadados do PDF/A, e proíbem criptografia — um arquivo arquivável criptografado é uma contradição que o padrão não acolhe
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'invoice-archive.pdf';
Pdf.PDFACompliance := '4F'; // PDF/A-4f: associated files of any format
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(50, 760, 0, 'Invoice 2026-0731');
Pdf.AddPDFAssociatedFile('invoice.xml', 'text/xml',
'Structured invoice data', 'Data', LoadInvoiceBytes);
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
AddPDFAssociatedFile embute o arquivo, constrói seu FileSpec com um /AFRelationship, e o registra tanto no array /AF do Catálogo quanto na árvore de nomes EmbeddedFiles. Ambos os registros são exigidos; um arquivo listado em apenas um deles é o motivo mais comum de uma fatura híbrida passar por uma verificação rápida a olho nu e falhar em um validador de verdade. A string de relacionamento aceita Source, Data, Alternative, Supplement ou Unspecified, e o perfil ativo deve ser PDF/A-3, PDF/A-4e ou PDF/A-4f — o perfil base da parte 4 não admite arquivos associados. O nome antigo AddPDFA3AssociatedFile ainda funciona para código existente
O que o PDF/UA-2 exige e o PDF/UA-1 não exigia
PDF/UA-2 força PDF 2.0 e emite pdfuaid:part=2 com pdfuaid:rev=2024, e introduz namespaces na árvore de estrutura. Um documento da parte 1 tinha um vocabulário plano de papéis padrão. Um documento da parte 2 pode carregar papéis personalizados desde que cada um pertença a um namespace declarado, que é o que torna a marcação específica de domínio legível para tecnologia assistiva em vez de adivinhação
Dois métodos implementam isso. RegisterStructureNamespace cria ou reutiliza um dicionário indireto /Type /Namespace e o lista em StructTreeRoot /Namespaces, devolvendo o dicionário para que você possa reutilizá-lo. AddStructureElementNS cria um elemento de estrutura cuja entrada /NS aponta para esse dicionário, que é o que licencia um nome de papel fora do conjunto padrão. Chamadas repetidas com o mesmo URI reutilizam um único dicionário em vez de acumular duplicatas
var
Root: THPDFDictionaryObject;
begin
Pdf.PDFUACompliance := True;
Pdf.PDFUAPart := 2; // part 2 forces PDF 2.0
Pdf.Lang := 'en-US';
Pdf.BeginDoc;
Root := Pdf.AddStructureElement('Document', nil);
Pdf.AddStructureElementNS('WidgetGroup',
'https://example.com/ns/widgets', Root);
Pdf.EndDoc;
end;
Lang não é decoração aqui. Um documento tagged sem idioma natural declarado deixa um leitor de tela adivinhando a pronúncia, e o PDF/UA trata a omissão como defeito em vez de preferência
Quais erros de estrutura o EndDoc pega?
Quatro, e cada um corresponde a um documento que de outro modo chegaria quebrado a um validador. A raiz da estrutura deve conter exatamente um elemento Document no nível superior. Cada dicionário de namespace deve ser indireto, tipado como Namespace, e carregar um URI único não vazio. Toda referência /NS de elemento de estrutura deve resolver para um dicionário de fato listado no array /Namespaces da raiz. E um papel sem namespace deve ser um papel padrão de PDF 2.0 ou resolver por meio do RoleMap
Esses disparam em EndDoc porque esse é o último momento em que a árvore inteira existe em memória e o primeiro em que está completa. Pegá-los antes significaria rejeitar estados intermediários válidos; pegá-los depois significaria não pegá-los de jeito nenhum. A consequência prática para o seu código é que um bug de estrutura aparece no fim da geração com uma mensagem nomeando o problema, em vez de aparecer semanas depois como um relato veraPDF que alguém encaminha de um cliente
Os papéis do PDF 2.0 que valem conhecer
O enum de papéis tipados ganha DocumentFragment, Aside, Title, FENote, Sub, Em, Strong e Artifact. Três desses mudam como você marca documentos de negócios comuns. Aside finalmente dá a barras laterais e pull quotes uma casa que não seja um Sect mal usado. FENote marca notas de rodapé e notas finais como o que são, de modo que um leitor pode oferecê-las em vez de intercalá-las com o texto do corpo. Em e Strong substituem a adivinhação semântica que vinha de marcar ênfase como formatação em nível de span
A sobrecarga por string adicionalmente aceita a forma aberta Hn, incluindo H7 e além. PDF 1.7 parava em H6, o que forçava documentos técnicos profundos a achatarem seu esboço ou a reutilizar níveis. Se você gera documentos de normas, códigos jurídicos ou catálogos de peças, só isso pode ser o motivo para mover a saída para PDF 2.0
O que verificar antes de trocar a saída de produção
PDF 2.0 é uma mudança de cabeçalho com uma cauda longa. Ferramentas antigas de ingestão arquivável, alguns RIPs de impressão e um número surpreendente de visualizadores line-of-business aceitam apenas até PDF 1.7, e falham no cabeçalho em vez de em qualquer coisa que você tenha feito de errado. Antes de trocar, confirme os sistemas consumidores, e lembre-se de que selecionar um perfil PDF/A-4 seleciona PDF 2.0 tenha você pedido ou não
Uma sequência segura é manter PDF/A-3 para documentos que vão para fora a leitores desconhecidos, usar PDF/A-4f para arquivos internos onde você controla a ingestão, e adotar PDF/UA-2 apenas quando a política de acessibilidade o nomeia. Se você está trabalhando primeiro o lado arquivável, os guias de validação de PDF/A, PDF/X e PDF/UA e de faturas híbridas ZUGFeRD e Factur-X em PDF/A-3 cobrem as escolhas de perfil que importam antes do número de versão, e as notas sobre relatórios de preflight automatizados mostram como tornar o veredito parte da sua build em vez de uma etapa manual
O HotPDF entrega toda a superfície de autoria de PDF 2.0 como código VCL nativo para Delphi e C++Builder, de modo que a saída PDF/A-4 e PDF/UA-2 não precisa de motor externo nem redistribuível — a página do componente HotPDF lista os perfis e versões do RAD Studio suportados