Commit Graph
1242 Commits
Author SHA1 Message Date
aiongg f679b4cf1f Integration: rustfmt the merged tree, for #6195 and #5857
cargo fmt --check failed on #6195's module order and canvas.rs guard, and on the IMPORT_ONLY line.
2026-10-20 22:07:10 +00:00
aiongg 6265d67de9 Integration: naming templates and more read-only formats use same_format, for #5857
With a naming template, Format Same still took the raw extension (IMG_0001_001.dng: unknown file format). HEIC, SVG, Cineon, PCX and XPM open but have no writer, so they save as PSD too; DDS has a writer and keeps its format.
2026-10-20 22:07:10 +00:00
aiongg f5c2f2091e Merge PR #5857: Batch: Format "Same" saves camera raws as PSD instead of failing (#5799) 2026-10-20 22:07:10 +00:00
David Mann 6db0473b43 Merge PR #7180: Brushes: accept .abr files up to 1 GiB 2026-10-20 22:39:24 +02:00
David Mann 2adfe0c4e2 Merge PR #5807: Type: keep superscript and subscript when a text layer is re-rendered (#5645) 2026-10-20 22:39:12 +02:00
aiongg d94c277566 Merge PR #5499: perf(retouch): row-parallel Blur/Sharpen dabs, 2.6-3.3x faster strokes (#5426) 2026-10-20 18:41:28 +00:00
aiongg db56aeb10a Merge PR #7813: Choose the graphics adapter on multi-GPU Linux machines (#1885)
# Conflicts:
#	apps/photocraft/src/gpu_startup.rs
#	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
#	crates/ui-egui/src/prefs_ui.rs
2026-10-20 18:41:25 +00:00
aiongg 1ca8a8aad0 Merge PR #7964: Preserve near-black ICC colors on the GPU canvas
# Conflicts:
#	contributors/people.toml
2026-10-20 18:39:43 +00:00
aiongg 1e2bea1060 Merge PR #6395: Windows: PhotoCraft starts without Windows.Data.Pdf.dll (#5884) 2026-10-20 18:39:29 +00:00
aiongg e2169d0dfd Merge PR #7847: Print: Portrait and Landscape in the Print dialog on Windows 2026-10-20 18:39:29 +00:00
aiongg c8cf9eaf0d Merge PR #7180: Brushes: accept .abr files up to 1 GiB 2026-10-20 18:39:28 +00:00
aiongg 0ae688b59a Merge PR #6939: Mixer Brush: Clean Brush empties the brush, and the automatic Load and Clean can be switched off 2026-10-20 18:39:27 +00:00
David MannandClaude Opus 5.5 b22b7b4645 Merge main into fix/5559-bitmap-dialog
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:24:57 +02:00
David MannandClaude Opus 5.5 738541efda Merge main into perf/p25-blur-cancel
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:23:08 +02:00
David MannandClaude Opus 5.5 31dd6e7e41 Merge main into feat/ui-217-4-animated-zoom
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:23:08 +02:00
David MannandClaude Opus 5.5 a939785d63 Merge main into feat/ui-217-1-tool-options-persist
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:23:07 +02:00
David MannandClaude Opus 5.5 f81230d86f Merge main into fix/6268-psd-perspective-warp-sf
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:20:37 +02:00
David MannandClaude Opus 5.5 c033313aae Merge main into fix/6267-psd-hue-sat-sf
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:19:06 +02:00
David MannandClaude Opus 5.5 73ba0b7a68 Merge main into feat/tool-213-4-cam-preview-large
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:12:13 +02:00
David Mann 38605ceac5 Merge main into feat/tool-213-7-live-retouch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	crates/ui-egui/src/canvas.rs
#	docs/gaps.md
#	docs/target-app-parity.md
2026-10-20 19:05:39 +02:00
David Mann c2ce75f9b7 Merge main into feat/ui-217-4-save-in-background
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	docs/gaps.md
#	docs/scorecard.md
2026-10-20 19:05:35 +02:00
Guillem Hermida 872748fb5b Codecs: save DDS textures, uncompressed or BC1–BC3, with optional mipmaps (#1327) (#5993)
DDS textures can now be saved, not just opened: uncompressed (BGRA, BGRX, L8, A8L8; lossless) or BC1/BC2/BC3 (DXT1/3/5) from a clean-room block encoder, with an optional box-filtered mip chain, in the legacy header. Save As and Save a Copy ask with DDS Options; scripts pass `ddsCompression`/`ddsMipmaps` (file commands, control `app.save`, RPC `doc.save`, MCP `doc_save`/`doc_export`), and the CLI takes `--dds-compression`/`--dds-mipmaps`. Targa and DDS answers travel together as `FormatChoices` through the Save As flow.

Review follow-ups:
- File › Save behind DDS or Targa Options records a plain Save with its answer, and replaying `file.save` applies it (#3531).
- The block encoder finds the principal axis from every channel, so a channel that varies on its own can't hide the others' variation.
- DDS joins the shared round-trip suite; the header is built before the output buffer is allocated.
- Enter on a focused Cancel in DDS, Targa or TIFF Options cancels instead of saving.
2026-10-20 11:02:39 -06:00
David Mann ca506335e0 Merge main into fix/fill-layer-angle-finite 2026-10-20 17:18:33 +02:00
David Mann 1b0b3e218c Merge main into fix/6267-psd-hue-sat-sf 2026-10-20 17:13:41 +02:00
David Mann 0b39361076 Merge main into feat/tool-214-12-shape-feather 2026-10-20 17:12:29 +02:00
David Mann a3196466a3 Merge main into fix/6268-psd-perspective-warp-sf 2026-10-20 17:09:56 +02:00
David MannandClaude Opus 5.5 2f96260c99 Crop: the rotated target-size sampler test expects the turned pixel (10, 9) doubled (#7012)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 16:45:42 +02:00
David Mann 8aaf526108 Merge main into feat/file-215-18-export-resample 2026-10-20 16:36:25 +02:00
David Mann a738fcb9fe Merge remote-tracking branch 'origin/main' into HEAD 2026-10-20 16:34:25 +02:00
Derek GliwaandClaude Opus 5.5 d53101c9a1 Brushes: keep the 512 MiB .abr cap on 32-bit targets
On wasm32 a near-1 GiB .abr arrives as base64 and is copied several times
before decoding; with a 1 GiB sample budget the import could pass 4 GiB and
abort the tab instead of failing cleanly. Pick the decoder budget by pointer
width (like MAX_DECODED_BYTES) and derive the engine's file cap from it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:53:55 -05:00
Derek Gliwa 4992a4305e Merge remote-tracking branch 'upstream/main' into abr-1gib-limit 2026-10-20 08:35:56 -05:00
ha1des 472a8d6f29 Preserve near-black ICC colors on the GPU canvas 2026-10-20 14:18:00 +02:00
aiongg 03d0c7e3b3 Merge pull request #7823 from aiongg/integration-5
Integration batch: 8 PRs on main
2026-10-19 23:11:09 -04:00
Michael Higgins b05b641122 Merge branch 'storytold:main' into fix/5799-batch-same-format-raw 2026-10-19 19:34:48 -04:00
WolfandClaude Opus 5.5 2f08860383 Print: Portrait and Landscape in the Print dialog on Windows
On Windows the Print dialog takes the paper and its orientation from the
printer driver, and had no way to change the orientation short of the
driver's own Print Settings… dialog. Photoshop has Layout buttons for it.
A print laid out landscape on portrait driver settings (from a script,
the CLI or another app) stopped with "the driver paper or orientation
differs from the print layout".

- The dialog has an Orientation row (Portrait, Landscape) under Print
  Settings…. It turns the driver settings through file.print.page and
  takes the paper from the driver again, so the paper and preview turn.
- file.print.page takes "orientation": "portrait|landscape" and returns
  the turned settings as printerSettings, with the page they give.
- print_windows turns the settings (the given ones or the printer's
  defaults) to the layout's orientation when the driver has the layout's
  paper the other way round; another paper is still refused.

Turning sets dmOrientation and its dmFields bit in the DEVMODE and keeps
every other byte, the driver's private settings included; the driver
validates the result as it does settings from Print Settings…. No new
UI strings: "Orientation", "Portrait" and "Landscape" are in every
catalog.

Tests: the turned settings (orientation set, all else kept, with and
without private driver bytes), when a paper counts as turned, an unknown
orientation refused before any printer is asked, the dialog's reading of
the driver paper and its error path, and, run by hand on Windows, a
real "Microsoft Print to PDF" driver turning for a landscape layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:46:41 +02:00
David MannandClaude Opus 5.5 e306bcd685 Crop: a turned crop rotates only what the frame keeps (#5006) (#5007)
A turned crop rotated the whole canvas, then cropped to the frame. With
Delete Cropped Pixels on, every layer, mask and channel is now trimmed to
the frame's source (plus the interpolation kernel's reach) before the
turn, so the rotation costs the frame's size: a 512x442 frame turned 3°
on a 3859x2594 two-layer document goes from 541 ms to 42 ms.

Rotate Canvas also fills the Background with shared tiles instead of a
canvas-sized float buffer.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 14:20:42 -04:00
MarekSpodBiedry 1a03735cc6 fix(engine): apply document-wide image and colour conversions to stored video frames (#4956) (#5078) 2026-10-19 14:20:35 -04:00
David MannandClaude Opus 5.5 5e1d90d86e Preferences: a wrongly typed value resets only that field (#6611) (#6641)
One value of the wrong type in prefs.json (say "recentFileCount": "ten")
made the whole file fail to deserialize, so every preference fell back
to its default for the session, and since the file was never rewritten
it happened again on every launch.

load_prefs_json now reads leniently when the file doesn't deserialize as
a whole: it starts from the defaults and lays the file's values over
them one at a time, descending into section objects and map entries,
keeping every value that still reads and leaving out only the ones that
don't. Colour settings get the same treatment instead of resetting as a
whole. It returns the left-out values (keys and original value); text
that isn't a JSON object still fails as before.

On launch the app shows a notice naming the reset paths and saves once:
the three-way merge base gets the unreadable values, so the merge
replaces (or removes) exactly those in the stored file and keeps
everything else, including keys this version doesn't know.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 14:20:09 -04:00
David MannandClaude Opus 5.5 77b845e098 Actions: loading a set renames each Play target once (#6806) (#6807)
Load Actions applied each rename as its own pass over every action in the set, so chained
renames ("A" -> "A 2", "A 2" -> "A 2 2") retargeted a step twice, and with replace:false it
also rewrote steps of actions already in the set. Now one original->new map is applied once
to the newly loaded actions' Play and Conditional (then/else) steps and to function keys.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 14:20:02 -04:00
David MannandClaude Opus 5.5 b67502e20f Reveal All: one History step named "Reveal All" (#7145) (#7147)
image.revealAll ran image.crop, whose step is labelled "Crop". It now
runs it inside analysis_cmds::compound with the label "Reveal All".

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 14:19:35 -04:00
NetterSilverandClaude Haiku 5.5 5a649f8e4e Apply background jobs to the layers they started on (#7620)
Fixes #7366

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-19 14:19:22 -04:00
dfe94d6ab9 Actions: export Box Blur, Surface Blur, Flatten Image and Black & White under ids Photoshop runs (#6330) (#6331)
Save Actions wrote these four steps under the four-char codes BoxB, SrfB,
Fltn and BlnW, which Photoshop does not run: executeAction fails with "the
command is not currently available" (measured in Photoshop on a document
with a filled pixel layer; Fltn resolves to the flatness property, not the
flatten event). The names boxblur, surfaceBlur and blackAndWhite and the
code FltI run.

- Box Blur, Surface Blur and Black & White now export by name
  (boxblur, surfaceBlur, blackAndWhite); Flatten Image exports as FltI.
  The descriptors are unchanged.
- Import accepts the names, FltI and flattenImage, and still accepts the
  old codes (a LEGACY_CODES table consulted only for four-char codes), so
  actions PhotoCraft saved before keep loading.
- Tests: each step exports the new id and imports back to the same command
  and params under the new id, the name and the legacy code; a set mixing
  Photoshop-shaped and legacy steps loads and re-saves with the new ids;
  near-miss ids (case, padding, empty, NULs) stay Photoshop steps; broken
  descriptors don't panic.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-19 14:18:18 -04:00
Ernie SmithandClaude Sonnet 5.5 0b6480cdc5 Address review: adapter override process, wasm build, saved-name warning
- PHOTOCRAFT_GPU_ADAPTER now counts as a per-process launch option, so a
  second launch with it set doesn't forward to the running window and drop it.
- Gate RenderState::available_adapters to native targets (it doesn't exist on
  wasm, which broke the web build).
- Share the adapter name matcher (engine prefs) between startup and
  Preferences, so a saved fragment like "nvidia" isn't flagged as missing when
  it matches a listed adapter.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 14:13:55 -04:00
2ef8a9d3f5 Reject exporting a partial Play Action call to .atn (#7602)
Fixes #7186

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-19 13:45:07 -04:00
Korg1chandBrandon Thomas 990483a95e Actions: Apply Layer Comp is recorded by the comp's name, so it plays in any document (#7181) (#7790)
* fix(engine): record Apply Layer Comp by the comp's name, not its document-local id (#7181)

* test(engine): a recorded Apply Layer Comp applies the comp of that name in another document (#7181)

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-19 13:44:51 -04:00
FinnNkandClaude Opus 5.5 8c3c3237f4 refactor(engine): drop the second damage pass after single-edit duplicates and pastes (#5880)
Session::edit has reported a new layer's bounds as damage since #3847, so
Duplicate Layer, Duplicate Layers and Paste no longer need to keep the
document from before the edit and work the damage out again with
note_insert. Paste Into still does: it is three edits.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 13:33:06 -04:00
Omar Saidahmed 1c74da7baa keep layer-based slices when duplicating a document (#6133) 2026-10-19 13:32:59 -04:00
David MannandClaude Opus 5.5 4252fb7743 Presets: Migrate Presets reads tool presets like the launch loader (#7375) (#7376)
Migrate Presets deserialized the incoming tool presets all or nothing, so
one damaged entry dropped every good one, and it skipped the checks the
launch loader applies: blank or overlong names were imported and then lost
on restart, and a large file pushed the library past MAX_PRESETS. Read the
list with `presets::tools::load` and stop at MAX_PRESETS.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 13:32:07 -04:00
NetterSilverandClaude Haiku 5.5 fe64e5a2bd Keep arbitrary canvas rotation interpolation in ATN export (#7630)
Fixes #7504

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-19 13:31:49 -04:00
David MannandClaude Opus 5.5 cbe6c4e131 Guides: colours follow Crop, Canvas Size and rotations (#7724) (#7725)
transform_doc_marks moved guide positions but not their colour entries,
which are keyed by exact position: after a crop the coloured guide fell
back to the preference colour and a guide that landed on its old place
took the colour. Map the entries with the same expressions as the
guides (swap orientation on quarter turns, clear on arbitrary angles).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 13:31:41 -04:00