Commit Graph
1995 Commits
Author SHA1 Message Date
David Mann 59b49ca14f Merge PR #9979: feat(ui): live preview in Color Pickers for dialog colour fields and the Crop shield 2026-11-04 01:51:22 +01:00
David Mann 2c4666aa6e Merge PR #10814: Edit › Transform › Distort: side handles move their edge, Perspective's side handles skew (#10085) 2026-11-04 01:51:10 +01:00
David Mann 545d447c10 Merge PR #10998: Actions: map recorded Scale Effects and Create Layers 2026-11-04 00:51:01 +01:00
David Mann e06d1cbdc1 Merge PR #11067: Layers panel: filter by layer effect (#10880) 2026-11-03 22:55:47 +01:00
Psychotoxical 66b9f2f68b Merge remote-tracking branch 'origin/main' into feat/layer-filter-effect
# Conflicts:
#	crates/automation/src/server.rs
#	crates/ui-egui/src/panels/layer_filter_ui.rs
#	crates/ui-egui/src/state.rs
#	docs/control-protocol.md
2026-11-03 21:55:06 +01:00
yoriswind 27f86af55b Merge main into recorded layer style mappings 2026-11-03 12:12:41 -08:00
yoriswind 7763e2578f Merge main into recorded Shear mapping 2026-11-03 12:11:27 -08:00
ljkxandClaude Opus 5.5 a0986a3977 Merge origin/main into feat/color-picker-live-preview
Resolve docs/ui-parity.md: keep main's status line and prepend this PR's entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 20:41:33 +01:00
ljkxandClaude Opus 5.5 9df16201aa Merge origin/main into feat/distort-edge-handles
Resolve the parity-doc conflict: keep main's status line and entries, re-add this PR's entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 20:39:56 +01:00
David MannandClaude Opus 5.5 72c2585177 Merge origin/main (287352bf92) into integration-batch-13
Conflict in crates/engine/src/jobs.rs: main's save commit point (#5333,
OPEN/COMMITTED/CANCELLED phase) met the batch's cancel state
(CANCEL_REQUESTED/WORK_FINISHED). Both now share one atomic with a
COMMITTED bit; commit vs cancel and the batch's late-cancel guard each
stay one compare-and-swap. A Batch that refuses a repeated or late cancel
reports CancelRefused::Finishing ("finishing") in jobs.cancel's
notCancelled list, still {"cancelled": 0}. control-protocol.md documents both.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 19:35:44 +01:00
FredApps 287352bf92 Merge pull request #5333 from vistaero/codex/streamed-psb-save
Integrate streamed PSB saves with the shared save service
2026-11-03 18:41:16 +01:00
yoriswind 0edb29a18c Merge upstream main into Shear action mapping 2026-11-03 09:32:21 -08:00
David Mann 3d36330d94 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	docs/scorecard.md
2026-11-03 18:08:29 +01:00
FredAppsandClaude Opus 5.5 d07684a379 fix(ui): Overscroll off keeps an image smaller than the window centred (#10488) (#11085)
* fix(ui): Overscroll off keeps an image smaller than the window centred (#10488)

With Tools › Overscroll off, an image smaller than the window stayed
wherever zooming around the pointer left it, inside the window, so
zooming out drifted it off centre. #1718 measured that on Photoshop 25.4,
but two reports of Photoshop itself (#10488, #4799) say it stays centred
with Overscroll off. The owner chose the centred behaviour:
scrollbars::clamp_axis now centres an axis on which the image is no
larger than the view; a larger image still can't leave its edges, and
Overscroll on keeps the free view.

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

* test(ui): Overscroll off centres a fitting rotated image (#10488)

CodeRabbit on #11085: the rotated clamp path was only tested from an
already-centred view. A 600 px square at 45 degrees, started off centre
in a 900-point view, now ends with its screen bounds centred.

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

* style(ui): keep the rotated centring test within rustfmt's width

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:55:50 +01:00
d21c403e5f Type: add OpenType Numerals submenu (figure styles) (#11051)
* Type: add OpenType Numerals submenu (figure styles)

Type › OpenType › Numerals sets lnum/onum/pnum/tnum as a radio style
(Default through Tabular Oldstyle). Checkmarks follow the selection
start; TYPE-218-5 scorecard/gaps updated; parity floor 640.

* refactor(engine): one style-at-character lookup for the OpenType menus

feature_on_at and numerals_style_at each walked the runs the same way;
they now share style_at. NumeralsStyle::from_id and numerals_style_of
read the existing tables instead of repeating them.

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

* fix(text): persist OpenType numeral tags through PSD EngineData

Map lnum/pnum/tnum as EngineData bools and the width×height combos as
FigureStyle (Krita/Illustrator), so Numerals choices survive PSD round-trip.

* docs(gaps): note Numerals PSD figure-tag round-trip

* revert(text): keep PSD EngineData to the keys Photoshop writes

Backs out the PSD half of 18610324 and its gaps note (58813de3); the
engine reformat in that commit stays.

- `LiningFigures`, `ProportionalFigures` and `TabularFigures` are not
  Photoshop EngineData keys (the commit says Photoshop only has
  `OldStyle`), so writing them puts keys of our own into users' PSDs.
- The `/FigureStyle` code table (1-4) has no oracle: no Photoshop-authored
  file in photocraft-corpus, and neither ag-psd nor psd-tools reads it.

AGENTS.md rule 3 asks for public specs or observation. PSD persistence
of the numeral styles can come back with a Photoshop-authored oracle.
The Numerals menu still round-trips through .pcraft.

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

* test(text): lock PSD EngineData to Photoshop OldStyle for numerals

Document AGENTS.md clean-room: only onum survives TySh round-trip; lnum/pnum/tnum stay .pcraft-only until a Photoshop-authored corpus oracle.

---------

Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:55:35 +01:00
ljkxandClaude Opus 5.5 0a379e2465 Merge origin/main into feat/color-picker-live-preview
Resolve docs/ui-parity.md: keep main's status line and prepend this PR's entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 17:46:51 +01:00
David Mann 559d3fe0f4 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/engine/src/cmd/file_cmds.rs
#	crates/ui-egui/src/app/files.rs
#	crates/ui-egui/src/dialogs/tiff_options_ui.rs
#	docs/file-format-parity.md
#	docs/gaps.md
#	docs/ui-parity.md
2026-11-03 17:11:53 +01:00
FredApps 26d151d061 Jobs: a save past its commit point can't be reported as cancelled
jobs.cancel, cancel_all_jobs and closing a document (cancel_jobs_on) cancelled
any running job, so they could report a save as cancelled while its worker
went on to replace the file. The point of no return was tracked only by the
desktop shell's own Cancel/Esc path.

The commit point now lives in the engine's JobCtx: commit() and a cancel race
on one compare-and-swap, so exactly one wins.
- Cancelled before commit: commit() fails, the save writes nothing and the
  job ends Cancelled.
- Committed: every cancel path leaves the job running and says so
  (Session::try_cancel_job -> CancelRefused::Committing; cancel_all_jobs and
  cancel_jobs_on return a CancelReport). The job then reports its real
  outcome, applied even if its document was closed meanwhile.
- jobs.cancel (engine and desktop control) replies {cancelled: n} as before,
  plus notCancelled: [{job, reason: "committing"}] for a save left running.
  This is not an error: the job is fine and will report how it ended.
  Single-job print refusals are unchanged.
- The shell's SaveCtl::commit and Cancel/Esc use the engine gate, so the
  status bar, control and scripting agree.

Tests: cancel before commit (target untouched, Cancelled), cancel after
commit (refused, Done, file written), cancel_all and document close with
mixed committed/open jobs, a commit/cancel race, and desktop jobs.cancel
before and during the write with real files.
2026-11-03 16:09:07 +01:00
ljkxandClaude Opus 5.5 c2acddae8c Transform: Distort side handles move their edge, Perspective's skew (#10085)
Edit › Transform › Distort ignored its mid-edge handles: mode_allows
rejected Hit::Edge in Distort, so a press there armed no gesture. As in
Photoshop, a Distort side handle now moves its edge freely: both of that
edge's corners move by the drag offset and the opposite edge stays put,
stopping before the box folds flat (keep_convex), as a Distort corner
does. Like the corner, it ignores Shift and Alt. The reference point
keeps its place in the box. Preview and commit share the session quad,
and the commit is one history step.

Perspective mode's side handles now skew along their edge, as in
Photoshop, by reusing the Skew-mode edge arm. Before, they scaled.

The handle pointer follows: the distort pointer on Distort side handles
and the skew pointer on Perspective side handles. Free Transform's plain
side handles (scale) and its Cmd-drag (free edge move) are unchanged.

Tests cover each edge's exact corner offsets, modifier independence, the
collapse stop, a real pointer drag committed in one step with the pixels
inside the shown quad, and Perspective edge slides. docs/ui-parity.md is
updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 15:39:32 +01:00
Yuki-init e3a84b628d TIFF Options: compression, image pyramid and Save Transparency (#8827) (#10932)
Offer TIFF compression, image pyramid and transparency options on Save As and Save a Copy, with matching CLI and automation parameters.

Follow-up: preserve the unsaved state when a copy discards layers over the document's own file, and check the other export formats for the same issue.

Closes #8827.
2026-11-03 15:39:15 +01:00
Hartmut NörenbergandClaude Opus 5.5 2fff1f8688 fix(ui): Ctrl+Alt + wheel zooms the canvas like Alt + wheel (#10488) (#10517)
* fix(ui): Ctrl+Alt + wheel zooms the canvas like Alt + wheel (#10488)

Ctrl+Alt+wheel over the canvas did nothing useful because two conditions in
wheel_nav.rs excluded it from the Alt gesture:

    let latest_alt = wheel.last().map(|(_, _, m, _)| m.alt && !m.command && !m.ctrl);

and, in the raw-event accumulator, every branch was filtered with
`!m.command && !m.ctrl`. Ctrl+Alt+wheel therefore never set the tracked `alt`
and never contributed a notch to `raw`: with Preferences > General > Zoom with
Scroll Wheel ON it produced nothing at all (raw stayed zero, so the zoom read an
eased ~0), and with it OFF it fell through to classify's `_` arm and merely
scrolled vertically, because egui keeps vertical_scroll_modifier = ALT and does
not fold the delta onto x when both scroll patterns match. The combination is a
dead/incorrect gesture today, so no working behaviour is being replaced.

The new `alt_gesture` helper forgives `command` only when `ctrl` is set as well.
winit mirrors a held Ctrl on Windows (and Linux) into BOTH ctrl and command, so
a bare `!command` test can never match what a Windows reporter typed; macOS
Cmd+Alt (command set, ctrl not) is left out of the zoom gesture (egui 0.37 does not fold it sideways either: with Alt held both scroll patterns match, so its delta stays vertical). `latest_shift` stays strict, so
Ctrl+Alt+Shift+wheel zooms continuously instead of snapping to the ladder, and
the Shift-only and plain branches are untouched, so plain Ctrl+wheel still
scrolls sideways (#635). `legacy_pinch_to_zoom` is untouched and cannot
double-count a fractional Ctrl+Alt pinch step: it matches `modifiers.ctrl`
whatever else is held, but it *replaces* the wheel event with `Event::Zoom`, so
`wheel_events` never sees that step a second time.

Deliberately out of scope: the other half of the report, the centred-zoom /
overscroll complaint. The per-frame view clamp at canvas.rs:1737-1741 runs only
when Preferences > Tools > Overscroll is off (it is on by default), so with the
defaults nothing pulls the view centre back, and what the reporter is seeing is
more likely the deliberate wheel_anchor nearest-image-point clamp
(view_xform.rs:239, #3720) or Zoom Clicked Point to Center. That needs its own
reproduction and issue, and is noted as still open in the dev log.

Tests, fail-first: each_modifier_maps_like_photoshop gained Windows Ctrl+Alt
rows (preference off and on, instant and eased, a fractional pinch step counted
once, and a macOS Cmd+Alt guard row) while keeping its Ctrl-only sideways-scroll
rows; new full-app kittest test
input_tests::ctrl_alt_wheel_zooms_the_canvas_like_alt_wheel zooms five notches
around the pointer and holds the document point under it. Both failed before the
production change and pass after.

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

* test(ui): Ctrl + Alt + Shift + wheel is dead today, not a zoom (#10488)

CodeRabbit 4432102938 asked for an assertion on the Ctrl + Alt + Shift combination instead of
only a comment, and for the reason: the filter rejects the wheel event. Both are right. With ctrl
held, latest_shift (wheel_nav.rs:381) is false because it excludes ctrl and command, so the alt
branch of the filter (wheel_nav.rs:413-422) runs and its "!m.shift" drops the notch out of raw;
shift stays false, so the snap branch never takes it either.

The new row in each_modifier_maps_like_photoshop first asserted what my own comment claimed - a
continuous zoom, with Zoom with Scroll Wheel off and Animated Zoom off - and failed exactly that
way: "Ctrl + Alt + Shift + wheel zooms 10%, at once: [0.0 0.0] 1 snaps 0". Pan zero, zoom 1.0,
snaps 0, and the same numbers with Animated Zoom on, while plain Alt + Shift still snaps. The
gesture is dead, and only the ctrl half of it kills it.

So the three places that asserted a continuous zoom are corrected here instead of left to rot: the
module doc (wheel_nav.rs:8-11), the comment above the filter (wheel_nav.rs:407-413) and the parity
row (docs/ui-parity.md:193). They now state that the gesture is dead, point at the test that pins
it, and name the open question. No behaviour change: the repo has no measured Photoshop evidence
for this combination (the issue names only Ctrl + Alt), so the choice - (a) accept Shift in the alt
branch when Ctrl is held, making it zoom like Alt + wheel, or (b) treat it as exactly Alt + Shift
and snap - goes to a maintainer rather than being invented. Option (b) has a measured cost worth
knowing before anyone picks it: plain Ctrl + Shift + wheel pans sideways today ([40,0], zoom 1.0,
snaps 0, and no test covers it), and under (b) that becomes a no-op with Zoom with Scroll Wheel on.

Gates: cargo test -p photocraft-ui-egui --lib -- wheel = 102 passed, 0 failed (with the promised
assertion first: 101 passed, 1 failed); cargo clippy -p photocraft-ui-egui --all-targets
-- -D warnings clean; cargo fmt -p photocraft-ui-egui -- --check clean.

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

* test(ui): pin Ctrl + Alt + Shift + wheel with Zoom with Scroll Wheel on (#10488)

Review 4433950859: both Ctrl + Alt + Shift + wheel assertions ran with Zoom with
Scroll Wheel off, while the test comment, the wheel_nav.rs filter comment and the
ui-parity.md Wheel row stated the no-action result unqualified. Measured, not
copied: a temporary probe test ran one Ctrl + Alt + Shift notch (Line unit,
gesture_with, 60 frames summed) in all four preference combinations and printed
(pan, zoom, snaps) through an assert that was made to fail:

    zww=off anim=off ([0.0 0.0], 1.0, 0) | zww=off anim=on ([0.0 0.0], 1.0, 0)
    zww=on  anim=off ([0.0 40.0], 1.0, 0) | zww=on  anim=on ([0.0 40.0], 1.0, 0)

    test result: FAILED. 102 passed; 1 failed; 0 ignored; 0 measured; 4526 filtered out; finished in 2.63s

The suggestion's premise holds: the dead-gesture claim is true only with Zoom
with Scroll Wheel off. With the preference on, alt_gesture keeps the notch out of
the branch's raw, but `alt != zoom_with_wheel` is false so the zoom arms are
skipped, and egui's own smoothed scroll delta (which the raw filter never gates)
pans the notch through the ordinary scroll path: one whole notch, 40 points
vertical, no zoom, no snap, with Animated Zoom off AND on (it only spreads the
same 40 points over later frames).

Probe deleted; the qualified version landed in all three artefacts:
- wheel_nav/tests.rs: the two dead assertions now say "with Zoom with Scroll
  Wheel off", two new assertions pin the preference-on pan (near [0.0 40.0],
  zoom 1.0, snaps 0, both Animated Zoom modes), and the comment and the
  "not even a scroll" sentence carry the preference condition and the numbers.
- wheel_nav.rs classification comment: the dead-gesture sentence is qualified
  the same way.
- docs/ui-parity.md Wheel row: same qualification plus the measured numbers.

Final gates: cargo test -p photocraft-ui-egui --lib -- wheel ->
test result: ok. 102 passed; 0 failed (also re-run after cargo fmt re-wrapped
one over-long assert, same result); clippy -D warnings clean; fmt --check exit
0; cargo xtask layers: OK, 31 crates, no layering violations.

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

* fix(ui): keep Cmd+Ctrl+Alt + wheel off the Alt zoom path, pin AltGr (#10488)

alt_gesture now also requires !mac_cmd when forgiving command, so macOS
Cmd+Ctrl+Alt (command, ctrl, mac_cmd, alt) is not the zoom gesture. Tests pin
the macOS and Windows/Linux modifier shapes and that AltGr reaches egui as
neither ctrl nor alt.

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

* fix(ui): keep Ctrl+Alt+Shift + wheel as before, correct the AltGr note, pin the Alt key fallback (#10488)

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 15:36:39 +01:00
Psychotoxical f72165ad42 Layers panel: filter by layer effect (#10880)
Effect comes after Name in the filter-type dropdown. A second dropdown picks
Bevel & Emboss, Stroke, Inner Shadow, Inner Glow, Satin, Overlay, Outer Glow or
Drop Shadow, and the panel lists the layers with that effect turned on.
Overlay covers Color, Gradient and Pattern Overlay. ui.set {layerFilter}
takes the effect by id.
2026-11-03 15:17:12 +01:00
David MannandClaude Opus 5.5 a0418a2e29 Address CodeRabbit review: Batch failures, late Esc, CLI format, bridge result
- A failed input stays in `errors` when `jobs.cancel` or Esc lands while it runs, instead of
  showing up as skipped without its reason.
- Esc after the last input is refused: the worker closes the interrupt window once no
  checkpoint is left, so `request_batch_interrupt` no longer answers true for a question
  that never comes.
- `photocraft-cli batch` without `--format` saves a file PhotoCraft only opens as PSD, the
  format `--naming`'s {ext} already plans, instead of asking the encoder for the input's
  import-only extension.
- `--recursive` help says the output is flat.
- The app bridge keeps a cancelled Batch's partial result in the error it returns to MCP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 14:50:52 +01:00
David Mann 7329c700bb Merge remote-tracking branch 'origin/main' into integration-batch-13
# Conflicts:
#	apps/photocraft-cli/src/args.rs
#	crates/engine/src/jobs.rs
#	crates/engine/src/jobs/tests.rs
2026-11-03 13:52:30 +01:00
FredApps 66e9325379 Merge remote-tracking branch 'upstream/main' into pr-5332 2026-11-03 11:16:12 +01:00
FredApps 5f70428dfc Merge storytold/main (d0bff086d) into PR #10897 branch
Resolve conflicts with #5331 (EXR streaming): the block-by-block EXR import now
reads from the same identity-verified handle as the rest of the open path, and
docs/scratch-disks.md keeps both the EXR streaming pointer and the RAM/scratch
admission notes.
2026-11-03 10:33:10 +01:00
FredApps 57443b6a30 Merge remote-tracking branch 'upstream/main' into pr-5332
# Conflicts:
#	crates/codecs/src/exr_stream.rs
#	crates/codecs/tests/it/exr_stream.rs
#	crates/io/src/exr_native.rs
#	crates/io/src/lib.rs
#	crates/io/tests/it/streaming_exr.rs
#	docs/roadmap.md
#	docs/scorecard.md
#	docs/scratch-disks.md
#	docs/streaming-io.md
#	scorecard/reliability.toml
2026-11-03 10:26:54 +01:00
FredApps 0ec30fcf7c Merge storytold/main into codex/gpu-viewport-streaming
Main moved the GPU canvas into canvas/gpu_canvas/* and gained its own
budget, LayerFit and background-redraw machinery. Conflicted files take
main's version; the viewport streaming is re-integrated on top of main's
budget in the following commit.
2026-11-03 09:59:21 +01:00
FredApps 3695186329 Consolidate RAM detection in raster::memory::system; scratch-aware PSD/TIFF admission
One RAM detector: the cgroup v1/v2, macOS reclaimable and Windows commit providers move from
photocraft-io into photocraft_raster::memory::system (L0), which the residency budget (#5330)
and photocraft_io::memory both read. Unreadable container limits still fail closed, swap is
never counted as RAM. sysinfo is unified on =0.40.1 (raster only).

While the scratch disk is spilling (on, not paused), import admission credits the tile pixels
of an estimate against spill::scratch_capacity() (free space above the reserve, within the
Scratch Size Limit); decode buffers, conversion copies and merged planes stay RAM-only. Spilling
off/paused and the web keep the RAM-only policy unchanged. PsdMemoryEstimate gains tile_bytes;
the flat TIFF streaming check credits its tile surface the same way; engine approveMemory's
fast pre-check uses the credited hard limit and the import re-checks exactly.
2026-11-03 09:48:22 +01:00
FredApps 7e29a9999c Wire EXR band streaming into main's path open
- import_file_for_open_with decodes single-part flat scanline EXR block by block into
  tiles; headers the band decoder refuses fall back to the whole-file decoder, so files
  main opened still open. Band-time failures and cancellation publish no document.
- The RAM tile budget and scratch-disk checks live in exr_native (the PSD stream module
  they came from is dropped); over-budget opens fail with IoError::OutOfMemory.
- The band decoder picks colour channels with exr_color_channels, like the byte decoder.
- Tests move into the per-crate it binaries and use import_file; an engine open-job test
  covers the OpenSource::Path route. The ui-egui sync open test is dropped: main's
  synchronous open reads bytes, and the io test covers the oversized header.
- docs/streaming-io.md, roadmap, scratch-disks and REL-212-1 describe EXR only.
2026-11-03 09:23:15 +01:00
FredApps fdab6c0a33 Merge remote-tracking branch 'upstream/main' into pr-5331 2026-11-03 09:06:31 +01:00
FredApps 25f21db893 Revert "Stream native PSD and EXR imports through bounded seekable bands"
This reverts commit 89ed4cb284 from the
#5332 branch so the GPU viewport streaming lands standalone. The import
work is rescoped separately in #5331 (EXR streaming only).
2026-11-03 09:03:38 +01:00
yoriswind 446e1a4589 Merge commit '655295b2a2c400bded0640f5d97367000a057b2e' into codex/10723-nested-lefx 2026-11-03 00:01:32 -08:00
Khawar Zamman Wani 259b5590ae Merge origin/main (655295b2a2) into PR #10897 branch
Keep the PSD memory admission work and upstream's scratch storage
together. Conflicts resolved:
- Cargo.lock: both sysinfo versions are required. 0.40.1 serves
  photocraft-io's adaptive import budget; 0.37.2 serves
  photocraft-raster's scratch volume and memory supervision. Cargo
  metadata resolved the lock with no other changes.
- crates/engine/src/lib.rs: Session keeps pending_preflights and
  next_pending_preflight beside scratch_runtime and scratch_epoch.
  Session derives Default, so neither set needs a manual initializer.

Upstream: 655295b2a2
2026-11-03 12:54:59 +05:30
FredApps 8ce599da3a Merge remote-tracking branch 'upstream/main' into pr-5330 2026-11-03 07:12:38 +01:00
yoriswind 3271b4acf0 Actions: map Scale Effects and Create Layers recordings 2026-11-02 22:03:52 -08:00
yoriswind 8e17f90c06 Bound Shear action curves and preserve native precision 2026-11-02 18:26:17 -08:00
David MannandClaude Opus 5.5 3ce04b52f4 Address CodeRabbit review: Batch writes, recording and dialog edge cases
- CLI batch: recursive inputs keep the engine's tree order for {serial};
  --format picks the encoder whatever extension --naming writes; the
  summary prints before --error-log is written.
- Batch: a jobs.cancel during a write keeps that file in `files`;
  Opened Files refuses a default-named result that replaces another open
  document's file; a recorded Save leaves a document changed when Batch
  writes nothing for it.
- Recording: folded Move-tool nudges add whole-pixel steps; a null
  Check Spelling `action` is recorded as Check Spelling.
- Linked files: a document without links lists none missing; a look
  whose links changed while it ran is dropped.
- Save for Web: a null or empty destination opens the picker; a rename
  while the picker is open writes the picked file.
- Actions: a Check Spelling step fails instead of replacing a dialog
  opened by hand.
- Docs: desktop Batch cancel flow, Check Spelling step shape, filter row
  history count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 03:02:19 +01:00
dotCooCoo fef15729aa Merge main into feat/pcraft-full-composite
Main now takes the manifest envelope from craft-pcraft-format, which has
no full_composite member. The save writes the member after the envelope
when it writes composite/full.png, and read_full_composite reads it back.
2026-11-02 17:02:14 -08:00
yoriswind c9fc8458b4 Map recorded Shear actions with measured curve settings 2026-11-02 16:40:07 -08:00
FredApps ed681787c3 Add a Scratch Size Limit preference and honour the web memory cap in the memory policy 2026-11-03 01:16:52 +01:00
David Mann 4f6a2c50f0 Merge #4579: the author's latest commits
# Conflicts:
#	docs/gaps.md
#	docs/target-app-parity.md
2026-11-03 01:05:27 +01:00
David Mann eb3c2044d4 Merge #10755: Support newer recorded Action events
# Conflicts:
#	crates/engine/src/cmd/artboard_cmds.rs
#	crates/engine/src/cmd/atn_cmds.rs
#	crates/engine/src/cmd/atn_cmds/events.rs
#	crates/engine/src/cmd/atn_cmds/steps_make.rs
#	crates/engine/tests/it/main.rs
#	docs/atn.md
#	docs/development.md
#	docs/file-format-parity.md
2026-11-03 00:44:15 +01:00
David Mann b0aa230ae8 Merge #10765: Actions: support direct Gradient Map and Lab-range Replace Color
# Conflicts:
#	crates/engine/src/cmd/atn_cmds.rs
#	crates/engine/src/cmd/atn_cmds/events.rs
#	crates/engine/tests/it/main.rs
#	docs/atn.md
#	docs/development.md
#	docs/file-format-parity.md
2026-11-03 00:38:44 +01:00
Fabio Lissi 1b561c02ca Separate Batch conformance table from following notes 2026-11-02 17:37:51 -06:00
Fabio Lissi a2c4ac0b0c Match Batch Esc flow and show read-only input preview 2026-11-02 17:36:55 -06:00
David Mann 2915849b07 Merge #4514: Record actions in a document-independent form (#219) [depends on #4496]
# Conflicts:
#	crates/engine/src/cmd/type_spell_cmds.rs
#	crates/engine/src/jobs.rs
#	docs/gaps.md
#	docs/target-app-parity.md
2026-11-03 00:36:40 +01:00
David Mann 98c2213e5c Merge #9211: Layers panel: the filter row lists linked, missing or embedded smart objects
# Conflicts:
#	crates/automation/src/server.rs
#	crates/ui-egui/src/control/tests.rs
#	crates/ui-egui/src/panels/layer_filter_ui.rs
#	crates/ui-egui/src/panels/layer_filter_ui/tests.rs
#	docs/control-protocol.md
#	docs/ui-parity.md
2026-11-03 00:34:07 +01:00
David Mann 3e8db12b49 Merge #9315: Layers panel: the filter row lists the artboards that hold the selected layers
# Conflicts:
#	crates/automation/src/server.rs
#	crates/ui-egui/src/panels/layer_filter_ui.rs
#	crates/ui-egui/src/panels/layer_filter_ui/tests.rs
#	docs/control-protocol.md
#	docs/ui-parity.md
2026-11-03 00:32:13 +01:00
David Mann 037450f71d Merge #10439: Layers panel: filter by Color, as in Photoshop (#5898)
# Conflicts:
#	crates/ui-egui/src/panels/layer_filter_ui/tests.rs
2026-11-03 00:31:20 +01:00