Commit Graph
3967 Commits
Author SHA1 Message Date
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
FredAppsandCodex GPT-6.1 2c6a0fed48 fix(ui): honor current clipboard text and elapsed paste timing
Menu paste refuses cached images when system text supersedes them. Keyboard and menu paste share the text check; image validation reuses Create. Expire shortcut context by elapsed time even when frames are sparse. Regression tests fail with the old checks restored.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 12:54:52 +01:00
FredAppsandCodex GPT-6.1 f62c1cfafe refactor(text): share source font names and selection defaults
Reuse the existing subset-tag parser through the engine facade and share the fallback formatting state.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 12:54:52 +01:00
FredAppsandCodex GPT-6.1 d08097f286 chore: restore formatting and lint gates for preserved edits
Remove the rectangle helper whose only caller was the deleted crop test, and format the preserved text_script tool additions.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 12:54:51 +01:00
FredAppsandCodex GPT-6.1 355078d141 refactor(ui): consolidate image preview geometry and cached inventory
Use the shared content Matrix, one image-frame painter, texture-mesh builder, crop-pill style and rectangle comparison. Replace rotated resize arms with signed anchors and reduce crop arithmetic while preserving UV and screen scale. Reuse the edit-generation image cache for drag painting and image menus, and keep the menu flag temporary.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 12:45:14 +01:00
FredAppsandCodex GPT-6.1 f607d26d14 fix(edit): preserve printing state when arranging images
Refuse relocation into transfer, overprint, black-generation, undercolor-removal or halftone state that cannot be restored. Preserve implicit device color spaces before sc/scn and restore rendering intent from both ri and ExtGState RI, including its initial default. Three synthetic regressions fail against the previous implementation; all 411 edit tests and scoped clippy pass on GGEO-AI02.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 12:41:19 +01:00
FredAppsandCodex GPT-6.1 aef42635d0 fix(ui): reject nonfinite crop drag bounds before clamping
Keep invalid image geometry and drag coordinates out of crop clamps and discard an invalid in-progress gesture. The regression panics at f32::clamp without the guard (cropred) and passes with it (cropgreen2), alongside 81 image and crop checks.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 12:39:45 +01:00
FredAppsandCodex GPT-6.1 91f94ec26a refactor(ui): simplify image and page context menus
Share click handling, set crop mode in the image menu, remove duplicate export and inactive editor entries, and format shortcuts for the platform. Add a selection constructor for callers.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 12:39:45 +01:00
FredAppsandCodex GPT-6.1 3c394bb860 fix(edit): remove only editor-owned image crops
Identify crop paths with a marked-content point and preserve ownership through arrange reconstruction. Find the same isolated or outermost image scope as Crop, preserving authored and shared clips. Both regressions fail with the fix reverted; all 410 edit tests, scoped clippy, fmt, layers and assets pass on GGEO-AI02.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 12:37:24 +01:00
FredAppsandClaude Opus 5.5 a016923829 refactor(ui): crop mode is crop.is_some(); drop dead drag state
crop_rect was only ever reset to None outside tests, and crop_mode was
always set together with crop, so readers now test crop.is_some() and
the writers are gone. The fields stay until the last struct literals in
content_ui stop naming them. Tests that set crop_rect to drive the crop
now set the crop's box the same way crop_input did.

The rotated-drag match had a DragTarget::Rotate arm that the turning
branch above always pre-empts, and image_input's ImageAction parameter
was unused (let _ = &action).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:35:35 +01:00
FredAppsandClaude Opus 5.5 fc6dc4f2d6 refactor(ui): drop dead and test-only image geometry
HandleId duplicated ImageHandle with conversion tables both ways; the
image engine now takes ImageHandle, which also carries the cursor icon,
and the crop grips map through one GRIPS table instead of two index
matches. ImageObb loses from_center_size_angle, scale_proportional,
project_delta, new, handle_id, handles_with_ids and the width, height
and theta fields, which only the test of scale_proportional read.
reset_crop, RESIZE_ACCENT, image_owns_pointer and DragTarget::CropHandle
had no callers, and turn_degrees is test-only. The image engine is
private and its unused re-exports are gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:35:35 +01:00
FredAppsandClaude Opus 5.5 d1cba7fdd1 refactor(ui): remove update_image_crop, which only its test called
The image panel crops through Edit::UpdateContent with the fractions it
reads, and nothing else called update_image_crop. Removed with its test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:34:57 +01:00
FredAppsandClaude Opus 5.5 8abd35cf67 feat(automation): text_script tool for superscript and subscript
Format text's Superscript and Subscript had no headless path (AGENTS §3):
text_script toggles them on a paragraph, or a byte range of its editor text,
through the engine's text_script and writes the paragraph as text_edit does.
The parity entry now lists the tool and its tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:34:56 +01:00
FredAppsandClaude Opus 5.5 f01823f6fa refactor(edit): one superscript/subscript toggle, in the engine
The four character match blocks become two const tables in a new engine
module, text_script, keeping the minus sign's mapping. One toggle_script in
Edit text replaces the three copies (paragraph editor, added-text draft and
the Format text button state).

