pdfluent-forms 1.0.0-beta.17

AcroForm engine for PDF interactive forms.
Documentation

pdfluent-forms

AcroForm engine for PDF interactive forms — parse, fill, inspect, and export form data. Powers the form layer of the PDFluent Rust SDK and all language bindings.

Free for evaluation. Production use requires a valid license.

What it does

  • Parse any ISO 32000 AcroForm into a typed field tree — text, checkbox, radio, combo/list, push-button, and signature fields; hierarchical names (parent.kid); inherited flags and attributes.
  • Fill fields reliably: apply_field_value is the single writeback chain for the whole SDK. One call keeps /V, per-widget /AS, and regenerated /AP streams consistent, working in every viewer without /NeedAppearances.
  • Inspect the complete form model: one FormFieldModel per logical field with per-page widget rectangles, typed kind, on-state names, choice options, comb/multiline/password flags, access flags, and resolved font info.
  • Regenerate appearances for documents filled by other tools that only wrote /V (e.g. with /NeedAppearances true).

Quick Start

use std::sync::Arc;
use lopdf::Document;
use pdfluent_forms::{
    apply_field_value, build_form_model, parse_acroform, WriteValue,
};

// --- Read the form model ---
let pdf = pdf_syntax::Pdf::new(Arc::new(std::fs::read("form.pdf")?)).unwrap();
let tree = parse_acroform(&pdf).expect("no AcroForm");

for field in build_form_model(&tree) {
    println!("[{:?}] {} = {:?}", field.kind, field.name, field.value);
}

// --- Fill a field ---
let mut doc = Document::load("form.pdf")?;
apply_field_value(&mut doc, "Name", WriteValue::Text("Jane Doe"))?;
apply_field_value(&mut doc, "Agree", WriteValue::Checkbox(true))?;
apply_field_value(&mut doc, "Country", WriteValue::Radio("NL"))?;
doc.save("form-filled.pdf")?;

Writeback Guarantees

apply_field_value maintains the following invariants, mirroring the convergent behaviour of pdfium, mupdf, and pdf.js:

Property Guarantee
/V encoding ASCII → PDF literal string; non-ASCII → UTF-16BE+BOM whole string
Button /V Byte-exact /Name object; WinAnsi re-encoding fallback for Latin-1 on-state names
/AS consistency Set per widget to the on-state iff that name is a key of the widget's own /AP /N; else /Off (mupdf set_check_grp rule)
/AP /N Regenerated as a self-contained Form XObject: /Tx BMC … EMC, WinAnsiEncoding show-text bytes, embedded Standard-14 AFM widths, comb/multiline/quadding support, ~2 pt inset
Font resources Self-contained /Resources with explicit WinAnsiEncoding — never references /DR fonts (which carry PDFDocEncoding Differences that remap characters)
/NeedAppearances Set true only for non-WinAnsi values (Cyrillic, CJK, …); stale /AP removed in that case
Read-only Rejected at set-time (WritebackError::ReadOnly) — the SDK has no UI layer, so this is the only enforceable point
Inline /AcroForm Promoted to an indirect object before mutation (92% of real-world corpora use inline /AcroForm)
Hierarchical names Resolved through /Kids recursion, not top-level-only

API Reference

Entry points

Function Description
parse_acroform(pdf) Parse an AcroForm from a pdf_syntax::Pdf; None if absent
build_form_model(tree) Build Vec<FormFieldModel> from a parsed FieldTree
apply_field_value(doc, name, value) Fill one field in a lopdf::Document
apply_choice_multi(doc, name, &[String]) Fill a multi-select list box: /V array + rebuilt sorted /I index cache
regenerate_appearances(doc) Regenerate all appearance streams in a lopdf::Document

Key types

Type Description
FieldTree Arena-based tree mirroring the AcroForm parent/child hierarchy
FieldNode A single field or group (partial name, type, value, flags, …)
FieldId Opaque index into the FieldTree arena
FieldType Text / Button / Choice / Signature
FieldValue Text string or array of selected strings
FieldFlags Bit-field from /Ff — read-only, required, multiline, comb, …
FormFieldModel Complete editor-facing model for one logical field
FormFieldKind Typed variant: Text, Checkbox, RadioGroup, ComboBox, ListBox, PushButton, Signature
WidgetModel One widget annotation: page index, rect, on-state, /AS
DaInfo Resolved /DA: font name, size, color
WriteValue Text(&str) / Checkbox(bool) / Radio(&str) / Choice(&str)
WriteOutcome How many appearances were generated, whether fallback was used
WritebackError FieldNotFound / ReadOnly / WrongType / InvalidOption / Malformed

FormFieldKind variants

pub enum FormFieldKind {
    Text { multiline: bool, comb: bool, password: bool },
    Checkbox { on_state: String, checked: bool },
    RadioGroup { options: Vec<String> },     // one entry per widget
    ComboBox  { editable: bool, options: Vec<ChoiceOption> },
    ListBox   { multi_select: bool, options: Vec<ChoiceOption> },
    PushButton,
    Signature,
}

FormFieldModel

pub struct FormFieldModel {
    pub name:          String,               // fully qualified ("parent.kid")
    pub kind:          FormFieldKind,
    pub value:         Option<String>,       // current /V
    pub default_value: Option<String>,       // /DV
    pub tooltip:       Option<String>,       // /TU
    pub read_only:     bool,
    pub required:      bool,
    pub max_len:       Option<u32>,          // /MaxLen (text fields)
    pub quadding:      Quadding,             // /Q: Left/Center/Right
    pub da:            Option<DaInfo>,       // resolved /DA
    pub widgets:       Vec<WidgetModel>,     // one per visual occurrence
}

Known Limitations

  • Non-WinAnsi values (Cyrillic, CJK): /V is always lossless via UTF-16BE; appearance generation falls back to /NeedAppearances true. The SDK renderer does not honour /NeedAppearances — call regenerate_appearances after opening such documents for correct rendering.
  • DA fonts outside Standard-14: the nearest standard face is substituted in generated appearances (Helvetica unless /DA names a Times/Courier variant).
  • Widget rotation (/MK /R): not yet applied in generated appearances.

Licensing

  • Free for evaluation, development, and testing
  • Production use requires a valid PDFluent commercial license
  • Redistribution requires the OEM Redistribution add-on

See LICENSE for full terms, or visit https://pdfluent.com/terms.

Links