Skip to content

docs(design): plan pdf markup annotations - #842

Merged
andiwand merged 1 commit into
mainfrom
docs/pdf-annotation-design
Sep 6, 2026
Merged

docs(design): plan pdf markup annotations#842
andiwand merged 1 commit into
mainfrom
docs/pdf-annotation-design

Conversation

@andiwand

@andiwand andiwand commented Sep 6, 2026

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

Records the architecture for adding markup annotations — text highlight and freehand ink — to an existing PDF. Scope is markup only; editing or removing a PDF's existing text stays out.

Nothing is implemented here. docs/design/pdf-annotation.md sits beside editing.md and follows its shape: decisions with their rationale, a phased plan, open questions.

The finding that makes this cheap

Annotations are additive — no content stream changes, no object is renumbered — and most of the machinery is already in the tree:

  • pdf_object.cpp's to_stream already emits real PDF syntax (a few escaping gaps aside).
  • Annotation::appearance already resolves and paints /AP /N, and blend_mode_to_css already maps /BM /Multiply. So what we write, we already render — the round trip is self-verifying and the feature needs no new rendering code.
  • begin_page()'s to_box gives an invertible user-space → page-box map with /CropBox and /Rotate folded in.

Decisions recorded

  1. File-level api on PdfFile, addressed by page + geometry, not ElementIdentifier — which sidesteps the id-stability linchpin editing.md Phase 0 is blocked on. This feature does not depend on that work.
  2. Incremental update, never a rewrite — a full rewrite turns every read-side gap into data loss. Consequence: files opened only via xref recovery are refused.
  3. Always write an appearance stream — our renderer paints nothing without one, and it is also the interop-safe choice.
  4. No PDF library — MuPDF is AGPL, PDFium contradicts the module's no-native-renderer premise for the sake of four dictionaries, QPDF is a second parser beside ours.
  5. Fat browser, as in editing.md.
  6. Encrypted files refused in v1 (the module deliberately never retains the derived key).

Plus the concrete JSON wire format, the object listing a highlight actually writes, an eight-phase plan (~15–20 days, with a 6–8 day MVP cut), what the writer unlocks next, and four open questions — the sharpest being that a selection-driven highlight tool turns the existing link-overlay-vs-selection conflict from theoretical into user-visible.

Docs only; no consumer-visible change, so no changelog entry.

Highlight and freehand ink written back as standard annotations through an
incremental update, so every viewer sees them. The read side already paints
`/AP /N` and already maps `/BM /Multiply`, so what we write we render.

Records why no PDF library is worth taking, why the api hangs off `PdfFile`
rather than the deferred element-id editing work, the JSON wire format, and
the phase-by-phase cost.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018e3PEzyU2oAFSzsEoWsSmz
@andiwand
andiwand merged commit d34c4f8 into main Sep 6, 2026
35 checks passed
@andiwand
andiwand deleted the docs/pdf-annotation-design branch September 6, 2026 14:36
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