Skip to content

feat(pdf): paint annotation appearance streams - #704

Merged
andiwand merged 1 commit into
mainfrom
feat/pdf-annotation-appearance
Aug 18, 2026
Merged

feat(pdf): paint annotation appearance streams#704
andiwand merged 1 commit into
mainfrom
feat/pdf-annotation-appearance

Conversation

@andiwand

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

Stacked on #703.

A filled form rendered as empty boxes. What a form field displays is its widget
annotation's appearance stream, and annotations only ever reached the HTML
layer as raw dictionaries, for links — nothing painted them.

How

The parser resolves /AP /N into a form XObject, following /AS when /N is
a dictionary of states (a check box's /Off and /Yes), and stores it on the
Annotation along with the matrix that fits its /Matrix-transformed /BBox
onto the annotation's /Rect — 12.5.5's algorithm. extract_annotation then
runs that form the way Do runs any other: fit matrix, the form's own
/Matrix, the /BBox clip. So an appearance yields ordinary page elements,
painted after the page content, and the text one draws is selectable like any
other text.

Not painted: annotations flagged Hidden or NoView (/F), and popups, whose
appearance shows only while the viewer has them open. AcroForm interactivity
stays out of scope — the appearance is whatever the writer left in the file,
never regenerated from /V and /DA.

Test

  • Three unit tests over the placement: the fit onto /Rect, the form
    /Matrix concatenating onto it, and an annotation with nothing to paint.
  • Full suite green. Two reference-output files change and both now match a
    ghostscript render of the same file: phd-agreement.pdf shows every filled
    value and the selected radio button, VZA_Ankauf_Kunde.pdf its filled values
    and its /Square markup.

Note

/Rect corners are routinely indirect, and one deep_resolve reaches only the
array — its elements stay references, which as_reals cannot read. The rect is
resolved element by element instead. That is why VZA_Ankauf_Kunde.pdf threw
bad any cast the moment annotations started being parsed.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3fced5cd8d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/odr/internal/pdf/pdf_page_extractor.cpp
Comment thread src/odr/internal/pdf/pdf_page_extractor.cpp
@andiwand
andiwand force-pushed the feat/pdf-annotation-appearance branch from 3fced5c to 91fc12e Compare August 18, 2026 18:12
@andiwand
andiwand force-pushed the feat/pdf-annotation-appearance branch from 91fc12e to e02e4dc Compare August 18, 2026 18:14
@andiwand
andiwand force-pushed the feat/pdf-jbig2 branch 2 times, most recently from da4b56a to 02e476f Compare August 18, 2026 18:23
Base automatically changed from feat/pdf-jbig2 to main August 18, 2026 18:24
A filled form showed its empty boxes and none of its values: what a field
displays is its widget annotation's appearance stream, and annotations only
ever reached the HTML layer as raw dictionaries, for links.

The parser now resolves `/AP /N` — through `/AS` when it is a dictionary of
states — into a form XObject, along with the matrix fitting its
`/Matrix`-transformed `/BBox` onto `/Rect` (12.5.5). `extract_annotation` runs
that form like a `Do`, so an appearance yields ordinary page elements, painted
after the page content and selectable where it draws text.

Hidden and NoView annotations (`/F`) paint nothing, and neither do popups,
whose appearance shows only while the viewer has them open. AcroForm
interactivity stays out of scope: the appearance is what the writer left in the
file, never regenerated from `/V` and `/DA`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014VsAxi7RXU1TNQVz8EM7VJ
@andiwand
andiwand force-pushed the feat/pdf-annotation-appearance branch from e02e4dc to 87fbee8 Compare August 18, 2026 18:27
@andiwand
andiwand merged commit 10fe276 into main Aug 18, 2026
25 checks passed
@andiwand
andiwand deleted the feat/pdf-annotation-appearance branch August 18, 2026 18:31
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