Skip to content

Embedpdf/feature/forms - #31

Merged
bobsingor merged 13 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/forms
Jul 20, 2026
Merged

Embedpdf/feature/forms#31
bobsingor merged 13 commits into
embedpdf/feature/read-purityfrom
embedpdf/feature/forms

Conversation

@bobsingor

Copy link
Copy Markdown
Contributor

No description provided.

bobsingor added 13 commits June 24, 2026 13:51
Introduce runtime-registered font support and per-annotation font subsetting for FreeText appearance generation. Adds CPDF_AnnotFontMap and CPDF_AnnotFontSubset to route fallback lookups to CFX_FontRegistry, create marker font entries in the AcroForm DR, and produce subsetted Type0/CIDFont dictionaries (using HarfBuzz) that embed only glyphs used by an annotation/layer. Update CPDF_Font::FallbackFontFromCharcode to prefer registered fonts and create runtime fallbacks, and switch FreeText AP generation to use CPDF_AnnotFontMap so resources include any registered fallback/subset fonts actually used. Expose UpdateDefaultAppearanceRegisteredFont to set a DA referencing a registered runtime font. Update BUILD.gn to include the new files and third_party/harfbuzz-ng, and add supporting CFX_FontRegistry and public/epdf_font glue.
Persist registered-font identity in marker font dictionaries and make font registry behavior robust.

- Store registered font id in marker font dict (key "EmbedPDFRegisteredFontId") and add CPDF_AnnotFontSubset::GetRegisteredFontIdFromMarkerFontDict to read it. CPDF_AnnotFontMap now checks the marker dict for identity instead of inferring from BaseFont/resource alias.
- Create marker font dicts with the new id field; make subset base-name comment deterministic.
- Prevent CFX_FontRegistry::ClearRegisteredFonts from resetting next_font_id to avoid reusing ids that may still be referenced by existing document markers.
- Update CPVT_FontMap unicode/charcode logic to use CharCodeFromUnicode checks and safe numeric conversions; preserve upstream appearance font selection behavior.
- Add/adjust tests and helpers in fpdfsdk to validate stable appearance streams, alias-suffix survival, fallback rendering, checksums, and related utilities.
- Update public API docs for font registration to clarify thread/ownership rules and ClearRegisteredFonts semantics.

Also includes small cleanup/refactors and added includes needed by new code and tests.
Prefer registered-font mapping when generating appearance streams for persistent form widgets: if the target is persistent and there are registered fallback fonts or the font dict indicates a registered subset, create a CPDF_AnnotFontMap with registered fallbacks and embed the corresponding Font resources. Refactor duplicated AP generation into a lambda to reduce code duplication and preserve the previous CPVT_FontMap path for non-registered cases. Add CFX_FontRegistry::HasFallbackFonts() and its declaration. Add tests and a DroidSansFallbackFull.ttf test font, plus helpers to register and assert registered fallback behaviour for FreeText, TextField, ComboBox, and ListBox Korean glyphs. Also include small test fixes (initializer_list include, wchar_t usage).
Introduce a session-free EPDF form snapshot API and related utilities to support EmbedPDF use-cases. Adds a large new implementation (fpdfsdk/epdf_form.cpp) and public/epdf_form.h plus embedder tests and test PDF resources. Extend CPDF_InteractiveForm with ResolveCurrentDict and ReconcileWidget to rebind dictionaries to a document's current view and recover widgets reachable from page /Annots but missing from /AcroForm /Fields. Make ExportToFDF honor a skip_empty_required flag to preserve historic omit-empty-required behavior. Add whitespace-exact XML serialization APIs (CFX_XMLNode::SaveCompact and CFX_XMLElement::SaveCompact) to avoid corrupting xml:space="preserve" payloads, and unconditionally include CFX_MemoryStream in the build. Numerous helper routines implement form snapshotting, write transactions (toggles, text, choice), FDF/XFDF import/export, and layer-correctness rules. Update BUILD.gn files to expose new sources and tests. Tests/resources for recovered/orphan widgets and toggle fields are added.
Introduce EmbedPDF PieceInfo support: add public header and full implementation for namespace-scoped document/page PieceInfo metadata (typed values, last-modified timestamps, arrays, clear operations, and page/document variants). Add embedder tests covering save/reload and layer/delta flows. Update BUILD.gn and fpdfsdk/BUILD.gn to expose the new header and include the new sources, and switch component("pdfium") to shared_library("pdfium") while adding resources.rc to its sources.
Introduce EmbedPDF APIs and implementations: adds detached, read-only action model (epdf_action.* + helpers + public/epdf_action.h) with embedder tests; implements layer-safe selective annotation/page flattening (epdf_flatten.cpp) and test resources. Plumbing and API changes: expose CPDF_AnnotContext::GetAnnotIndex(), add CPDF_GenerateAP::GenerateFormAPWithValueOverride and thread value_override through AP generation to allow regenerating widget appearances without changing /V, and adjust CPDF_GenerateAP::GenerateFormAP calls. Fix CPDF_InteractiveForm export logic for skip_empty_required to correctly treat missing/null/array values. Update BUILD.gn entries and public headers to export new APIs and add fpdfsdk build sources and tests. Adds test PDFs/resources for flattening.
Compute the true painted bounds of /InkList by accumulating all ink points into an ink_bounds rectangle and inflating it by half the border width. Only expand the annotation /Rect when the painted bounds would otherwise be clipped, and only then persist the change for persistent targets. This prevents unconditional inflation of /Rect on every regeneration (which could cause unbounded growth) and makes appearance updates idempotent.
Add EmbedPDF attachment extraction APIs and file-attachment appearance generation. Implement EPDFDoc_GetAttachmentKey and EPDFDoc_GetAttachmentIndexByKey, the EPDFAttachmentExtractStatus enum, EPDFAttachment_ExtractFile and EPDFAttachment_ExtractFileToOwnedBuffer, and wire them into the public header. Introduce a streaming inflate helper FlateModule::FlateDecodeToSink (and its SinkDecodeStatus) to decode large/Flate-compressed embedded files without materializing the full output; add corresponding unit tests. Implement ExtractAttachmentFileToSink and supporting logic in fpdfsdk/fpdf_attachment.cpp (filter classification, sink-based and in-memory paths, size capping and error mapping). Add GenerateFileAttachmentSymbolAP/GenerateFileAttachmentAP and rotation/float-handling fixes in cpdf_generateap.cpp so file-attachment icons render correctly. Update API test checks and add extensive embedder tests for the new extraction APIs. Misc: include and build fixes and small helper utilities.
Expose a way to resolve a destination to its page dictionary object number. Implements CPDF_Dest::GetPageObjectNumber (handles numeric page indexes and page dictionary references, validates page visibility and XFA/extension cases) and exports EPDFDest_GetPageObjectNumber in the public API. Adds unit tests covering numeric and dictionary destinations and invalid references, updates headers and includes, and makes minor formatting/whitespace fixes in the C API test harness.
Retain action dictionaries on ActionNodeRecord so node payloads can be read on demand. Implement EPDFAction_GetNodeDest, EPDFAction_GetNodeURI, EPDFAction_GetNodeFilePath and EPDFAction_GetNodeName (with header docs) to expose goto/URI/file/name payloads; these getters consult the retained dictionary and may require the originating FPDF_DOCUMENT for name resolution. Update AppendAction to keep the dictionary alive. Make EPDFAnnot_SetAction remove any direct /Dest (ISO 32000-1 compliance) and add EPDFAnnot_RemoveAction and EPDFAnnot_RemoveDest with a shared RemoveLinkDictEntry helper. Add unit tests covering URI, destination, file path and named-action payloads and a missing include required by the tests.
Avoid resource-pruning bugs when content streams are appended by tracking whether this pass regenerated every existing content stream (CPDF_PageContentGenerator: CountExistingContentStreams + UpdateResourcesDict(regenerated_all_streams)).

