pub struct Form {
pub fields: Vec<Field>,
pub need_appearances: bool,
}Expand description
Every terminal field of a document’s interactive form.
Loaded once from the catalog; the walk is the expensive part and nothing below repeats it.
Fields§
§fields: Vec<Field>The terminal fields, in the order the /Fields tree reaches them.
need_appearances: boolWhether the form asks a reader to regenerate every widget’s appearance
(/NeedAppearances).
Implementations§
Source§impl Form
impl Form
Sourcepub fn load<R: Resolve>(
catalog: &Dict,
r: &R,
limits: &Limits,
diags: &mut Diagnostics,
) -> Option<Form>
pub fn load<R: Resolve>( catalog: &Dict, r: &R, limits: &Limits, diags: &mut Diagnostics, ) -> Option<Form>
Loads the document’s form, or nothing when the catalog declares none.
A catalog with an /AcroForm whose /Fields is absent or empty still
yields a Form — an empty form is a different thing from no form, and
only the second means “this document is not interactive”.
use pdfrum_common::{Diagnostics, Limits};
use pdfrum_doc::form::Form;
use pdfrum_object::{Array, Dict, Name, NoResolve, Object, PdfString};
let field = Dict::from_pairs([
(Name::from("FT"), Object::Name(Name::from("Tx"))),
(Name::from("T"), Object::Str(PdfString::literal(b"name"))),
(Name::from("V"), Object::Str(PdfString::literal(b"Ada"))),
]);
let catalog = Dict::from_pairs([(
Name::from("AcroForm"),
Object::Dict(Dict::from_pairs([(
Name::from("Fields"),
Object::Array(Array::of([Object::Dict(field)])),
)])),
)]);
let mut diags = Diagnostics::default();
let form = Form::load(&catalog, &NoResolve, &Limits::default(), &mut diags)
.expect("the catalog declares an /AcroForm");
assert_eq!(form.len(), 1);
assert_eq!(form.fields[0].name, "name");Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
How many terminal fields the form has.
use pdfrum_common::{Diagnostics, Limits};
use pdfrum_doc::form::Form;
use pdfrum_object::{Array, Dict, Name, NoResolve, Object, PdfString};
let field = Dict::from_pairs([
(Name::from("FT"), Object::Name(Name::from("Tx"))),
(Name::from("T"), Object::Str(PdfString::literal(b"name"))),
]);
let catalog = Dict::from_pairs([(
Name::from("AcroForm"),
Object::Dict(Dict::from_pairs([(
Name::from("Fields"),
Object::Array(Array::of([Object::Dict(field)])),
)])),
)]);
let mut diags = Diagnostics::default();
let form = Form::load(&catalog, &NoResolve, &Limits::default(), &mut diags)
.expect("the catalog declares an /AcroForm");
assert_eq!(form.len(), 1);Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Whether the form has no fields at all.
use pdfrum_common::{Diagnostics, Limits};
use pdfrum_doc::form::Form;
use pdfrum_object::{Array, Dict, Name, NoResolve, Object, PdfString};
let field = Dict::from_pairs([
(Name::from("FT"), Object::Name(Name::from("Tx"))),
(Name::from("T"), Object::Str(PdfString::literal(b"name"))),
]);
let catalog = Dict::from_pairs([(
Name::from("AcroForm"),
Object::Dict(Dict::from_pairs([(
Name::from("Fields"),
Object::Array(Array::of([Object::Dict(field)])),
)])),
)]);
let mut diags = Diagnostics::default();
let form = Form::load(&catalog, &NoResolve, &Limits::default(), &mut diags)
.expect("the catalog declares an /AcroForm");
assert!(!form.is_empty());Sourcepub fn field(&self, name: &str) -> Option<&Field>
pub fn field(&self, name: &str) -> Option<&Field>
The field with this fully-qualified name.
use pdfrum_common::{Diagnostics, Limits};
use pdfrum_doc::form::Form;
use pdfrum_object::{Array, Dict, Name, NoResolve, Object, PdfString};
let field = Dict::from_pairs([
(Name::from("FT"), Object::Name(Name::from("Tx"))),
(Name::from("T"), Object::Str(PdfString::literal(b"name"))),
(Name::from("V"), Object::Str(PdfString::literal(b"Ada"))),
]);
let catalog = Dict::from_pairs([(
Name::from("AcroForm"),
Object::Dict(Dict::from_pairs([(
Name::from("Fields"),
Object::Array(Array::of([Object::Dict(field)])),
)])),
)]);
let mut diags = Diagnostics::default();
let form = Form::load(&catalog, &NoResolve, &Limits::default(), &mut diags)
.expect("the catalog declares an /AcroForm");
assert!(form.field("name").is_some());
assert!(form.field("absent").is_none());Sourcepub fn calculation_order<R: Resolve>(&self, catalog: &Dict, r: &R) -> Vec<usize>
pub fn calculation_order<R: Resolve>(&self, catalog: &Dict, r: &R) -> Vec<usize>
The order a recalculation visits fields in, read from /AcroForm /CO.
Indices into Form::fields, in the order the array lists them.
§An absent /CO is the answer, not a fallback
A document with no /CO array recalculates nothing, however many
of its fields carry an /AA /C script: the sweep that drives
calculation walks exactly this list and nothing else. So an empty
answer here is “no calculation runs”, and a reader tempted to fall
back to “every field, in /Fields order” would recalculate documents
that must be left alone — visibly, on any file with a calculation
script and no /CO.
Entries that resolve to nothing, to a non-dictionary, or to a dictionary that is not one of this form’s terminal fields are dropped. Duplicates are kept: the array is the order, and it is indexed positionally.
use pdfrum_common::{Diagnostics, Limits};
use pdfrum_doc::form::Form;
use pdfrum_object::{Array, Dict, Name, NoResolve, Object, PdfString};
let field = Dict::from_pairs([
(Name::from("FT"), Object::Name(Name::from("Tx"))),
(Name::from("T"), Object::Str(PdfString::literal(b"name"))),
(Name::from("V"), Object::Str(PdfString::literal(b"Ada"))),
]);
let catalog = Dict::from_pairs([(
Name::from("AcroForm"),
Object::Dict(Dict::from_pairs([(
Name::from("Fields"),
Object::Array(Array::of([Object::Dict(field)])),
)])),
)]);
let mut diags = Diagnostics::default();
let form = Form::load(&catalog, &NoResolve, &Limits::default(), &mut diags)
.expect("the catalog declares an /AcroForm");
// No `/CO`: nothing recalculates. That is the answer, not a fallback.
assert!(form.calculation_order(&catalog, &NoResolve).is_empty());