Artigo Técnico

Estrutura do Arquivo PDF: Como o Formato Realmente Funciona

O PDF não é um formato de documento da mesma forma que o Word ou o RTF. Esses formatos armazenam uma sequência de conteúdo que um renderizador interpreta no momento da exibição, de modo que a saída depende das fontes e do mecanismo de layout que estiverem presentes. O PDF armazena o resultado desse processo: instruções precisas de renderização, programas de fontes, fluxos de imagens compactadas e um grafo de objetos que os une em uma descrição autossuficiente de cada página. O arquivo carrega informações suficientes para reproduzir cada página de forma idêntica em qualquer renderizador em conformidade, o que é seu principal objetivo de design e a fonte da maior parte da complexidade que você encontra ao tentar gerar, analisar ou modificar um de forma programática

O modelo de objetos

Todo PDF é uma coleção de objetos numerados. Um objeto pode ser um valor booleano, inteiro, número real, nome, string, array, dicionário, fluxo (stream) ou nulo. Quase tudo o que é interessante é um dicionário, que é um conjunto de pares chave-valor onde as chaves são nomes e os valores são qualquer outro tipo de objeto, incluindo referências a outros objetos por número e contagem de geração. Um fluxo é um dicionário seguido por uma sequência de bytes, normalmente compactada

O dicionário do catálogo é a raiz. Ele aponta para a árvore de páginas, que organiza os dicionários de página em uma estrutura de árvore balanceada em vez de uma lista plana, portanto, navegar até a página 5.000 de um documento de 10.000 páginas não requer a passagem por todos os descritores de página anteriores. Cada dicionário de página faz referência aos seus fluxos de conteúdo (uma ou mais sequências de operadores de descrição de página), ao seu dicionário de recursos (que, por sua vez, faz referência a descritores de fontes, espaços de cores e XObjects de imagens) e à sua media box (o espaço de coordenadas em que a página se encontra). A origem das coordenadas fica no canto inferior esquerdo, com Y positivo indo para cima, em unidades de 1/72 de polegada

No final do arquivo fica a tabela de referência cruzada, que mapeia cada número de objeto para seu deslocamento de bytes no arquivo. É isso que permite o acesso aleatório: um visualizador lê a tabela de referência cruzada primeiro e, em seguida, busca diretamente os objetos de que precisa. O PDF 1.5 introduziu os fluxos de referência cruzada, que compactam a tabela em um objeto de fluxo e agrupam objetos relacionados em fluxos de objetos, reduzindo visivelmente o tamanho do arquivo para documentos com muitos pequenos objetos

Fluxos de conteúdo e o modelo gráfico

O conteúdo visual de uma página fica em um ou mais fluxos de conteúdo. Cada fluxo é uma sequência de operadores de PDF intercalados com seus operandos. O operador de texto BT inicia um objeto de texto, Tf seleciona uma fonte e um tamanho no dicionário de recursos, Td posiciona o cursor de texto, Tj ou TJ pinta uma string e ET fecha o objeto de texto. Os gráficos vetoriais seguem um padrão semelhante: m define o ponto inicial de um caminho, l acrescenta um segmento de linha, c acrescenta uma curva de Bézier e f ou S preenche ou contorna o caminho

O estado gráfico controla tudo o que acontece entre os operadores: matriz de transformação atual, largura da linha, espaço de cores, cor de preenchimento, cor de traço e o caminho de recorte (clipping path). Operadores como q e Q empurram e retiram o estado gráfico de uma pilha, que é a forma como o PDF implementa transformações de coordenadas locais e substituições de estado temporárias sem afetar o contexto ao redor deles. Os XObjects de formulário generalizam isso: um fluxo de conteúdo independente com seu próprio dicionário de recursos que pode ser pintado em uma página em posições e escalas arbitrárias com um único operador Do

Incorporação de fontes e extração de texto

O PDF pode referenciar fontes por nome e contar com o visualizador para substituir por algo, mas na prática qualquer documento que você pretende compartilhar deve incorporar os dados da fonte. Uma fonte Type 1 ou TrueType/OpenType incorporada em um PDF carrega um dicionário de descritor de fonte apontando para um fluxo de arquivo de fonte. Para fontes TrueType, esse fluxo contém o programa binário da fonte; para Type 1, são os dados PFB. O uso de subconjuntos (subsetting), que é o que todo gerador de PDF sério faz, retira os glifos não referenciados pelo documento, mantendo o tamanho do arquivo gerenciável até mesmo para grandes fontes Unicode

