Pular para o conteúdo
getnextpdf.com

De formulário preenchível a registro congelado: preenchimento e flatten de AcroForm

Spec: ISO 32000-2, §12.7

Um formulário PDF tem duas vidas. Primeiro ele é preenchível: um conjunto de campos tipados em que uma pessoa digita, marca ou escolhe. Depois, quando o acordo é feito, ele se torna um registro congelado: os valores são impressos na própria página, de modo que todo visualizador, em todo dispositivo, vê exatamente o que foi acordado. O NextPDF constrói o primeiro e produz o segundo, com uma garantia deliberada — ele não vai silenciosamente jogar os valores fora na travessia.

A lacuna entre “o que eu preenchi” e “o que você vê” é onde os formulários dão errado.

Um campo preenchível é, tecnicamente, um pequeno widget interativo desenhado sobre a página. Visualizadores diferentes podem renderizá-lo de formas diferentes. Uns honram um valor salvo, uns regeneram a aparência a partir de uma fonte que você não tem, uns deixam um leitor editá-lo novamente. Para um rascunho em que você quer que colaboradores continuem editando, esse é o ponto. Para a cópia assinada do que foi acordado, é uma vulnerabilidade: o registro não deveria depender de qual aplicação o abre, e não deveria ser editável depois do fato.

O flatten fecha a lacuna. Ele pega o valor atual de cada campo e o pinta na página como gráficos comuns e imutáveis — o mesmo tipo de conteúdo de um título ou um logotipo. Depois disso, não há campo para editar nem aparência para regenerar. O documento mostra uma coisa, a mesma coisa, em todo lugar.

  • Um AcroForm é o formulário interativo do documento: uma árvore de campos tipados declarada no catálogo (Spec: ISO 32000-2, §12.7).
  • Cada campo é tornado visível por uma widget annotation — o retângulo na página em que você clica ou digita (Spec: ISO 32000-2, §12.5).
  • O NextPDF traz builders tipados para todo controle de formulário sem assinatura suportado — text, checkbox, radio, list box e combo box (choice), e push button — mais um gerenciador de campos que os escreve como objetos PDF apropriados.
  • O flatten renderiza o valor de cada campo no content stream da página e remove o formulário interativo agora redundante, deixando um registro congelado.
  • Se você pedir para fazer flatten de um documento que não tem páginas, o NextPDF não destrói silenciosamente os valores dos seus campos. Ele preserva o formulário, avisa você, e permite que você adicione uma página e faça flatten corretamente.

O modelo mental são duas camadas. O campo é o dado: um nome, um tipo, um valor, e um conjunto de flags. O widget é a imagem: um retângulo em uma página específica que permite a um visualizador interagir com o campo (Spec: ISO 32000-2, §12.5). Um campo pode até aparecer por meio de vários widgets — é exatamente assim que um grupo de radio funciona, várias escolhas na página conectadas a um único valor subjacente.

O NextPDF dá a cada tipo de campo seu próprio builder tipado, de modo que você nunca monta um dicionário bruto à mão. O tipo carrega os detalhes corretos do PDF por você. Um checkbox, um radio button, e um push button compartilham todos o mesmo tipo de formulário subjacente na norma e são distinguidos por suas flags; o motor define essas flags a partir do tipo que você escolheu, em vez de pedir que você lembre qual bit significa “radio”. Um list box e um combo box são ambos campos de choice; novamente, o builder escolhe a codificação certa. Você declara o tipo do campo uma vez, em palavras, e os bytes seguem.

O flatten é a segunda metade. O flattener agrupa as widget annotations por sua página dona, usando o retângulo de cada widget para o posicionamento naquela página, depois renderiza cada valor como uma pequena sequência de operadores de content stream — definir uma cor, definir uma posição de texto, desenhar os glifos — anexada ao conteúdo existente daquela página (Spec: ISO 32000-2, §8.4). O valor deixa de ser um campo vivo e se torna tinta pintada. Como o formulário não carrega mais nenhum campo interativo, o motor então remove a entrada do AcroForm: não resta nada para ser interativo.

  1. Declarar campos tipadosAdicione campos de text, checkbox, radio, choice e button por meio de seus builders tipados; o motor define o tipo e as flags de PDF corretos pela norma.
  2. Posicionar os widgetsCada campo é desenhado como uma widget annotation — um retângulo em uma página escolhida em que um visualizador pode digitar, marcar ou escolher.
  3. Coletar entradaEnvie-o preenchível: um leitor fornece valores, ou seu código os define, deixando um documento preenchido, mas ainda editável.
  4. Fazer flatten dos valoresRenderize o valor de cada campo no content stream da página como gráficos; o valor pintado agora é imutável.
  5. Descartar o formulário interativoCom todo valor gravado, remova o AcroForm para que nada permaneça editável — um registro congelado do que foi acordado.
