Commit Graph

891 Commits

Author SHA1 Message Date
Claude 237a4707eb
Packaging: Windows MSI setup wizard (folder choice, progress, version, launch on finish)
Double-clicking the MSI now opens WixUI_InstallDir without the licence page:
Welcome, install folder (remembered for upgrades in
HKLM\Software\PhotoCraft\InstallDir), Ready, progress, and a Finish page with
a ticked "Launch PhotoCraft" box (WixShellExec, unelevated). The pages name
the full version, pre-release tag included (photocraft.en-us.wxl).
package.ps1 draws the banner and side bitmaps from the app icon, so no WiX
stock art ships. msiexec /qn still installs silently. The release and ARM64
workflows install the WiX UI and Util extensions; packaging-lint checks the
.wxl. Ported from VectorCraft (storytold/vectorcraft@aa548d2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AP7ThRN3kpNmjsuJUerJui
2026-10-09 13:58:45 +00:00
coolvitto 214e062af8
Japanese: translate about 1,000 more UI strings (#1669)
Filter and gallery parameter names and choices, command, tool and menu names, hints, preferences, metadata fields and colour spaces, using Photoshop's Japanese terms (浅浮き彫り, チョーク・木炭, アンシャープマスク …).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:57:14 -04:00
storybored379 15e35cf605
MCP: shared conventions and cancellable Render Video (#1668)
The MCP server follows the crafts' shared conventions (FilmCraft #28): core tools
incl. render_preview, titles and annotation hints, strict argument keys (-32602),
live photocraft://document and photocraft://commands resources, and -32700
recovery from malformed JSON lines. Headless Render Video writes through the
granted write root, reports progress, stays ping-responsive and can be cancelled,
removing only the files it created. docs/mcp.md describes it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:54:14 -04:00
Elvis33LE 7533254791
Keep PNG text metadata through document saves (#1684)
PNG tEXt/zTXt/iTXt entries (and TIFF ASCII tags) were dropped on open with a warning. The
document now keeps them in Metadata.text, the .pcraft manifest saves them (older files still
load), and PNG/TIFF saves write them back; Metadata: None and embed_metadata=false strip them,
and PSD/PSB and palette PNG exports warn that they are dropped. XMP in a tEXt or zTXt chunk is
read as XMP too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:53:37 -04:00
Nigel Ihza Firdausy 75e6bad453
Control: ui.inspect reports the open Brush Preset picker (#1672)
ui.inspect now has brushPicker: null while closed, {pos, list} while the Brush
Preset picker is open (list is its collapsed/filter/view/renaming state), so
agents can see what a right-click with a painting tool opened. Fixes #1558.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:50:01 -04:00
Nigel Ihza Firdausy 8bc9861224
Control: ui.menu.invoke respects the modal menu policy (#1671)
A control-channel menu click could run an edit behind an open dialog (a rotation
under Image Size), which the native menu bar already refuses (#1354). The modal
gate moves to menus::modal_allows and ui.menu.invoke checks it; view navigation
stays live, engine.execute is unaffected. Fixes #1556.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:49:56 -04:00
Harrison O'Connor-Hoover 18bb712f43
Save/Close: finish layered TIFF writes before discarding documents (#1723)
Choosing Save in the close prompt for a layered TIFF only parked the save behind TIFF Options,
yet the prompt went on to close the document. The prompt now waits for TIFF Options and
advances only once the write succeeded and the document is clean; the save stays bound to the
document that asked even if the active tab changes, and Discard Layers and Save a Copy leaves
the original's path and unsaved changes alone, as in Photoshop. Fixes #1098.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:49:09 -04:00
Brennan Stehling 9fee51c308
macOS: save to SMB shares that refuse a full flush (#1639)
sync_all on Apple platforms asks for F_FULLFSYNC, which SMB shares (ENOTSUP) and some virtual
file systems (ENOTTY) refuse, so every save there failed. atomic::sync_file falls back to a
plain fsync for exactly those errors, as Apple's removefile does; the automation workspace
writes use it too. rustix is already in the lock on Apple targets. Fixes #1336.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:36:03 -04:00
Chandirasegaran f338454f36
Layers panel: the eyes on effect rows show and hide effects (#1664)
The eyes on a layer's Effects row and on each effect's row did nothing. As in Photoshop, the
Effects eye now hides or shows all of the layer's effects and an effect's eye just that one, each
one history step that keeps the settings, via the new layer.setEffectsVisible command. Fixes #1622.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:25:57 -04:00
kayrockscreenprinting 1284e79d23
Selective Color and Color Lookup: a wrong-typed key is an error (#1790)
Selective Color and Color Lookup params with the wrong type (a string percentage, a short range
array, an unknown method, range or interpolation) were silently ignored, so layer.setAdjustment
kept the old values without saying so. They are now BadParams errors naming the key; null still
means not given. Fixes #936.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:23:34 -04:00
Nigel Ihza Firdausy c017b119ff
Gradient tool: the options-bar swatch opens the Gradients presets (#1681)
Clicking the gradient swatch in the options bar did nothing; as in Photoshop it now opens a
popup with the Gradients preset browser, so a preset is picked without opening Window › Gradients.
Fixes #1651.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:17:21 -04:00
midasdf b5320e590e
Preferences: System Title Bar says it applies at next launch (#1677)
On Windows and Linux the System title bar checkbox now carries the existing "Applies at next
launch." note, since saving it does not change the current window. Fixes #1661.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:17:05 -04:00
Nigel Ihza Firdausy 681e7f3b89
Layers panel: right-click opens the fx and adjustment footer menus (#1680)
As in Photoshop, a secondary click on the Layers footer's Add a layer style and Create new fill or
adjustment layer buttons opens their menus too (a primary click still toggles them), and a small
arrow marks them as menu buttons. Fixes #1579.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:17:02 -04:00
Nigel Ihza Firdausy efa62efa0c
Liquify: test that Alt-reversed strokes survive replay, undo and redo (#1675)
Follow-up to #1494: Alt captured at stroke-down records the reversed tool, a
later stroke records the selected one, and the field rebuilt from the strokes
matches after undo and redo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:11:07 -04:00
midasdf 40f14d25e8
Plug-ins: keep the originating error across parallel bands (#1654)
When one band failed, its siblings stopped with a generic "another band failed"
error, which could win the collection order and hide the real cause. The abort
flag now carries the first error, so every band reports it; tests cover traps,
error codes and the instruction budget across parallel bands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:11:00 -04:00
Jason Xiang c88dbd26cd
Live strokes: reject out-of-range coordinates before the preview changes (#1652)
The live brush, pencil, retouch and dab previews fed pointer batches to the
stroke renderer unchecked, so a NaN or huge coordinate could hang the path
walker. Every push now runs the shared check_coords first and rejects the whole
batch without touching the preview; tests cover 8/16/32-bit and every live tool.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:10:53 -04:00
Alan Rockefeller 9b4562f2a0
Open dialog: upper- and mixed-case extensions on Linux and the BSDs (#1439)
The portal and zenity match rfd's *.ext globs case-sensitively, so IMG_0001.JPG or DSC_0001.NEF didn't show. On Linux and the BSDs each letter of an Open filter extension becomes a [jJ] class; Windows and macOS keep plain extensions.
Duplicate #1682 by @switch87 took the same approach.

Co-authored-by: switch87 <switch87@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:10:04 -04:00
David Mann 347a0f9fc9
Gradient Map: pick presets from the gradient library (#1780)
The Gradient Map preset picker lists the session's gradient library by group with a swatch per preset, in the Properties panel and the dialog, as Photoshop's gradient picker does. Picking one writes its colour stops as one undoable edit.
Fixes #1588.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:09:51 -04:00
Nigel Ihza Firdausy 616f206c5d
Filter previews: only for the active document, and computable without a GPU (#1676)
A command dialog's preview is never shown in another tab, and the preview is computed even without a GPU texture, so headless tests can check it (90° Arbitrary rotation, Preview off, document untouched).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:09:45 -04:00
kayrockscreenprinting a0abb59044
View › Show › Target Path hides the path outlines (#1794)
Target Path (and Extras) now gate the work path, shape and vector-mask outlines and Direct Selection's paths; the Pen's path in progress stays visible.
Part of #1119.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:09:39 -04:00
kayrockscreenprinting cf8044bcb1
Equalize, Average and Clouds edit the targeted channel, not the layer (#1777)
These four ran through map_pixels, which always rewrote the active layer, so with an alpha
channel, the Quick Mask or a layer mask targeted they changed the layer and left the channel
alone. They now rewrite the targeted grayscale surface, as the core filters do. Fixes #935.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:07:43 -04:00
Nigel Ihza Firdausy 864d9ce991
Selection outline: trace serially while background jobs run (#1690)
A long filter could occupy every worker in Rayon's global pool, and the marching-ants trace on
the UI thread then waited for those workers, so the job's Cancel control froze. While jobs run
the outline is traced serially; a test checks it matches the parallel trace. Fixes #1554.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:04:35 -04:00
Duke242 2f3e1c0842
Pen: Esc ends the path and keeps it as the work path (#1787)
Esc while drawing with the Pen ended the path by throwing it away. As in Photoshop, it now ends
the path where it is, left open, and keeps it as the Work Path, the same as Return. Fixes #1769.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:04:22 -04:00
kayrockscreenprinting 3e1407ba68
Liquify: a stroke segment walks only the dabs that can reach the field (#1736)
A segment to a far-off point walked one dab per spacing step along its whole length (about
3e14 for a point at 1e15). Only the steps whose dab can reach a field node are walked now; a
test checks the result is bit-identical to the full walk for every tool. Fixes #937.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:57:14 -04:00
Brandon Thomas bb3108cfd2
CI: no macOS on PRs or main; macOS is built and tested by releases (#1820)
The org has 5 macOS slots in total (GitHub Team), shared by every repo's CI and
release builds, and PR CI kept them full, so release builds queued behind it.
macOS now runs only in release.yml; a release that fails on macOS is fixed and
rebuilt.

Co-authored-by: Brandon Thomas <shared2@storyteller.ai>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:51:18 -04:00
kayrockscreenprinting dd41598d4c
Retouch tools: test the stroke-point bound on all eleven commands (#1784)
The painting and retouch tools now share one check_coords helper for the ±1e6 point bound,
and a regression test sends far-off points to all eleven retouch commands at every depth.
Fixes #976.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:30:06 -04:00
Streetblock 3a2dda1996
German: clearer terms for 30 UI strings (#1791)
Screen is Negativ multiplizieren, Perceptual is Perzeptiv, Blend If is Farbbereich, Oldstyle is Mediävalziffern and Protect Tones is Tonwerte schützen, as in Photoshop's German UI; the font weight Black no longer reads as a colour.
Tool names keep the catalog's -Werkzeug form, Black Point Compensation is Tiefenkompensierung, and Float in Window is In Fenster schweben lassen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:27:46 -04:00
初心Yearth c63d04a09c
docs: explain Windows source build prerequisites and app-control failures (#1692)
Document the MSVC toolchain and C++ build tools workload, and how to diagnose
Smart App Control blocking Cargo or build outputs (os error 4551), with a
pointer to the packaged release. Fixes #1585.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:04:05 -04:00
Nigel Ihza Firdausy 351736ef6b
docs(mcp): grant scoped file roots in headless registration examples (#1673)
The PHOTOCRAFT_AUTOMATION_*_ROOT variables are read only by the desktop app, so
headless photocraft-cli mcp/serve need the --automation-*-root flags. Say so,
and pass explicit roots in the .mcp.json and claude mcp add examples.
Fixes #1551.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:03:58 -04:00
Nigel Ihza Firdausy 6b1075e240
docs(control): align method signatures with accepted parameters (#1674)
ui.set gains rotation, gradientBlendMode and gradientClassic in its signature
and the stale duplicate ui.set line goes; ui.menu.invoke documents params,
ui.pointer tool, app.save an optional path, and serve's doc.save tiffLayers.
Fixes #1550.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:03:30 -04:00
buivanvu94 f7d8a328e4
docs(control): Preferences Apply and OK are refused over control (#1678)
The Preferences entry said ui.dialog.apply/confirm save the dialog, but the
automation policy refuses whole-preferences updates (SECURITY.md). Document the
refusal, what happens to the dialog, and prefs.set for single safe preferences.
Fixes #1555.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:03:06 -04:00
BFlat 89922792c5
Clarify that muda is a native menu crate, not Tauri (#1786)
muda is maintained by the tauri-apps org but is standalone: AppKit menus,
no webview or JS, so it fits the no-Tauri rule. Reword the comments that
called it "Tauri's menu crate".


Claude-Session: https://claude.ai/code/session_01UHgFEHEsefoQoBParH47JA

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-09 18:53:59 +07:00
BFlat 8e8e9f2c68
Merge pull request #1778 from storytold/community/1607-affinity
AF.3: native Affinity import (layers, artboards, vectors, text, images), carrying #1607 by @callmeBalloch
2026-10-09 18:00:53 +07:00
Elvis33LE 6cd2d61398
CR2: read ColorData's as-shot white balance as words (#1640)
* CR2: read ColorData's as-shot white balance as words

CANON_COLOR_DATA is an UNDEFINED entry: uints() hands its bytes back one
by one, but the WB_RGGBLevelsAsShot offsets count 16-bit words. Reading
word i at entry offset i*2 (file byte order, bounds-checked) finds the
quadruple at 0x47 in the corpus PowerShot SX50 HS: [1613, 951, 951, 1605]
-> [1.70, 1.0, 1.69], matching the white balance its own DNG conversion
neutralises (AsShotNeutral -> [1.58, 0.955, 1.666] through the color
matrix). With this the file's balance is used instead of the grey-world
estimate; the regression test pins the words and the missing estimate
warning. (The remaining brightness gap between the CR2 and the DNG of
the same camera is the CR2 path's exposure normalisation, to be looked
at next; the estimate was never what brightened the file.)

* cr2: drop the unused glob import in the corpus test

* CR2 WB: synthetic word-offset oracle, entry bounds, corpus test behind the feature

testgen writes ColorData as Canon does, UNDEFINED bytes that are 16-bit words
with the PowerShot's WB_RGGBLevelsAsShot at word offset 0x47, and the new
color_data_wb_as_words test checks the decoded balance in every CI run (the
corpus oracle stays behind the corpus feature and now panics when its file is
missing instead of silently skipping). word() reads stay inside the entry's
own byte count, and the shared inspect example moves back to the corpus PR.
2026-10-09 18:00:50 +07:00
McClabe c58d20bd39
Fix small caps rendering across fonts (#1644)
* fix: synthesize small caps across fonts

* fix: use native small caps when available
2026-10-09 18:00:47 +07:00
llduyll10 efca9b270d
Layered TIFF: keep blending ranges as bytes in Intel-order files (#1712)
Photoshop writes the per-channel blend-if ranges byte for byte in either byte
order (an II TIFF holds the defaults as 00 00 ff ff). The transcoder swapped
them as u32s, turning every range into ff ff 00 00, which hides every pixel of
the layer: a Photoshop layered TIFF opened with an empty canvas.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 18:00:43 +07:00
eric 60018dea69
fix(compose): don't clip Add and Divide at 1 in 32-bit documents (#1722)
- Linear Dodge (Add) and Divide keep values above 1 in 32-bit float documents, clipped only at f32::MAX. Integer depths still clip at 1.
- CPU: add psblend::HDR and generic::blend_rgb_hdr / blend_channel_hdr; render sets the flag per document depth.
- GPU: add the F_HDR pass flag, and compose.wgsl uses it for the same clip bound.
- Non-separable modes are unchanged.
- Tests: colour unit tests, compose depth tests, and the GPU parity test float_documents_blend_past_white.

Co-authored-by: hideoneric <hideoneric@users.noreply.github.com>
2026-10-09 18:00:39 +07:00
MarekSpodBiedry 68c2e21da8
docs: README tool count and list match Tool::ALL (#996) (#1710) 2026-10-09 18:00:32 +07:00
MarekSpodBiedry 088dbba090
fix(engine): prefs.set and prefs.reset apply the text blending gamma (#987) (#1709) 2026-10-09 18:00:29 +07:00
MarekSpodBiedry 66ab5012be
fix(compose): a Precise inner glow from the centre is no longer blank (#966) (#1708) 2026-10-09 18:00:26 +07:00
MarekSpodBiedry 57be0f58d8
fix(ui): Keyboard Shortcuts dialog rejects a malformed overrides map instead of wiping shortcuts (#956) (#1707) 2026-10-09 18:00:22 +07:00
MarekSpodBiedry 2feaf055cc
fix(xtask): the scorecard's performance summary no longer counts not-run scenarios as tracked (#947) (#1705) 2026-10-09 18:00:19 +07:00
MarekSpodBiedry 1fd600d3ad
fix(automation): bridge doc_save without path writes back like headless (#946) (#1704) 2026-10-09 18:00:16 +07:00
MarekSpodBiedry 4f33c81524
fix(io): keep a PSD Anno block that cannot be read instead of deleting it on save (#944) (#1703) 2026-10-09 18:00:12 +07:00
MarekSpodBiedry 8a31f2431b
fix(io): a CMYK Channel Mixer using the black source stays raw in CMYK documents (#940) (#1702) 2026-10-09 18:00:09 +07:00
MarekSpodBiedry 1db0dde9a4
fix(engine): Move tool Auto-Select clicks through fully locked layers (#1641) (#1701) 2026-10-09 18:00:05 +07:00
MarekSpodBiedry a4c4a02364
fix(ui): the Navigator keeps its image during a live paint stroke (#1631) (#1699) 2026-10-09 17:59:58 +07:00
MarekSpodBiedry 549baa778f
fix(ui): the Photoshop-style status bar shows messages with no document open (#1567) (#1698) 2026-10-09 17:59:55 +07:00
MarekSpodBiedry 5cfbf89917
fix(engine): layer bounds drop the area a selection transform moved pixels out of (#1097) (#1697) 2026-10-09 17:59:51 +07:00
MarekSpodBiedry 1433c3c520
fix(engine): Layer via Copy and Cut deselect, as Photoshop does (#1096) (#1696) 2026-10-09 17:59:48 +07:00