Commit Graph
4058 Commits
Author SHA1 Message Date
FredAppsandCodex 5259491cf4 Tests: update save and search regressions for current behavior (#2484)
Co-authored-by: Codex <codex@openai.com>
2026-10-15 16:50:39 +02:00
mtlcl410andClaude Opus 5.5 491ce2da5b fix(i18n): zh-hant had two keys twice after concurrent merges (#2414)
the Revert prompt to zh-hant.tsv; merged together, the catalog held both
copies and `bundled_catalogs_are_consistent` (and the tests that load
zh-hant as a reference) failed on main. Keep #1750's wording (字型大小,
「」 quotes, as the rest of the catalog) and drop the other copy.


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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 16:50:33 +02:00
mtlcl410andClaude Opus 5.5 1bc3a31814 fix(parity): merge the keys concurrent merges left twice in acrobat-features.toml (#2419)
Nine features carried `evidence`, `notes` (and once `tools`) twice, so the
file was no longer valid TOML and `cargo xtask parity` stopped with
"duplicate key". Each pair is merged into one: evidence and tools as the
union of both lists, notes keeping every fact either side added.


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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 16:50:26 +02:00
wstockandClaude Fable 5.1 224416a3dd Tests: the signing test's password meets the 8-character minimum (#2417) (#2420)
signing_with_translated_labels_through_tools (from #1951) creates and uses
a digital ID with the password "secret1"; #2201 ("harden .p12 digital IDs")
now requires at least 8 characters. Each passed alone; together the test
fails on main, and so does every PR's test job. The password is "secret12"
in both places.


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

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-15 16:50:04 +02:00
Codex 403323f425 Merge main and address button export-value review follow-up 2026-10-15 16:22:36 +02:00
Combiler01 b31e6b49db merge: reconcile upstream/main with local changes 2026-10-15 19:36:23 +05:30
oracola91 d0a3427184 fix(platform): a save keeps the permissions of the file it replaces
On Unix the staging file got the default mode for a new file (usually
0644) and was renamed over the original, so saving a private 0600 PDF
left it readable by other local users. The staging file is now created
owner-only and given the original's permissions before anything is
written. A new file still gets the usual mode. Desktop save, the CLI
and the automation tools all write through this function.

Fixes #1790.
2026-10-15 16:40:45 +03:00
arpan-star 521fdaa4b5 Merge branch 'storytold:main' into main 2026-10-15 19:01:15 +05:30
Marco Arnulfo d5bde67e74 Ctrl+V doesn't paste a picture while preparing a form 2026-10-15 14:41:59 +02:00
Marco Arnulfo b248dffdff Hebrew file names: draw them with an installed Hebrew face when the build has none (part of #586) 2026-10-15 14:27:21 +02:00
Osvaldo Duran e46cc70d73 Merge main (afa8e184) into pr/attachments 2026-10-15 07:59:50 -04:00
Combiler01 6f9ec0f576 feat(ui): pinned tools section on Home 2026-10-15 17:27:45 +05:30
Marco Arnulfo 6882ce3436 Ctrl+V pastes a picture from the system clipboard onto the page (fixes #2494) 2026-10-15 13:00:32 +02:00
Codex d8e46c7b74 Merge current main into Pages sidebar select-all fix 2026-10-15 12:56:18 +02:00
komo1iddinandClaude Opus 5.5 e0ef098381 M7: drop the fallback fonts a text edit leaves unused
Each edit that draws Japanese or Hebrew characters the page's fonts lack
generates new Type 3 fonts with the outlines of every character it draws.
Editing the paragraph again generated new ones and left the old ones in
the page's resources, so every edit added a set of glyph outlines to the
file.

After replace_line and rewrite_block, the page's generated fallback fonts
(Type 3, /Name /PCJapanese or /PCHebrew) that no Tf selects any more are
removed from its own font dictionary. The content read for this is the
page's streams, every form XObject it can reach that has no resources of
its own (those use the page's, ISO 32000-1 7.8.3), and the glyph
procedures of Type 3 fonts without resources. If any of those can't be
decoded strictly, nothing is removed. Registered fonts (PCFull) and the
file's own fonts are never touched.

Tests: a page with an unused generated font, one its content selects,
one only a resource-less form selects and a file's Type 3 font that only
shares the name prefix keeps all but the first after a rewrite, and keeps
everything when such a form can't be read. Rewriting Japanese text twice
(with craft-fonts) leaves only the second rewrite's fonts. The first test
fails without this change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:13:34 +05:00
komo1iddinandClaude Opus 5.5 2109c6785e M7: show a shaped run in one text object instead of one per glyph
Shaped text (Arabic, Indic, combining marks) was written as one text
object per glyph: BT, the whole text state (Tf Tc Tw Tz TL Ts and the
colour), Tm, Tj and ET. A 15-glyph row took 15 text objects and 392
tokens (the whole stream), a long Arabic paragraph thousands of operators, and other
viewers saw every glyph as a separate piece of text.

Each run is now one text object: the state once, one Tm, and the glyphs
in TJ arrays. A glyph's adjustment moves it from where the glyph before
it ends (its width in the embedded font) to where shaping put it, and a
mark shaped above or below its letter is raised with Ts, then reset
(ISO 32000-1 9.4.3, 9.3.7). Character and word spacing are part of those
positions, so Tc and Tw are 0 in the run. The same row is now 1 text
object (90 tokens for the stream), and renders the same at 300 dpi (138 of 33
million bytes differ, by 1 level, from rounding).

The new test shapes marks beside and above their letters with Inter,
reads each glyph's origin back from the TJ displacements and checks it
against the shaped position. It fails without this change (15 text
objects in the run against 1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 14:58:32 +05:00
Philip 0c06186486 Merge remote-tracking branch 'origin/main' into feat/edit-scanned-page-offers-ocr
# Conflicts:
#	ROADMAP.md
2026-10-15 10:31:33 +01:00
Philip 8dfdf32a77 Merge remote-tracking branch 'origin/main' into feat/system-cjk-font-fallback
# Conflicts:
#	ROADMAP.md
2026-10-15 10:28:06 +01:00
alehelandClaude Opus 5.5 3ec7ce8aae M3: All tools expands to a full, searchable view
An expand button at the top-left of the All tools sidebar opens a view that
fills the workspace, like Acrobat's tools page: every tool as a tile, filed
under five categories (Create & Edit, Review & Compare, Forms & Signatures,
Protect & Standardize, Customize & Automate), with a search field that matches
tool names and the items inside each tool, in English or the UI language.
Choosing a tile opens that tool's panel; Collapse, Esc or another workspace
puts the view away. `--tools full` opens it from the command line and the
control channel.

The categories live in the engine catalogue (TOOL_CATEGORIES), with a test
that every tool group is in exactly one. Six new strings are translated in
all 22 catalogues.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 10:41:14 +02:00
marcintrojnackiandClaude Opus 5.5 d2fc6c1be3 M14: Polish says what a signature says, and the rest of the interface
A Polish signature panel headed "Ważność podpisu jest NIEZNANA" and listed
its details in English: the catalog had none of the engine's signature
wordings (sign::pdf::WORDINGS, 57) or the changes after signing they name
(kind::ALL, 10), and lacked 34 UI literals besides.

All 101 are translated, and two tests keep them so:
- polish_covers_ui_literals, every tl!() literal (as Japanese has);
- polish_says_what_a_signature_says, the signature wordings and change kinds
  with their {} holes.
Both fail on the previous catalog. ATTRIBUTION.toml carries the new hash.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 10:24:02 +02:00
afa8e1843c M3: Wayland: stop retaining Ctrl zoom for pixel-only wheel input (#1569)
* M3: release Ctrl zoom for pixel-only Wayland wheel events

Use the reported scroll source to avoid unterminated finger gestures for wheel, wheel-tilt and continuous input. Exercise the production policy through egui, including modifier release and preserved finger momentum.

Assisted-by: OpenAI Codex

* M3: keep Cargo lockfile dependency ordering canonical

Record the dependency ordering produced by the completed workspace and wasm gates.

Assisted-by: OpenAI Codex

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:08:34 -04:00
cdf44d7999 Comments panel: page groups fold from their chevron (#1614)
* Comments panel: page groups fold from their chevron (fixes #1554)

* Comments panel: translate the fold-all buttons in every catalog

"Collapse all pages" and "Expand all pages" were missing from the 21
catalogs, so the covers_ui_literals tests failed; the catalogs' hashes
are re-pinned in ATTRIBUTION.toml.

* Add the Vietnamese entries for Collapse/Expand all pages; refresh catalog hashes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Refresh catalog hashes after merging main

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:03:49 -04:00
ab45a1855f Keep annotations readable under reading colours (#1548) (#1557)
* fix(render): keep annotations readable under reading colours (#1548)

Reading colours remapped annotation paints as line art: the yellow
highlight fill is luminance-light, so it was mapped toward the dark
background, and Multiply then darkened the remapped-white words under
it into invisibility.

Two changes in hayro:

- The /Annots loop in interpret_page is bracketed by a new
  begin_annotations/end_annotations Device signal (patch 26), and the
  renderer's reading-colours mapping leaves annotation paints alone.
  Reading colours replace document colours, never the colours a
  comment was given — the Acrobat model.
- The page background is painted inside the page transparency group
  (patch 27), as the initial backdrop, so a Multiply highlight blends
  with the background too. With the background outside the group the
  band kept its own flat colour and the words vanished into it. White
  pages are unaffected: multiplying with white is the identity.

Regression test reading_colors_keep_highlight_annotations_readable
covers both annotation paths (/AP and the no-/AP /QuadPoints
fallback) under WHITE_ON_BLACK; parity entry a11y.replace-page-colors
updated with the behaviour and evidence.

Co-Authored-By: GLM <noreply@z.ai>

* contributors: credit @edurbs as Eduardo Soares

The contributor's own entry, chosen by them (real and display name).

Co-Authored-By: GLM <noreply@z.ai>

* #1557: record the vendored hayro patches in vendor/README.md

Main already uses hayro-interpret patches (26)-(28), so the annotation hooks become
hayro-interpret (29) and the renderer's parts hayro (17) and (18).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: GLM <noreply@z.ai>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:03:25 -04:00
e62d3db31b M6: keep AcroForm XML field tags within the NCName grammar (#1588)
Constrain the existing normalization to XML1.0 name characters while preserving
valid tags and original PDF names through xfdf:original. Verify Unicode names,
prefixes and normalization collisions with saved-PDF round trips.

Co-authored-by: MMexicann <MMexicann@users.noreply.github.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:03:00 -04:00
53b9bc1059 M6: preserve carriage returns in form CSV exports (#1563)
* M6: preserve carriage returns in exported form CSV

Quote CR in names and values so reimport cannot discard a trailing CR as a
record terminator. Verify eleven combinations through saved-PDF round trips.

Co-Authored-By: Codex <noreply@openai.com>

* Keep main's ROADMAP status line

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: MMexicann <MMexicann@users.noreply.github.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:02:35 -04:00
ac69c29823 M14: Fix(nixos): discover installed UI fallback fonts on NixOS (#1553)
* M14: discover installed UI fallback fonts through Fontconfig

Find existing fallback faces in configured directories, including Nix store paths. Bound and cache discovery while preserving candidate names, glyph checks and the screenshot opt-out.

Assisted-by: OpenAI Codex

* M14: keep the drop-dispatch regression deterministic

Select inline document preparation in the existing drop-dispatch test, matching the validation fix used by both Wayland branches. Full workspace, strict Clippy and wasm gates pass.

Assisted-by: OpenAI Codex

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:02:11 -04:00
cccd55fab2 M1: edit finds the pages a damaged file's readers find (#1664)
* M1: edit finds the pages a damaged file's readers find (fixes #1656)

* M1: rebuild a lost page tree only when the reader shows the same pages, and refuse edits to signed rebuilt files (#1656)

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:01:45 -04:00
9479561ffa Complete the Arabic (العربية) catalog: every missing row translated (#1559)
* Complete the Arabic (العربية) catalog: every missing row translated

ar.tsv covered 2,325 of the interface rows; the newer catalogs (lt, cs,
es and friends) had since grown to a 2,578-row union. This adds the 253
rows Arabic was missing, in the same clean-room Modern Standard Arabic
and Acrobat-style vocabulary the file already uses:

- digital-signature verification detail: every ECDSA/RSA/BER/DER reading
  note, timestamp-token and revocation sentence, the certificate
  inspector's sixteen fields (المُصدر، الرقم التسلسلي، صالح من/إلى…)
  and the key-usage purposes (عدم الجحود، تشفير المفاتيح…)
- the accessibility checker's full vocabulary (وسوم، بنية المستند،
  النص البديل، خلايا الرأس…) and its report grades
- the eight newer @plural rows with all six Arabic forms (صور محسّنة،
  بكسلات، نتائج…) and the calendar's weekday abbreviations
- PDF/A output intents, combine/organize status lines, panel restore
  errors, and the small chrome (اختيار…، تنظيم، تقرير مفصل…).

Same catalog, same lookups — Arabic now covers the union of every
language's rows (2,578).

* Refresh the ar.tsv sha256 in ATTRIBUTION.toml

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Refresh catalog hashes after merging main

---------

Co-authored-by: hasan-sdaif <306196098+hasan-sdaif@users.noreply.github.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 03:57:18 -04:00
fcd72747cd M6: make list boxes directly selectable and scroll to selection (#1524) (#1543)
* M6: make list boxes directly selectable and scroll to selection (#1524)

- In-place selection: List boxes are rendered directly on the page and
  selectable in place. Clicking an option row selects it immediately;
  Ctrl/Cmd-clicking toggles items in multi-select lists, and Shift-clicking
  selects ranges, without opening a popup menu.
- Appearance and scroll (/TI): When options are selected, /TI (top index)
  is automatically adjusted so the selected items are scrolled into view
  within the widget's visible rows, and option rows and selection highlights
  are drawn into the appearance stream.
- Unit and UI tests: Added tests in pdfcraft-forms verifying /TI scrolling
  and appearance generation for multi-select lists, and UI tests in
  pdfcraft-ui-egui covering in-place click and Ctrl-click toggling.
  Also ensured test harness in reload.rs explicitly sets language to en.

Fixes #1524

* List boxes: keep the engine's page appearance, consume arrow keys

Drop the overpaint of every fillable list box with an egui mock (it ignored the
PDF's fonts, colours and /MK /R; the engine redraws the appearance with the new
/TI), and consume ArrowUp/ArrowDown in the list overlay so they don't also
scroll the page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 03:52:55 -04:00
d1bc200115 M7: grow text boxes and edit existing text (#1539)
* M7: grow text boxes and edit existing text

Text boxes now grow to the page edge and vertically as needed, retaining their size when saved. Clicking native or added text in either text tool edits the existing item instead of layering a duplicate over it.\n\nCo-authored-by: OpenAI gpt-6.1-sol <noreply@openai.com>

* #1539: build against main's Document::added() accessor and draft-aware prepare

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 03:52:33 -04:00
3805be7669 M14: store XDG preferences in configuration directory (#1395) (#1536)
Generated with Codex for @DWAA1660.

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 03:52:12 -04:00
FredApps d8726b1b4f Merge main into Pages sidebar select-all fix 2026-10-15 09:49:10 +02:00
57c8de09ab M6: preserve XFDF field text around XML comments (#1647)
Join the text nodes in each field value so XML comments and processing instructions do not truncate imported text. Cover data extraction and form import through PDF save/reopen.

Co-authored-by: storybored379 <storybored379@users.noreply.github.com>
Co-authored-by: OpenAI Codex <noreply@openai.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 03:47:41 -04:00
7aac682ef8 M7: Cut, Redact, Create Link and Recognize Text in the picture menu; keep the menu open (#1621)
* M7: add Cut, Redact, Create Link and Recognize Text to the picture menu; keep the menu open

The right-click menu of a picture in Edit text & images gains Cut Image,
Redact Image (a redaction mark over the picture), Create Link… and Recognize
Text… (for the picture's page), with translations in every catalog.

The menu was drawn only while the pointer was over the picture, so an item
outside it, which is most of a small picture's menu and Delete once the menu
reaches below the page, could not be clicked. An open menu is now drawn
wherever the pointer is.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Update the catalog checksums in ATTRIBUTION.toml

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Fix the merged test file and checksums

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Refresh catalog hashes after merging main

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-15 03:47:20 -04:00
10ad9b46e5 Keep added text selectable over form fields (#1528)
* Keep added text selectable over form fields

Generated with Codex for @FredApps.

* Fix the content.rs test harness merge: harness_bytes and harness_with_step_dt share one builder

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 03:42:56 -04:00
b7976ef40e M12: show structure tag content (#1496)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 03:38:35 -04:00
980bd90087 Print: 4 x 6 in label paper and a Label layout for shipping labels (#1583)
* Print: 4 x 6 in label paper and a Label layout for shipping labels

Thermal label printers (e.g. VEVOR Y486) could not be used for eBay/carrier
labels: the paper list had no 4 x 6 in size, the chosen paper was never sent
to CUPS (the queue's default was used), and labels laid out sideways on a
Letter/A4 sheet printed small or rotated.

- PAPERS gains "4 x 6 in label (101.6 x 152.4 mm)"; cups_media() sends the
  chosen sheet to the spooler as `-o media=` (Letter, Legal, Tabloid, A3-A5
  and w288h432 for the label), so the driver feeds the size the PDF was
  laid out on.
- New Layout::Label: each page is cut to its printed area (a low-resolution
  render, as Fit Visible does), turned a quarter turn when it is sideways in
  the direction that makes its text upright (text_reads_up reads the text
  and form matrices), and fitted uniformly with a small margin. Vector
  content is kept, so barcodes stay sharp and undistorted. "Turn upside
  down" flips it 180 degrees. One label per sheet.
- Choosing the label paper selects the Label layout, and vice versa.
- Strings translated in every bundled catalog.

Tests: label geometry (crop, quarter turns, no stretching, margins),
cups_media, text direction; print, ui-egui and automation unit tests pass.

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

* Refresh catalog hashes after merging main

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Alessio Boschi <alessio.boschi@dinova.one>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-15 03:38:06 -04:00
24f93e6102 feat(ui): preference to hide author-only highlight hover previews (#1432) (#1466)
* feat(ui): preference to hide author-only highlight hover previews (#1432)

* Keep the Identity heading, translate the new hover preference, move its persist key out of json!

The heading rename dropped the existing Identity translation in every catalog; the
new checkbox label now has an entry in every catalog. The json! object in persist()
is at serde_json's recursion limit, so the new key is set after it like redact_prefs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* cargo fmt

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Refresh catalog hashes after merging main

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 03:33:43 -04:00
a6124bcdfe M12: find untagged accessibility content (#1463)
* M12: find untagged accessibility content

* i18n: translate untagged content checker (rebased)

* fix(i18n): refresh untagged content translation hashes

* fix(tests): restore full test modules for find-untagged content

* fix(i18n): preserve existing translations after rebase

* ci: rerun shared timeout test

* chore(deps): refresh rust for the advisory gate

Use the current lockfile, including the rustls security update, so the dependency check can run on this branch.

* Refresh catalog hashes after merging main

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 03:33:19 -04:00
afa50999ef M12: tag unstructured AcroForm widgets (#1451)
* M12: tag unstructured AcroForm widgets

* i18n: translate form tag command

* i18n: repair form-field label merges

* fix(i18n): refresh translation catalog hashes

* fix(i18n): preserve main translations after rebase

* Merge main; tag a widget listed on several pages once, docs say existing trees are extended

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Merge main; add the Vietnamese catalog entry for Tag form fields

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 03:24:55 -04:00
Osvaldo Duran 524ca95848 Merge main (41809cf7) into pr/attachments 2026-10-15 03:20:43 -04:00
Osvaldo Duran 77d9f7509f Merge main (7461c297) into pr/attachments
Conflicts: the language catalogs (both sides' rows kept), ATTRIBUTION.toml's checksums
(recomputed from the merged files), and tests both sides appended at the same place.
Upstream's new Vietnamese catalog gets this change's labels.
2026-10-15 03:20:43 -04:00
416c85579b Perf: defer marker and link index scans until first use (#1434)
* Defer secondary PDF indexes until first use

* Merge main into #1434; read Document::added through the new method in content_ui

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 03:20:32 -04:00
95a972a3e7 M2: preserve known unfiltered inline-image sample boundaries (#1562)
Use checked sample lengths and row padding before the EI delimiter heuristic.
Cover valid binary terminator-like samples, masks, Indexed, aliases, invalid
layouts and saved classic/packed PDFs.

Co-authored-by: MMexicann <MMexicann@users.noreply.github.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 03:20:10 -04:00
ae9fb42688 M3: scroll the view when drawing at an edge; take back a polygon's last point (#1549)
While a comment is being drawn, the pointer in a band along any edge of the
viewport (or just past it) scrolls the view toward that edge, so a point
outside what is shown can be reached. Polygon, cloud and connected-lines
drawings take back their last point with Backspace, Delete or Undo; removing
the only point cancels the drawing.

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-15 03:19:50 -04:00
41809cf765 fix(macos): Cmd+Q asks about unsaved changes (#1136) (#1533)
* fix(macos): Cmd+Q asks about unsaved changes (#1136)

winit's default app menu sends Quit (Cmd+Q) straight to
-[NSApplication terminate:], so PdfCraft quit without asking and
unsaved edits were lost; the close button and Dock > Quit already ask.

Install craft-quit's app menu (storytold/craft-libs#21) from the app
creator. Its Quit sends ViewportCommand::Close, which guard_quit
handles like the close button. If the menu can't be built, winit's
menu stays and a warning is logged.

craft-quit is pinned to the head of craft-libs#21 until #5 and #21
are merged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(macos): closing the window quits through terminate: (#1136)

On Touch Bar Macs the close button crashed PdfCraft (exit 133,
-[_NSTouchBarFinderObservation invalidate]): eframe drops the window
inside AppKit's run loop. craft_quit::on_close_request, right after
guard_quit in `logic`, cancels an allowed close and quits through
-[NSApplication terminate:] instead. A close that guard_quit holds for
the unsaved-changes prompt is left alone. Elsewhere it does nothing.

craft-quit moves to the workspace dependencies, pinned to craft-libs
main (f58bc1a, with #5 and #21 merged) instead of #21's head.

The on_close_request change and its Touch Bar test are from jmacek.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-15 03:15:34 -04:00
7461c29791 MCP: confine file access with --automation-read-root and --automation-write-root (#1448)
* Automation: check the read and write roots on every path a tool reads or writes

* CLI: add --automation-read-root and --automation-write-root to mcp

* Docs: document --automation-read-root and --automation-write-root for mcp

* #1448: count main's doc_batch helpers as resolved by their caller

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 03:11:12 -04:00
a790a046a5 M7: keep line breaks when editing a multi-line paragraph (#1443) (#1486)
Adding a word to a multi-line paragraph merged or reflowed its lines.
Two causes:

- Chrome/Skia subset fonts leave glyphs of the /DW width out of /W.
  has_glyph treated those CIDs as missing, so words containing them
  measured short, run calibration inflated, unchanged rows rewrapped
  and new letters fell back to Helvetica. A composite subset with an
  explicit /DW now counts a ToUnicode-mapped CID absent from /W as
  present.
- Text drawn turned on the page (landscape pages drawn a quarter turn
  round) was joined into lines and rows along the page's x axis, so the
  whole paragraph became one line. Lines, rows and blocks are now found
  along each text's own baseline (identical values for upright text), a
  turned paragraph is rewritten in its own text space, and that rewrite
  keeps explicit line breaks. Formatting part of turned text is refused
  instead of being misplaced.


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

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-15 03:10:46 -04:00
02a4d81a22 Keep selected form values and page content through later edits (#1319, #1305, #1324, #1306) (#1452)
* Keep selected form values and page content through later edits (#1319, #1305, #1324, #1306)

An XFA radio item whose text contains a space was written back as an appearance-state name, so the next layout selected nothing. Replace Pages filled the gap between a split selection. Marking a figure decorative replaced every content stream on the page. Control clicks and drags accepted coordinates that overflow to infinity.

* Move the decorative-figure regression out of pdfcraft-edit

edit and a11y are both layer 4, so a dev-dependency from edit to a11y fails the layer check. The same regression now runs in the engine, which already depends on both.

* Drop pdfcraft-a11y from the edit crate's lockfile entry

* Run a tool after a background open of the file it asked for

A tool chosen with no document opened the picked file on the worker, but only ran when that open finished inside the picker callback. Remember the command on the pending open, and let the command test wait for the worker.

* Wait for background opens in the command tests

Opening a picked file or a recent file finishes on the worker, so a fixed handful of frames can assert before the tab exists.

* Compare batch copies to the PDF that was written

A new text PDF stamps the current second, so a later pdf() call is a different file. The numbered copy and the source must match the bytes that were saved.

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 03:05:21 -04:00
9b6dab142f M10: Windows print jobs show per-sheet progress; printers list faster (follow-up to #944) (#1236)
* M10: Windows print jobs show per-sheet progress; printers list faster

Follow-up to #944, carrying the two parts main doesn't have yet.

- The progress card follows a job being spooled and counts its sheets
  as they reach the spooler ("Sending sheet 2 of 3 to Office…"), using
  craft-print's new submit_with_progress. It replaces the "Sending to…"
  toast, leaves another long job's card alone, and goes when the job
  ends; the spooler's answer is still a notice.
- craft-print bumped to storytold/craft-libs#27, which also lists
  Windows printers through .NET's PrinterSettings (the API jobs spool
  with) instead of a CIM query of Win32_Printer.
- "Sending sheet {s} of {n} to {printer}…" in all 20 catalogs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Refresh catalog hashes after merging main

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-15 03:04:29 -04:00