diff --git a/crates/xfa/README.md b/crates/xfa/README.md index 2d08a74bb2..c48058385e 100644 --- a/crates/xfa/README.md +++ b/crates/xfa/README.md @@ -27,6 +27,18 @@ that warning and keeps the existing layout and accepted widget values. text-field limits (`text/maxChars` and `exData/maxLength`, carried into AcroForm `/MaxLen`), inline JPEG, PNG and GIF images, lines, rectangles, occurrences, `breakBefore`/`breakAfter`, overflow leaders, `columnWidths` and `colSpan`. +- **Prototypes** (`proto`, XFA 3.3 chapter 6, "Prototypes"): before parsing, every `use` and + `usehref` reference into the same template is resolved and the template is written again + with it merged in, so Designer style sheets (`usehref=".#som($template.#subform.styles.X)"`) + give their fields and draws size, anchor, borders, fills, fonts and captions. The element's + own attributes, content and children win; `id` and `name` are not inherited; children match + by class and position, a matched prototype child being the prototype of the element's own; + a `ui` widget or `value` kind and rich text are taken from the nearest layer that has one. + References are `#id`, `#som(…)` (or `.#…`) and, for `use`, a SOM expression. Loops are cut + where they close, chains merge at most 32 layers, nesting stops at 256 elements, SOM look-ups + share a budget of 2 million elements, and the written template may grow to 4 times its size + (at least 1 MB, at most 64 MB); past a budget the template is read unresolved. Each case is a + warning. - **Layout** (`layout`): positioned, `tb`, `lr-tb`/`rl-tb`, `table` and `row` layouts; a container without a width is as wide as its content; flow across content areas and pages with page masters chosen by occurrence; a table's header row repeats after a break; presence @@ -159,6 +171,11 @@ let form = pdfcraft_xfa::layout_xml(template_xml)?; // pages of items, for file's data is held as a tree and written with the packet's own namespace prefix, never as the file's markup, and every rewrite of the packet is parsed back before it is written; the engine then lays a dynamic form out again from it and runs its calculations. +- **Prototypes in other documents** (`usehref="file.xdp#…"`) are not followed: that would + mean reading files or the network on opening a form. The reference is left out with a + warning. SOM references cover names, `#class` and `[n]`, not `[*]`, `..` or relative forms; + traversal declarations are merged like other children, not knitted together as "Resolving + Prototypes with Traversals" describes. - Missing: `keep` constraints, `subformSet` relations, `rl-tb` is mirrored `lr-tb`, font metrics are the approximate Helvetica ones, and line heights are 1.15 × size. - Acrobat cannot be an oracle here (clean-room rules): layout follows the specification, and diff --git a/crates/xfa/src/lib.rs b/crates/xfa/src/lib.rs index 7e63218c90..07b75a2042 100644 --- a/crates/xfa/src/lib.rs +++ b/crates/xfa/src/lib.rs @@ -16,6 +16,7 @@ pub mod packets; pub mod parse; pub mod pdf; pub mod picture; +mod proto; pub mod script; pub mod text; diff --git a/crates/xfa/src/parse.rs b/crates/xfa/src/parse.rs index 838d1730ea..b6526eb955 100644 --- a/crates/xfa/src/parse.rs +++ b/crates/xfa/src/parse.rs @@ -740,7 +740,21 @@ pub fn parse(xml: &str) -> Result<(Template, Vec), XfaError> { } else { root.descendants().find(is_template).ok_or_else(|| XfaError::Malformed("no