100 Commits
Author SHA1 Message Date
FredApps f42fda7342 Merge pull request #6416 from storytold/house-rules
Copy the shared house rules into AGENTS.md
2026-11-06 14:58:52 +01:00
FredApps 465783fc47 docs: preserve local guidance in house-rules rollout 2026-11-06 12:37:25 +01:00
FredApps 81b0833b24 Copy the shared house rules into AGENTS.md.
The blocks come from craft-contrib at dde09ea31e2e457f5b4653a6e76f7cdf55944bdf. CLAUDE.md imports AGENTS.md. The house-rules workflow checks the copy.
2026-11-06 11:50:02 +01:00
FredAppsandClaude Opus 5.5 250c2623d1 Tests: pin the file identifier formula, not a whole rewritten file (#6346)
The written file differs on Windows, so an identifier hashed from it cannot be
pinned, and main's Windows gate failed. The formula is pinned on fixed bytes.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 22:44:29 +01:00
FredApps c56a63bcb6 Merge pull request #4732 from helenkwok/web/host-page
feat(web): page host mode, so a page can host PdfCraft in its own document (#4731)
2026-11-05 14:20:12 +01:00
FredApps 419b267ee5 Merge pull request #5125 from huppiflupp/feat/scan-clean
M10: Enhance scanned file cleans scanned pages in place
2026-11-05 13:36:55 +01:00
FredApps 15c505d1c6 Merge pull request #3858 from Kronbii/fix/scan-image-resampling
M2: scans stay sharp at screen size and smooth when zoomed (area-average shrink, bilinear enlarge)
2026-11-05 06:03:58 +01:00
FredApps 84e85c1ff3 Merge pull request #5758 from hasannadeem/feat/update-check-preference
M14: Preferences can turn off the update check at start (#5737, #5460)
2026-11-05 05:39:12 +01:00
FredApps f3dc867651 Merge remote-tracking branch 'origin/main' into w
# Conflicts:
#	vendor/README.md
2026-11-05 05:14:13 +01:00
FredApps 21540829cd Merge pull request #5754 from agent-reed/fix/fill-sign-quick-bar-controls
M5.7: the Fill & Sign text controls use a colour dot and a size flyout
2026-11-05 04:48:17 +01:00
FredAppsandClaude Opus 5.5 943718ea98 fix(ui): About credits tables fit without side-scrolling and their columns resize (#6052)
* fix(ui): About credits tables fit without side-scrolling and their columns resize

The Contributors table and the Models table were egui Grids inside a
two-way scroll area: they opened wider than the dialog, so they scrolled
sideways, and Company and Model sat almost touching. Both are now
egui_extras tables. Each column opens at the width of its header and widest
cell, the spare width goes to the text columns (Name; Company and Model),
and every column edge can be dragged. Widening a column grows the table
like a spreadsheet, and only then does it scroll sideways; the header stays
put while the rows scroll. Counts and dates are right-aligned and every
cell is vertically centred.

The sorted column stays highlighted and its direction shows on the
toolbar's sort-order button, so headers no longer reserve room for an
arrow. The opening widths come from fit_widths, a pure function with unit
tests that a fitted table fills its room exactly and that only the text
columns give way when room is short.

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

* Let every credits column be dragged, and refit changed tables

The last column was egui's remainder column, which has no drag handle, so
it could only be resized from the edge before it. It is now an ordinary
column with its own handle.

A table keeps its column widths, so switching to a longer name left the
Name column at its old width and clipped the text. The table now goes
back to the opening fit whenever that fit changes: a longer widest cell
or a resized window. Dragged widths are dropped at that point.

fit_widths could overflow the room when one column hit the minimum,
because the other columns did not take up its share. Columns now give
way in proportion to their width above the minimum.

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

* Refit credits tables on what they measure, not the fitted widths

Comparing the fitted widths missed the case it was meant for. Name is the
only growing column, so a longer name takes its extra width from the
spare room and the fit comes out the same: a dragged Name width stayed,
clipping the longer name.

It could also drop dragged widths by accident. The fit comes from the
available width inside the scroll area, which scrolling can nudge, so
scrolling a widened table could reset it.

The table now compares the natural widths and the clip rect's width,
which scrolling does not move.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 04:33:21 +01:00
FredApps 13cb547434 Merge remote-tracking branch 'origin/main' into fix5754
# Conflicts:
#	crates/ui-egui/tests/it/fill_sign.rs
2026-11-05 04:06:56 +01:00
FredApps 713c61548f Merge pull request #5435 from agent-reed/feat/fill-sign-rail-default
M5.7: the quick bar's Fill & Sign button shows the tool it picks
2026-11-05 04:06:42 +01:00
FredApps 083b3aca44 Merge pull request #6087 from KenM76/feat/model3d-render
M12: model_render, a page's 3D model drawn to a PNG (stacked on #6069)
2026-11-04 20:19:35 +01:00
FredApps 52d68d7844 annot: share threed's MAX_MODEL_BYTES with model3d
main's 3D-embed change (#5808) added crates/annot/src/threed.rs with its own
pub MAX_MODEL_BYTES (same 256 MiB value), so both were re-exported from the
crate root and pdfcraft-annot no longer compiled after merging main. model3d
now uses threed's constant.
2026-11-04 19:52:51 +01:00
FredApps 697a02e2ef Merge storytold/main into feat/model3d-render
# Conflicts:
#	crates/automation/src/lib.rs
#	crates/automation/tests/it/main.rs
2026-11-04 19:52:51 +01:00
FredApps ef8c71ac9c Merge pull request #6069 from KenM76/feat/prc-render
M12: headless renderer for PRC models (`pdfcraft-prc-render`), stacked on #5786
2026-11-04 19:42:33 +01:00
FredApps 8f8842e3ab Merge pull request #5396 from KenM76/fix/ocr-edit-under-scan
fix(edit): an edited OCR phrase under its scan image is drawn on top (#3973)
2026-11-04 19:42:25 +01:00
FredApps 60894af44d Merge pull request #6125 from KenM76/feat/bookmark-clipboard
feat(ui): cut, copy and paste bookmark subtrees (#3994)
2026-11-04 19:33:28 +01:00
FredApps 9070431ed3 Merge pull request #5250 from KenM76/fix/cleared-max-len-stays-cleared
fix(forms): clearing a field's length limit leaves it with none, not its parent field's
2026-11-04 19:08:06 +01:00
FredApps 3788af11d3 Merge pull request #5808 from KenM76/feat/3d-embed
M12: add a 3D model (U3D or PRC) to a page with a poster (#1297)
2026-11-04 18:53:39 +01:00
FredApps 83cbf8f89f Merge pull request #5476 from KenM76/fix/xfa-check-button-width
M12: an XFA check box without a width is as wide as its box and caption
2026-11-04 18:53:31 +01:00
FredApps 5bf6b63910 Merge pull request #5487 from KenM76/fix/file-dialog-extension-case
fix(ui): list X.PDF in file pickers on Linux and the BSDs (#5481)
2026-11-04 18:53:24 +01:00
FredApps 0429b23ea9 Merge storytold/main into feat/prc-render 2026-11-04 18:51:49 +01:00
FredApps 8d7eb74ff7 Merge remote-tracking branch 'upstream/main' into pk-6125m 2026-11-04 18:50:24 +01:00
FredApps 7d17aea92c Merge pull request #5786 from KenM76/feat/prc-reader
M12: PRC reader crate (`pdfcraft-prc`) (#1297)
2026-11-04 18:50:09 +01:00
FredApps 899f3806b1 Merge pull request #5432 from KenM76/perf/png-predictor-bytes
perf(render): undo PNG predictors a byte row at a time (#5430)
2026-11-04 18:44:45 +01:00
FredApps 61b80cb646 Merge pull request #6115 from KenM76/feat/outline-io
feat(organize): export, import and copy bookmark trees (#6018)
2026-11-04 18:44:33 +01:00
FredApps e989e48e63 Merge pull request #6058 from Piohrun/fix/jbig2-page-refinement-area
fix(render): a JBIG2 refinement of the page refines only its area (hayro-jbig2 patch 16)
2026-11-04 13:33:52 +01:00
FredAppsandClaude Opus 5.5 031af8cef8 vendor/README.md: one Test cell in the hayro-jbig2 row
The merge left a | after patch (13)'s test, which made a sixth cell and
hid (14) and (16) from the rendered table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 13:16:44 +01:00
FredAppsandClaude Opus 5.5 160ee3d421 Merge main into fix/jbig2-page-refinement-area
vendor/README.md: patch (13), from #5999, goes into this branch's
hayro-jbig2 row ahead of (14) and (16).

The page-area test now fills the page's words with 1s, padding included:
since patch (13) new_with clears the padding, so the test no longer
exercised the page-width half of the mask.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 12:50:48 +01:00
FredApps 3683150ee0 Merge pull request #5803 from alehel/refactor/page-press-dispatch
refactor(ui): tell page modules whether a press is theirs (router PR 4a)
2026-11-04 11:56:35 +01:00
FredApps a4d148bf48 Merge pull request #6031 from dotCooCoo/fix/scroll-regression-1230
Scroll: smooth wheel bursts and preserve precise movement
2026-11-04 09:49:20 +01:00
FredApps 69fda9959e Merge storytold/main into fix/scroll-regression-1230 2026-11-04 08:56:42 +01:00
FredApps 9bbcde4699 Merge pull request #6063 from dotCooCoo/fix/continuous-scroll-prefetch
fix(ui): continuous view renders the pages ahead of the scroll
2026-11-04 08:56:30 +01:00
FredApps d21abe9881 test(ui): keep the eviction-order test over the window-sized allowance 2026-11-04 07:42:59 +01:00
FredApps 933a92fad0 Merge storytold/main into fix/continuous-scroll-prefetch 2026-11-04 07:42:58 +01:00
FredApps 1f8cb45353 Merge pull request #6065 from dotCooCoo/fix/window-sized-page-budget
fix(ui): size the whole-page raster allowance to the pages on screen
2026-11-04 07:42:41 +01:00
FredApps bde72b6f26 test(ui): pin the whole-page allowance ceiling per target 2026-11-04 07:03:52 +01:00
FredApps c64402dfde Merge branch 'main' into fix/fill-sign-quick-bar-controls 2026-11-03 14:28:20 +01:00
FredApps a933d2aa4c Merge branch 'main' into feat/fill-sign-rail-default 2026-11-03 14:28:16 +01:00
FredApps 168a3cb91e Merge pull request #5740 from Combiler01/fix/panel-resize-scrollbar-5730
fix(ui): prevent panel resize handle collision with scrollbar (#5730)
2026-11-02 17:47:35 +01:00
FredApps 8f1441a3f2 fix(ui): keep pane resize edges right of the border, off the page scrollbar (#5730)
The centred 4 pt strip still covered the right 3 pt of the page's
scrollbar beside a right-docked pane. Register the host's resize edge
again from the border rightwards, on the host's own layer, and leave an
inert edge inert. The test now hovers and drags both scrollbars beside a
right-docked Tools pane (CodeRabbit) and checks the width is unchanged.
2026-11-02 16:59:26 +01:00
FredApps 1997b8ed94 Merge remote-tracking branch 'origin/main' into pr5740 2026-11-02 16:29:14 +01:00
FredApps e261518727 Merge pull request #5569 from Piohrun/feat/jbig2-run-allowance
M2.6: the images of a run, and a page's JBIG2 images, share one allowance of decoding
2026-11-02 15:11:32 +01:00
FredApps 1303684851 Merge pull request #5639 from RiceDee/fix/rail-page-zoom-fields
fix(ui): the rail's page box fits, and the zoom field looks like a field (#5636)
2026-11-02 14:46:11 +01:00
FredApps 2d4e317a58 Merge pull request #5638 from RiceDee/fix/quick-bar-centred-in-margin
fix(ui): centre the quick-tools bar in the margin beside the page (#5635)
2026-11-02 14:45:58 +01:00
FredApps 52574b4fe5 Merge pull request #5637 from RiceDee/fix/format-text-fields-fit-pane
fix(ui): Format text fields read as fields, line up, and fit the Tools pane (#5634)
2026-11-02 14:45:46 +01:00
FredApps ec25e7d327 M2.6: images decode outside the renderer only through an ImageBudget
`ImageBudget::decode` is now the one public way to decode an image's
CCITT fax or JBIG2 data: `Document::decoded_image` and
`decoded_image_within`, which decoded with no limit on the work, are
test-only in pdfcraft-cos, and pdfcraft-filters exports only
`decode_ccitt_within` and `decode_jbig2_within`, which spend from a
caller's allowance (`decode_jbig2` is gone, `decode_ccitt` private).
So an operation over many images can't decode them without sharing an
allowance; the compiler holds new callers to it. Doctests that must not
compile check both crates; with the old entry points public they fail.

Tests outside the crates decode through an unlimited ImageBudget.
Streams in general (`Stream::decoded`) are left for a follow-up.
2026-11-02 14:24:21 +01:00
FredApps 4ffe5908c8 Merge origin/main into feat/jbig2-run-allowance
# Conflicts:
#	vendor/README.md
2026-11-02 14:15:33 +01:00
FredApps f47618f59b Merge pull request #5710 from Combiler01/feat/preferences-cards-refresh
ui: modernize preferences dialog with card-based layout
2026-11-02 11:38:28 +01:00
FredApps f89a5917ed M2.6: streams made in memory enlarge a run's image allowance as a file's bytes do 2026-11-01 23:52:37 +01:00
FredApps 5eb82d1f68 M2.6: an image pays for the pixels its data holds, not those its size declares 2026-11-01 23:52:07 +01:00
FredApps 74d51ebf4a M2.6: a JBIG2 image stored again without its globals decodes within the run's allowance 2026-11-01 23:50:39 +01:00
FredApps bc4acf7bfc Merge origin/main into feat/jbig2-run-allowance 2026-11-01 23:50:04 +01:00
FredApps 0cba87ae6f Merge pull request #5677 from Arch-amon/arclight/freehand-hotbar
feat(ui,annot): customizable hotbar strip, freehand highlight, and moveable navigation rail
2026-11-01 23:34:38 +01:00
FredApps 85c8a2a0bf Merge pull request #5474 from Piohrun/feat/redact-bilevel-codec
M8: a redacted black-and-white scan is stored as Group 4, or JBIG2 again, when smaller (protect.redact-image-pixels)
2026-11-01 23:09:46 +01:00
FredApps 616ddca371 M8: images stored again without shared JBIG2 globals are stored as a cleared copy is
An image that shared a redacted image's /JBIG2Globals is now stored
again as the smallest of Flate, Group 4 or JBIG2 coded alone (smallest),
like a cleared copy, rather than always Flate, so the other pages of a
scan don't balloon either. The shared-globals test's second page is a
ragged scan and checks it is no longer Flate and is smaller.
2026-11-01 22:48:29 +01:00
FredApps 54d0ea7c59 Merge branch 'main' into feat/redact-bilevel-codec 2026-11-01 22:44:58 +01:00
FredApps 4d8eede62a Merge pull request #5472 from Piohrun/feat/mono-jbig2
M11: Monochrome Images reads JBIG2 scans: averaged like any, and stored again as JBIG2 (optimize.mono-compression)
2026-11-01 22:44:16 +01:00
FredApps 2850d52825 Merge pull request #5471 from Piohrun/feat/mono-indexed-polarity
M11: Monochrome Images averages indexed black-and-white images, the palette saying which sample is dark (optimize.downsample-images)
2026-11-01 22:43:06 +01:00
FredApps 99e63d4238 Merge pull request #5461 from Piohrun/feat/redact-jbig2
M8: redaction clears the covered pixels of JBIG2 scans instead of removing them (protect.redact-image-pixels)
2026-11-01 22:39:07 +01:00
FredApps a87c4fb6b7 M8: redaction stores again without them the images that share a redacted JBIG2 image's globals, so the globals leave the file (protect.redact-image-pixels)
A JBIG2 image's /JBIG2Globals hold the symbol dictionary of every image that
shares them (jbig2enc -s and most scanners give one to all of a scan's pages),
so the bitmaps of marks drawn only under a redaction stayed in the file while
another page's image used them. Every image using the globals of a removed or
replaced image (or of one in a removed or replaced form) is now decoded and
stored again in place as Flate without them; a full save then drops them. One
that can't be decoded for certain refuses the redaction
(RedactError::SharedJbig2Globals). Report::images_restored counts them.
2026-11-01 22:14:52 +01:00
FredApps 0804a9b86c Merge origin/main into feat/jbig2-run-allowance 2026-11-01 21:10:07 +01:00
FredApps cc986fa289 Merge origin/main into feat/jbig2-run-allowance 2026-11-01 21:06:29 +01:00
FredApps 2cd50b8d39 Merge pull request #5491 from Piohrun/fix/jbig2-retained-bitmaps
fix(render): a JBIG2 page's segments are bounded in what they hold and refer to (hayro-jbig2 patches 5 to 9, hayro-syntax 29)
2026-11-01 21:04:29 +01:00
FredApps 67e86f2b27 Merge pull request #5620 from Piohrun/fix/mask-resample-allocation
fix(create,optimize): a mask of other proportions doesn't take the process down
2026-11-01 19:44:58 +01:00
FredApps b3023b4b28 Merge pull request #5624 from Piohrun/feat/xfa-rotate
M12: an XFA draw placed by position turns about its anchor
2026-11-01 19:43:57 +01:00
FredApps 61140ed807 Merge pull request #2155 from Combiler01/main
feat: Acrobat UI parity for image editing, text formatting, and UI stabilization and Bug Fixes
2026-11-01 18:50:01 +01:00
FredAppsandCodex GPT-6.1 a9de3db628 docs: record image editing review fixes and movement semantics
Validated with 3231 passing scoped tests (10 skipped), clippy, wasm checks, repository gates, and 42 CLI smoke steps including saved-document verification.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 17:59:35 +01:00
FredAppsandCodex GPT-6.1 6816d14e02 Fix context image placement and canvas selection ownership
Convert context-paste user coordinates into AddImage display coordinates and
identify the inserted image through its new owning stream and XObject. Keep
legacy added-image metadata aligned with the active image controller, route
Delete to the visible selection, and clear hidden image selections when leaving
the controller while preserving text selections and drafts.

Separate selection-dependent Copy from whole-page Snapshot and document Export
permissions. Add synthetic UI regressions covering transformed page placement,
identity collisions, shared image references, saved deletion results, tool
transitions, and permission controls.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 17:54:15 +01:00
FredAppsandCodex GPT-6.1 75e012de9a fix(edit): compose inside-scope group translations in order
Fold a leading transform inside the image scope as cm followed by the local transform; an enclosing transform uses the opposite multiplication order. This preserves the complete requested image and crop displacement under an outer scale. The exact crop-arrange-group-move fixture previously moved only five points for a ten-point request; saved geometry and rasters now match an independent direct Transform control across both axes and signed offsets. Full scoped Linux native, wasm and repository gates pass.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 17:41:13 +01:00
FredAppsandCodex GPT-6.1 e677c009b3 fix(edit): restore inherited text state when arranging Forms
Track the text-state operators with saved drawing state, restoring inherited spacing, scaling, leading, rendering mode, rise and known font before relocated Form artwork. Emit restoration inside BT/ET, and leave a font selected by a replayed ExtGState authoritative over an older direct Tf. The exact inherited 12 Tc fixture failed its saved-PDF raster comparison before this fix; zero-spacing and destination-state controls now preserve rendering. Scoped Linux native, wasm, clippy and formatting checks pass.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 17:41:13 +01:00
FredAppsandCodex GPT-6.1 8669aa48aa fix(edit): preserve graphics state chronology and mask identity
Replay repeated ExtGState names in last-application order. Compare each complete soft-mask value and its establishment matrix instead of only its group reference, and retain cached shared definitions across saved states. Saved-PDF raster regressions cover Alpha versus Luminosity over the same group, repeated aliases at different matrices, and ordinary sequence/single-mask controls. Definition checks also cover backdrop and transfer parameters. Actual baseline and reverted-comparator tests fail; scoped Linux native, wasm, clippy and formatting checks pass.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 17:41:12 +01:00
FredAppsandCodex GPT-6.1 fdb6a6f33e fix(ui): rotate cropped image previews around the committed pivot
Project the visible user-space bounds centre for the drag preview, matching the RotateBy engine operation. The full image centre differs for cropped artwork and caused the preview to jump on release.

The regression compares actual painted preview corners with saved/reopened image corners and verifies a requested 90-degree turn on cropped and uncropped controls, including page rotation. Linux scoped clippy, 106 tests, wasm, formatting, layering and assets pass.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 17:34:13 +01:00
FredAppsandCodex GPT-6.1 c0a5a5cbf8 fix(ui): resize image frames relative to the captured press
Invert the actual affine basis instead of projecting onto assumed orthogonal axes. Capture the displayed crop frame for handles and apply its relative transform to the full artwork, preserving author clips on rotated pages. Exact out-and-back gestures preserve bytes and undo state, including off-centre presses.

Synthetic headless regressions verify sheared and rotated images, crop-frame anchors, press-offset independence and saved/reopened placement. Degenerate and nonfinite bases are refused; the inverse guard has a negative-control test.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 17:34:13 +01:00
FredAppsandCodex GPT-6.1 393bd30701 fix(ui): leave source text untouched when script conversion is a no-op
Only request a script conversion from the panel; the caller decides whether conversion changed the text. Do not create a paragraph rewrite merely because the button was clicked. A hidden QQQ fixture checks both script buttons preserve document bytes, undo history and saved rendering, while supported conversions remain covered. Actual reverted-fix raster failure and scoped Linux native, wasm, clippy and repository checks passed.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 17:19:21 +01:00
FredAppsandCodex GPT-6.1 2ab9c6992c docs(edit): record latest PR 2155 review fixes
Record delivered clipboard events, the mixed-size display correction, and explicit mixed-script normalization with Undo. Combined scoped Linux validation passed: 2785 tests, clippy, doctest checks, wasm, formatting, layers, assets, parity, and a 26-step CLI smoke test.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 16:38:24 +01:00
FredAppsandCodex GPT-6.1 27e34098d3 fix(ui): size the font field for the localized mixed label
Measure Mixed with the active body font and include the input margins and caret allowance. Keep that minimum stable while typing so the full label is visible without shifting the row on each keystroke.

A themed panel regression fails against the old 40-pixel input, verifies the text fits inside the field margins and keeps the alignment control inside a 272-pixel pane. Linux scoped clippy, format tests, wasm, formatting, layering and assets pass.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 16:34:38 +01:00
FredAppsandCodex GPT-6.1 a3840e1eda fix(ui): paste delivered images instead of guessing from key releases
The pinned integration consumes native clipboard shortcut keys and delivers PasteImage pixels. Handle those payloads in order, keep text cache invalidation, and use the delivered image even if the OS clipboard changes before processing. Preserve alpha and validate dimensions and byte counts before allocation.

Remove release timestamps so Windows clipboard history cannot reuse a completed paste gesture. Keep explicit shortcut fallback for control-channel and browser internal-image paste, with modal, focus and permission guards unchanged. Tests cover both release orderings, history after prior paste, mixed batches and duplicate prevention.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 16:30:06 +01:00
FredAppsandCodex GPT-6.1 b7d04009a2 fix(ui): refresh font-size text when selection becomes mixed
Include the mixed-size flag in the font-size draft cache key. Selecting a mixed block can preserve the previous representative number, so a value-only key left the field showing 24 instead of Mixed. Unchanged formatting still preserves partially typed input across frames.

The headless regression covers uniform-to-mixed and mixed-to-uniform transitions with the same number, draft preservation and a single committed edit. Linux scoped clippy, tests, wasm, formatting, layering and assets pass; reverting the cache fix reproduces the stale display.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 16:18:26 +01:00
FredAppsandCodex GPT-6.1 e7762568cc docs(text): define mixed-script normalization and undo policy
Document the existing policy: mixed plain and target-script text normalizes to that script, then to plain text, rather than reconstructing the original mixture. Undo restores exact prior text. Cover both scripts in engine and headless tool tests, including document-byte restoration, redo and save/reopen, and record the evidence in parity. The new tests pass against unchanged conversion logic; this is policy documentation and coverage, not a product behavior fix. Scoped Linux native, wasm, clippy, formatting, layers, assets and parity validation passed.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 16:12:39 +01:00
FredAppsandCodex GPT-6.1 73655948c6 fix(automation): flip images along displayed page axes
Map horizontal and vertical tool actions to PDF user-space axes after accounting for page rotation. The tool description states the displayed-coordinate semantics. A four-quadrant raster and transformed-corner regression covers both actions at 0, 90, 180 and 270 degrees, with undo between actions; it fails on the wrong axes before this fix. Scoped automation clippy, all 354 tests, wasm, formatting, layers and assets pass on GGEO-AI02.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 15:05:32 +01:00
FredAppsandCodex GPT-6.1 0b0d39c661 docs(edit): record PR 2155 review follow-ups
Record image crop and stream ownership, visible orientation, clipboard and formatting fixes, Home controls, and reloadable font discovery as PR candidates. Estimates remain unchanged.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 15:01:00 +01:00
FredAppsandCodex GPT-6.1 0595d4d397 fix(ui): preserve author clips and route crop controls before page content
Offer Remove Crop only for editor-owned clips, reset draft cropping to the author-visible bounds, and remove only an owned crop when confirming the full image. Active crop mode owns presses on its page so underlying text and marquee selection cannot steal crop controls. Label the painted controls for accessibility and automation.

The author-clip regression opens the real menu, resets a draft crop and confirms it while preserving the authored clip. It failed before ownership checks and again before the router fix.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 14:58:21 +01:00
FredAppsandCodex GPT-6.1 d423dd03ec fix(ui): keep image grips and flips aligned with the visible page
Use matrix resizing whenever image axes are turned or reflected on screen, including document and view rotation. Share the visible grip geometry for cursor claims and hit routing, and use only the drawn rotate knob. Map flip labels to the visible axis and defer Cut selection clearing to its result.

Regressions cover all page/view rotation combinations and 64 outward drags across every grip, asserting fixed anchors and pointer tracking for upright and rotated images.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 14:58:21 +01:00
FredAppsandCodex GPT-6.1 0046177f47 fix(engine): validate image transforms and promote arbitrary added-image transforms
Reject finite but singular or overflowing determinants at the engine boundary. Promote added images for arbitrary transforms, as RotateBy already does, while preserving editable quarter turns and reflections. Regressions verify transformed placement, promotion, undo and refusal without mutation.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 14:58:20 +01:00
FredAppsandCodex GPT-6.1 aa68d0c27f fix(home): show pinned tools once and expose unpin controls
Omit pinned tools from Recommended and keep unpin buttons in the accessibility tree without requiring pointer hover.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 14:51:28 +01:00
FredAppsandCodex GPT-6.1 faf85f5af9 fix(text): apply explicit sizes and preserve script characters
An explicit size commit normalizes mixed-size selections even when the value matches the displayed size. Caret-only script commands format the whole draft. Mathematical minus uses reversible Unicode forms and ASCII hyphen-minus remains unchanged. Correct the applied-selection comment and document the character policy in parity and the tool.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 14:51:27 +01:00
FredAppsandCodex GPT-6.1 a310d5a41a fix(ui): respect clipboard authority and retain refused cut selections
Do not reuse stale native images for unsupported clipboard contents, while preserving web internal image paste. Observe text paste before focus gating and keep image-less key releases silent. Tie release fallback to V gestures. Check modification permission before copying and clear selection only after successful deletion.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 14:51:27 +01:00
FredAppsandCodex GPT-6.1 36a6a572b8 fix(engine): match added images by their owning stream
An original image and an added item may share an XObject without sharing editable metadata. Require the selected drawing stream to own the added item instead of falling back to any matching resource. The regression actually moved the added sibling before the fix; scoped native and wasm gates now pass.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 14:47:46 +01:00
FredAppsandCodex GPT-6.1 9a1334e04d fix(edit): preserve image scopes and content ownership
Move editor crop scopes with grouped images while retaining fixed author clips and folding repeated transforms. Arrange keeps relocated original artwork in its own stream beside an added item, so later edits or deletion cannot discard it; unusual shared owned streams are refused. Refuse nested marked-content extraction when its tags cannot be preserved. Synthetic regressions and the headless group-move, undo/redo, save/reopen, arrange, delete and render lifecycle fail before these fixes and pass afterward.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 14:47:46 +01:00
FredAppsandCodex GPT-6.1 3a0ea63c33 fix(edit): share saved drawing operands across graphics scopes
Keep dash, color and extended printing operand payloads shared across q snapshots. Copy-on-write color updates preserve saved values without multiplying large operand arrays by nesting depth. A pointer-sharing regression failed before the change; scoped native tests, clippy and wasm check pass on GGEO-AI02.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 14:47:46 +01:00
FredAppsandCodex GPT-6.1 43ad4bf418 feat(edit): expose image crop ownership to frontends
Report active PdfCraft crop markers through PageImage::has_editor_crop and page_images.has_editor_crop so frontends can distinguish removable editor crops from author clipping paths.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 14:47:46 +01:00
FredAppsandCodex GPT-6.1 6e4d9a6838 fix(fonts): rescan installed fonts and preserve accepted results
Resolve explicitly configured font roots while skipping descendant links; retain all accepted fonts within the existing bounded scan. Allow an explicit Reload without duplicate workers or an app restart. Three actual reverted-fix regressions fail; scoped engine/UI clippy, 2400 tests, wasm, formatting, layers and assets pass on AI02.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 14:34:36 +01:00
FredAppsandCodex GPT-6.1 321f976f93 fix(ui): preserve crop scale at large screen offsets
Reconstruct moved edges from the fixed opposite anchor in f64 and round each coordinate once. This avoids cancellation introduced by adding a nearly full-width UV displacement to the old screen edge. The deterministic Linux CI case fails against the previous implementation and passes with the fix.

Check scale on both axes in screen space against a derived f32 coordinate-rounding bound, using the stored rectangle dimensions. Verify fixed edges for every handle and reject a deliberately stretched result. Both CI regression seeds and 10000 randomized cases pass; scoped UI clippy/tests, wasm, formatting, layering and assets are green on AI02.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 13:33:53 +01:00
FredAppsandCodex GPT-6.1 1184bd02cb docs(edit): record safe crop and arrange semantics
Describe editor-owned crop removal, preserve authored clipping paths, and link the scope/state regressions in parity evidence. Record the maintainer changes without changing readiness estimates.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 13:00:26 +01:00
FredAppsandCodex GPT-6.1 d4810fd00f refactor(ui): finish shared image selection and clipboard state cleanup
Use the common image-selection constructor across owners, remove obsolete crop and copied-coordinate fields, keep only a shortcut timestamp, and make the internal UI modules private. Combined GGEO-AI02 validation: 4198 tests passed, scoped clippy, doctests, fmt, layers, assets, parity and wasm; 25-step CLI save/reopen smoke and real-shell screenshot checked.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 13:00:26 +01:00
FredAppsandCodex GPT-6.1 bea79e1884 fix(i18n): translate clipboard and Home tool messages
Fill five notification/search entries in all catalogs and the missing Home tool labels in ckb, lo, nb and th. Correct Albanian crop labels and Italian/Kazakh unpin meanings. Catalog additions are AI-assisted and not separately native-reviewed.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 12:54:52 +01:00
FredAppsandCodex GPT-6.1 21a48ac735 fix(ui): finish font discovery when its worker panics
Contain discovery panics and publish the empty result so the font menu leaves its pending state. A synthetic panic regression fails when containment is removed.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 12:54:52 +01:00