A range is now 'already in the script' when at least one character is and
none of the others has a form in it. Before, one character with no Unicode
form (a space, q, H in H2O) kept the range from ever counting as converted,
so the second click converted again, changed nothing, and the text could not
be toggled back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:34:54 +01:00
FredAppsandClaude Opus 5.5 2ef192b7cd refactor(ui): remove the unused list helpers from Edit text
is_bulleted, is_numbered, toggle_bullet_list and toggle_numbered_list had no
caller outside their own tests: Format text shows bulleted and numbered lists
as planned. Removed with their tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:34:54 +01:00
FredAppsandCodex GPT-6.1 1a2f7b2a34 fix(edit): refuse arrange across crossed scope boundaries
Require both graphics and marked-content boundaries to balance inside source, destination and removed spans. Regression fails before the guard; all 408 edit tests, scoped clippy, fmt, layers and assets pass on GGEO-AI02.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 12:33:51 +01:00
FredAppsandClaude Opus 5.5 eb0d5e64c7 refactor(edit): fold duplicated image scope and arrange helpers
PR #2155 review item A5 (part 2), plus the unreachable Ok(()) exits in
arrange_image from B11. No behaviour change for well-formed content:
- image_exclusive_scope and image_transform_scope were one scan; they are
  now image_scopes, and transform/crop take ImageScopes::transform_scope.
  The shared scan resets an open path at Q, as the exclusive one did; the
  two only differed on content that leaves a path open across Q.
- arrange_image and remove_image_crop took page and index and listed the
  page's images again; change_image now passes the page, its streams and
  the image, and neither is public any more.
- content_units' four copied scan loops are one sequence_end.
- DrawingState keeps its line-style, intent and flatness operators in a
  table; the w/J/j/M/d guards in compute_inherited_drawing_ops tested ops
  extract_scope_state never collects.
- clip_path_to_ops: ImageState never builds a quadratic segment and only
  stores finite points, so the QuadTo arm and finite checks were dead; it
  now reports a segment it can't write instead of dropping the clip.
- target_destination_unit and determine_arrange_spans are shorter; the
  Ok(()) exits for lookups that cannot fail are now errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:33:50 +01:00
FredAppsandClaude Opus 5.5 71b39aec5b refactor(edit): drop test-only image API and dead graphics-state code
PR #2155 review item A5 (part 1). No behaviour change for callers:
- crop_image, and the arrange_image/crop_image/remove_image_crop/MaskIdentity
  re-exports, existed only for tests; tests now go through change_image.
- PageImage.smask was read only by tests; page_images no longer tracks
  ExtGState for it. The nested-mask test keeps its rendered-pixel check.
- MaskIdentity's Display, ExtractedScopeState.effective_cm, the
  ExtendedGStateTracker overflow_depth (an error ends the scan, so it was
  never read) and the EffectiveGState one-line getters were unused.
- merge_dict always gets the ExtGState name, so the hash fallback for an
  unnamed inline soft mask was unreachable outside a test.
- cid_to_gid_map_odd_length_is_trimmed_to_even exercised no crate code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:33:50 +01:00
FredAppsandCodex GPT-6.1 a910b8cca2 fix(automation): reject invalid transform coefficients
Reject malformed matrices instead of dropping non-numeric coefficients and applying an unintended transform. The regression failed against the previous parser on GGEO-AI02; all 1721 scoped tests pass with the fix.

