304 Commits

Author SHA1 Message Date
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 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 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 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 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
bmh129 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
nleva 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
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
Piohrun ba01244987 M6: calculations read their notation only from a comment, and a regex after a condition as a regex (#3993)
* M6: calculations read their notation only from a comment, and a regex after a condition as a regex

Two findings from CodeRabbit's review of #3550, both reproduced first:

- parse_calculate and calculation_sites found BVCALC and EVCALC anywhere
  in the script, so `var s = "BVCALC a EVCALC";` read as the notation `a`:
  renaming `a` rewrote the string, and the form calculated `a` instead of
  running the script. The lexer now keeps the text of each comment, and
  the notation is read from the first comment that holds BVCALC and the
  EVCALC after it (notation_range), by both the Calculate tab and a
  rename. A line comment counts, and a comment that never ends runs to
  the end of the script, as before.
- A `/` after any `)` divided, so after the condition of `if`, `while`,
  `for` or `with` a regular expression was read as code: renaming `a`
  rewrote `if (flag) /getField("a")/.test(x)`, and in
  `if (flag) /"/.test(x)` the quote started a string that hid the
  script's real getField calls. The lexer now notes which `(` opened
  such a condition (not a method of that name, `o.if(x)`), and a `/`
  after its `)` starts a regular expression.

af::tests::notation_is_read_only_from_a_comment,
af::tests::a_regex_after_a_condition_is_not_read_as_code and
tests::a_script_that_spells_the_markers_in_a_string_runs_as_a_script
fail without the fix. Parity, ROADMAP.md and docs/roadmap.md updated.

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

* M6: form.props-calculate notes that a regex right after a brace is still read as code

From CodeRabbit's review of this PR. The lexer still divides after `}`,
which ends a block as often as an object literal, so in
`if (x) { } /"/.test(s); event.value = getField("a").value;` the quote
starts a string and the getField is hidden from a rename and from the
calculation order. Checked with a scratch test before writing it down.

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

* M6: a line comment ends at any line terminator, so code after `\r` is still read

From CodeRabbit's review of this PR. A `//` comment ran to the next `\n`,
so with `\r` line endings it hid the rest of the script: a rename missed
the getField calls after it (since #3550), and a string after it that
spells BVCALC ... EVCALC read as the notation. A `/` taken for the start
of a regular expression likewise looked past `\r` for its end, and could
swallow the next line's code.

Both now stop at any of JavaScript's line terminators (`\n`, `\r`,
U+2028, U+2029; line_ends_at), and U+2028 and U+2029 between tokens are
skipped rather than read as the start of a word.

af::tests::a_line_comment_ends_at_any_line_terminator fails without each
of the three changes: with `\r`, the string read as notation `a`; with
the comment fixed but not the regex scan, `i++ / 2;\r` swallowed the
getField after it; without skipping U+2028, the getField after it was
not a call.

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

* M6: a word, number or regex's flags end at U+2028 and U+2029

From CodeRabbit's review of this PR. The scans for an identifier, a
number and a regular expression's flags took every byte past ASCII as
part of a word, U+2028 and U+2029 included, so in `x\u{2028}getField("a")`
the getField was part of one word and not a call: a rename missed it, and
the calculation order didn't read it.

`word` now takes a position and is false where line_ends_at is true, so
the three scans share one rule. The arm that skips U+2028 and U+2029
between tokens stays: without it, the punctuation arm would step one byte
into the character.

af::tests::a_token_ends_at_a_line_separator fails without the fix, for a
word, a number and a regex's flags alike; it and
a_line_comment_ends_at_any_line_terminator fail without the skipping arm.

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

* M6: the `while` that ends a `do` loop counts as a condition, said and tested

A `/` after the `)` of a do-while starts the next statement, so it starts a
regular expression there too. The comment on BEFORE_CONDITION says so, and
a_regex_after_a_condition_is_not_read_as_code covers it (from review).

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 10:42:48 -04:00
skylar taylor-barrick adea2c908a M14: recover existing macOS PDF associations after open and save (#3558)
* M14: recover existing macOS PDF associations

* M14: address macOS association recovery review

* M14: reuse upstream save metadata preservation
2026-10-22 15:49:13 -06:00
PerchAnton c5279baf35 M6 PR #2648: retain active-XFA script isolation with current main 2026-10-22 20:21:39 +03:00
PerchAnton d323e86706 M7 PR #3000: retain batched styled fallbacks with current main 2026-10-22 20:11:21 +03:00
jonathanwxh-cell 17f84e4391 Merge main into feat/optimize-compatibility-version
Retain compatibility regression coverage with upstream content-boundary and image-size tests.
2026-10-22 21:34:02 +08:00
aiongg 472717fcd7 Merge upstream main 88dad98dd into next
# Conflicts:
#	ATTRIBUTION.md
#	ATTRIBUTION.toml
#	crates/engine/src/dates.rs
#	crates/ui-egui/src/i18n/ar.tsv
#	crates/ui-egui/src/i18n/bg.tsv
#	crates/ui-egui/src/i18n/cs.tsv
#	crates/ui-egui/src/i18n/de.tsv
#	crates/ui-egui/src/i18n/el.tsv
#	crates/ui-egui/src/i18n/es.tsv
#	crates/ui-egui/src/i18n/fr.tsv
#	crates/ui-egui/src/i18n/hu.tsv
#	crates/ui-egui/src/i18n/it.tsv
#	crates/ui-egui/src/i18n/ja.tsv
#	crates/ui-egui/src/i18n/kk.tsv
#	crates/ui-egui/src/i18n/lt.tsv
#	crates/ui-egui/src/i18n/mod.rs
#	crates/ui-egui/src/i18n/pl.tsv
#	crates/ui-egui/src/i18n/pt-br.tsv
#	crates/ui-egui/src/i18n/ru.tsv
#	crates/ui-egui/src/i18n/sl.tsv
#	crates/ui-egui/src/i18n/te.tsv
#	crates/ui-egui/src/i18n/tr.tsv
#	crates/ui-egui/src/i18n/uk.tsv
#	crates/ui-egui/src/i18n/vi.tsv
#	crates/ui-egui/src/i18n/zh-hans.tsv
#	crates/ui-egui/src/i18n/zh-hant.tsv
#	crates/ui-egui/tests/fonts.rs
#	docs/localization-parity.md
#	docs/localization.md
#	docs/roadmap.md
#	parity/acrobat-features.toml
2026-10-22 05:22:09 +00:00
aiongg fb05fda269 Integration: ROADMAP.md, docs/roadmap.md, docs/gaps.md merged line by line
The track merges used a union driver for these files, which kept two
versions of a milestone row or status line wherever two tracks changed the
same one. They are recomputed as base plus each track's changes, with two
edits of one line combined into one line. The status lines that #2805, #3808
and #3532 put above the Stage line join the status list below it, newest
first.
2026-10-22 02:30:24 +00:00
aiongg ad04768906 Merge r2 track t17: choice-pass takes
# Conflicts:
#	ATTRIBUTION.md
#	ATTRIBUTION.toml
#	apps/pdfcraft/src/main.rs
#	crates/engine/src/dates.rs
#	crates/fonts/src/lib.rs
#	crates/ui-egui/src/canvas.rs
#	crates/ui-egui/src/i18n/mod.rs
#	crates/ui-egui/src/system_fonts.rs
#	crates/ui-egui/src/theme.rs
#	crates/ui-egui/tests/content.rs
#	crates/ui-egui/tests/fonts.rs
2026-10-22 02:25:34 +00:00
aiongg 2c13fd9373 Merge r2 track t16: mixed: automation-mcp, crate:misc, crypt-security, export-convert, optimize, preflight-pdfa, save-io
# Conflicts:
#	ATTRIBUTION.toml
#	contributors/people.toml
#	crates/automation/src/comments.rs
#	crates/edit/src/tests.rs
#	crates/engine/src/tests.rs
#	parity/acrobat-features.toml
2026-10-22 02:23:58 +00:00
aiongg dcf2802f96 Merge r2 track t15: mixed: accessibility-tags, dialogs-prefs, javascript, organize-pages
# Conflicts:
#	crates/edit/src/tests.rs
#	crates/engine/src/tests.rs
2026-10-22 02:23:22 +00:00
aiongg 3cf35888d7 Merge r2 track t12: i18n, i18n: new language catalogues
# Conflicts:
#	ATTRIBUTION.toml
2026-10-22 02:21:42 +00:00
aiongg 123b214180 Merge r2 track t10: xfa 2026-10-22 02:21:06 +00:00
aiongg 2363b0619b Merge r2 track t09: print
# Conflicts:
#	ATTRIBUTION.toml
#	crates/ui-egui/src/lib.rs
2026-10-22 02:21:06 +00:00
aiongg 69e755c439 Merge r2 track t08: fonts
# Conflicts:
#	crates/automation/src/tools.rs
#	vendor/README.md
2026-10-22 02:20:50 +00:00
aiongg 4d5025c6da Merge r2 track t07: text-extract-select
# Conflicts:
#	crates/edit/src/tests.rs
#	crates/render/src/raster.rs
#	vendor/README.md
2026-10-22 02:20:03 +00:00
aiongg a2c46a9298 Merge r2 track t06: annotations-comments
# Conflicts:
#	crates/automation/tests/automation.rs
#	crates/render/src/raster.rs
2026-10-22 02:19:23 +00:00
aiongg 8724f6b1a5 Merge r2 track t05: forms
# Conflicts:
#	crates/engine/src/tests.rs
#	crates/ui-egui/src/canvas.rs
#	crates/ui-egui/src/forms_ui.rs
#	docs/ui-parity.md
2026-10-22 02:18:46 +00:00
aiongg 0bba8dcafb Merge r2 track t04: render 2026-10-22 02:18:22 +00:00
aiongg 2bd66fbe90 Merge r2 track t03: viewer-ui
# Conflicts:
#	crates/automation/tests/automation.rs
#	crates/engine/src/tests.rs
#	crates/ui-egui/src/content_ui.rs
#	crates/ui-egui/src/edit_text_ui.rs
#	crates/ui-egui/src/fill_sign.rs
#	crates/ui-egui/src/forms_ui.rs
#	crates/ui-egui/tests/editing.rs
2026-10-22 02:18:22 +00:00
Aleksander Helgaker 88dad98dd4 M14: add Norwegian Bokmål interface and date language (#1836)
* M14: add Norwegian Bokmål interface and date language

A 2,592-entry `nb.tsv` covering every key the other bundled catalogs have,
written from the meaning of the English labels (clean-room); terminology
reviewed by a native-speaking contributor. Registers `nb` with the English
one/other plural rule, adds Norwegian month and weekday names for Fill &
Sign dates, resolves `no` and `nn` locales to Bokmål until a Nynorsk catalog
exists, attributes the catalog and records it in parity.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* M14: translate the strings main added since the Norwegian catalog was written

69 keys (signature appearance labels, word count, full-screen prompt, print
as image, image crop, redaction mark appearance, …) and the attribution hash.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* M14: translate the picture-menu and label-paper strings in the Norwegian catalog

Seven keys main added (Cut/Redact Image, Create Link…, Recognize Text…,
Turn upside down, the 4 x 6 in label paper) and the attribution hash.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* M14: translate the page-group folding commands in the Norwegian catalog

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* M14: drop the superseded localization summaries left beside the current ones

Concurrent merges on main left older copies of several localization
summaries next to their replacements. Review of #1836 flagged them:

- localization-parity.md: remove the 2026-10-13 status line and the
  14-language summary that still listed Norwegian as missing; the
  current summary keeps the Italian (and now Norwegian Bokmål)
  measurement dates.
- localization.md: keep one catalog-coverage paragraph (now naming
  Norwegian Bokmål, up to about 2,700 entries) and one font paragraph.
  The font paragraph folds in what only the older copies said: the
  installed Chinese face fallback (#826) and Slovenian's Latin faces and
  four plural forms.
- roadmap.md: end the M14 Missing list before the Fontconfig note.

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

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: aiongg <67543387+aiongg@users.noreply.github.com>
Co-authored-by: aiongg <aiongtaigi@gmail.com>
2026-10-21 22:05:23 -04:00
aiongg e1652d5dbe Merge PR #3540: Render: radial luminosity fades have regression coverage
ROADMAP.md: progress log union, newest first
docs/roadmap.md: main's M2 notes with the PR's sentence appended
2026-10-22 01:52:42 +00:00
aiongg eec82da6a2 Merge PR #2060: fix(ui): respect reading background while pages load 2026-10-22 01:52:27 +00:00
aiongg b2f913a7b6 Merge PR #3438: fix(render): use unfiltered inline image byte length before EI heuristic (#3107)
docs/roadmap.md: main's M2 notes with the PR's sentence appended
ROADMAP.md: the PR's progress-log line moved to the top (newest first)
2026-10-22 01:52:27 +00:00
aiongg 13b21c7f64 Merge PR #2227: M14: add Catalan interface and date localization
crates/engine/src/dates.rs, crates/ui-egui/src/i18n/mod.rs: both sides' language rows, arrays sized 27.
crates/ui-egui/tests/fonts.rs: both catalog lists; Catalan added to main's comment.
ATTRIBUTION.toml/.md: both sides' assets; hashes and counts regenerated after all merges.
ROADMAP.md: both log lines.
docs/localization-parity.md: main's rows plus the ca row; 27 interface languages; both revision rows.
docs/localization.md: main's text with Català, the ca locales, code and catalog paragraph added.
2026-10-22 01:52:24 +00:00
aiongg 2530f52d22 Merge PR #3101: feat(viewer): add optional gapless continuous page display
Conflict resolutions:
- ATTRIBUTION.toml: main's entries kept; #3101's page-gap provenance note appended to the 22 catalogs it translates (hashes recomputed separately).
- ATTRIBUTION.md: main's side kept; regenerated from ATTRIBUTION.toml separately.
- ROADMAP.md: #3101's two 2026-10-18 progress-log lines placed after the 2026-10-19 entries.
- docs/roadmap.md: both 2026-10-18 status lines kept; M3 row carries both sides' insertions.
2026-10-22 01:52:18 +00:00
aiongg be19528dca Merge PR #3735: M4: resolve indirect initial-view boolean preferences
Conflicts:
- ROADMAP.md, docs/roadmap.md: the PR's progress-log entry, revision row and status line added on top
2026-10-22 01:49:09 +00:00
aiongg 88c21daaed Merge PR #2615: fix(xfa): enforce maxLength on rich-text fields
ROADMAP.md, docs/roadmap.md: all status lines and progress-log lines kept; M12 row takes both 'Done since' insertions.
parity/acrobat-features.toml: form.xfa evidence lists unioned, notes take both sides' insertions.
2026-10-22 01:48:32 +00:00
aiongg aa6b39513a Merge PR #2321: fix(optimize): reject hostile image dimensions safely
ROADMAP.md: progress-log line added at the top
docs/roadmap.md: the M11 note applied onto main's row (which #3622 extended)
crates/optimize/tests/optimize.rs: new tests appended after main's
2026-10-22 01:48:29 +00:00
aiongg 9865f27d8c Merge PR #2619: fix(xfa): run click scripts for every repeated print button
ROADMAP.md, docs/roadmap.md: both status lines and progress-log lines kept; M12 row takes both 'Done since' insertions.
crates/automation/tests/automation.rs, crates/xfa/src/fixtures.rs: union of #2624's and #2619's tests and fixtures.
parity/acrobat-features.toml: form.xfa evidence lists unioned, notes take both sides' insertions.
2026-10-22 01:48:18 +00:00