28 Commits
Author SHA1 Message Date
JGF 35cb32be20 fix(export): report skipped layers in doc_export_layers (#8491) (#8713)
* fix(export): report skipped layers across automation surfaces

* test(export): use the MCP visible_only parameter spelling

* test(export): restore old adapter for hosted regression proof

* Revert "test(export): restore old adapter for hosted regression proof"

This reverts commit 397a5ffa2a.

* docs(export): qualify workspace-only response guarantees
2026-10-23 17:41:19 -04:00
bommerts 6425a23309 Merge main and preserve sharp CPU rendering during animated zoom 2026-10-22 13:58:21 -04:00
bommerts bd195276e9 Merge current main and preserve compact clipping evidence 2026-10-22 13:35:05 -04:00
JGF 2c8929d801 Merge upstream main into CPU pixel alignment fix
Preserve current upstream behavior and existing regressions; refresh hosted validation and SonarCloud configuration.
2026-10-22 11:30:54 -04:00
JGF 4778942d5d Merge upstream main to refresh adjustment clipping checks
Retain GitHub's clean merge tree and upstream's quick-export formatting correction.
2026-10-22 11:06:10 -04:00
JGF 2a5985a5d1 Apply CI formatter output to compact panel test 2026-10-22 09:41:49 -04:00
JGF 493c58c67d Match compact Rust formatting for wheel input fixture 2026-10-22 09:27:41 -04:00
JGF 51b9a89348 Test compact adjustment editor and visibility reachability 2026-10-22 09:26:27 -04:00
JGF 87a066ad53 Refresh adjustment clipping PR and align progress dates 2026-10-21 19:41:41 -04:00
bommerts d1c30954aa Fix compound layer property exports for Photoshop actions 2026-10-21 17:08:17 -04:00
bommerts 6351ee0609 Preserve continuous camera movement in default Crop 2026-10-21 16:19:24 -04:00
bommerts 76c514cdf5 Keep the CPU canvas sharp at 100% zoom (#8321) 2026-10-21 16:15:23 -04:00
bommerts e2a238737d Scale shape strokes when resampling documents (#8341) 2026-10-21 16:15:22 -04:00
JGF e481bbe32a New Document: labels show the arrow, not a text cursor (#8331)
In File > New, the field labels and headings (Width, Height, Resolution,
Color Mode, Background Contents, PRESET DETAILS, the Saved tab's text)
were selectable egui labels, so hovering them showed the I-beam as if
they were editable. In Photoshop they are static text.

- The dialog body turns off selectable labels, so every static label
  keeps the arrow. The name field keeps its text cursor and the size
  fields their scrub cursor.
- The preset-save error message stays selectable so it can be copied.
- Test: a kittest hovers the six labels and the empty Saved list
  (arrow) and the name field (text cursor). It fails without the fix.
2026-10-21 15:30:21 -04:00
JGF a310863330 Actions: Photo Filter saves to .atn under the name Photoshop runs (#8301)
Save Actions wrote Photo Filter steps with the four-char event code PhtF.
Photoshop loads the file but stops on playback ("The command 'Photo
Filter' is not currently available"). The same descriptor runs under the
string event photoFilter (measured by the reporter in Photoshop 27.11 at
8 and 16 bits). PhtF is the adjustment's class, not an event.

- Photo Filter now exports by name (photoFilter), like Black & White,
  Box Blur and Surface Blur since dfe94d6a. The descriptor is unchanged.
- Import still accepts PhtF through LEGACY_CODES, so actions PhotoCraft
  saved before keep loading, and they re-save under the name.
- Tests: Photo Filter joins the by-name/legacy-code test (export id,
  import by name and old code, near misses stay Photoshop steps). A new
  test records the issue's exact step, saves it strictly with nothing
  skipped, loads a Photoshop-authored step and an old PhtF step, re-saves
  both as photoFilter, and plays both the same as a direct run at 8 and
  16 bits. Both tests fail without the fix.
2026-10-21 15:30:15 -04:00
JGF 067ff89bef ci: validate clipping PR against upstream test-helper fix 2026-10-20 20:02:46 -04:00
JGF 22c97457bd docs: align clipping evidence dates and screenshot paths 2026-10-20 20:02:46 -04:00
JGF a05fee0719 Keep adjustment clipping visible in compact Properties panels 2026-10-20 20:02:35 -04:00
JGF 65879ba0fb Shortcuts: Ctrl+F4 closes the document beside Ctrl+W (Windows/Linux)
Photoshop on Windows closes the current document with Ctrl+F4 as well as
Ctrl+W. PhotoCraft bound only Ctrl+W, so Ctrl+F4 did nothing.

Add ("file.close", "Cmd+F4") to prefs::ALTERNATE_SHORTCUTS off the Mac
(macOS keeps Ctrl+F4 for window focus, and Photoshop for Mac has no such
key). It goes through the same guarded Close, so unsaved changes still
get the save prompt; the test checks both cases.
2026-10-19 18:43:25 -04:00
JGF b48a916b13 fix(algo): normalize nonpositive filter tile sizes (#7554) 2026-10-18 16:57:08 -04:00
JGF 2a952f164c Windows/Linux: open files in the running PhotoCraft instead of a second instance (#3708) (#3755)
Fixes #3708; part of #1540 (Flatpak needs its own follow-up: each sandbox has its own loopback).

A second launch hands its files to the running instance over an authenticated loopback channel (random port, 32-byte token in a private instance.json, constant-time check, bounded clients, requests and paths). Files are acknowledged only once the UI has taken them; the instance shuts the hand-off down before a CPU-compatibility relaunch; it runs only in the per-user settings mode. --new-instance and PHOTOCRAFT_NEW_INSTANCE=1 opt out.

Thanks to @MrCloudy2 (#2358), whose Linux version first handled the relaunch and per-user endpoints, and @Desayuno64 (#5273), whose shutdown flag and read deadline informed the final design.
2026-10-15 22:48:30 -07:00
JGFandClaude Opus 5.5 033ec991c2 fix(ui): show a magnifier cursor for the Zoom tool on Windows (#3735) (#3783)
winit maps CursorIcon::ZoomIn/ZoomOut to the plain arrow on Windows, so
the Zoom tool showed no cursor feedback there. Draw the magnifier (plus,
or minus while Alt zooms out) as an OS cursor bitmap, like the Hand
tool's #2196 fix; macOS and Linux keep their stock zoom cursors. Camera
Raw's preview zoom uses it too.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 12:29:13 -04:00
5c579ba81a Channels: Channel Options dialog to make alpha channels spot colours (#3761) (#3784)
* feat(channels): Channel Options dialog to make alpha channels spot colours (#3761)

Double-clicking an alpha channel's thumbnail in the Channels panel now opens
Photoshop's Channel Options dialog (double-clicking the name still renames it):
Name, Color Indicates Masked Areas / Selected Areas / Spot Color, the overlay
or ink colour (Color Picker) and Opacity, which becomes Solidity for spot
channels. A saved selection can now be turned into a spot channel with its own
ink for screen-print separations. The row context menu gains Channel Options…
and Quick Mask Options…, and `channel.options` without params from a menu
opens the dialog on the targeted channel. OK runs the existing engine command,
so agents can still call it directly with params.

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

* style: rustfmt module order in ui-egui lib.rs

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

* feat(channels): New Spot Channel dialog (#3761)

Channels › New Spot Channel… now opens Photoshop's dialog instead of adding
a channel straight away: Name (prefilled with the next free "Spot Color N"),
and Ink Characteristics: Color (opens the Color Picker) and Solidity. OK
creates the spot channel from the selection, as before, and remembers the ink
and solidity for next time. `channel.newSpot` with params still runs the
engine directly for agents, the CLI and MCP. The engine's `next_alpha_name`
helper is now public so the dialog's name matches the engine's default.

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

* i18n: keep main's Czech rows, add Vietnamese strings (#3761 review)

- cs.tsv: main has removed its duplicate copies of Tool, Stroke Path…,
  Clone Stamp, History Brush, Dodge, Burn and Sponge, so this branch keeps
  main's single rows; the only Czech change is the Channel Options / New Spot
  Channel block.
- vi.tsv: the Vietnamese catalog is complete since #2636, so it gets rows for
  Channel Color, Color Indicates:, Solidity: and Ink Characteristics.
- it.tsv: main now translates Masked Areas and Selected Areas, so this
  branch's duplicate rows are dropped.

Every catalog now only adds lines relative to main.

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

* Channel Options: Serbian, Hungarian and Turkish rows for the new strings

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-13 02:59:12 -04:00
JGFandClaude Opus 5.5 63a0e43e74 fix(type): key font menu caches on the shared engine's fonts (#4200)
The font menu's preview samples, family list and localized names were
cached on fonts::generation(), which any FontDb moves, and the previews
also on the served catalog's generation. Other engines registering fonts
(tests running in parallel) re-rendered every visible sample each pass,
and families covering Arabic asked for a repaint, so Harness::run never
settled: options_font_family_preserves_peer_faces_and_batches_layer_flags
and the font picker tests failed intermittently with "exceeded max_steps".

- photocraft-text: fonts::shared_generation(), moved only by the shared
  engine's FontDb (FontDb::mark_shared from new_shared).
- ui-egui: families(), localized_families() and the preview cache key on
  it; previews no longer key on the served catalog (a served family's
  sample appears when its fonts register, which moves the generation).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 21:17:10 -04:00
JGFandClaude Opus 5.5 5a0e2e2658 Web: wasm back under the 24 MiB gate with ~1 MiB headroom (25.38 -> 24.17 MB)
The "web build and wasm size gate" job failed on main and every PR: the
release `_bg.wasm` measured 25,379,677 bytes at 8d49ecf5, over the
25,165,824-byte limit in packaging/web/package.sh.

- egui's default fonts (Ubuntu Light, Hack, Noto Emoji, emoji-icon-font)
  were embedded uncompressed (1.4 MB) by egui's `default_fonts` feature.
  The app now builds egui without it; ui-egui's build.rs deflates the
  same files from the `epaint_default_fonts` crate (a build-dependency,
  so no font files are committed) and `egui_fonts.rs` rebuilds egui's
  exact default stack from them on first use. Test builds keep the
  feature as the oracle: the rebuilt definitions equal egui's byte for
  byte.
- Translation catalogs: every catalog repeated the same English sources.
  build.rs now stores the `context<TAB>source` keys once and each catalog
  as references plus translations, losslessly (`text()` still returns
  each .tsv byte for byte; malformed lines are kept as they are).
- wasm-release profile: opt-level "z" for PhotoCraft's own crates.
  Dependencies stay at "s" (at "z" the wasm grew 0.4 MB, measured), the
  file-decoding crates (codecs, psd, raw, heif, vector) stay at "s" and
  the pixel crates at 3, so decoding and filters keep their speed.

Measured with `trunk build --release` (trunk 0.21.14, wasm-opt v123 -Oz):
  upstream main 8d49ecf5      25,379,677 bytes
  this change                 24,167,186 bytes (-1,212,491)
  gate                        25,165,824 bytes (998,638 headroom)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:59:25 -04:00
JGFandClaude Opus 5.5 edc1b1e774 View: remember Extras, Show and Snap To across restarts (#3762) (#3787)
* View: remember Extras, Show and Snap To across restarts (#3762)

View › Extras, the View › Show items (Pixel Grid, Grid, Guides, …) and
the View › Snap To targets reset to their defaults on every launch. They
are now saved in Preferences (`viewExtras`) as they change and restored at
startup, as Photoshop keeps them between sessions.

Only items that differ from their defaults are stored, so a default
changed in a later release still reaches users who never touched it. A
hand-edited file can't break them: unknown keys and non-boolean values
keep their defaults.

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

* View: rustfmt the view-extras restart test (#3762)

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 07:47:33 -04:00
JGFandClaude Opus 5.5 a2cdc6c2d7 fix(ui): drag a document tab off the strip to float it in its own window (#3733) (#3785)
Dragging a document tab more than 24 pt above or below the tab strip now
tears it off into a separate OS window placed where it was dropped, so it
can be moved anywhere, other screens included (as in Photoshop). Sideways
drags still reorder. Both tab strips share the new tab_drag helper.

window.arrange.floatInWindow takes optional `document` and `position`
params (validated: bad values are errors, not panics); DocWindow gains a
serde-default `position`.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 05:13:48 -04:00
JGF f091c7fbf0 Windows: Alt-click clone hint and Ctrl+N channel errors (#251 follow-up) (#336) (#336) 2026-10-06 10:46:41 -04:00