Flatten form fields into static page content
At a glance
Section titled “At a glance”Use this recipe to flatten an interactive AcroForm. NextPDF draws each field’s
current value into the page content stream as ordinary graphics, then removes
the AcroForm dictionary. The result is a non-interactive form: a static
representation of the fields that looks the same everywhere, even in a reader
without form support (ISO 32000-2 §12.7). The recipe builds the form from
examples/30-form-fields.php, then calls flattenForms().
Install
Section titled “Install”composer require nextpdf/core:^3Conceptual overview
Section titled “Conceptual overview”Flattening “prints” each widget onto its page. Text fields become
BT … Tj … ET text. Checkboxes and radio buttons become drawn paths. Choice
fields render their selected item. Push buttons render as a static button-like
box. This matches the spec model for a statically defined appearance when the
field contents are known in advance (ISO 32000-2 §12.7). Because NextPDF bakes
the values into the page, the deprecated NeedAppearances mechanism is not
needed.
The profile is structural. The document carries a trailer /ID, which the
post-pass normalises before it compares two runs.
API surface
Section titled “API surface”NextPDF\Core\Concerns\HasFormFields::flattenForms(): static flattens every
field created on the document into static page content and drops the AcroForm.
When no fields are present, it does nothing. Internally, it delegates the work
to NextPDF\Form\FormFlattener.
Build the form with the field constructors. For detailed steps, see
Build and pre-fill a PDF form. Then call
flattenForms() before save().
Code sample — Quick start
Section titled “Code sample — Quick start”<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Flattened Form');$doc->addPage();
$doc->textField(name: 'full_name', x: 20, y: 30, w: 90, h: 8, default: 'Ada Lovelace');$doc->checkBox(name: 'agree', x: 20, y: 45, size: 5, checked: true);
// Bake the field values into the page; the AcroForm is removed.$doc->flattenForms();
$doc->save(__DIR__ . '/flattened.pdf');echo "Wrote flattened.pdf (no interactive fields)\n";Code sample — Production
Section titled “Code sample — Production”The full example below builds the multi-section form from
examples/30-form-fields.php. It pre-fills the form, flattens it, and writes
to NEXTPDF_COOKBOOK_OUTPUT for the harness.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Customer Registration — Flattened');$doc->addPage();
$doc->setFont('helvetica', 'B', 20);$doc->cell(0, 14, 'Customer Registration (read-only copy)', newLine: true);$doc->ln(4);
$leftMargin = 15.0;$fieldX = 70.0;$fieldW = 120.0;$fieldH = 8.0;$rowSpacing = 12.0;
$prefill = [ 'full_name' => 'Ada Lovelace', 'phone' => '+44 20 7946 0000', 'company' => 'Analytical Engines Ltd',];
$y = 40.0;$doc->setFont('helvetica', '', 10);foreach ($prefill as $name => $value) { $doc->setXY($leftMargin, $y); $doc->cell(50, $fieldH, ucwords(str_replace('_', ' ', $name)) . ':'); $doc->textField(name: $name, x: $fieldX, y: $y, w: $fieldW, h: $fieldH, default: $value); $y += $rowSpacing;}
$y += 6;$doc->setXY($leftMargin, $y);$doc->cell(0, 7, 'Newsletter');$doc->checkBox(name: 'newsletter', x: $leftMargin + 70, y: $y, size: 5, checked: true);
// Flatten: widgets become static page content; the AcroForm is dropped.$doc->flattenForms();
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');$doc->save($out !== false ? $out : __DIR__ . '/registration-flattened.pdf');
echo "Wrote flattened registration form\n";Expected output:
Wrote flattened registration formThe output shows the same values, with no interactive fields. A reader without form support renders it the same way.
Edge cases & gotchas
Section titled “Edge cases & gotchas”- Flattening is irreversible. Once you call
save(), the interactive fields are gone. Keep the un-flattened source if you might need to edit the values later. - Call order. Run
flattenForms()after you create the fields and beforesave(). Calling it with no fields does nothing, which is safe. - Signature fields are not flattened. A
/Sigfield’s visual surface is the appearance produced from its Cryptographic Message Syntax (CMS) SignedData, not a re-renderable value. Re-rasterising it would create a static “ghost” graphic that no longer matches any verifiable signature. For that reason, the flattener skips signature fields on purpose. Flatten the form before you sign, never after. - Checkbox truthiness. A checkbox renders its checkmark when its value is
Yes/On/1/true. An empty orOffvalue renders the box only. - Font for flattened text. Flattened text uses the current font. With no
font set, it falls back to Helvetica. For Chinese, Japanese, and Korean
(CJK) or custom-font field values, set the font you want before
flattenForms().
Performance
Section titled “Performance”Flattening scales linearly with the field count. For each field, NextPDF appends a bounded content block, then removes the AcroForm object. Typical forms stay well inside the 1500 ms / 64 MB budget.
Security notes
Section titled “Security notes”Flattening makes field values non-editable in normal readers. This is a presentation change, not access control. The values stay visible in the page content, and any text tool can extract them. Do not treat flattening as redaction or as protection for sensitive values. For confidentiality, use Encrypt with permissions. Read the reader-cooperative caveat there too, because permission bits do not enforce read restrictions either. Never flatten a signed document. Flatten first, then sign.
Conformance
Section titled “Conformance”| Statement | Spec | Clause | reference_id |
|---|---|---|---|
| A flattened form is a non-interactive (static) representation of the fields. | ISO 32000-2 | §12.7 | |
| Field appearance is statically defined when its contents are known in advance. | ISO 32000-2 | §12.7 | |
Baked-in appearances make the deprecated NeedAppearances flag unnecessary. | ISO 32000-2 | §12.7 |
NextPDF produces the static structure described by the cited clauses. It does not claim blanket ISO 32000-2 conformance.