Commit Graph
2074 Commits
Author SHA1 Message Date
David Mann f162c19e81 Merge remote-tracking branch 'origin/main' into integration-batch-17
# Conflicts:
#	crates/ui-egui/src/control/dispatch.rs
#	crates/ui-egui/src/control/params.rs
2026-11-05 12:44:02 +01:00
Khawar Zamman Wani e3ecd73569 feat(frame): rework the Frame tool's selection, handles and placement (#8920)
Thanks @wanikhawar — merging the Frame Tool rework.

Summary: Frame Tool selection/handles/placement now distinguish frame vs image (border / click / double-click and Layers thumbnails), with independent transforms, shape variants, Properties/options-bar stroke and fit commands, Convert to Frame, CLI/MCP `layer.frame.*` commands, native `.pcraft` persistence, and PSD export via editable groups + `pcFr` metadata (not Photoshop's native frame type). Tests cover selection, transforms, fitting, locks/hostile geometry, and native/PSD round-trips.
2026-11-05 12:39:02 +01:00
Khawar Zamman Wani 7ba589e01c MCP headless: waited commands run as jobs, with progress and cancel (#8129) (#8132)
Thanks @wanikhawar — merging.

**Summary:** In headless MCP, waited `command_run` / batch steps run job-capable commands as engine jobs (lock released while polling), with progress notifications and cancel/abandon on request drop. Fixes the “cancel does nothing / inspect blocks” behaviour for long filters. Cap of 16 background jobs; docs updated. Stack base for #8134.
2026-11-05 12:28:48 +01:00
David MannandClaude Opus 5.5 16000b01ef Address CodeRabbit review: batch 17 findings
Engine: droplet dependency capture skips disabled steps; a nested Batch
that was cancelled or could not write its error log fails the caller;
runDroplet forwards overrideOpen; actions.rename follows named Batch
steps; Batch steps inside a script count against MAX_SCRIPT_STEPS;
output claims compare destination identity; Save and Close never
replaces a read-only source. ATN: Md must be a BlnM enumeration,
adjustment-layer names must round-trip, Calculations exports a missing
blending as Multiply, Apply Image refuses unnamed-layer transparency.
Filters: Shape Blur records its resolved geometry, reserves its kernel
memory first, and reports a preparation failure as an error, not a
cancel; Crop keeps an artboard preset when the size is unchanged and
fits the board on a turned crop.

Codecs/cms/algo: zero-axis FITS image HDUs are empty; a GIF walk that
breaks off before the trailer fails closed; two-value .3dl shaper rows
are applied; fragmented custom kernels are refused and their work polls
cancellation.

UI: Conditional branches play through panel playback; paused actions
refuse to resume after being replaced; Playback Options OK validates
its fields; transform double-click ignores a hidden pivot; path boxes
snap to a stationary selection; modal blocking uses the effective tool;
a picker-consumed release clears snap lines and ends a Move drag; the
Crop preset control shows Selection and checks only it; Crop box undo
restores frame_from_selection; Bosnian fill labels.

Tests: timing asserts moved to an ignored test, plus the review's
coverage nitpicks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 11:37:38 +01:00
David Mann cf65810dda Merge remote-tracking branch 'origin/main' into integration-batch-17
# Conflicts:
#	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/id.tsv
#	crates/ui-egui/src/i18n/it.tsv
#	crates/ui-egui/src/i18n/ja.tsv
#	crates/ui-egui/src/i18n/ko.tsv
#	crates/ui-egui/src/i18n/nl.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/sr.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
#	docs/gaps.md
2026-11-05 09:03:28 +01:00
d7d138b1e5 Art History Brush: Opacity on the options bar (#10263) (#10278)
* Art History Brush: Opacity on the options bar (#10263)

The Art History Brush's own brush opacity is shown in its options bar
(0-100%) and sent to paint.artHistoryBrush. It is kept per tool, saved
across launches, set by the 1-0 keys and restored to 100% by Reset Tool,
as the Clone Stamp's is. Tests cover the UI wiring, per-tool persistence,
Reset Tool and stroke output at 8/16/32-bit.

* Update crates/ui-egui/src/panels/options_bar.rs

Co-authored-by: aiongg <67543387+aiongg@users.noreply.github.com>

* Art History Brush starts at 100% opacity on first use

A tool picked for the first time takes the outgoing brush; the Art
History Brush now takes it at full opacity, as the issue's default asks,
so a 30% Brush no longer makes the first Art History stroke 30%. Other
tools keep inheriting opacity.

* Art History Brush: document Opacity in the command contract and carry it in tool presets

---------

Co-authored-by: aiongg <67543387+aiongg@users.noreply.github.com>
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
2026-11-05 07:15:57 +01:00
9247c9e40a Port #5212: regenerate the scorecard for the two Playback Options preferences
Co-Authored-By: Zer0C00L01 <12090083+Zer0C00L01@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 06:30:37 +01:00
Khawar Zamman WaniandFredApps ad59d9962c Type: add OpenType Stylistic Sets submenu (Set 1–20) (#10304)
* Type: add OpenType Stylistic Sets submenu (Set 1–20)

Type > OpenType > Stylistic Sets toggles ss01–ss20 through new
type.openType.stylisticSets.setN commands on the usual formatting scope
(selected characters while editing, else the selected type layers).
The toggle direction and the menu checkmark follow the style at the
selection start. Updates TYPE-218-5 and G8.

Closes #10285

* Stylistic Sets: round-trip test through a full PSD; scorecard parity count

* Stylistic Sets: test PSD round trip on an opened file; record the new-document PSD gap

Documents made in PhotoCraft get no Txt2 block on PSD save, and the set
mask lives only there, so their sets are not saved to PSD yet. The engine
test keeps the .pcraft round trip, an io test covers the PSD round trip
of a file with type objects, and TYPE-218-5 and G8 record the gap.

* Stylistic Sets: share one tag table between the engine and the menu

The engine exports STYLISTIC_SET_TAGS; the Set 1–20 commands index it and
the menu checkmarks read it, so the 20 tags are listed once.

* Stylistic Sets: check malformed menu ids through the resolver, not the menu list

* Scorecard: TYPE-218-5 notes PSD save of stylistic sets in documents made here (#10308)

---------

Co-authored-by: FredApps <FredApps@users.noreply.github.com>
2026-11-05 06:16:54 +01:00
e580cca07a Port #5212: document Playback Options
Co-Authored-By: Zer0C00L01 <12090083+Zer0C00L01@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 06:13:13 +01:00
Khawar Zamman WaniandFredApps 13b481f892 Expose optional GPU composition and export in photocraft-cli (#10912)
* Add headless GPU backend foundation for composition and flat export (issue #8062 PR 1)

* Fix headless GPU readback bounds, API compliance, and error preservation (#8062)

* Fix GPU readback bounds, context thread spawn error, and test parity (#8062)

* Fix BandRenderer Send bound, PNG reborrows, and clippy lints (#8062)

* Fix effect shadow test construction and remove dead code wrappers (#8062)

* Use short reborrows for Headless renderer without lifetime escaping (#8062)

* Fix clippy collapsible_if and ensure multi-band geometry in flat export tests (#8062)

* Fix automation Rect import, add renderer diagnostics, and harden flat export retries (#8062)

* Expose optional GPU rendering in photocraft-cli (#8062)

* Fix GPU feature test APIs and native target gates

* Fix CLI locked metadata, bounded benchmark params, and protocol diagnostics (#8062)

* Verify unsupported GPU effects before testing band seams

* Fix CLI renderer borrows and GPU-enabled test compilation

* Use compositor buffer ownership API after upstream memory accounting change

* Fix GPU CLI lint failures and validate run environment policy

* Update export renderer test helper for owned compositor buffers

* Fix needless benchmark layer name borrow

* Fix headless GPU backend review findings (#10842)

- release a closed document's GPU caches through a BandRenderer hook
- bound the monitored readback wait and report a stalled GPU as device loss
- reject 32-bit float documents before band readback so exports fall back to CPU
- keep previews at 8-bit RGBA and report the palette/Duotone renderer bypass
- retain renderer diagnostics when encoding fails
- strengthen renderer, save-path and GPU diagnostics tests

* Use valid batch arguments and inspect method in GPU CLI tests

* Add GPU close-hook and 8-bit preview regression tests (#10842)

* Fix GPU CLI review findings (#10912)

- guard the benchmark's modulo divisors for one-pixel dimensions
- count a cold export as GPU only when the renderer context was used
- report every batch file's export warnings, deduplicating only GPU diagnostics
- drain renderer diagnostics before propagating convert and run save errors
- cover renderer use in the GPU precedence, bridge and serve tests

* fix(io): correct renderer binding mutability

* test(cli): verify narrow benchmark inputs and GPU diagnostics

* Fix remaining headless GPU review findings (#10842)

- release a document's GPU caches when file.close, file.closeAll or
  file.closeOthers removes it through a command
- honor cancellation while band readback waits, polling in 100 ms slices
- fault the device after a readback timeout so later exports skip it
- report single-layer, CMYK ink-mixing, ORA and PDF CPU paths to a
  requested renderer
- keep fallback warnings in their export instead of leaking them into the
  next one
- requeue renderer diagnostics when a renderer-aware save's final write
  fails
- write MCP/serve diagnostics without panicking on a broken stderr
- document the actual colour-space contract and drop F32 from the GPU
  depth list

* Fix remaining headless GPU review findings (#10842)

- release a document's GPU caches when file.close, file.closeAll or
  file.closeOthers removes it through a command
- honor cancellation while band readback waits, polling in 100 ms slices
- fault the device after a readback timeout so later exports skip it
- report single-layer, CMYK ink-mixing, ORA and PDF CPU paths to a
  requested renderer
- keep fallback warnings in their export instead of leaking them into the
  next one
- requeue renderer diagnostics when a renderer-aware save's final write
  fails
- write MCP/serve diagnostics without panicking on a broken stderr
- document the actual colour-space contract and drop F32 from the GPU
  depth list

* Fix remaining GPU CLI review findings (#10912)

- reject non-UTF-8 PHOTOCRAFT_GPU values instead of silently using the CPU
- release a batch item's document caches before taking the renderer to the
  next item, and report fallbacks once
- count warm benchmark runs that fell back to CPU in the summary
- write serve diagnostics without panicking on a broken stderr
- assert that the batch test's --gpu policy reaches the renderer

* Use question mark for cancellable readback errors

* Use question mark for cancellable readback errors

* Keep GPU export diagnostics with their attempt and stop bands on cancel

Encode native .pcraft bytes before draining renderer diagnostics, and
requeue export warnings when a workspace write fails, so callers still
report the adapter or fallback reason with the error.

Move a failed GPU attempt's queued diagnostics into its CPU retry result
instead of leaving them for a later successful export to report.

Stop GPU band readback at the next band after cancellation, and check the
interrupt before each CpuRenderer sink delivery.

Band readback uploads half-precision textures, so reject U16 alongside
F32: their samples cannot survive the upload. Tighten the 8-bit CPU/GPU
parity checks to 1/255.

* Keep GPU export diagnostics with their attempt and stop bands on cancel

Encode native .pcraft bytes before draining renderer diagnostics, and
requeue export warnings when a workspace write fails, so callers still
report the adapter or fallback reason with the error.

Move a failed GPU attempt's queued diagnostics into its CPU retry result
instead of leaving them for a later successful export to report.

Stop GPU band readback at the next band after cancellation, and check the
interrupt before each CpuRenderer sink delivery.

Band readback uploads half-precision textures, so reject U16 alongside
F32: their samples cannot survive the upload. Tighten the 8-bit CPU/GPU
parity checks to 1/255.

* Report partial warm fallbacks and CPU fallback on stderr

The averaged GPU Warm row now says how many warm runs fell back to the
CPU and were excluded from the average, through the existing helper.

The single-layer convert diagnostic test checks that the CPU fallback is
reported on stderr, in GPU-enabled and CPU-only builds alike.

* Keep headless export warnings when a workspace write fails (#10842)

A capability-scoped save encodes the export, then writes it; when the write
fails, the export warnings (folded together with renderer diagnostics) were
pushed back through `BandRenderer::push_diagnostic`, whose default is a no-op.
A custom renderer that overrides only `drain_diagnostics` therefore lost the
adapter or fallback reason that belonged with the error.

Keep them in `Headless` instead and return them from the next
`drain_diagnostics`, alongside the renderer's own queue. The regression uses a
renderer without a `push_diagnostic` override and checks the warnings survive
the failed write and drain exactly once.

Also name the actual source of the depth limit in the headless GPU matrix:
layer content is uploaded as half-precision textures, not band readback.

* Stop CPU bands and CPU retries on cancellation (#10912)

The CPU retry after a retryable GPU error composes through
`FlatSource::bands`, whose shared `emit` sink did not poll the export
interrupt: a cancel was only observed after the whole composite finished.
Check it once per band, as `CpuRenderer` does, for both RGB and CMYK ink
bands. The flat and streamed-PNG retry branches also check before starting
the full CPU composite again, so a cancelled export returns
`IoError::Cancelled` instead of re-rendering the document.

Tests: band-sink cancellation for RGB and CMYK inks, a renderer call counter
proving a second export reaches the renderer, and a pending `wait_slices`
poll observing cancellation set mid-wait.

* Merge origin/main into GPU foundation (#10842)

* Keep GPU-path diagnostics on every failure path, honour cancel in native copy

- save: export warnings of a failed local write stay in Headless pending diagnostics
- render: preview fallback warnings are returned, drained, and added to the doc.render reply
- io: renderer-neutral fallback wording; native single-layer copy checks cancellation per band
- gpu: gate wait_slices tests off wasm32 (#10842)

* Address CodeRabbit review: keep fallback reasons on failed retries, report native-copy and quick-export CPU use, guard diagnostics drain (#10912)

* Accept render diagnostics from the doc.render reply in the serve GPU test (#10912)

---------

Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
2026-11-05 05:39:59 +01:00
David Mann 5385ebd95b Merge PR #10788: Support recorded dialog filters, Calculations and Batch naming
# Conflicts:
#	crates/engine/src/cmd/actions_cmds.rs
#	crates/engine/src/cmd/automate_cmds.rs
#	crates/engine/src/cmd/file_cmds.rs
#	crates/engine/src/cmd/file_cmds/batch_run.rs
#	crates/engine/src/cmd/file_cmds/tests.rs
#	crates/engine/tests/it/main.rs
#	crates/ui-egui/src/panels/actions.rs
2026-11-05 05:19:44 +01:00
a331258dff bs: Add Bosnian (bs) to the interface languages (#10290)
* Add Bosnian (bs) to the interface languages

bs.tsv: 4,552 rows, Latin script, Ijekavian, the same keys as the newest
catalogs. Wording shared with storytold/craft-i18n locales/bs/; the 306
strings craft-i18n doesn't have yet are new. Every Bosnian locale,
Cyrillic included, resolves to it, as for Serbian; plurals reuse the
one/few/other rule of plural_russian.

Locale and plural tests, live locale case, localization docs and an
ATTRIBUTION row (AI-assisted, not yet reviewed by a native speaker).

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

* Add Bosnian to the translation license notice; document the locale test

LICENSE-translations.txt now lists the Bosnian catalog and its
provenance (shared with storytold/craft-i18n locales/bs/, AI-assisted,
not yet native-reviewed), as ATTRIBUTION.md points to it. The touched
live locale test gets a doc comment.

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

* bs: wording from the craft-i18n catalog review

The Bosnian catalog review (storytold/craft-i18n#72) asked for one word
per concept; this catalog follows: pan is "pomjeranje" (not
"pomicanje"), a spreadsheet is "proračunska tabela", Greek & Cyrillic
reads "Grčko pismo i ćirilica". Placeholders and ellipses are unchanged.

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

* bs: translate the 30 strings added on main; match Camera Raw labels

Main gained Path operations, the SVG smart object editor, Esc/Return pen
status messages and more since this catalog was written, so the
every-language tests (esc_ends_a_refused_draft_and_return_keeps_it) failed
on bs. Five cameraRaw-context entries (White Balance: As Shot, Tone
Histogram, Show Selected Region, Opened {name}, Loaded Camera Raw settings
from {file}) differed from the plain entries the panel actually draws, which
failed the Camera Raw localization test; they now match.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
2026-11-05 05:16:02 +01:00
David Mann 04291e6055 Merge PR #11210: Expose Move transform controls through the control channel 2026-11-05 04:58:01 +01:00
David Mann 5031d0f2b9 Merge remote-tracking branch 'origin/main' into integration-batch-17 2026-11-05 04:57:59 +01:00
362a307449 Port #8659: show Stop messages and continue called actions after a pause
A Stop step with its dialog toggle on now shows a Message window with
the recorded text and Continue (when the step allows it) and Stop,
keeping the steps already applied; with the toggle off it ends playback
silently, and Insert Stop turns the toggle on, as measured in the
reference application. Allow Continue is read from the paused playback,
not from the dialog's fields. Agents and headless playback keep the
engine's Stop semantics.

A pause inside a called action now carries its callers (at most 16):
confirming finishes the called action and then each caller after its
call, replayed inside the callers' playback frames so recursion checks
and the single history state still hold. A silent stop ends the callers
too. Fixes #8386.

Co-Authored-By: bommerts <44821497+bommerts@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 04:56:41 +01:00
Khawar Zamman WaniandFredApps 1089932ae9 Add a headless GPU backend for composition and flat export (#10842)
* Add headless GPU backend foundation for composition and flat export (issue #8062 PR 1)

* Fix headless GPU readback bounds, API compliance, and error preservation (#8062)

* Fix GPU readback bounds, context thread spawn error, and test parity (#8062)

* Fix BandRenderer Send bound, PNG reborrows, and clippy lints (#8062)

* Fix effect shadow test construction and remove dead code wrappers (#8062)

* Use short reborrows for Headless renderer without lifetime escaping (#8062)

* Fix clippy collapsible_if and ensure multi-band geometry in flat export tests (#8062)

* Fix automation Rect import, add renderer diagnostics, and harden flat export retries (#8062)

* Fix GPU feature test APIs and native target gates

* Verify unsupported GPU effects before testing band seams

* Use compositor buffer ownership API after upstream memory accounting change

* Update export renderer test helper for owned compositor buffers

* Fix headless GPU backend review findings (#10842)

- release a closed document's GPU caches through a BandRenderer hook
- bound the monitored readback wait and report a stalled GPU as device loss
- reject 32-bit float documents before band readback so exports fall back to CPU
- keep previews at 8-bit RGBA and report the palette/Duotone renderer bypass
- retain renderer diagnostics when encoding fails
- strengthen renderer, save-path and GPU diagnostics tests

* Add GPU close-hook and 8-bit preview regression tests (#10842)

* fix(io): correct renderer binding mutability

* Fix remaining headless GPU review findings (#10842)

- release a document's GPU caches when file.close, file.closeAll or
  file.closeOthers removes it through a command
- honor cancellation while band readback waits, polling in 100 ms slices
- fault the device after a readback timeout so later exports skip it
- report single-layer, CMYK ink-mixing, ORA and PDF CPU paths to a
  requested renderer
- keep fallback warnings in their export instead of leaking them into the
  next one
- requeue renderer diagnostics when a renderer-aware save's final write
  fails
- write MCP/serve diagnostics without panicking on a broken stderr
- document the actual colour-space contract and drop F32 from the GPU
  depth list

* Use question mark for cancellable readback errors

* Keep GPU export diagnostics with their attempt and stop bands on cancel

Encode native .pcraft bytes before draining renderer diagnostics, and
requeue export warnings when a workspace write fails, so callers still
report the adapter or fallback reason with the error.

Move a failed GPU attempt's queued diagnostics into its CPU retry result
instead of leaving them for a later successful export to report.

Stop GPU band readback at the next band after cancellation, and check the
interrupt before each CpuRenderer sink delivery.

Band readback uploads half-precision textures, so reject U16 alongside
F32: their samples cannot survive the upload. Tighten the 8-bit CPU/GPU
parity checks to 1/255.

* Keep headless export warnings when a workspace write fails (#10842)

A capability-scoped save encodes the export, then writes it; when the write
fails, the export warnings (folded together with renderer diagnostics) were
pushed back through `BandRenderer::push_diagnostic`, whose default is a no-op.
A custom renderer that overrides only `drain_diagnostics` therefore lost the
adapter or fallback reason that belonged with the error.

Keep them in `Headless` instead and return them from the next
`drain_diagnostics`, alongside the renderer's own queue. The regression uses a
renderer without a `push_diagnostic` override and checks the warnings survive
the failed write and drain exactly once.

Also name the actual source of the depth limit in the headless GPU matrix:
layer content is uploaded as half-precision textures, not band readback.

* Stop CPU bands and CPU retries on cancellation (#10912)

The CPU retry after a retryable GPU error composes through
`FlatSource::bands`, whose shared `emit` sink did not poll the export
interrupt: a cancel was only observed after the whole composite finished.
Check it once per band, as `CpuRenderer` does, for both RGB and CMYK ink
bands. The flat and streamed-PNG retry branches also check before starting
the full CPU composite again, so a cancelled export returns
`IoError::Cancelled` instead of re-rendering the document.

Tests: band-sink cancellation for RGB and CMYK inks, a renderer call counter
proving a second export reaches the renderer, and a pending `wait_slices`
poll observing cancellation set mid-wait.

* Merge origin/main into GPU foundation (#10842)

* Keep GPU-path diagnostics on every failure path, honour cancel in native copy

- save: export warnings of a failed local write stay in Headless pending diagnostics
- render: preview fallback warnings are returned, drained, and added to the doc.render reply
- io: renderer-neutral fallback wording; native single-layer copy checks cancellation per band
- gpu: gate wait_slices tests off wasm32 (#10842)

---------

Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
2026-11-05 04:53:25 +01:00
Khawar Zamman Wani 0a9717fa64 PDF export: keep the top text and shape layers as vectors, with selectable text (#10355)
* Skip compositing for geometric measurements

* Preserve simple PDF shapes and glyph source ranges

* Preserve text and shapes in PDF export (#10269)

- Export topmost simple text layers as vector glyph outlines with selectable text
- Embed ActualText unicode span and invisible text operators (mode 3 Tr) for 100% extraction
- Support stroked shapes in vector PDF export (centered solid strokes, dashes, line caps/joins)
- Retain glyph style indices in text rendering outlines

* Drop a product name from the glyph outline doc comment

* PDF export: keep path text and synthetic bold raster

* Fix PDF Unicode selection and respect font embedding permissions

* Render the text cache in PDF raster fallback fixtures

* Fix PDF vector selection eligibility and finite text matrices

* Preserve upper PDF vectors and reject overflowing curve controls

* Fix text shape import in PDF regression test

* Cover PDF Unicode map blocks and leading selection whitespace
2026-11-05 03:33:35 +01:00
yoriswind 7029dca60a Merge current main before pointer-control qualification 2026-11-04 11:28:43 -08:00
yoriswind 1720af269d Merge current main while preserving recorded Batch safeguards 2026-11-04 10:47:01 -08:00
David Mann b69d1f26b0 Merge PR #11011: Crop: Fill labels follow Delete Cropped Pixels, and the Selection preset entry (#10872) 2026-11-04 19:27:41 +01:00
David Mann cb323e9aea Merge PR #10965: Group action playback into one history state 2026-11-04 14:51:18 +01:00
David Mann d7e2bbe4a4 Merge PR #11077: Layers panel: filter by layer attribute (#10881)
# Conflicts:
#	crates/ui-egui/src/panels/layer_filter_ui.rs
#	docs/control-protocol.md
2026-11-04 14:51:17 +01:00
David Mann aac944a315 Merge PR #11223: Actions: map supported classic Gradient recordings
# Conflicts:
#	crates/engine/tests/it/main.rs
2026-11-04 14:51:00 +01:00
David Mann fd736f7ddc Merge PR #10986: Actions: map recorded Content-Aware Fill settings 2026-11-04 14:50:49 +01:00
David Mann a7f34dfa9f Merge PR #11222: Actions: support recorded Type Create Work Path 2026-11-04 14:50:47 +01:00
David Mann 3ea385cef3 Merge PR #11017: Layers filter: fill layers match no Kind button, and the Mode list has no Pass Through (#10878) 2026-11-04 14:50:46 +01:00
yoriswind a629a725f0 Preserve source data and diagnostics during Batch saves 2026-11-04 05:48:09 -08:00
David Mann 2c68cc6b95 Merge pull request #11203 from davidmann4/integration-batch-15
Integration batch 15: Crop, Free Transform and Actions epic PRs
2026-11-04 14:18:54 +01:00
Tareq HalabyandFredApps 2472b4a46b PSD: keep stylistic sets in Txt2 for PhotoCraft-native documents (#10313)
* PSD: keep stylistic sets in Txt2 for PhotoCraft-native documents.

needs_txt2 now covers Txt2-only OpenType flags (ss01–ss20 and non-default TXT2_FEATURES). Fresh documents get a framed point-text object with full style runs so Set 1/5 round-trip on save/reopen (#10308).

* Txt2: seed fill colour and font list on PhotoCraft-native blocks.

Fresh style runs get a /53 paint dict, and an empty font list gets a CoolTypeFont entry so index 0 resolves (CodeRabbit on #10313).

* Txt2: tag SimplePaint and ensure numbered /0 on legacy blocks.

CodeRabbit: write /99 /SimplePaint on fresh /53 dicts, and create the numbered resource dictionary before pad_frames when a legacy block lacks it.

* Txt2: treat a missing stylistic-set mask as 0 when comparing styles

A style run without key 85 used to agree with any ssNN mask, so enabling
ss01 could leave the file's runs in place on save. Align with import's
default of 0. Also restore the G8 gaps note after rebasing onto main.

* style(io): rustfmt psd_kerning stylistic-sets test

* Txt2: keep Photoshop /0 stable when seeding fonts and frames

Only seed a CoolTypeFont list and inject /0/8 when the block is
PhotoCraft-native or already had those keys / needs new frames, so
unedited Photoshop Txt2 saves stay byte-identical (#2374).

* style(text): rustfmt oversized-template assert

* PSD: keep the Txt2 scaffolding to PhotoCraft-native blocks

A file's own Txt2 block (any Photoshop era) is written as before: no
numbered /0 or /0/8 frame list is injected, a layer without a template
object gets its stub, a run without /53 isn't given one, and no
minimal style base is used. Only a block PhotoCraft creates itself
(prev.is_none()) gets fresh point-text objects, minimal runs, a seeded
font list and a frame list.

Fresh objects now write one /5 paragraph run per paragraph (UTF-16
lengths, checked conversion), as edited objects are refitted.

Tests: Photoshop blocks with an empty or missing /0 get no native
scaffolding; the oversized-template test is back to main's assertion;
fresh paragraph runs; the PSD round trip checks ss01 and ss05 on every
run.

---------

Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
2026-11-04 13:28:06 +01:00
skylar taylor-barrick 68b6dbfa79 Merge pull request #10750 from RickiNano/perf/bench-cmd-refresh-split
perf(bench): split command and refresh time; refresh like the app; stop rows timing setup
2026-11-04 12:39:54 +01:00
Tareq HalabyandFredApps 4d0ecd746f Toolbar: Alt/Option-click cycles the flyout tool slot (#10301)
* Toolbar: Alt/Option-click cycles the flyout tool slot.

Matches Photoshop: plain click keeps the shown tool; Alt-click advances through the slot without opening the menu (including tools Shift+letter skips).

* Toolbar: don't fit-on-screen on rapid Alt-clicks through Hand.

Alt-click only cycles the flyout slot; exclude Alt from the Hand/Zoom double-click handlers and cover inactive-slot cycling.

* Toolbar: ignore Hand/Zoom double-click after an Alt-click.

egui pairs a plain click with a prior Alt-click as a double-click; remember the previous click's Alt so fit-on-screen and actual-pixels only run for two plain clicks.

* Toolbar: read click modifiers from the slot's pointer release.

Match DesignCraft/EffectCraft: bind release mods to the tool rect, treat any modifier as blocking Hand/Zoom double-click, and harden the Alt-cycle test by clearing i.modifiers before release.

* Toolbar: cover 1/2/3-tool Alt-click cycles and hidden-tool slots.

Addresses ReviewerA on #10301: next_slot_tool wrap cases for short flyouts, and visible_sections so Edit › Toolbar hidden tools shrink the Alt-click cycle.

* style(ui): rustfmt after rebase onto main

* Toolbar: next_slot_tool never panics on an empty slot

Index with checked arithmetic and get() (house rule: no panics on
input-derived indices); an empty slot returns the current tool. Test
added.

---------

Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
2026-11-04 12:29:11 +01:00
yoriswind 508a35c83d Align Batch playback namespaces and retain child results 2026-11-04 01:51:41 -08:00
Psychotoxical c71677a159 Merge remote-tracking branch 'origin/main' into feat/layer-filter-attribute
# 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/state.rs
#	docs/control-protocol.md
2026-11-04 09:49:44 +01:00
Hamza e85b360248 Merge remote-tracking branch 'origin/main' into fix/layer-filter-kind-and-mode
# Conflicts:
#	crates/ui-egui/src/control/tests.rs
#	crates/ui-egui/src/panels/layer_filter_ui.rs
#	docs/control-protocol.md
2026-11-04 12:48:11 +05:00
yoriswind 85fc78bb64 Merge current main into recorded Actions dialog support 2026-11-03 21:55:00 -08:00
yoriswind 2974772936 Map supported classic Gradient action recordings 2026-11-03 19:32:28 -08:00
yoriswind 16b24885e6 Support recorded Type Create Work Path actions 2026-11-03 19:28:31 -08:00
yoriswind 1bcf7a3c6a Merge batch 14 main before action-history review fixes 2026-11-03 17:27:25 -08:00
yoriswind 1f9f37ae8e Merge batch 14 main into Content-Aware Fill recordings 2026-11-03 17:24:10 -08:00
yoriswind 336f95cd7d Expose Move transform controls through the control channel 2026-11-03 17:17:05 -08:00
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 94a6b68a04 Merge remote-tracking branch 'origin/main' into feat/layer-filter-attribute
# 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 22:09:02 +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 3028355333 Merge main and retain action history across Batch and Spelling 2026-11-03 12:42:57 -08:00
yoriswind 1b6bc4136c Merge main into recorded Content-Aware Fill mapping 2026-11-03 12:14:13 -08: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