Guide

Form Flattening

Flatten AcroForm fields into static page content

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