feat(pdf): paint annotation appearance streams - #704
Merged
Conversation
There was a problem hiding this comment.
💡 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".
andiwand
force-pushed
the
feat/pdf-jbig2
branch
from
August 18, 2026 18:09
b64b1de to
81191cc
Compare
andiwand
force-pushed
the
feat/pdf-annotation-appearance
branch
from
August 18, 2026 18:12
3fced5c to
91fc12e
Compare
andiwand
force-pushed
the
feat/pdf-jbig2
branch
from
August 18, 2026 18:14
81191cc to
0653899
Compare
andiwand
force-pushed
the
feat/pdf-annotation-appearance
branch
from
August 18, 2026 18:14
91fc12e to
e02e4dc
Compare
andiwand
force-pushed
the
feat/pdf-jbig2
branch
2 times, most recently
from
August 18, 2026 18:23
da4b56a to
02e476f
Compare
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
force-pushed
the
feat/pdf-annotation-appearance
branch
from
August 18, 2026 18:27
e02e4dc to
87fbee8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 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 /Ninto a form XObject, following/ASwhen/Nisa dictionary of states (a check box's
/Offand/Yes), and stores it on theAnnotationalong with the matrix that fits its/Matrix-transformed/BBoxonto the annotation's
/Rect— 12.5.5's algorithm.extract_annotationthenruns that form the way
Doruns any other: fit matrix, the form's own/Matrix, the/BBoxclip. 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, whoseappearance 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
/Vand/DA.Test
/Rect, the form/Matrixconcatenating onto it, and an annotation with nothing to paint.ghostscript render of the same file:
phd-agreement.pdfshows every filledvalue and the selected radio button,
VZA_Ankauf_Kunde.pdfits filled valuesand its
/Squaremarkup.Note
/Rectcorners are routinely indirect, and onedeep_resolvereaches only thearray — its elements stay references, which
as_realscannot read. The rect isresolved element by element instead. That is why
VZA_Ankauf_Kunde.pdfthrewbad any castthe moment annotations started being parsed.