Rewrite redaction appearance generation to synthesize/flatten a final overlay form when no /RO is present: add helpers to get redact regions/BBox, build Form XObjects (MakeRedactFormStream / BuildRedactOverlayForm), layout overlay text with /DA and /Repeat, and emit overlay ops (AppendRedactOverlayOps). Update GenerateRedactAP to use the new overlay form and commonize resources.

Simplify the public redaction APIs and internal reporting: remove the complex removed-annotation report buffers and replace them with an optional out_removed_annot_count that returns the number of non-REDACT annotations removed as a side-effect. Ensure pages are parsed before applying redactions and resolve overlays (pre-baked /RO wins, otherwise synthesize). Update public header signatures accordingly and add a test PDF (testing/resources/redact_inherited_colorspace.pdf) for inherited colorspace cases.

Misc: minor include cleanups and refactors.
Allow appearance generation for non-persistent targets by creating an ephemeral AcroForm view instead of failing when the document lacks /AcroForm. Relax DR (/DR) handling so a missing or font-less /DR does not veto generation: persistent targets seed or mutate the document's DR/Font to add a fallback, while ephemeral targets use a direct fallback font dict without mutating the doc.

Introduce a reconciled form view and related helpers in epdf_form.cpp: BuildReconciledForm, FinishTxnControl, CollectRawTxnControls, ReconciledFieldByObjNum, CollectReconciledTxnControls and an overload of CollectTxnControls that accepts an optional reconciled CPDF_InteractiveForm. Transactional control collection now prefers the reconciled (merged) widget set and falls back to the raw /Kids walk when needed. Update callers to accept and pass the reconciled view where appropriate (including using a fresh reconciled form during repair/bake steps). These changes improve correctness for multi-plane documents (e.g. recovered fields, twin widgets) and avoid unnecessary document mutation for ephemeral operations.
Add MirrorFieldValueToTwinControls to copy /V, /I and /RV from a promoted field to same-FQN twin control dictionaries (same-name twins living in their own plane) and call it from ApplyTextValue, ApplyChoiceValues and EPDFForm_ResetField so appearance generation sees the value. Update form/embedder tests by adding a two_plane_form.pdf fixture and a TwoPlaneTwinWidgetsFillTogether test that verifies toggles, text commits, and /DR seeding cover both twins. Adjust annotation appearance-related expectations (rect/BBox inflation) and refactor many fpdfsdk tests: rename MemoryFontFileAccess->MemoryFileAccess, replace detailed redaction-report helpers with simpler removed-count helpers, add bitmap/render helpers and numerous redaction overlay tests, and modernize action/form test usage (ScopedPage, null-model handling, widget creation via annot+field attach). Also tweak DestGetPageObjectNumber behavior for out-of-range legacy Dests and various minor test cleanups.
@bobsingor
bobsingor merged commit a39fb54 into embedpdf/feature/read-purity Jul 20, 2026
@bobsingor
bobsingor deleted the embedpdf/feature/forms branch August 5, 2026 11:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant