Commit Graph
269 Commits
Author SHA1 Message Date
Combiler01 42b2a3ebdb fix(fonts): subset added TrueType fonts to used glyphs on document save 2026-10-25 15:35:28 +05:30
Combiler01 9579a217a8 Fixed 3 Must Fix Bugs 2026-10-24 15:12:26 +05:30
Combiler 9ff83883eb Merge branch 'main' into main 2026-10-24 04:40:50 +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
Combiler e85c654ead Merge branch 'main' into main 2026-10-23 16:06:49 +00:00
mtlcl410andClaude Opus 5.5 e6b9792539 M4: bookmarks show and set their title colour and style (ISO 32000-2 Tables 151, 152) (#4171)
* M4: the Bookmarks panel shows each bookmark's colour and style (#3193)

ISO 32000-2 §12.3.3: an outline item's /C is "An array of three numbers
in the range 0.0 to 1.0, representing the components in the DeviceRGB
colour space of the colour that shall be used for the outline entry's
text" (Table 151), and its /F flags say italic (bit 1) and bold (bit 2)
(Table 152). Both were ignored: every title was drawn in the theme's
text colour and face.

The inspector (OutlineItem) and the bookmark list (organize::Bookmark,
used once a document is edited) now read them: each component is kept
within 0-1, and black (the default) or a /C that isn't three numbers
reads as no colour. The panel draws bold titles in the semibold face,
italic ones slanted, and the colour as given, lightened towards the text
colour only as far as it needs to read on the panel (3:1), so dark blue
stays visible in the dark theme. bookmark_list reports color, bold and
italic where they differ from the defaults.

Mutants, each failing a test: italic or bold bit ignored (both readers,
the panel), black kept as a colour, no clamping, a four-number /C
accepted, colour ignored or truncated in the panel, the contrast floor
removed, always jumping to the text colour. Checks for non-finite
numbers were equivalent (clamping already covers any size), so they
are gone.

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

* M4: set a bookmark's style and colour from its menu or bookmark_set_style (#3193)

#3193 asks for a way to mark bookmarks by colour, for example chapters
that are rarely used. ISO 32000-2 §12.3.3 gives every outline item a
title colour (/C, Table 151, DeviceRGB, default black) and style flags
(/F, Table 152: bit 1 italic, bit 2 bold, default 0); the previous
commit shows them, and this one lets the user change them.

- organize: set_bookmark_color writes /C, removing it for black (the
  default) and refusing a component outside 0-1; set_bookmark_style
  sets or clears the bold and italic bits, keeps any bit the table
  doesn't define, and removes /F when no bit is left.
- engine: SetBookmarkColor and SetBookmarkStyle edits, undoable, under
  the same assemble permission as the other bookmark edits. Their undo
  labels are the menus' own names, already translated in every
  catalogue.
- ui-egui: the bookmark menu gains Style (Bold and Italic check boxes)
  and Colour (the comment swatch grid, with Other colour...). Only
  existing UI strings are used.
- automation: bookmark_set_style takes any of color ([r, g, b], 0-1),
  bold and italic, and changes only what it is given.

Mutants, each failing a test: no range check (library and tool), black
kept as /C, a bit not set, a bit not cleared, an untouched bit cleared,
/F 0 written, the bits swapped (library and menu), the tool accepting
nothing to change or ignoring bold/italic, the menu's colour ignored.

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

* M4: a colour and a style set in one bookmark_set_style call are one undo step (#3193)

Review on #4171 (CodeRabbit). Given both, the tool applied two edits,
so undo took back only the style and left the colour, and a failing
second edit left the first applied. They now go in one Edit::Batch
named "Style", all or nothing. "Colour" and "Style" join EDIT_LABELS,
and "Style" BATCH_LABELS, so the history can translate them.

The test sets colour and style together and undoes once; with the two
edits applied separately it fails.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 10:42:59 -04:00
Jayesh Prajapati 8af35de464 M5: stamp_custom places a picture fitted inside a rect (#4077) (#4233)
* M5: stamp_custom places a picture fitted inside a rect

stamp_custom only centred a PDF page or image at its natural size, at
most 200 pt, so a vector diagram could not be placed at a text column's
width. It now takes rect [x0, y0, x1, y1] (displayed-page points, like
at) as an alternative to at: the picture is scaled to fit inside the
box, keeping its shape, and centred in it. A PDF page stays a form
XObject, so it remains vector.

- Engine: Edit::AddCustomStamp fits the picture inside a non-point rect
  instead of stretching it (fit_picture). A box already of the
  picture's shape is kept exactly, so signatures and other callers that
  size the box themselves are unchanged. The displayed sides are
  swapped on quarter-turned pages, as for the natural size.
- Automation: rect is validated (four finite numbers, each side
  at least 1 pt and at most 14400 pt, the largest PDF page; not clipped
  to the page, like at); passing both at and rect,
  or neither, is refused. path still goes through the read root.
- Tool schema and description, parity note and evidence.

Fixes #4077

* M14: update ctutils to 0.4.5 for RUSTSEC-2026-0385

The dependency-advisory gate rejects ctutils 0.4.2 (non-constant-time
mask generation and u128 comparisons, fixed in 0.4.4). It comes in
through crypto-bigint for the signing crates. Only its version and
checksum change in Cargo.lock.

(cherry picked from commit 8a687ee2c6012e3d18399633d2fb9fb3742f02ae)
2026-10-23 10:42:20 -04:00
Jayesh Prajapati 6765ae0b5c M11: Convert to PDF/A needs the owner's permission on an encrypted document (#3921) (#4203)
Save as PDF/A removes the encryption (PDF/A forbids it), but it was gated
only by the modify permission, so a document opened with the user password
whose owner withheld printing or copying could be saved unencrypted with
every restriction gone. It now needs the same rights as Protect and Remove
security, also inside a batch.

Fixes #3921
2026-10-23 10:42:14 -04:00
Combiler01 3641801f13 Fixes: Refactored System not opening for Added/Pasted Images 2026-10-23 14:49:01 +05:30
Combiler01 e4476b007d Fix:Added Image don't follow the Refactored Edit_image 2026-10-23 13:08:57 +05:30
Combiler01 91c575b1df Merge remote-tracking branch 'upstream/main'
# Conflicts:
#	crates/edit/src/images.rs
#	crates/engine/src/tests.rs
#	crates/xfa/src/script.rs
2026-10-23 11:08:12 +05:30
Combiler01 2a9f7eb862 Fixes suggested by Reviewers 2 2026-10-23 10:28:47 +05:30
aiongg 22aa6d5f9a fix(redact): place glyphs with the inherited and ExtGState-set text state
The redaction interpreter started every form XObject with an empty text
state (no font, size 0, no spacing) although a form inherits its caller's
graphics state, and it ignored the /Font entry of an ExtGState set by gs.
Text shown that way was placed at the wrong positions, so removal and
the verify pass could both miss glyphs under a mark. Forms now start
from the caller's state, and gs sets the font and size as Tf does.

The engine's renderer cross-check test used the gs case as its example
of interpreter/renderer disagreement; it now runs the check directly on
an unredacted page, which also covers an input stream labelled as a
redaction overlay.
2026-10-22 15:17:44 -04:00
aiongg 6ca4431b50 fix(redact): check every input content stream, whatever it calls itself
Both checks for text left under applied redaction marks (redaction's own
verify pass and the engine's renderer cross-check) skipped any page
content stream whose dictionary said /PCMark /Redaction, so that the
overlay's label would not count. An input file could put that label on
its own content stream and keep it out of both checks. Applying
redactions now records the overlay streams it adds (stamp returns the
new stream), and only those are skipped.
2026-10-22 15:17:44 -04:00
Combiler01 dea68e6350 Fixes Suggest by Reviewers 2026-10-23 00:21:21 +05:30
Combiler 5c8db57e5c Merge branch 'storytold:main' into main 2026-10-22 17:32:38 +00:00
aiongg 77480498b2 fix(engine): low-resolution printing prints only the chosen content
Pages printed as pictures were drawn with everything on them, so form fields only
printed the page content, and the document with stamps printed every comment. The
pictures are drawn from a copy holding only what the vector print draws.
2026-10-22 13:18:26 -04:00
aiongg 28ab616eb6 fix(engine): print as low-resolution pictures when only that is allowed
Printing checked the print permission but not the separate high-quality one
(Table 22, bit 12), so a document limited to low-resolution printing came out
as its original vector pages, text included. Such a document now always
prints as pictures of at most 150 dpi, whatever the settings ask for.
2026-10-22 13:18:26 -04:00
Combiler01 4d93503937 Merge remote-tracking branch 'upstream/main'
# Conflicts:
#	ATTRIBUTION.toml
#	crates/automation/src/tools.rs
#	crates/automation/tests/automation.rs
#	crates/edit/src/images.rs
#	crates/edit/src/lib.rs
#	crates/edit/src/tests.rs
#	crates/engine/src/lib.rs
#	crates/ui-egui/src/create_ui.rs
#	crates/ui-egui/src/edit_text_ui.rs
#	crates/ui-egui/src/editing.rs
#	crates/ui-egui/src/i18n/es.tsv
#	crates/ui-egui/src/i18n/pt-br.tsv
#	crates/ui-egui/src/i18n/vi.tsv
#	crates/ui-egui/src/lib.rs
#	crates/ui-egui/tests/content.rs
#	crates/ui-egui/tests/editing.rs
2026-10-22 13:32:03 +05:30
Combiler01 67f1a57f08 Merge remote-tracking branch 'upstream/main'
# Conflicts:
#	ATTRIBUTION.toml
#	crates/ui-egui/src/content_ui.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/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/src/lib.rs
#	crates/ui-egui/src/panels.rs
2026-10-22 11:59:39 +05:30
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 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 123b214180 Merge r2 track t10: xfa 2026-10-22 02:21:06 +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 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
aiongg 7bf122eea8 Merge r2 track t02: edit-content
# Conflicts:
#	crates/edit/src/tests.rs
#	crates/edit/src/text.rs
#	crates/ui-egui/src/canvas.rs
#	crates/ui-egui/src/edit_text_ui.rs
2026-10-22 02:17:34 +00:00
aiongg da7f592cd0 Merge PR #1648: XFA: decode BMP and TIFF pictures
crates/xfa/src/tests.rs: union of fixture imports (tiny_bmp, tiny_tiff).
parity/acrobat-features.toml: form.xfa and the XFA image entry: evidence lists unioned, notes take both sides' insertions.
2026-10-22 01:49:05 +00:00
aiongg 4949724ec8 Merge PR #3875: M4: a new bookmark goes to where the reader is (#3865) 2026-10-22 01:48:54 +00:00
aiongg a447dd3db5 Merge PR #2731: Layers panel: Reset to Initial Visibility
Conflicts:
- ATTRIBUTION.toml: ours (sha256 lines only); hashes recomputed at the end of the track
- crates/engine/Cargo.toml: main's workspace chrono entry, plus the PR's pdfcraft-testkit dev-dependency
2026-10-22 01:48:51 +00:00
aiongg be2b7ae411 Merge PR #3452: fix(engine): a reload keeps reading colours and hidden comments (#3443) 2026-10-22 01:48:35 +00:00
aiongg a663f2e9c8 Merge PR #2825: fix(cli): info, text, render and audit take the owner password of R2–R4 files 2026-10-22 01:48:29 +00:00
aiongg 0f0d7dcb67 Merge PR #1830: M11: remove PDF/A or PDF/X identification (optimize.remove-standards-id)
ATTRIBUTION.toml: sha256 lines taken from main, recomputed after all merges
2026-10-22 01:47:19 +00:00
aiongg a456f516d9 Merge PR #2756: M7: a paragraph number keeps naming the paragraph text_paragraphs listed (#2516)
ROADMAP.md: kept both sides' progress-log lines.
crates/edit/src/lib.rs: re-export list is the union (TextSession from #3942; BlockKey, block_overlapping from #2756).
2026-10-22 01:47:18 +00:00
aiongg 3ba586fe31 Merge PR #2624: fix(xfa): reflow growable multiline fields after filling
crates/xfa/src/script.rs: template_field and named_in moved to crate::data in #3397; field_grows_with_text calls crate::data::template_field.
parity/acrobat-features.toml: form.xfa evidence lists unioned, notes take both sides' insertions.
2026-10-22 01:46:50 +00:00
aiongg 8949d34632 Merge PR #2711: Wake idle windows for pending recovery snapshots (#2663) 2026-10-22 01:46:43 +00:00
aiongg 5a13228b57 Merge PR #3520: M5: a stamp grows and shrinks with its handles before release (#3518) 2026-10-22 01:46:28 +00:00
aiongg 8cdfe0f4e8 Merge PR #3475: fix(forms): draw fields the file leaves to the viewer, for display only (#3470) 2026-10-22 01:45:38 +00:00
aiongg 87f0f4bcbf Merge PR #3043: M3: layer_set shows or hides a layer, and page_render draws with the document's view settings (#2986) 2026-10-22 01:45:26 +00:00
aiongg 145a08ae96 Merge PR #3788: M5: drag a line's ends (and a polygon's corners) to change its length and angle
ROADMAP.md: union of progress-log lines.
crates/ui-egui/src/i18n/*.tsv (20 catalogs): union of appended keys.
2026-10-22 01:45:21 +00:00
aiongg d133dfbf75 Merge PR #1989: Edit images: rotate an image by any angle with a knob (#1940) 2026-10-22 01:44:58 +00:00
d676fd44ea M6: Prepare a form ▸ Text field table: rows and columns of text fields as one edit (#3479)
* M6: Prepare a form ▸ Text field table: rows and columns of text fields as one edit

Drag an area with the Text field table tool and set it up in a movable
window: rows, columns, row and column spacing, the first row number,
column widths (draggable dividers, arrow keys once focused) and a name
pattern per column, with the table previewed on the page. Add fields adds
every cell as one undoable edit ("Add text field table").

- forms: `table` lays the table out in view space and names its cells. It
  refuses the whole table for a cell under MIN_FIELD_SIDE (now one
  constant) or a name with a period, used twice or already taken, and
  free_base picks the first free TableK for default names.
- engine: `field_table::edit` maps the cells onto the page, /Rotate and
  /UserUnit included, and checks their size again there.
- automation: `form_add_field_table`, with an end-to-end test.
- ui-egui: the window belongs to one page of one document and closes when
  that stops being the one prepared; Enter commits a number instead of
  adding the table; dividers between many columns no longer panic in
  f64::clamp. Strings in all 22 catalogs, and the Spanish engine-wording
  tests cover the table's mistakes.
- parity: form.multiple-copies is partial; copying an existing field into
  a grid is still missing.

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

* M6: text field table: refuse corners past the page's number range, run it by its command

Review follow-up on #3479.

- engine: a corner finite as an f64 but past f32's range came back from
  the page's f32 mapping infinite. With one such corner a side was
  infinite rather than NaN, so the cell passed and add_field refused it
  only once the edit was applied ("the field is too small"). The edit now
  refuses any corner that isn't finite on the page with the table's own
  reason, before anything is added.
- automation: form.add.text_table runs form_add_field_table through
  command_run, as comment.stamp runs stamp_custom.
- ui-egui: doc comments for the window's three remaining helpers.

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

* M6: text field table: close on document edits, lay out once per change, keep Escape for fields

Review follow-up on #3479 (benandez).

- The window belongs to the document as it was when it opened: it closes
  when the edit generation moves (a page rotated, moved or deleted, an edit
  undone), so a table set up for one page never lands on another or off it.
- The table is laid out and checked once per change, not several times a
  frame: the window and the page preview share one `Laid` (cells and the
  edit), and the preview draws only the cells in view, naming only those
  with room for a name.
- Escape in a field of the window leaves the field and keeps the setup; a
  second Escape closes the window.
- A table placed with a click is moved in from the page's edges, so all of
  it is on the page.
- `free_base` takes one pass over the names; `{seq}` is documented as
  counting from the first row number; `form_add_field_table` takes its
  names from the batch instead of laying the table out again; the
  unreachable `Dialog::FieldTable` arm says why it is there.

Each new test fails with its fix reverted.

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

* M6: text field table: drawn with its panel closed, the window opens Prepare a form instead of closing

With the tool picked and the Prepare a form panel closed, the form is
still prepared and a table can be drawn. Drawing sends the tool back to
Select, though, so nothing was prepared on the next frame, and the table
window, which lasts only while the form is prepared, closed itself at
once: the table couldn't be set up. Opening the window now opens the
Prepare a form panel it belongs to. Closing the panel while the window
is open still closes the window.

Found by CodeRabbit, which saw the preview stop drawing; the window
closing first was the larger effect. prepare.rs
a_table_drawn_with_the_panel_closed_opens_it_again fails without the fix
("the window stays open": (None, false)).

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

* Drop the second generation binding the main merge left in document_area

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: aiongg <aiongtaigi@gmail.com>
2026-10-21 21:27:31 -04:00
jonathanwxh-cell 895ccb90c3 fix(engine): guard undo and redo refresh and roll back on failure (#3925) 2026-10-22 08:28:37 +08:00
e451934f72 M6: calculation order: read, check, fix and set the order fields calculate in (#3708)
* M6: renaming a field renames it in the calculations that read it

A rename silently broke every formula that used the field: a sum dropped
it, notation read it as 0 and a script kept a stale value. set_props now
rewrites the name in each field's Calculate script, in the same edit:
AFSimple_Calculate field lists, simplified field notation (the BVCALC
comment and its translation) and getField calls naming it in one string
literal. The rest of each script is kept as written; names built at run
time, non-UTF-8 script streams and a name another field still has are
left alone, and a self-check keeps a script whose meaning would change.

Notation is read by one lexer shared by notation_js, eval_notation and
the rename. form_set_props returns formulas_updated; Field Properties
says how many calculations now use the new name.

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

* M6: form_set_props leaves the renamed field out of formulas_updated by object

The renamed field was matched by the name given, but set_props stores it trimmed and under
its parent's prefix. When the same call changed the field's own formula, formulas_updated
listed the field as one the rename had rewritten.

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

* M6: calculation order: read, check, fix and set the order fields calculate in

A form's calculations run in its calculation order (/CO), which a field
joins when it gets a calculation, so a chain defined in the wrong order
shows stale values. calculation_order reads the order against the fields,
with what each formula reads (field lists, notation names, literal getField
names) and what is wrong: a field reading one that calculates later, a loop
(strongly connected components, found without recursion), a field /CO
leaves out, and /CO entries that calculate nothing. Fix order is a stable
topological sort that moves only what must move and leaves loops alone.
set_calculation_order writes /CO afresh; a name two fields share (a
malformed form) stands for the next of them in the current order.

Edit::SetCalculationOrder sets it in one undo step and recalculates, and
form_calculation_order reads, sets, moves one field or fixes the order
headlessly. An edited formula now keeps its field's place in /CO, a field
/CO lists twice calculates once, and recalculation runs each field by
object, so two fields sharing a name both calculate. The /CO code of the
Calculate tab, field scripts and recalculation goes through one place.

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>
Co-authored-by: aiongg <aiongtaigi@gmail.com>
2026-10-21 19:56:27 -04:00
6898094e77 M6: renaming a field renames it in the calculations that read it (#3550)
* M6: renaming a field renames it in the calculations that read it

A rename silently broke every formula that used the field: a sum dropped
it, notation read it as 0 and a script kept a stale value. set_props now
rewrites the name in each field's Calculate script, in the same edit:
AFSimple_Calculate field lists, simplified field notation (the BVCALC
comment and its translation) and getField calls naming it in one string
literal. The rest of each script is kept as written; names built at run
time, non-UTF-8 script streams and a name another field still has are
left alone, and a self-check keeps a script whose meaning would change.

Notation is read by one lexer shared by notation_js, eval_notation and
the rename. form_set_props returns formulas_updated; Field Properties
says how many calculations now use the new name.

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

* M6: form_set_props leaves the renamed field out of formulas_updated by object

The renamed field was matched by the name given, but set_props stores it trimmed and under
its parent's prefix. When the same call changed the field's own formula, formulas_updated
listed the field as one the rename had rewritten.

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>
Co-authored-by: aiongg <aiongtaigi@gmail.com>
2026-10-21 19:25:43 -04:00
Adrian 946a77cf9b M4: a new bookmark goes to where the reader is (#3865)
A bookmark made in the app always went to the top of the page. It now goes to
the top-left of the selected text, or with nothing selected to the top of the
window, as /XYZ left top null: the reader's zoom is kept, and with only the top
pinned so is the horizontal position.

- render: PageInfo::xyz_for_view, the inverse of dest_fraction. It pins only
  the coordinates given; on a page turned a quarter the displayed y decides the
  user left and the displayed x the user top.
- organize: add_bookmark_at and OutlineError::BadPosition (a coordinate that is
  not finite is refused before anything changes).
- engine: Edit::AddBookmark takes left and top (None, None is the page top, as
  before).
- automation: bookmark_add takes top and left in points from the top-left of the
  displayed page, as bookmark_list reports them, bounded and refused when not a
  usable number.
- ui: DocView::bookmark_position. It follows the window's vertical when the view
  is turned a quarter (View > Rotate View), picks the selection's corner that
  shows at the top-left, and in a spread of unequal pages uses the page that
  crosses the window's top edge.
- parity: organize.bookmark-add evidence and what is still missing.
2026-10-21 12:12:03 -04:00
Combiler01 cf336c2ff2 Stored the added-image rotation in the direction used by AddedImage.rotation 2026-10-21 17:49:31 +05:30
Combiler01 b3b555ff5e Fixes the bug regarding duplicate images 2026-10-21 16:33:31 +05:30
Oliver HagmannandClaude Opus 5.5 4cd646811a M5: drag a line's ends (and a polygon's corners) to change its length and angle
Once drawn, a line or arrow could be moved but not changed: selected, it showed a frame and
no handles, so a wrong length or angle meant drawing it again. A selected line, connected
lines, polygon or cloud now has a handle on each end or corner instead of the frame; dragging
one moves that point (Shift holds it to 45° from the point before), the new shape is drawn
while dragging, and the release is one undo step. The drawing tools keep drawing from an end
(a new line starts there); the Select and Fill & Sign tools pick the handles up.

pdfcraft_annot::set_points sets /L or /Vertices, lets /Rect follow with room for the width
and arrowheads (the rule a new comment is drawn with) and draws the appearance anew;
measurements keep the points they measured, locked comments their shape. Edit::ReshapeAnnotation
("Reshape comment"), comment_edit `points`; the comment list (Summary, DocInfo, comment_list)
carries a line's ends and a polygon's corners.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 21:29:14 +02:00
Combiler01 d4a739c3b5 Code Rabbit Fixes 2026-10-20 23:32:53 +05:30