Commit Graph
641 Commits
Author SHA1 Message Date
David Mann 2ed222416d Merge remote-tracking branch 'origin/main' into feat/file-215-2-mezzotint-halftone 2026-10-21 11:38:50 +02:00
aiongg b097800e78 Merge pull request #8095 from aiongg/integration-7
Integration batch: 9 PRs on main
2026-10-20 20:44:51 -04:00
aiongg 9ac1d5adc6 Integration: regenerate docs/scorecard.md for the batch
#7813's performance.gpu_adapter is read from the prefs file before the window opens (gpu_startup::read_gpu_adapter), which the prefs audit's heuristic doesn't see, so it counts as unread.
2026-10-20 22:07:10 +00:00
David Mann f498375d52 Merge PR #6272: PSD: render constant RGB noise gradient fills 2026-10-20 22:39:17 +02: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 60764172aa Merge PR #7217: GPU startup: Auto on Windows leaves Vulkan out when an Intel adapter is present (#4) 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 ea7553f031 Merge PR #5111: Large documents: a gigapixel New Document draws without freezing (#4017) 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 60ba61b1a4 Merge main into feat/file-215-2-mezzotint-halftone
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:21:06 +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 2cb994459f Merge main into feat/file-215-2-mezzotint-halftone 2026-10-20 17:01:53 +02: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
Ernie SmithandClaude Sonnet 5.5 0e97ac4ca8 Make adapter choice Linux-only everywhere, not just the dropdown
The Preferences row was Linux-only, but PHOTOCRAFT_GPU_ADAPTER and
performance.gpuAdapter were honoured on every platform, so Windows and macOS
could pick a non-default adapter without being tested for it. Ignore the
request off Linux (and in CPU mode, as before), and don't make a launch
standalone for a variable that is ignored there.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 16:19:51 -04:00
Ernie SmithandClaude Sonnet 5.5 2644d06081 Review: rustfmt, cap the env adapter name, docs in their own paragraph
- cargo fmt on the adapter selection and its launch code.
- PHOTOCRAFT_GPU_ADAPTER is capped at 256 characters like the saved preference.
- Put the multi-GPU paragraph in docs/development.md on its own instead of
  appending to the --safe-gpu paragraph, so the diff only adds lines.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 16:07:04 -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
