Commit Graph
563 Commits
Author SHA1 Message Date
skylar taylor-barrick e90f7882f1 Migrate PdfCraft to egui 0.37 (#4591)
* Record successful PdfCraft web application check

* E21: bound startup requests and validate font and license inputs

* E21: separate pending control completion and gesture regression phases

* M-egui037: enforce control admission and per-family font notices

* M-egui037: qualify capture fixes and document migration behavior

* egui-037: identify current and historical qualification results
2026-10-25 14:30:31 -04:00
58d368f1f0 M10: Word export keeps an italic run inside its sentence's paragraph (#4158) (#4411)
The reading blocks keep style boundaries, so "Before Chevron after." with an
italic case name reached the Office exporters as three blocks, and each writer
emitted one paragraph per block. A block that continues another on the same
line (the test `continuations` already applies to keep such blocks out of
table cells) is now a run in its own size, bold/italic and colour inside the
paragraph of the block it continues, in Word, HTML, RTF and PowerPoint.

- `continued_from` names the block each one continues (nearest end);
  `continuations` is its `is_some`, so table detection is unchanged.
- `paragraphs` groups blocks left to right, joining only a block that starts
  strictly further left, with the same rotation, and never a table cell or the
  slide title.
- Block text is trimmed, so the engine records the source's spaces at its ends
  (`Block::space_around`, from the reading block's editor text); runs keep that
  space, or one where the page shows a gap.
- A paragraph is a heading only if its runs are (a bold lead-in no longer makes
  its line a heading); a smaller footnote marker does not demote a heading.

Style changes that wrap onto the next line still split paragraphs; that needs
the reading-block grouping change and is left for later.


Claude-Session: https://claude.ai/code/session_0175FWj4xFhMhSH3UpMU8DSC

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-25 10:11:00 -04:00
f0eccde407 M3: give the kept button release back before the pointer leaves (Wayland) (#4500)
* M3: give the kept button release back before the pointer leaves (Wayland)

After a desktop grab the next input on Wayland often brings only
PointerGone. The synthetic release went after it, and a button event
sets egui's pointer position, so the gone pointer came back and hover
stuck at the old place until the pointer moved. The release now goes
before the first PointerGone as well as before the first press; a
release that follows PointerGone is still the kept one and not doubled.
Found by CodeRabbit in review of #3970.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017rPQFoRmQbw8vWhGgGVrRs

* M3: move a release that follows the pointer leaving in front of it

A release the input brings after PointerGone is the one the desktop kept.
Left after PointerGone, it brought the gone pointer back at the release
position; it now moves in front, still not doubled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017rPQFoRmQbw8vWhGgGVrRs

---------

Co-authored-by: bmh129 <11478682+bmh129@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 10:01:56 -04:00
aiongg c276f92b54 Integration: the roadmap entry for comment threads says what the count counts (#4061) 2026-10-24 23:55:17 +00:00
aiongg d821f91001 Integration: fix(comments): thread replies by their /IRT reference, count comments like Acrobat (#4061) 2026-10-24 22:48:11 +00:00
aiongg 78dbea442e Integration: M3: the community card on Home can be closed for the rest of the run (#2617) 2026-10-24 22:34:42 +00:00
alehel ad8c2f46dd Merge origin/main into fix/comment-threads-by-irt
Conflicts:
- crates/render/src/inspect.rs: this branch's reply-linking methods and main's NoRotate
  rectangles (#3016) both go in the Annotation impl; the annotation reader takes this
  branch's loop with main's no_rotate field.
- crates/automation/src/comments.rs: this branch's HashMap import, main's import list.
- ATTRIBUTION.toml: each catalogue's source note keeps main's secured-document clause and
  this branch's reply-count clause; ATTRIBUTION.md regenerated (cargo xtask assets --write).
- The 33 catalogues: main's new rows, then this branch's reply-count row.

main's #3016 tests build Annotation field by field; they now set parent and grouped.
2026-10-24 20:42:11 +02:00
Perchenko AntonandBrandon Thomas 94a12715ce Remember the annotation tool pin across restarts (#4253) (#4276)
* M14 #4253: remember the annotation tool pin across restarts

* M14 #4253: clarify roadmap timezone and Markdown formatting

* Keep main's roadmap status lines; only the progress-log entry is new

* Take main's forms.rs: main already gives each form test its own folder

* Roadmap: drop the form-test folder note (main already has its own)

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-24 10:44:33 -04:00
aiongg 431d1c2364 Merge PR #3012: M11: Optimize keeps a JPEG's colour transform (#1201)
ROADMAP.md: kept both progress lines.
crates/optimize/README.md: PR's decoder sentence plus the target-version section from main.
Cargo.lock: auto-merged.
2026-10-24 06:59:38 +00:00
aiongg 21eed36aa4 Merge PR #1609: M10: recognize a scanned page when Edit is turned on for it 2026-10-24 06:59:03 +00:00
aiongg ce684cd1d3 Merge track r3-t06 2026-10-24 06:50:31 +00:00
aiongg 6a206a0a2e Merge track r3-t05 2026-10-24 06:48:48 +00:00
aiongg 692f34fce2 Merge track r3-t04 2026-10-24 06:40:21 +00:00
aiongg 9705e7a6c1 Merge track r3-t03 2026-10-24 06:39:33 +00:00
aiongg 1d270206be Merge PR #3227: M11: target PDF version and object streams option in PDF Optimizer
Conflicts: docs/roadmap.md: all status lines kept, M10 row from main, M11 row with #3227's two sentences. parity/acrobat-features.toml: save-with-object-streams entry from #3227 with its test paths under tests/it/.
2026-10-24 06:25:55 +00:00
aiongg 80f9555cf8 Merge PR #3786: M5: the arrow keys move the selected comment 2026-10-24 06:23:32 +00:00
aiongg a6351a5328 Merge PR #2195: M3: restore last view settings when reopening documents (#1767)
Conflicts:
- ROADMAP.md: progress log, kept both lines.
2026-10-24 06:23:31 +00:00
aiongg f71a305915 Merge PR #4230: M7: paste added text boxes and images in the engine and through content_copy (#2636)
ROADMAP.md, docs/roadmap.md: kept both sides' status and progress-log lines; did not restore the older M14 status line that the branch had already trimmed.
2026-10-24 06:23:24 +00:00
aiongg 8a64b65e4f Merge PR #4330: M8: redact labelled Italian international slash numbers
ROADMAP.md: kept both progress-log lines, newest first by position (HEAD's #4280 line, then this one).
2026-10-24 06:23:03 +00:00
aiongg 9c47dd36cf Merge PR #4331: M10: apply soft-mask Decode intervals to image exports
Conflicts: ROADMAP.md, docs/roadmap.md: both sides' status, progress and change-log lines; M10 row has the soft-mask sentence added to ours, M11 row from the earlier merge.
2026-10-24 06:22:48 +00:00
aiongg ad54ef3a5f Merge PR #3970: M3: resize and move the window again right after a resize or move (Wayland) 2026-10-24 06:22:33 +00:00
aiongg c097653162 Merge PR #4329: M10: preserve table text from covered export slots
Conflicts: ROADMAP.md, docs/roadmap.md: both sides' status, progress and change-log lines; M10 row has both sentences. parity/acrobat-features.toml: export.docx evidence has both tests, notes has both statements.
2026-10-24 06:22:30 +00:00
aiongg d626a4ae72 Merge PR #2190: M3: a fresh install follows the desktop's appearance (#1248) 2026-10-24 06:22:29 +00:00
aiongg ee989ab5ca Merge PR #3016: M5: sticky notes stay upright where they are placed on rotated pages (NoRotate, #2583)
Conflicts:
- parity/acrobat-features.toml: comment.note: kept main's icon notes text, added the NoRotate sentence and the PR's three evidence entries.
- vendor/README.md: kept main's rows; added the PR's hayro-interpret patch as (53) with its test (53).
2026-10-24 06:22:25 +00:00
aiongg 496e3b3308 Merge PR #4312: M10: preserve page artwork when printing annotations 2026-10-24 06:22:19 +00:00
aiongg 0041a3b10e Merge PR #4161: M10: every paper size reaches the printer, from the dialog and doc_print (#3752)
Conflicts: ROADMAP.md: kept both progress-log lines.
2026-10-24 06:22:15 +00:00
aiongg 8b1f21f77a Merge PR #4311: M10: write DOCX cell widths from their grid columns
Conflicts: ROADMAP.md and docs/roadmap.md took both sides' status lines, progress-log and change-log rows; M10 table row from #4311, M11 row from #4310.
2026-10-24 06:21:54 +00:00
aiongg 4167ac6d5a Merge PR #4310: M11: honor page UserUnit when measuring image resolution 2026-10-24 06:21:23 +00:00
aiongg 4fedfe7e8c Merge PR #2648: fix(xfa): skip PDF fallback scripts while XFA layout is active
crates/engine/src/js.rs: kept main's DocInfo.xfa field and multi-line layout, added the PR's xfa_active gate on doc_scripts.
2026-10-24 06:21:20 +00:00
aiongg fa3a0221d9 Merge PR #3000: fix(edit): batch styled paragraph fallback glyphs 2026-10-24 06:21:12 +00:00
bmh129andClaude Opus 5.5 0b63a73c04 M3: progress docs for repeated window resizes and moves on Wayland
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wrwtfrnom6Eg1Jt7xZ7VA8
2026-10-24 00:46:28 -05:00
mtlcl410andClaude Fable 5.1 946fb31eef M3: restore last view settings when reopening documents (#1767)
A file opened again shows the page, zoom and page display it was last
shown with, as Acrobat's "Restore last view settings when reopening
documents" does: remembered by path (the last 100 files) when its tab
closes or settings are saved with it open, applied over the file's own
initial view, on by default and switched off in Preferences ▸ Documents
and view.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-24 10:09:47 +08:00
nlevaandOpus 5.5 medium ultracode 5515f321c8 M7: copy added JPEG 2000 images as their file (#2636)
Review: copying an added JPEG 2000 image failed even within its own
document, because the exporter can't write JPEG 2000 yet. Add Image stores
such a picture as the file it was given, so that file is the copy: it
pastes into the same document as the same object and into another as one
embedded image. The notes now also say that a CMYK picture stored
losslessly turns to RGB in another document.

Co-Authored-By: Opus 5.5 medium ultracode <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017gEgu9NcTcPqKovsLyfPxK
2026-10-24 01:17:34 +02:00
nlevaandOpus 5.5 medium ultracode 302ad68502 M7: paste added text boxes and images in the engine and through content_copy (#2636)
Edit::PasteContent pastes an added text box or image copied in the same
document or another, as it was (a text box's style; an image's picture,
turns, flips and crop), as one undo step. A pasted image draws its picture
from the copied object while that is still the picture in the target, else
from an added image there that already holds it (an earlier paste from
another document), else the file is embedded. Document::added_image_file
gives a copied image's picture as a file and honours the copy permission.

pdfcraft_edit::added::paste_rect / paste_place place a paste where the item
was, 18 pt down and to the right past each copy of it on the page (an image
with the same box and transforms counts whichever object holds its
picture), or at a point, kept on the page.

The content_copy tool drives it headlessly, across pages and documents.

The desktop keys and menus come in follow-up PRs.

Co-Authored-By: Opus 5.5 medium ultracode <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017gEgu9NcTcPqKovsLyfPxK
2026-10-24 01:17:34 +02:00
Kyle Kassen e373dffa20 M8: redact labelled Italian international slash numbers 2026-10-23 16:37:10 -05:00
Kyle Kassen 50b5e90d63 M10: apply soft-mask Decode intervals to image exports 2026-10-23 16:37:10 -05:00
Kyle Kassen 9dc4bd598c M10: preserve table text from covered export slots 2026-10-23 16:37:10 -05:00
Kyle Kassen 30d85bbf15 M10: write DOCX cell widths from their grid columns 2026-10-23 16:37:10 -05:00
Kyle Kassen a8839bc5b1 M10: preserve page artwork when printing annotations 2026-10-23 16:37:10 -05:00
Kyle Kassen bf86689fd7 M11: measure optimizer image resolution in physical page units 2026-10-23 16:37:10 -05:00
Lcoding15 0b3b243e9a M7: a bold paragraph's stand-in font no longer turns earlier edits bold (#4280)
Edit text set a paragraph whose font lacks a typed character (an accent
missing from a subset) in a standard font, always under the resource
name PCEdHelv, whatever face it stood for. Rewriting a bold paragraph
after a regular one replaced PCEdHelv with Times-Bold, so every
paragraph set in the earlier stand-in turned bold, and the editor's
draft measurement saw those paragraphs change and grew its frame over
them.

The stand-in is now named after its face (PCEdTimesBold, ...), as the
line and region rewrites already name theirs.

Fixes #4280
2026-10-23 22:46:56 +02:00
alehelandClaude Opus 5.5 931b9a599a fix(comments): a status whose comment can't be found is listed nowhere
`link_replies` makes an annotation whose /IRT leads nowhere a comment of
its own. For a status or checkmark that meant a card in the Comments
panel (and an invisible hit area on the page, and a root in
comment_list) that the header's count left out; before threading by
reference, most of these were hidden. The realistic case is a comment
deleted from another page than its status replies.

`Annotation::is_comment` (not a reply, not a status or checkmark) is now
the one test for "listed as a comment": the panel's cards, page badges,
filter menus and count, the page's hit-testing, comment_list's roots and
the summary all use it. A Replace Text caret still shows in its
strikeout's card: it holds the replacement text, and the count already
treats the pair as one comment.

From CodeRabbit review on #4061.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:30:08 +02:00
alehelandClaude Opus 5.5 f35ec52fda fix(automation): comment_list reports a reply's own status and checkmark
The previous commit filed a status or checkmark under the annotation it
was set on, but comment_list only reported states for comments, so one
set on a reply dropped out of the listing. Each reply in `replies` now
carries its own `status` and `marked`, read the same way as a
comment's, and the tool description says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:30:08 +02:00
alehelandClaude Opus 5.5 ecb3f6527e fix(automation): comment_list reads a status or checkmark from the annotation it was set on
A status or checkmark is a state reply whose /IRT names the annotation
it applies to (ISO 32000-2 §12.5.6.2). comment_list gathered state
replies at any depth of a thread (since #839 listed nested replies), so
a checkmark or status set on a reply was reported as the comment's own,
while the Comments panel, comment properties and the page's context
menu showed the comment unmarked. comment_list now files them under the
annotation they were set on, as the panel does.

A UI regression pins the card and the page's menu (it also fails if the
menu counts checkmarks at any depth), and an automation one pins
comment_list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:30:08 +02:00
alehelandClaude Opus 5.5 a629835fec fix(automation): refuse a comment id that several comments share
The comment tools resolved `id` (the comment's /NM, as comment_list
reports it) to the first annotation with that name. /NM need not be
unique: in a PyMuPDF file every page's first comment is `fitz-A0`, so
comment_reply, comment_set_status and the rest acted on page 1's
comment whatever page the caller meant. A shared id is now refused
with a message pointing at `page` + `index`, which always name one
comment. A new end-to-end test also checks that comment_list threads
such a file by reference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:30:08 +02:00
alehelandClaude Opus 5.5 21814f60f5 fix(comments): show stray and nested replies, leave Replace Text out of the count
Follow-up to threading by /IRT reference, from review:

- An /IRT that reaches no listed comment (the annotation itself, a
  loop, a pop-up, an object no page lists) left the annotation a reply
  shown nowhere, though still counted. `link_replies` now settles the
  links in both readers (inspect on open, the engine's list after an
  edit): a reply keeps its parent only when the chain reaches a comment
  within 64 steps, and anything else stays a comment of its own.
- A reply to a reply was never shown in the Comments panel (only
  comment_list followed the chain, #806), but the new header line
  counted it. The panel now files every text reply under the comment
  its thread starts from (`thread_tops`); a status or checkmark stays
  with the annotation it was set on.
- A Replace Text caret (/RT /Group) is grouped with its strikeout, not
  a reply to it, so the header no longer counts it (new `grouped`
  field on both readers).
- The engine summary and comment_list gather replies once instead of
  rescanning every annotation per reply (quadratic on large reviews).
- Inspect takes the first listing in page order instead of a min over
  an unordered map.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:30:08 +02:00
Claude c2fd321ce3 fix(comments): show the reply count under the Comments header
The header keeps Acrobat's count of comments and adds the replies in
small text below it ("16 replies"), left out when there are none and
counting the whole document rather than the current search. Status
changes and checkmarks are not replies. The plural label is in all 33
catalogues with each language's plural forms; ATTRIBUTION.toml records
the new hashes and that the label is an AI-assisted translation not yet
reviewed by native speakers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KvugvPrjZtPVudhh7cMa54
2026-10-23 17:30:08 +02:00
Claude be600950c9 fix(comments): thread comment replies by /IRT reference, count comments like Acrobat
Replies were matched to their parent by /NM across the whole document.
/NM need not be unique: PyMuPDF names the first comment on every page
`fitz-A0`, so every reply in such a file was filed under page 1's
comment, and the other pages showed none. Both comment readers (render
inspect on open, annot summaries after an edit) now resolve /IRT to the
parent's page and /Annots position by object reference, and the
Comments panel, comment properties, the canvas thread, the engine's
comment summary and the comment_list tool thread by that.

The Comments header now counts comments without their replies, as
Acrobat does (28 rather than 44 for the reported file), and a reply's
thread line runs from the avatar above it (the comment's or the
previous reply's) to its own instead of a 12 px stub.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KvugvPrjZtPVudhh7cMa54
2026-10-23 17:30:07 +02:00
Philip 9ee24d7ca9 Merge remote-tracking branch 'origin/main' into feat/edit-scanned-page-offers-ocr
# Conflicts:
#	parity/acrobat-features.toml
2026-10-23 16:10:49 +01:00
Ahmad Mu 44e8eeb289 Cancel stale Organize page drags after document changes (#4039)
* M4: Cancel stale Organize page drags after document changes

* M4: Record Organize drag cancellation coverage
2026-10-23 10:43:05 -04:00