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_valueis the single writeback chain for the whole SDK. One call keeps/V, per-widget/AS, and regenerated/APstreams consistent, working in every viewer without/NeedAppearances. - Inspect the complete form model: one
FormFieldModelper 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 Arc;
use Document;
use ;
// --- Read the form model ---
let pdf = new.unwrap;
let tree = parse_acroform.expect;
for field in build_form_model
// --- Fill a field ---
let mut doc = load?;
apply_field_value?;
apply_field_value?;
apply_field_value?;
doc.save?;
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
FormFieldModel
Known Limitations
- Non-WinAnsi values (Cyrillic, CJK):
/Vis always lossless via UTF-16BE; appearance generation falls back to/NeedAppearances true. The SDK renderer does not honour/NeedAppearances— callregenerate_appearancesafter opening such documents for correct rendering. - DA fonts outside Standard-14: the nearest standard face is substituted in
generated appearances (Helvetica unless
/DAnames 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
- Main crate: https://crates.io/crates/pdfluent
- Documentation: https://pdfluent.com/docs
- Trial: https://pdfluent.com/trial
- Pricing: https://pdfluent.com/pricing
- Changelog: CHANGELOG.md