Moving an image whose crop is its own (`q re W n cm Do Q`) as part of a
group put a fresh `cm` before the clip path on every move, so twenty
moves left twenty `cm` operators in front of one `re`. It never nested
deeper, but the content stream grew with every drag.
When a `cm` already sits right before that clip (one an earlier move
added, or the file's own), `translate_images` now replaces it with the
product of the new and old matrices. The CTM at the clip is
`c · prev · outer` either way (ISO 32000-1 8.3.4, 8.4.4). A previous
`cm` that is not finite, or a product larger than 1e12, keeps the old
behaviour and inserts a separate `cm`.
The new test moves an image cropped smaller than itself twenty times and
checks that the image and its visible crop both moved by the full offset,
that the operator count stays at its value after the first move, and that
the caption after it is untouched. It fails without this change
(32 operators against 13).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The fix landed as #2698 (9dfc91e0) with its parity evidence, but no
progress-doc record did: add the status line and progress-log entry in
ROADMAP.md, the status line, revision row and M8 milestone note in
docs/roadmap.md, and gap 6's evidence and revision history in
docs/gaps.md — the wrong-result backlog the issue belongs to.
Estimates unchanged.
Preserve the idle repaint and second-edit recovery regression while refreshing already-merged upstream work. Validated exact tree with full local CI and native Linux idle recovery.
ROADMAP.md: next's file; the PR's progress line and revision row added once; status-line edit dropped.
docs/roadmap.md: next's file; the PR's revision row and M6 milestone sentence added once; status-line edit dropped.
crates/xfdf/README.md: all three paragraphs kept (#1917, #2686, this PR).
crates/xfdf/src/tests.rs: #2686's test and this PR's two tests all kept.
parity/acrobat-features.toml: form.data-xml-csv-txt keeps every evidence entry and note.
ROADMAP.md: next's file plus this PR's 2026-10-13 progress line and revision row; the #1919 refresh line and the status line repeating an M13 item dropped
docs/roadmap.md: next's file plus this PR's revision row; its refresh status line and the refresh note in the M4 row dropped
ROADMAP.md: next's file; the PR's progress line and revision row added once; status-line edit dropped.
docs/roadmap.md: next's file; the PR's revision row and M6 milestone sentence added once; status-line edit dropped.
crates/xfdf/README.md: both paragraphs kept (#1917 export whitespace, this PR's plain XML import text).
parity/acrobat-features.toml: form.data-xml-csv-txt keeps both evidence entries and both notes.
ROADMAP.md: next's revision history plus this PR's row; the #2267 refresh progress line dropped
docs/roadmap.md: next's revision history plus this PR's row; refresh wording dropped from the status line and the M1 row
ROADMAP.md: next's file; the PR's progress line and revision row added once; refresh line and status-line edits dropped.
docs/roadmap.md: next's file; the PR's revision row and M6 milestone sentence added once; refresh note and status-line edit dropped.
Main solved this branch's problem on its own: #1712 replaced the two
duplicated catalog paragraphs with one current paragraph that covers
every shipped language. Two and a half hours later #2320, branched
before that, added its two copies back, so main carries three again.
Keep #1712's paragraph exactly as main wrote it and delete only the two
stale copies, so this branch no longer rewords anything.
Docs only, no code.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(ui): validated signature display, snapshot tab reuse
Signature widgets with layered appearances baked the unverified state
into the page, so a valid signature kept reading 'Signature Not Verified'
while the banner and panel said valid. Validated verdicts are now drawn
into the icon and caption layers in the display copy only: the signed
bytes are untouched, saving keeps the original appearance, and files
without those layers or without a valid verdict render exactly as before.
Other valid signatures still get the verdict mark over their widget,
sharing one style with the Signatures panel, and hide it again once the
appearance itself shows the verdict.
View signed version and View revision opened a new tab on every click,
and every tab showed the document title, so repeats piled up identical
tabs. Repeats now reuse the snapshot tab, snapshot tabs read like their
source plus the suffix in the tab strip, window title and Combine picker,
and carry a notice bar naming the revision with a Close that asks about
saving first.
Signed-off-by: Chiranjeevi U <244287281+chiranjeevi-max@users.noreply.github.com>
* Address review comments on validated appearances and trust refresh
Count every field when checking shared appearance streams, so a
caption shared with an unvalidated field is never rewritten for the
valid one alone.
Pick the icon slot by drawing instead of length, and only when a
single layer qualifies. Bare rectangles never count as the icon, and
ambiguous or missing slots fall back to the overlay badge.
Revalidate and invalidate together through one helper, so trusting a
certificate always drops rendered pages. Trust alone still marks
nothing dirty.
Tests: mixed-verdict sharing, longer decorative borders, competing
and doubled layers, capture-before preservation, trust invalidation
without zooming, and signed Session round trips with rendering,
saving and passwords.
Signed-off-by: Chiranjeevi U <244287281+chiranjeevi-max@users.noreply.github.com>
* Prove the icon slot geometrically and cover real layered signatures
A lone line drawing is still not the icon: frames and borders span the
box while the status mark lives in a corner of it. The icon now has to
sit strictly inside the appearance frame and cover at most half of it;
anything else falls back to the overlay badge. Widgets without a
measurable frame veto the rewrite the same way.
Tests: parsed extents and inhabitant checks as units, both reported
border repros plus a frameless widget, and real layered signatures
built with cms::sign_detached through Session open, trust, rendering,
save and reopen, plain and password-protected.
Signed-off-by: Chiranjeevi U <244287281+chiranjeevi-max@users.noreply.github.com>
* Identify the icon by shape instead of geometry
A lone line drawing is still not the icon, but size and position were
the wrong signals: the real status mark is large, and geometry blocked
it. Frames, borders and panels are rectangles by nature while the mark
is not, so a drawing made only of axis-aligned rectangles is decoration
however it is stroked. Singularity, shared-stream and template checks
are unchanged; anything ambiguous still falls back to the overlay badge.
Tests: rectangularity as a unit, nested line-drawn frames, and a
triangular fixture mark in place of the rectangular one.
Signed-off-by: Chiranjeevi U <244287281+chiranjeevi-max@users.noreply.github.com>
* Budget the appearance walk and keep the marks with the bytes
The walk that finds a signature's icon and caption capped depth,
layers and fields, but not the work: a dictionary whose entries all
point at the next one is visited once per entry per level, so a small
hostile file never finishes opening. The walk now counts its visits
and gives up, and a field whose tree cannot be read to the end stops
the whole pass, because a layer we never read may be the one two
fields share and a rewritten shared layer puts one field's verdict on
another field's page. The sharing count is exact again with that: two
widgets of one field pointing at the same appearance claim it once,
or the field vetoes its own rewrite.
A mark used to outlive the bytes it described. A failed display write
left the page showing the file's own caption while the verdict still
claimed its state was drawn; a metadata edit dropped the mark while
the page kept drawing the state, so the badge landed on top of it. The
write fallback now drops the marks and logs the loss, and metadata
carries them over.
Tests: a self-referential appearance tree, which never finished before
the budget, two widgets sharing one appearance, a metadata edit that
keeps its mark, a save that goes through the writer instead of
short-circuiting on the opened file, and the snapshot bar's Close
button pressed for real.
Signed-off-by: Chiranjeevi U <244287281+chiranjeevi-max@users.noreply.github.com>
* Cite the new regressions in parity, restore main's installer note
The appearance entry now cites the bounded walk and the save through
the writer, and says what a tree that cannot be read to the end does.
The installer entry carried main's older text, which still claims
signed installers are planned; main's newer note is taken verbatim.
Signed-off-by: Chiranjeevi U <244287281+chiranjeevi-max@users.noreply.github.com>
* M9: preserve rounded decoration beside raster status glyphs
* M9: place appearance progress beside signature history
* M9: retain appearances with ambiguous curved layers
* M9: keep signature verdicts in viewer overlays
Defer generic appearance rewriting: caption text and a unique drawing do not establish an icon role. Preserve original artwork for saves, image and text exports, and both print modes while retaining snapshot reuse and trust refresh. Cover chamfered borders and mixed signer/caption streams through signed Session round trips.
---------
Signed-off-by: Chiranjeevi U <244287281+chiranjeevi-max@users.noreply.github.com>
Co-authored-by: skylar taylor-barrick <hi@skylar.cc>