Form Flattening

Overview

Since v1.0.4

gpdf can flatten interactive AcroForm fields (text fields, checkboxes, radio buttons, etc.) into static page content. After flattening, the form fields are no longer editable — their visual appearance is baked into the page.

Common use cases:

  • Archiving filled forms as static documents
  • Preventing further edits to submitted forms
  • Preparing forms for printing or distribution
  • Converting interactive PDFs to static PDFs

Basic Flattening

Use FlattenForms() on an existing document opened with gpdf.Open():

import gpdf "github.com/gpdf-dev/gpdf"

// Read a PDF with filled form fields
pdfBytes, _ := os.ReadFile("filled-form.pdf")

doc, err := gpdf.Open(pdfBytes)
if err != nil {
    log.Fatal(err)
}

// Flatten all form fields into static content
if err := doc.FlattenForms(); err != nil {
    log.Fatal(err)
}

result, _ := doc.Save()
os.WriteFile("flattened.pdf", result, 0644)

What Gets Flattened

FlattenForms() processes all widget annotations (form field widgets) that have appearance streams:

  • Text fields (Tx) — the entered text is rendered as static content
  • Checkboxes and radio buttons (Btn) — the selected state is rendered
  • Other widget types — any widget with an appearance stream (/AP dictionary)

What Gets Preserved

Non-widget annotations are not removed:

  • Link annotations (hyperlinks)
  • Text annotations (comments, sticky notes)
  • Other non-form annotations

Safe to Call on Any PDF

If the PDF has no AcroForm fields, FlattenForms() is a no-op and returns nil:

doc, _ := gpdf.Open(regularPDFBytes)

// Safe — does nothing if no forms exist
if err := doc.FlattenForms(); err != nil {
    log.Fatal(err)
}

result, _ := doc.Save()

Flatten + Overlay

Combine flattening with overlay to add stamps or watermarks after flattening:

doc, _ := gpdf.Open(filledFormPDF)

// Step 1: Flatten form fields
doc.FlattenForms()

// Step 2: Add a "PROCESSED" stamp
doc.Overlay(0, func(p *template.PageBuilder) {
    p.Absolute(document.Mm(130), document.Mm(15), func(c *template.ColBuilder) {
        c.Text("PROCESSED",
            template.FontSize(24),
            template.Bold(),
            template.TextColor(pdf.RGB(0, 0.5, 0)),
        )
    })
})

result, _ := doc.Save()

API Reference

MethodDescription
doc.FlattenForms()Flatten all AcroForm fields into static page content

Next Steps