Skip to content

feat(pdf): add read-only source-content classifier (#33) - #97

Open
nonamexishere wants to merge 7 commits into
McanKul:developmentfrom
nonamexishere:feat/33-source-content-classifier
Open

feat(pdf): add read-only source-content classifier (#33)#97
nonamexishere wants to merge 7 commits into
McanKul:developmentfrom
nonamexishere:feat/33-source-content-classifier

Conversation

@nonamexishere

@nonamexishere nonamexishere commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add a bounded, read-only backend that inspects the original source path (never the pagePdf preview extract) and lists existing text and image occurrences.
  • Each occurrence returns unrotated PDF-space bounds (same space as EditObject.rect), an opaque locator tied to a whole-file fingerprint, kind text | image, and supported or unsupported plus a specific reason code.
  • Walks page streams and Form XObjects. Anything reached through a Form Do is NESTED_FORM (real kind and bounds, never independently mutable).
  • supported means structurally classifiable for a later mutate loop. It is not a Save affordance and is not cover-and-overlay.

Fixes #33.

Why

Spike #11 needs a machine that can emit explicit unsupported reasons before anyone opens a production “edit existing text/image” issue. Overlay stamps and #34’s surviving source digest are not that machine. This is the #32 corpus classifier only: no dest write, no PDFium, no Edit PDF UI.

Validation

  • npm run build
  • npm test (283)
  • npm run typecheck
  • cargo test --manifest-path src-tauri/Cargo.toml --lib (237, including 31 source_content tests)

Privacy Checklist

  • This keeps OffPDF usable offline.
  • This does not upload, log, or transmit user files.
  • New dependencies or bundled binaries have compatible licenses. (none added)

Inspect the original source path and list existing text and image
occurrences with unrotated PDF-space bounds, an opaque locator, and
a supported/unsupported reason. Does not write a dest or edit page
operators.

Fixes McanKul#33.
Treat 180° text as ROTATED_TEXT, advance Tm after each show, refuse
only applied signatures (not empty /FT /Sig widgets), keep operators
after BI…EI, and scale text bounds by Tm×CTM.
Replace the same-agent fold with independently authored R1–R5 tests
and a walker that does not edit those tests. Behavior is the same:
180° ROTATED_TEXT, Tm advance, empty Sig widgets, leftover ops after
BI…EI, and Tm×CTM text bounds.
Strip only ID…EI payload so BI sees the live CTM. q/Q restores font
metrics and Tc/Tw (not Tm/Tlm). Tc/Tw advance consecutive shows.
Drop the fixture-history parenthetical on is_rotated_tm.
Indirect /Widths arrays are followed instead of falling back to
Helvetica. Named and array Pattern color spaces refuse as PATTERN.
ExtGState /SMask (not /None) marks following paints MASKED_IMAGE.
PDF cm / Form Matrix / Td / post-show Tm use mul(current, operand).
Stacked cm now maps a unique image to (72, 400) 40×40; a scaled Tm
plus a second Tj advances by 12× text-space width. Trm is unchanged.
Insert a newline between decoded /Contents chunks so Tj+ET cannot
fuse into TjET. A two-stream page now lists both Hi and Lo.
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