A extração de texto é onde a incorporação de fontes pode causar problemas. A representação visual de um caractere é determinada por um glifo no programa da fonte incorporada. O valor Unicode desse caractere é determinado por um fluxo ToUnicode CMap anexado ao dicionário da fonte. Quando o ToUnicode CMap está ausente ou incorreto, um visualizador de PDF pode renderizar o texto de forma legível, mas não consegue extraí-lo como um Unicode significativo, o que explica por que copiar e colar de alguns PDFs produz caracteres sem sentido (garbage). O PDF Marcado (Tagged PDF - ISO 32000 §14.8) adiciona uma segunda camada: uma árvore de estrutura lógica que mapeia o conteúdo da página para papéis semânticos do documento, como parágrafos, cabeçalhos e células de tabela. Leitores de tela e mecanismos de refluxo usam a árvore de estrutura em vez da ordem bruta do fluxo de conteúdo, o que explica por que um PDF visualmente bem diagramado ainda pode ser inacessível se a marcação estiver ausente ou errada

Atualizações incrementais e assinaturas digitais

Quando você salva as alterações em um PDF existente sem reescrevê-lo do zero, os novos objetos são anexados após o corpo original do arquivo junto com uma nova seção de referência cruzada e um novo dicionário trailer. O trailer atualizado aponta para os novos dados de referência cruzada, e os objetos substituídos permanecem no arquivo, mas simplesmente não são referenciados pela nova cadeia de referência cruzada. Isso é a atualização incremental, e tem duas consequências significativas

Primeiro, o arquivo cresce com cada ciclo de salvamento. Um documento editado e salvo repetidamente acumula camadas de objetos obsoletos. Ferramentas como o QPDF podem linearizar ou compactar-e-reescrever um arquivo para recuperar esse espaço, mas o padrão é o acúmulo. Em segundo lugar, as assinaturas digitais dependem de atualizações incrementais para seu modelo de integridade. Uma assinatura ISO 32000 cobre um intervalo de bytes do arquivo, normalmente tudo, exceto o espaço reservado para o próprio valor da assinatura. Quaisquer alterações pós-assinatura que apareçam como atualizações incrementais adicionais são visíveis para um leitor validador como modificações feitas após a assinatura, que é exatamente a trilha de auditoria que você deseja. No entanto, isso também significa que certas modificações, como a adição de uma assinatura de aprovação ou o preenchimento de campos de formulário, são explicitamente permitidas pelo padrão sem invalidar a assinatura original, desde que as alterações estejam de acordo com as configurações de permissão do documento (ISO 32000-2 §12.7.6). Uma modificação que se enquadre fora dessas permissões é sinalizada como não autorizada. Acertar nessa distinção é importante quando você está gerando documentos que serão contra-assinados posteriormente

Níveis de conformidade e a linhagem do ISO 32000

O PDF começou como um formato proprietário da Adobe em 1993, absorveu o modelo de imagem do PostScript e ao longo de quinze versões acumulou recursos: criptografia no 1.1, formulários interativos no 1.2, assinaturas digitais e estrutura lógica no 1.3, transparência no 1.4, fluxos de objetos no 1.5, criptografia AES no 1.6. A Adobe submeteu o PDF 1.7 à ISO em 2007 e o ISO 32000-1:2008 foi o resultado. O ISO 32000-2:2020 cobre o PDF 2.0, que reforçou várias áreas não especificadas adequadamente, revisou a derivação da chave AES-256 (revisão 6 substituindo a revisão 5) e adicionou suporte explícito a arquivos associados e rich media

Os subpadrões derivam da mesma base. O PDF/A (ISO 19005) troca recursos pela estabilidade de arquivamento: sem criptografia, sem dependências de conteúdo externo, todas as fontes incorporadas, espaços de cores independentes de dispositivo, metadados XMP obrigatórios. O PDF/A-1 é baseado no PDF 1.4, o PDF/A-2 no PDF 1.7, o PDF/A-3 permite a incorporação de arquivos de qualquer formato. O PDF/X (ISO 15930) é o subconjunto de produção de impressão: intenções de saída, caixas de sangria e de corte (bleed and trim boxes), sem transparência nos níveis de conformidade mais antigos. O PDF/UA (ISO 14289) exige estrutura marcada (tagged structure), mapeamentos Unicode e metadados de idioma para acessibilidade. Eles não são formatos concorrentes; eles são conjuntos de restrições adicionais sobre o núcleo do PDF e um único arquivo pode estar em conformidade com mais de um simultaneamente, desde que as restrições não entrem em conflito

Para quem escreve código que gera ou processa PDF, a linha de base prática é o ISO 32000-2, com cuidadosa atenção às seções que cobrem o modelo de referência cruzada (§7.5), o estado gráfico (§8.4), os operadores de estado de texto (§9.3), descritores de fonte e ToUnicode (§9.6 e §9.10), formulários interativos (§12.7) e assinaturas digitais (§12.8). O padrão é extenso, mas a maior parte do trabalho programático em PDF toca uma fatia estreita dele repetidamente. Entender o modelo de objetos e o mecanismo de referência cruzada é o ponto de entrada; todo o restante é uma especialização a partir daí