De um formulário preenchível a um registro congelado: declare campos tipados, desenhe seus widgets na página, preencha valores, depois faça flatten desses valores em gráficos de página imutáveis e descarte o formulário interativo agora vazio.

Um formulário pequeno e representativo: construa alguns campos tipados, depois faça flatten dele em um registro congelado.

<?php
declare(strict_types=1);
use NextPDF\Core\Document;
$document = Document::createStandalone();
$document->addPage();
// Typed builders, called straight on the document. You pick the field
// type by choosing its builder method — textField, checkBox, comboBox —
// and you pass the value to freeze at creation time. The engine writes
// the spec-correct PDF type and flags for you.
$document->textField('full_name', x: 40, y: 700, w: 220, h: 18, default: 'Ada Lovelace');
$document->checkBox('agree_terms', x: 40, y: 660, size: 14, checked: true);
$document->comboBox(
'plan',
x: 40,
y: 620,
w: 160,
h: 18,
items: ['Starter', 'Team', 'Enterprise'],
selected: 'Team',
);
// Flatten: the values become immutable page graphics and the
// interactive AcroForm is dropped. The result is a frozen record.
$document->flattenForms();
$bytes = $document->getPdfData();

Antes de flattenForms(), isto é um formulário preenchível. Depois dele, os mesmos valores são pintados na página e não resta nenhum campo para alterar. Você escolhe o tipo do campo escolhendo seu método builder — textField, checkBox, comboBox — de modo que um tipo errado não pode ser codificado como uma string solta: um erro de digitação é uma chamada a um método que não existe, capturado antes de qualquer campo ser escrito, não um campo silenciosamente errado. Essa é a mesma postura de recusar-a-adivinhar que o resto do motor adota; veja uma API que se recusa a adivinhar.

A armadilha é acreditar que preencher um campo o congela. Não congela. Um campo preenchido ainda carrega um valor vivo que um visualizador capaz pode editar, e uma aparência que alguns visualizadores vão regenerar. “Eu defini o valor” e “o documento agora é um registro fixo” são dois estados diferentes. Só o flatten cruza de um para o outro, porque só o flatten transforma o valor em gráficos de página que não se comportam mais como um campo.

O erro espelhado é fazer flatten de um rascunho do qual você ainda precisa coletar entrada. Uma vez achatado, os campos somem — esse é todo o ponto — então faça flatten da cópia que você pretende ser final, não daquela que você ainda está circulando.

O suporte a formulários do NextPDF é core completo: builders tipados para os controles de campo interativo comuns, um flattener de formulário, e um gerenciador de campos que escreve os campos como objetos PDF apropriados. Esta página descreve essa superfície do core.

AcroForm fields and flattening — edition availability
EditionAvailability
Core

Builders tipados para campos de text, checkbox, radio, choice (list box e combo box), e push-button; posicionamento de widgets; um gerenciador de campos; e um flattener de formulário que grava valores em gráficos de página. Disponível em todas as edições.

ProNot in this edition
EnterpriseNot in this edition

O flatten é de via única por design. Ele remove o formulário interativo para que o registro fique fixo; não é um botão de “travar temporariamente”, e não há um un-flatten que re-derive campos editáveis a partir de gráficos pintados. Se você precisa de uma cópia que as pessoas possam continuar editando, mantenha o formulário não achatado e faça flatten de uma duplicata.

O flatten também não é uma assinatura. Ele torna um documento não editável no sentido de visualizador comum, mas não prova criptograficamente quem o produziu nem que ele não mudou desde então. Quando o registro precisa ser comprovadamente aquele que foi acordado, faça flatten e depois assine; veja como as assinaturas ficam em um PDF.

Por fim, um formulário tagueado e acessível é uma preocupação separada de um achatado. Se a versão preenchível precisa ser utilizável com tecnologia assistiva, os campos precisam de nomes acessíveis e estrutura enquanto ainda estão interativos; veja o que torna um PDF acessível.

  • AcroForm — o formulário interativo de um PDF: a árvore de campos tipados declarada no catálogo do documento que torna o arquivo preenchível (Spec: ISO 32000-2, §12.7).
  • Campo (field) — o lado de dados de um controle de formulário: um nome, um tipo, um valor, e flags. Independente de como ele se vê na página.
  • Widget annotation — o retângulo visível e clicável em uma página por meio do qual um visualizador interage com um campo (Spec: ISO 32000-2, §12.5). Um campo pode ter vários.
  • Campo de choice — um campo que oferece um conjunto de opções: um list box as mostra abertas, um combo box mostra um menu suspenso. Ambos são o mesmo tipo de campo PDF.
  • Flatten — renderizar o valor atual de cada campo na página como gráficos imutáveis e remover o formulário interativo, produzindo um registro congelado.
  • Registro congelado — um documento achatado: ele mostra uma coisa fixa em todo visualizador e não tem campos restantes para editar.