aiongg 46f7e2422e Integration: drop #7690's benchmark report, as #7690 did before it merged 2026-10-19 18:41:15 +00:00
Brandon ThomasandClaude Opus 5.5 3a896a5efc docs: regenerate the scorecard (Show File Name In Title adds a preference) (#7829)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 14:23:47 -04:00
Marco Arnulfo 4f15642ee8 Toolbar: Edit Toolbar, Quick Mask and Screen Mode in every theme (part of #4653) (#4680) 2026-10-19 14:20:48 -04:00
aiongg 3f509f06ed Integration: regenerate docs/scorecard.md 2026-10-19 18:01:48 +00:00
Korg1ch 8c2cfdba6a fix(linux): keep crash-recovery autosaves in $XDG_STATE_HOME, out of the config folder (#6612) (#6941)
* fix(linux): keep crash-recovery autosaves in $XDG_STATE_HOME, out of the config folder (#6612)

* test(linux): cover the XDG state recovery folder (#6612)
2026-10-19 13:32:14 -04:00
aiongg acc853b517 Merge upstream main into integration-5
docs/file-format-parity.md: keeps both 2026-10-15 rows, main's #6063 PNG sTER row first, then #5976's PSD guides row
2026-10-19 17:20:29 +00:00
aiongg b8e856dffe Integration: #7022 write_region stays serial; the text rasterizer uses the parallel variant 2026-10-19 17:18:46 +00:00
Ernie SmithandClaude Sonnet 5.5 b892c0412e Choose the graphics adapter on multi-GPU Linux machines (#1885)
With the backend on auto, Linux installed no adapter selector, so wgpu took
the first discrete GPU the driver listed. On a machine with an eGPU, a
laptop dGPU and an iGPU that was not the one the user wanted.

- performance.gpuAdapter: a case-insensitive piece of the adapter's name
  (several words must all appear); empty is automatic.
- PHOTOCRAFT_GPU_ADAPTER overrides it for one launch.
- Preferences > Performance > Advanced > GPU adapter lists the adapters the
  instance found; a saved adapter that is absent stays listed, marked.
- A missing adapter, or one that can't present to the window, falls back to
  the automatic choice with a note in System Info. CPU mode ignores it.
- Shown on Linux only; tested on Linux only. Windows and macOS need their own
  work (the startup code honours the setting there, but it is untested).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 13:16:53 -04:00
KnottyDyes c9d7f1d984 Docs: install the CLI and register it with MCP clients (#7663) 2026-10-19 13:03:40 -04:00
640873de7b PNG: keep a stereo file's sTER pairing on save (#6063) (#6285)
* PNG: keep a stereo file's sTER pairing on save (#6063)

Read the sTER chunk (PNG Extensions 1.4.0 §3.6) when a PNG opens, store it
on the document's FileEncoding, and write it back when saving, so a stereo
PNG still says it is a stereo pair. Covers the ordinary and the palette
PNG encoders, including interlaced output.

* io tests: pass the new sTER argument to encode_png_indexed

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

---------

Co-authored-by: highperfocused <highperfocused@pm.me>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 13:02:18 -04:00
David Mann c30f9180e8 Merge PR #7692: perf(raster): Avoid redundant default pixel work 2026-10-19 16:51:48 +02:00
David Mann c0072ca2da Merge PR #7691: perf(io): Interleave PSD pixels in the final buffer 2026-10-19 16:51:45 +02:00
David Mann b2269e3bdb Merge PR #7690: perf(codecs): Avoid redundant PNG filter passes 2026-10-19 16:51:43 +02:00
David Mann 8e54897d43 Merge PR #7022: perf(text): rasterize a type layer's pixels on all cores, bit for bit the same 2026-10-19 16:51:41 +02:00
David Mann 284ee60705 Merge PR #5976: PSD: keep guide resources 1092/1097 only while they match the guides (#5966) 2026-10-19 16:51:27 +02:00
Rene Leonhardt 4d50e31efd perf(codecs): stop PNG candidates at the winning cost 2026-10-19 13:43:19 +02:00
Rene Leonhardt b5b5776a30 perf(io): remove the PSD export inlining hint 2026-10-19 13:15:06 +02:00
Rene Leonhardt 78a9982eec perf(raster): share contiguous region reads 2026-10-19 13:15:06 +02:00
Rene Leonhardt 6b1aa81561 docs(perf): measure PNG filtering on real images 2026-10-19 13:15:05 +02:00
Rene Leonhardt 76a6405f9b perf(io): Interleave PSD pixels in the final buffer
Remove intermediate band buffers while retaining byte-for-byte equivalence with the previous path at every sample depth.
2026-10-19 11:31:59 +02:00
Rene Leonhardt f6e7fc3c2a perf(raster): Avoid redundant default pixel work
Preserve default sample bits while skipping absent zero tiles and redundant default-pixel copies. Add the previous read path as the oracle.
2026-10-19 11:31:59 +02:00
Rene Leonhardt 850bf9fdaa perf(codecs): Avoid redundant PNG filter passes
Keep the previous filter path as an exact byte oracle and measure the filter kernel independently of compression.
2026-10-19 11:31:59 +02:00
Elvis33LE e2adb18165 fix(psd): render constant noise gradient fills 2026-10-19 01:05:13 +02:00
skylar taylor-barrick 4d4de45305 Merge pull request #7206 from skylartaylor/save-replace-metadata
Save: keep the replaced file's metadata
2026-10-18 16:48:40 -06:00
c6fd71241d docs: add user docs in docs/user (#3951)
* docs: add user docs for PhotoCraft

Adds docs/user/ (published at getartcraft.com/docs/photocraft), the docs
check and publish workflows (copied from craft-launcher), and a User docs
rule in AGENTS.md. Checker: 0 error(s), 0 warning(s).

Source notes per page:
- index.md: README (intro, status, Crafting Apps table), website
  crafting-apps.ts photocraft entry, links.rs (Discord, issues), menus.rs
  (Help > Report an Issue).
- getting-started/index.md: menus.rs and menu_catalog.rs labels, panels.rs
  (Layers, Properties, History), dialogs.rs (Create button).
- getting-started/install.md: README Downloads and Get started sections,
  gh release view v0.7.0 asset list, craft-launcher catalog.rs (lists
  PhotoCraft).
- guides/open-and-save-files.md: apps/photocraft/src/services.rs (open and
  save filters), README Formats and PSD sections, docs/file-format-parity.md.
- guides/adjust-colors-with-adjustment-layers.md: menu_catalog.rs, panels.rs
  (footer button, adjustment list), lib.rs (Properties shows new layer).
- guides/select-and-mask.md: menu_catalog.rs Select and Layer Mask menus,
  state.rs tool names, retouch_ui.rs (Select Subject button and message).
- guides/add-and-style-text.md: state.rs (Horizontal Type Tool, T),
  type_tool.rs, menu_catalog.rs Layer Style and Type menus, dialogs.rs.
- guides/export-an-image.md: export_dialog.rs (labels, formats, options).
- troubleshooting/taskbar-turns-black.md: issues 3550, 3864, 3430, 3144,
  PR 3308 (git: not an ancestor of v0.7.0), prefs_ui.rs (System title bar).
- troubleshooting/text-moves-when-editing.md: issues 3795, 1317, PR 3819
  (open).
- troubleshooting/get-help.md: menus.rs, links.rs, gpu_status.rs (System
  Info content).
- faq/*: README (status, license badge, offline, formats), LICENSE-MIT and
  LICENSE-APACHE, docs/file-format-parity.md.

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

* docs(user): apply final review fixes

Part 1: verified = latest release tag policy in docs/user/AGENTS.md; released-pages sentence in root AGENTS.md. Part 4 items 1-9: remove x86 row and TGA resolution, formats, new photocraft-does-not-start page, mask label, taskbar workaround, wording, Affinity read-only, index.

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

* docs(user): use the standard section title

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

* docs(user): describe PhotoCraft 0.7.0 startup behaviour

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

* docs(user): tighten PhotoCraft startup wording

Drop the unsourced "slower" claim for CPU mode and give the exact
Preferences path on Windows and macOS.

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

* docs: pin the docs checker to a commit and its SHA-256

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

* docs: drop the docs workflows until the checker is on artcraft-services main

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

* docs: re-verify against 0.8.2

- taskbar and PSD text pages: both fixes ship in 0.8.2; tell users to
  update and drop the "not in a release yet" wording and workarounds
- does not start: 0.8.2 fixes the Intel Iris Pro/Monterey Device(Lost)
  case; OpenCore Legacy Patcher Macs still have no fix
- install: Windows 10 or later, 32-bit Windows builds, RISC-V deb/rpm,
  Wayland paste and XWayland notice
- open and save: Krita and Paint.NET filters, Krita/PCX/FITS formats,
  save progress, JPEG/WebP encoding kept on Save
- export: TGA Resolution, multi-layer Export As and Quick Export
- text: Shift-click starts new text over existing type
- CLAUDE.md is now a regular file pointing to AGENTS.md
- verified: 0.8.2 on every page

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

* Drop the root AGENTS.md docs rule; keep the PR to docs/user/

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

* docs(user): drop the stale missing-tools count from the Photoshop FAQ

Re-verified the page against v0.9.0.

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

---------

Co-authored-by: Fabio Lussi <198260595+itrycodinganditsbad@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 16:15:53 -06:00
Brian TandClaude Opus 5.5 ca69059dd0 Edit: Copy with no selection keeps fill and adjustment layers (#2344) (#7497)
Copy refused fill and adjustment layers ("the active layer has no
pixels"). With no pixel selection they are now taken whole, like smart
objects, type, shape and group layers, and Paste recreates them in this
or another document. An adjustment layer's clip spans the canvas, so
paste placement and the OS-clipboard mirror stay consistent.

Scorecard UI-217-23 note, gaps.md G9 and target-app-parity.md updated;
the row stays partial (a single pixel layer still copies pixels only).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 17:23:26 -04:00
Nguyễn Minh Long 72a3423a7e Preferences: Enable Gestures off ignores touch-screen pinch and twist (#204) (#7478)
Edit > Preferences > Enhanced Controls > Enable Gestures (enhancedControls.touchGestures)
was saved but read by nothing, so it was hidden from the dialog. Now, with it off, two
fingers on a touch screen no longer zoom the canvas or the Navigator, nor turn the view.
The mouse and trackpad behave as before, including a trackpad pinch or Rotate event that
arrives while fingers rest on the screen.

- wheel_nav: pinch_factor() drops egui's multi-touch zoom when gestures are off and keeps
  the trackpad's own Event::Zoom (Windows' folded Ctrl + wheel pinch included);
  read_with() takes the preference.
- rotate_view: trackpad_delta() only falls back to the multi-touch rotation while gestures
  are on; Rotate events always count.
- canvas, Navigator: pass the preference through.
- prefs: touchGestures leaves HIDDEN_UNTIL_IMPLEMENTED, so the dialog shows it.
- Tests: synthetic two-finger pinch and twist, on and off, and the trackpad events with
  gestures off.
- docs/scorecard.md regenerated: settings that do nothing 26 -> 25 of 168.
2026-10-18 17:23:21 -04:00
Marco Arnulfo 8736098d38 Curves: Cmd/Ctrl-click on the image adds a point at the pixel's tone (#7473)
* Curves: Cmd/Ctrl-click on the image adds a point at the pixel's tone (part of #7325)

With Image > Adjustments > Curves open, a Cmd-click (Ctrl-click off the Mac) on
the image adds a point to the channel shown in the dialog, at the pixel's tone
and at the curve's current output there; Shift adds one point on each of Red,
Green and Blue. Only the press adds, an armed eyedropper still wins, and the
control channel's ui.pointer does the same with command: true.

* Curves: Cmd/Ctrl-click adds the point with the Hand tool too; Space and middle button still pan

The Hand tool took the Cmd-click press for a pan, so no point was added; the
press now counts before the Hand. On the control channel, ui.pointer with
space or the middle button pans as the mouse does instead of adding a point.

* Curves: the Cmd/Ctrl-click point's comment says where the curve can still change
2026-10-18 17:23:16 -04:00
JulienandClaude Opus 5.5 bbfeae98e4 Type: right-click on committed text opens the type layer menu (#7324) (#7430)
* Type: right-click on committed text opens the type layer menu (#7324)

With the Type tool, a right-click only opened a menu while text was being
edited; over committed type nothing opened. The menu was keyed on the edit
session alone (`editing_text`).

Over committed type, a Type tool (not a Type Mask tool) now opens
TYPE_LAYER_MENU: the type edit menu's layer rows, without the edit rows
(Undo, Cut, Copy, Paste, Select All), which would act on the document, and
without Faux Bold/Italic, which act on the characters being edited. Type
outside the selected layers becomes the target first, as a click with the
Type tool makes it. The control channel's right button takes the same path.

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

* Type layer menu: the clicked type becomes the active layer in a multiselection (#7324)

The structural rows (Rasterize Type, Convert to Shape, Create Work Path, the
paragraph/point conversions) act on the active layer. When the right-clicked
type was already selected but another selected type layer was active, they
acted on that other layer. Make the clicked type the active layer while
keeping the selection (layer_multi_cmds::set_selection), so the formatting
rows still act on every selected type layer. Found by CodeRabbit on #7430.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 17:23:05 -04:00
skylar taylor-barrick 915779b948 Merge storytold/main into save-replace-metadata
No textual conflicts, but the merge did not compile. main's 589941a5 added a
second AtomicFs test impl using copy_permissions, while this branch renames that
trait method to copy_metadata. Git merged both cleanly because they sit in
different parts of the file, giving a tree whose trait and impl disagree:
E0407, E0046 and E0599 in photocraft-format's lib test. That one error is what
failed all four CI jobs.

main's new impl is renamed to copy_metadata to match.

Verified with --features heif, which is what CI builds with and what I had
previously failed to pass locally: clippy --workspace --all-targets --locked
--features heif -- -D warnings is clean, and the workspace tests pass.
2026-10-18 15:12:41 -06:00
aiongg e7d4ce5e18 Merge PR #6364: Path Selection: the canvas right-click opens the path menu, as the Pen's does (#1056) 2026-10-18 14:19:00 +00:00
wwew 04967b12f9 docs: write product name as PhotoCraft in engine module doc, LUT export header and image sources (#5454) 2026-10-18 03:35:28 -04:00