Co-Authored-By: Codex GPT-6.1 <noreply@openai.com>
2026-11-01 12:33:50 +01:00
FredAppsandClaude Opus 5.5 e61da46f92 fixup! feat(automation): image_edit transform action
rustfmt layout of the new test's closure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:33:50 +01:00
FredAppsandClaude Opus 5.5 b5ddf2cc80 feat(automation): image_edit transform action
A resize of a turned image sends ImageEdit::Transform, which had no
headless path (AGENTS 3). image_edit now takes action transform with
matrix: six numbers in top-left-origin points, like the tool's other
geometry, applied after the image's placement. The tool converts it to
user space through the page's view mapping, and refuses a matrix that is
not finite, is flat (a·d − b·c = 0) or moves the image out of range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:33:50 +01:00
FredAppsandClaude Opus 5.5 ac4f26a00d chore: revert unrelated churn from #2155
Restore main's text where the PR changed things it did not need to:
intra-doc links turned into plain code spans (engine js.rs and
camera_edges.rs, forms raster.rs, fonts pdf.rs, sign keys.rs and
pkcs12.rs, ui-egui motion.rs and web_print.rs), the #[allow(dead_code)]
on render's byte_capacity and ui-egui's unit_for_tag (both are used on
every native target, as on main), the loosened combine_grid timings, the
forms test case rename (scratch() already numbers its folders), and the
computed xref size in a_recovered_page_tree_survives_a_full_save (always
5 there).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:33:50 +01:00
FredAppsandClaude Opus 5.5 92de289ecc fix(engine): spend the font budget only on fonts the picker lists
discover charged each candidate's size against the 64 MiB budget before
reading it, so proprietary or broken files early in a fonts folder could
use the budget up and hide openly licensed fonts after them. Charge only
fonts that pass validation and are not duplicates. Reads are still
bounded: every file read counts against four times the budget.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:33:50 +01:00
FredAppsandClaude Opus 5.5 3817a9f3ec refactor(engine): drop redundant image and font checks
- page_image_at: PageImage::contains already requires the point inside
  visible_rect (rect clipped by the placement clip), so the extra bounds
  test before it decided nothing.
- image_dimensions: the 256 MB input-length guard repeated the caller's;
  the decoder's max_alloc limit still caps what decoding allocates. Its
  test no longer allocates 256 MB to hit that guard.
- font_content_key hashed every font file twice; one 64-bit hash plus the
  length is enough to tell duplicate files apart.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:33:49 +01:00
FredAppsandClaude Opus 5.5 4c70761803 refactor(engine): use pdfcraft_content::Matrix for added-image edits
run_edit_page_image carried its own inverse, bbox and multiply; Matrix
already has invert, bbox and then with the same formulas and the same
degenerate-determinant guard. Also drop the second finite check on Move
(checked on entry), match the added item with two finds instead of a
four-way chain, and toggle flips in one place for both the parallel and
perpendicular cases. No behaviour change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:33:49 +01:00
FredAppsandClaude Opus 5.5 4416405232 refactor(fonts): drop the unused TrueType subsetter
subset_truetype, subset_tag and their table helpers had no caller apart
from their own test, and validate_document_input validated twice: names()
already runs validate() first. No behaviour change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:33:49 +01:00
FredAppsandClaude Opus 5.5 25916985ca fix(ui): keep document_area under the complexity gate after merging main
Main's page-edge-shadow preference (#2088) added a fade-strength branch to
document_area, and this branch's image-menu work added others; together they
put it one over clippy's cognitive-complexity limit. page_scroll, its only
caller's scroll helper, now takes the fade flag and restores the spacing itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 11:26:22 +01:00
FredAppsandClaude Opus 5.5 29913dcfca Merge current main into #2155
Brings the branch up to date with main (47f42ba0), which moved 37 commits since
the merge base, including page-edge shadows (#2088), full rewrite after page
delete (#4279) and the licence-check stage (#2212). No conflicts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 11:23:43 +01:00
Dylan M. Taylor 47f42ba07b ci: grant packages write permission to release workflow 2026-10-31 23:43:03 -04:00
FredApps eea00a6186 Merge pull request #2088 from srt8hellcat2-ui/fix/1577-optional-page-edge-shadows-integration
M3: Add optional page-edge shadows setting (fixes #1577)
2026-10-31 23:42:20 +01:00
FredApps f2e1a8ce29 Merge branch 'main' into fix/1577-optional-page-edge-shadows-integration 2026-10-31 23:38:40 +01:00
FredApps a471cb1664 Merge pull request #1433 from srt8hellcat2-ui/feature/two-paged-cli-1354
M3: add optional --two-paged CLI flag (fixes #1354)
2026-10-31 23:35:31 +01:00
FredApps 19c96011b2 Merge pull request #2212 from srt8hellcat2-ui/feat/license-check-stage1
Add automated licensing validation for bundled assets (#2175)
2026-10-31 23:27:03 +01:00
FredApps 2e853c5fe0 Merge pull request #4279 from srt8hellcat2-ui/fix-3407-rewrite-after-page-delete
Rewrite an unsigned file in full when saving after deleting pages
2026-10-31 23:24:48 +01:00
FredApps 9af62ceb38 Isolate UI frame-budget measurements under nextest 2026-10-31 23:07:05 +01:00
Combiler01 b77699a22b test(optimize): accept Flate or CCITT compression in monochrome scan test 2026-10-31 22:50:50 +01:00
Combiler01 af03f08494 test(optimize): accept Flate or CCITT compression in monochrome scan test 2026-10-31 22:50:50 +01:00