Commit Graph
327 Commits
Author SHA1 Message Date
alehelandClaude Opus 5.5 dc224884cb refactor(engine): gather lib.rs's imports and re-exports under the module list
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:10:38 +01:00
alehelandClaude Opus 5.5 51fbed293b refactor(engine): move the test-only hooks to test_hooks.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:09:57 +01:00
alehelandClaude Opus 5.5 8ca4bf641f refactor(engine): move the page filters to page_filter.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:09:38 +01:00
alehelandClaude Opus 5.5 fc6072154d refactor(engine): move the Fill & Sign geometry helpers to fill_sign.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:09:23 +01:00
alehelandClaude Opus 5.5 94b6110819 refactor(engine): move placed pictures and mark sources to pictures.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:09:11 +01:00
alehelandClaude Opus 5.5 8473403a5d refactor(engine): move layer visibility to layers.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:08:38 +01:00
alehelandClaude Opus 5.5 4972a4e1eb refactor(engine): move the bookmark list rows to bookmarks.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:08:14 +01:00
alehelandClaude Opus 5.5 20974e7822 refactor(engine): move the combine and page-source helpers to sources.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:08:01 +01:00
alehelandClaude Opus 5.5 71dccdda50 refactor(engine): move the comment list and summary to comments.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:07:23 +01:00
alehelandClaude Opus 5.5 748b20abb9 refactor(engine): move the XFA form helpers to xfa_form.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:05:58 +01:00
alehelandClaude Opus 5.5 ff361fe138 refactor(engine): move Document and its display helpers to document.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:05:07 +01:00
alehelandClaude Opus 5.5 5b75180759 refactor(engine): move Session and its operations to session.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:02:51 +01:00
alehelandClaude Opus 5.5 f148915730 refactor(engine): move the other crates' re-exports to reexports.rs
The doc comment for SplitPart had drifted above the LabelStyle re-export; it is back on SplitPart.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:02:51 +01:00
alehelandClaude Opus 5.5 05098de542 refactor(engine): move the open pipeline to open.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:02:51 +01:00
alehelandClaude Opus 5.5 631fc13f13 refactor(engine): move protection and the security summary to protection.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:02:51 +01:00
alehelandClaude Opus 5.5 58e7e36717 refactor(engine): move the Edit enum, its labels, permission check and runner to edit.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:02:50 +01:00
alehelandClaude Opus 5.5 7e72b583ed refactor(engine): move EditError and SourceProblem to error.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:02:50 +01:00
alehelandClaude Opus 5.5 ecf6231416 refactor(engine): move undo/redo state and labels to history.rs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 23:02:50 +01:00
mtlcl410andClaude Opus 5.5 6918d0be21 M6: a static XFA form whose data fills thousands of fields opens in seconds (#4638)
Opening a static XFA form gives its fields the values in its datasets
(a form filled in by another application). Each value went through
forms::set_value, which reads the whole field tree to find the field,
writes it, and recalculates, reading the tree again. With n values that
is about 2n readings of n fields: quadratic. A public 136-page form with
about 6,000 fields took 261 s to open, a 95-page one with about 4,000
took 112 s; 8,000 synthetic fields took over ten minutes.

forms::set_values fills a batch as set_value fills each in turn, reading
the form once and recalculating once after the last value (the
calculation order, ISO 32000-2 Table 224 /CO, runs once over the final
values). Fields with the same fully qualified name (12.7.4.2) still share
the value. A name the batch already wrote, or a twin of it, makes the
form be read again first, so each write starts from what the earlier one
left, as one by one. Each value reports its own result; a failed
recalculation fails the batch, as it fails set_value. The engine collects
the changed values and fills them with set_values, finding fields by name
through a map rather than a scan.

The two forms now open in 4 s and 3 s, with the same fields, values,
warnings and document information as before; 8,000 synthetic fields open
in 1.5 s.

Tests: set_values matches set_value one by one (values, twins, the
calculated total, every appearance, saved; refusals for an unknown name,
a read-only field, an unknown option and clearing a no-toggle-off radio
group the batch selected); it reads the form a fixed number of times; the
engine takes 59 data values on a 60-field static form exactly as filling
them one by one does (the read-only one refused); and opening 800 fields
takes under 16 times as long as 100 (about 4x now, about 48x before).


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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 10:02:35 -04:00
.CooCoo 0db7d57619 Tests: XFA calculation tests no longer fail when the machine is busy (#4535)
Five XFA tests failed at random on a busy machine. The scripts of an
opening or a change share a 3 s wall-clock budget (a click's share 5 s),
each script has 1 s or 3 s, and the engine has 10 s to start; under load
the tests went past one of them, and the scripts they check were skipped
or did not start.

Session::with_xfa_time_scale (and Automation::with_xfa_time_scale)
multiplies each of these limits for a test; the default stays 1. The
script session counts the engine threads it starts on the calling thread
(xfa_session::engines_started).

The hundreds-of-calculations tests run with the limits raised, and the
engine's test now checks that opening starts one engine and a change one
more. A new test sets the factor to 0 and checks that the budget skips
all 210 calculations and says so. Three more tests that failed the same
way under load run with the limits raised.
2026-10-25 10:02:00 -04:00
jonathanwxh-cell 24edde6563 forms: clear typed XFA password field values from datasets on save (#3944) (#4506) 2026-10-24 21:08:21 -04: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 f94b34adc9 Integration: fix(redact,cos): cleared redaction marks leave nothing behind (#4226) 2026-10-24 22:48:11 +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
.CooCoo 2ac1df2f1f M4: Document Properties has a Custom tab for custom properties (#4387)
* M4: Document Properties has a Custom tab for custom properties

Document Properties has a new Custom tab between Fonts and Advanced. It
lists the document's custom properties, and Name and Value fields with
Add, Update and Delete edit the list. Clicking a listed property fills
the fields with it. OK writes the changes through SetInfo in the
existing "Change document properties" step, so one undo reverts them
with the other tabs' changes.

Add is off for an empty value, a name already listed, a name that
check_custom_key refuses (its message is the button's tooltip), and a
name the file already uses for an entry the list leaves out (not text,
only padding, or past the 256 listed). A property already in the file
under a refused name or a name that is not UTF-8 is listed, and Add,
Update and Delete stay off for it, so OK cannot fail on it or write a
different key.

Clearing an /Info entry now removes it when /Info is a dictionary
written directly in the trailer. set_info_entry returned without a
change there, so a delete in the Custom tab, a cleared Description field
and a doc_set_info clear left the entry in the file. It now writes a
copy without the entry as a new indirect /Info.

The engine re-exports check_custom_key and adds Document::has_info
(organize::has_info). set_option("dialog", "custom") opens the tab.

* Contributors: add dotCooCoo (Robert Lee)

* M4: Add in the Custom tab stops at the 256 properties the tab lists

Document Properties > Custom lists at most 256 properties, so a property
added past that was saved but left out of the list when the dialog opened
again. Add is now off once the tab's list or the file's own list holds 256;
a new name goes after the file's entries, so a file with more than 256 keeps
Add off after a Delete as well.
2026-10-24 10:30:25 -04:00
alehel c16956f539 Merge origin/main into fix/comment-threads-by-irt
main's #4284 stopped hashing translation catalogues in ATTRIBUTION.toml; the
conflict took main's side (no sha256 lines) and kept this branch's source notes.
2026-10-24 11:31:20 +02:00
aiongg f9a179fee0 Merge integration batch B's review fixes 2026-10-24 08:26:10 +00:00
aiongg afa14c3b98 Merge integration batch A's review fixes 2026-10-24 08:26:10 +00:00
aiongg 29889fc1e0 Integration: list the attachment edit labels for translation (#1960)
"Attach {name}" and "Delete attachment {key}" were missing from EDIT_LABELS, so the translation-gap report left them out.
2026-10-24 08:20:44 +00:00
aiongg b04257d5eb Integration: a typed Password-field value stays in the open document after Save (#3943)
Recording a save reopens the saved file, which carries no Password values; they are put back in memory only, so the next save still omits them.
2026-10-24 08:15:01 +00:00
aiongg deffc376cf Integration: #2588 keep XMP-only document information across full refreshes
Session::refresh_with_indexes fills title, author and the other fields from XMP as build_document does; the test applies an edit and an undo and checks they stay.
2026-10-24 07:10:11 +00:00
aiongg b232ed217c Merge PR #2588: M3: Document Properties shows a title and author stated only in XMP (#2373) 2026-10-24 07:00:29 +00:00
aiongg f053da3d93 Merge PR #1960: Attachments: attach a file and delete one (panel, edit, tools); duplicate names numbered as text
i18n ca, fi, hi, id, ko, ro, sq .tsv: kept both sides' rows (no duplicate keys).
2026-10-24 07:00:24 +00:00
aiongg 6a206a0a2e Merge track r3-t05 2026-10-24 06:48:48 +00:00
aiongg 9705e7a6c1 Merge track r3-t03 2026-10-24 06:39:33 +00:00
aiongg a05dbdcb1e Merge track r3-t02 2026-10-24 06:38:46 +00:00
aiongg 880723e3af Merge PR #4266: M7: added text takes character spacing from Format text
crates/engine/src/lib.rs: union of the added:: re-exports (paste_place/paste_rect from #4230, CHAR_SPACING_LIMIT).
crates/ui-egui/src/content_ui.rs: editor keeps #4178's anchored width and horizontal_align and #4266's spacing layouter; spaced_job takes the alignment so the custom layouter keeps it.
crates/ui-egui/tests/it/content.rs: kept both tests.
2026-10-24 06:24:10 +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 f2c133b987 Merge PR #4258: M7: a batch of content edits refreshes the added content and page marks 2026-10-24 06:22:48 +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 2a1ceebb4f Merge PR #4339: M6: fields that don't scroll stop taking text when full
parity/acrobat-features.toml: form.fill-text-field evidence is the union of both sides; notes keep both sides' sentences (DoNotScroll clause and the Password sentence).
2026-10-24 06:22:02 +00:00
aiongg c0687edbbe Merge PR #3552: M12: a date typed by another of an XFA field's edit patterns is kept in its first 2026-10-24 06:22:01 +00:00
aiongg 01dc49c13c Merge PR #4053: fix: Issue #4018, form_fill warns when a value does not fit its field (#4018)
crates/forms/src/tests.rs: append conflict, kept both tests.
2026-10-24 06:21:41 +00:00
aiongg b6b6e6eca3 Merge PR #3943: M6: values typed into Password fields are written to no file (#3926)
crates/forms/src/tests.rs: append conflict, kept both tests.
2026-10-24 06:21:33 +00:00
a047c6ba09 chore: resolve SonarCloud maintainability issues (#4356)
* chore: resolve SonarCloud maintainability issues

* fix(packaging): use verify_sha256 helper function

* style: cargo fmt

* fix: restore wildcard imports and fix method-reference type errors

Revert the glob-import expansions (they missed SomIndices and left unused
imports), revert char::is_ascii_digit where the iterator yields char by
value, and pass the content slice to prune_doomed_xobjects as &[Vec<u8>].

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

* Keep XObject decodability check without binding content in interp

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Dylan Taylor <dylan@craftmaker.dev>
2026-10-23 23:28:18 -04:00
Eric Kaden 64bdea4e61 M6: fields that don't scroll stop taking text when full 2026-10-23 19:25:32 -04: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
alehelandClaude Opus 5.5 23f487b7f3 fix(cos,engine): saving leaves out what was added and removed again
An incremental save wrote every object added during the session, whether
anything still referred to it or not. A redaction mark added and then
cleared (or a comment added and deleted) was therefore written into the
file as an unreferenced object, with its QuadPoints, overlay text and
author.

`SaveOptions::drop_unlinked` writes such additions as free entries instead:
objects whose numbers the file never used and that nothing the update
writes refers to, walked from the trailer and the file's changed objects
through additions only. `/Size` and the numbering stay as before, so undo
past the save can bring an object back under its number. The option is off
by default because the standalone document timestamp is found by scanning,
not by reference; `Session::save_bytes` (Save, and the automation save)
turns it on. Full saves already left these objects out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:54:52 +02:00
Marco Arnulfo cd6f031b82 M7: added text takes character spacing from Format text (fixes #4245) 2026-10-23 17:31:02 +02:00
Osvaldo Duran MelendezandClaude Opus 5.5 dd396c2096 Merge upstream main 57e531cc into pr/attachments
Only ATTRIBUTION.toml met this branch: main's copy, hashes recomputed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 11:31:00 -04:00