Commit Graph
8174 Commits
Author SHA1 Message Date
yoriswind 69e93b8ca1 Add native profile flatten and placed-rasterization options 2026-11-01 07:05:52 -08:00
yoriswind ca60678754 Describe CAF action conversion and regression witnesses 2026-11-01 06:37:14 -08:00
yoriswind 376949a6f3 Preserve Content-Aware Fill options in ATN actions 2026-11-01 06:34:22 -08:00
yoriswind da496ec03f Document Content-Aware Fill adaptation helpers 2026-11-01 06:23:16 -08:00
yoriswind 4875f94ebb Expose Content-Aware Fill scale and mirror options 2026-11-01 06:13:03 -08:00
yoriswind de9c5e743e Preserve Image Size style scaling through ATN actions 2026-11-01 06:13:02 -08:00
yoriswind d7bce26deb Add optional layer-style scaling to Image Size 2026-11-01 06:13:00 -08:00
aiongg 84732d09bc Merge pull request #9618 from RickiNano/prefs/gpu-adapter-typed-read
Prefs: startup reads Graphics Adapter through the typed Performance section
2026-11-01 08:56:16 -05:00
aiongg dbe24c7e92 Merge pull request #10658 from RickiNano/fix/10640-preset-group-reimport
Ask before re-importing a brush or gradient file over its group (#10640)
2026-11-01 08:55:56 -05:00
aiongg 8442c105e5 Merge pull request #10681 from RickiNano/fix/10671-ants-over-guides
Paint the marching ants over the guides (#10671)
2026-11-01 08:31:13 -05:00
aiongg c79efbe05b Merge pull request #10685 from RickiNano/fix/save-for-web-zoom-creep-10675
Save for Web: keep its size and zoom while the pointer moves (#10675)
2026-11-01 08:30:53 -05:00
aiongg e5ca16c86b Merge pull request #10672 from RickiNano/fix/10656-preset-footer-glyphs
Preset panel footers use the Layers footer's glyphs and size (#10656)
2026-11-01 08:30:05 -05:00
aiongg 713197635d Merge origin/main into prefs/gpu-adapter-typed-read 2026-11-01 13:16:28 +00:00
aiongg af404cfb9f Trim the preset file name like the engine, and list the clash prompt's plural forms for translation (#10640) 2026-11-01 13:14:09 +00:00
Khawar Zamman WaniandFredApps 5d815c5a4b Stream PSD user and real masks into tile rows (#10532)
* Bound PSD import pixel storage before decoding

* Include ZIP inflater workspace in PSD preflight

* PSD import: budget unknown-mode layers, stop after a fatal layer error, keep best-effort for non-allocation limits (#8593 review)

* Stream PSD user and real masks into tile rows

* Correct streamed-mask fixture metadata and test lint issues

---------

Co-authored-by: FredApps <FredApps@users.noreply.github.com>
2026-11-01 14:03:08 +01:00
RickiNanoandClaude Opus 5.5 0f85d429d7 Save for Web: keep its size and zoom while the pointer moves (#10675)
The dialog grows to fit its contents, and the preview panes were sized in
fractional points, so they came out a fraction of a pixel wider than the room
given. Every repaint (any pointer move) widened the dialog a little and the
fitted zoom followed. The preview area and pane sizes are now floored to whole
physical pixels.

The new test moves the pointer over the preview at 5 scales x 3 screens x 3
views: 15 of the 45 cases drifted before the fix, none after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:49:27 +01:00
Khawar Zamman Wani 97a83f074f Bound PSD layer and mask import memory before decoding (#10503)
* Bound PSD import pixel storage before decoding

* Include ZIP inflater workspace in PSD preflight

* PSD import: budget unknown-mode layers, stop after a fatal layer error, keep best-effort for non-allocation limits (#8593 review)
2026-11-01 12:33:09 +01:00
RickiNanoandClaude Opus 5.5 44f356c6de Paint the marching ants over the guides (#10671)
A guide on the same device pixel as a selection edge hid it, at some zoom
levels and not others: the ants were painted in paint_canvas and the guides
after them in paint_primary_overlays. The ants are still traced in
paint_canvas from the frame's snapshot, but returned as shapes and painted
right after the grid and guides; a secondary view paints them where it did.

Free Transform's carried ants come from transform_tool::selection_ants
(was draw_selection), which returns shapes instead of painting.

Test: canvas::guide_ants_tests checks the paint order at three display
scales and nine zoom levels; it fails without the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:27:19 +01:00
RickiNanoandClaude Opus 5.5 ef36604c3c Preset panel footers use the Layers footer's glyphs and size (#10656)
The shared Swatches / Gradients / Patterns footer drew New Group as
`folder-plus` and New as `plus` at 24 pt, while the Layers footer uses
`folder` and `square-plus` at 26 pt. Both footers now take shared
`icons::FOOTER_*` constants, so they can't drift apart again; a test
checks the glyphs are bundled (a misspelt name draws the fallback square).

The footer grows from 28 to 30 pt, still under the 32 pt first-frame
guess; the #4790 footer-fit test passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 11:09:29 +01:00
RickiNanoandClaude Opus 5.5 586563fc2b Address review: one group-name set for clashes, test the .grd prompt (#10640)
- free_group's brush check builds the set of group names once instead of
  scanning every preset for each numbered candidate.
- reimporting_a_gradient_file_asks_before_touching_its_group covers the
  gradient branch of the prompt: no prompt for a new group, Cancel imports
  nothing, Import as New Group adds "Fire (2)", Replace swaps "Fire" alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:18:24 +01:00
RickiNanoandClaude Opus 5.5 2ab2ab2f0d Name the source file in the preset import status (#10640)
After a group-name clash the status read "Imported 2 brushes from Kit (2)",
naming the destination group as if it were the file. Keep the translated
"… from {file}" message and add the group only when it differs:
"Imported 2 brushes from Kit into “Kit (2)”".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 10:05:41 +01:00
RickiNanoandClaude Opus 5.5 122e55a4a0 Ask before re-importing a brush or gradient file over its group (#10640)
Importing an .abr or .grd whose name matched an existing group silently
deleted that group's user presets (edited or moved-in ones included); the
preset libraries are outside document history, so it could not be undone.

- brush.presets.importAbr / gradient.presets.importGrd: `replace` now
  defaults to false; a taken group name imports beside it as "Kit (2)",
  "Kit (3)"…, and the result's `group` names the one it landed in.
- UI: when the group already holds the user's presets, a prompt asks
  Import as New Group (default) / Replace (can't be undone) / Cancel.
  Agents drive it with ui.dialog.set {"choice":"replace"} / confirm / cancel.
- The status bar names the group the file landed in.

Fixes #10640

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 09:49:33 +01:00
Mohamed MahjoubandClaude 560beed83e Layers panel: draw artboard rows like Photoshop, not like folders (#10218) (#10519)
* Layers panel: draw artboard rows like Photoshop, not like folders

An artboard's row looked exactly like a layer group's: the same folder
thumbnail, font and height, so boards read as folders and it was hard to see
where one ended and the next began (#10218).

Artboard rows now have no thumbnail, a bold name, a shorter row (never taller
than a layer's) and a faint band from the theme's hover colour. Plain groups
and layers are unchanged.

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

* Artboard rows: keep mask thumbnails, paint the band under label colours

Review follow-ups:
- A board with a layer or vector mask kept no mask thumbnails, so clicking,
  dragging and loading its mask from the row stopped working. It now keeps a
  full-height row with its mask thumbnails; only the board's own thumbnail is
  left out, and the targeted mask still gets its brackets.
- The band was painted over the eye column's label colour and the dividers,
  so a board's label colour looked different from other rows'. It is now
  painted first.

Adds a_masked_artboard_row_keeps_its_mask_thumbnail, which failed before.

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

* Artboard rows: retarget the board, keep the mask chain off the triangle

Review follow-ups:
- With a board's mask targeted, nothing on the row targeted the board again:
  a board has no thumbnail to click. A click on its row, off the masks, now
  targets the board.
- On a masked board the mask chain started inside the disclosure triangle's
  hit area, so a click there toggled the mask link instead of opening or
  closing the board. The row now leaves the gap a layer thumbnail would.

Adds a_masked_artboard_row_keeps_the_triangle_clear_and_retargets_the_board,
which failed before on each point.

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

* Artboard rows: compact only for unmasked boards

Review follow-up. Leaving the thumbnail off a masked board kept costing what
the thumbnail does on any masked layer: clicking back from the mask, ending
the mask view, the target brackets and the spacing of the mask's chain, each
patched one at a time.

A board with a mask now keeps its usual row, thumbnail and all, so all of it
works as on any masked layer; only unmasked boards get the compact heading
row. This drops those special cases.

Tests: a masked board keeps its thumbnail and mask thumbnail with the chain
clear of the triangle, and its thumbnail ends the mask view and targets the
board (both failed before).

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-11-01 05:14:18 +01:00
Mohamed MahjoubandClaude baf8e654e8 Keep a layer's place on its board when dragged to another artboard (#10489)
Artboards share one canvas, so a layer dragged from one board onto another in
the Layers panel (layer.moveTo, including the Alt-drag copy) changed parent but
kept its old canvas position, outside the board it now belonged to, and the
board clipped it away.

apply_move now shifts a layer that lands on a different board by the offset
between the two boards' origins, through move_layers (the Move tool's path).
Reordering within a board, leaving or joining a board from the top level,
position-locked layers and moving a board itself are unchanged. The Layers
panel's drop preview uses apply_move, so it shows the same result.

Locks are read before the drop as well as after, so a layer whose position
was locked only through the board it left stays put (review follow-up).

Co-authored-by: Claude <noreply@anthropic.com>
2026-11-01 05:14:15 +01:00
Dylan M. Taylor 05b615fb1b ci: grant packages write permission to release workflow 2026-10-31 23:42:56 -04:00
Dylan M. Taylor 1f984bffb3 packaging(flatpak): add OCI image build and GHCR publishing helper (#10567) 2026-10-31 18:53:08 -04:00
aiongg 799e129628 Merge pull request #10145 from davidmann4/integration-batch-10
Integration batch: 18 PRs on main
2026-10-31 13:31:44 -04:00
Khawar Zamman Wani f3caa319a2 Keep brush state intact when preset tip loading fails (#10288) 2026-10-31 13:07:18 -04:00
David MannandClaude Opus 5.5 aca609ef49 Merge #8725's current head (6d1aef9bd) into the batch
Its two new commits merge main (8a87a457a, 422ca7bed), both already in the batch.
Their catalog resolutions place the "Edit Brush…" row differently; every row they
hold is already in the batch's catalogs, so the tree is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 15:15:47 +01:00
David MannandClaude Opus 5.5 e46be131e9 Merge #9274's current head (7da275ea6) into the batch
The author's main merge brings one new test (full coverage keeps Threshold over
extreme float channels) and rewords the #9483 tone comment; its main side
(b1cfff9d3) is already in the batch. Docs keep the batch's newer status lines and
revision rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 14:43:14 +01:00
David MannandClaude Opus 5.5 130244bace Merge #8571's current head (752daed44) into the batch
752daed44 makes nested SVG images share one XML depth budget in the bounded
parser. The batch's fix-up 1acb1f464 already does that (`xml_left` passed down
to each nested image), and also leaves an image the drawing has no depth left
for out instead of failing the drawing, so the tree keeps the batch's svg.rs and
its test `bounded_embedded_svg_gets_only_the_nesting_depth_the_drawing_left` (511 + 511 levels).
866b9d0e4 merged an older main than the batch has; the batch keeps its own,
reviewed resolutions of those files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 14:42:49 +01:00
David MannandClaude Opus 5.5 622707a36f Address CodeRabbit review: four findings on the batch
- Channel targeting routes an allow-list of pixel-editing paint commands, not every
  `paint.*` id: the Mixer Brush's Alt-click load and Symmetry no longer follow a colour
  set or get refused with "Rasterize the layer" on a fill layer. Patch and Content-Aware
  Move stay routed (#9274).
- Native vector save-back checks the preview SVG as strictly as stored previews are
  checked on load and PSD export, so a preview with an unreadable embedded image is
  refused instead of stored and later dropped (#8571).
- .pcraft blobs read their zstd frame with framing headroom, so an incompressible
  preview right at its 16 MiB limit still loads; the limit still bounds the data.
- Levels/Curves recall (Alt+shortcut) decides the combined Lab record from the target
  the dialog captured, as remembering does, so a viewed layer mask keeps its settings
  beside a Lab colour set (#9274).

Each comes with a test that fails without it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 14:41:36 +01:00
David Mann 9ec0f51dc1 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/ui-egui/src/i18n/nb.tsv
2026-10-31 13:55:06 +01:00
Claude 6d1aef9bd5 Merge storytold/photocraft main into the Fill/Stroke popover branch
Clean merge of 5 upstream commits; scorecard unchanged (12 of 183).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TYsCL5E2GM6hUabP9dmYAv
2026-10-31 06:53:03 +00:00
Dylan M. Taylor 422ca7beda Merge pull request #10420 from aiongg/docs-tidy
docs: tidy agent, contributor and release docs
2026-10-31 01:06:22 -04:00
Dylan M. Taylor e65dca0e46 Merge pull request #10421 from aiongg/update-result-dialog
Updates: shared check-result dialog from craft-update
2026-10-31 01:05:39 -04:00
aiongg 6c1da97387 updates: show check results with craft-update's CheckResultDialog 2026-10-31 04:43:12 +00:00
aiongg 27f9b5be9a docs: tidy wording 2026-10-31 04:25:34 +00:00
aiongg 6d737c219e docs: tidy agent, contributor and release docs 2026-10-31 04:17:45 +00:00
Claude 953728fdd0 Merge storytold/photocraft main into the Fill/Stroke popover branch
15 upstream commits; i18n conflicts were append-only (upstream's entries
first). Scorecard unchanged (12 of 183).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TYsCL5E2GM6hUabP9dmYAv
2026-10-31 03:47:42 +00:00
Brandon ThomasandClaude Opus 5.5 8a87a457ab Release 0.18.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.18.0
2026-10-30 23:26:40 -04:00
Brandon ThomasandClaude Opus 5.5 d5b564db93 Flatpak bundle: skip the debuginfo pass manifest-wide (runner has no eu-strip)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 23:26:31 -04:00
David Mann 6d84d33777 Merge PR #8725: feat(ui): Photoshop Fill/Stroke popover and full Color Picker for every colour swatch 2026-10-31 02:05:41 +01:00
David Mann e5b4ea6781 Merge main at e7b7cf11e into integration batch 10
i18n catalogs: main's new rows (#10328) appended after the batch's, as a union.
2026-10-31 02:05:31 +01:00
aiongg e7b7cf11e3 Merge pull request #10328 from davidmann4/fix/10204-reference-app-followup
Follow-up to #10204: match the reference application in ten places (#10327)
2026-10-30 20:54:57 -04:00
Claude 33fac7dbab Merge storytold/photocraft main into the Fill/Stroke popover branch
Clean merge of 1 upstream commit (Flatpak packaging only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TYsCL5E2GM6hUabP9dmYAv
2026-10-31 00:38:18 +00:00
Dylan M. Taylor 3ff283af35 fix(flatpak): allow reading launcher version pins (#10393)
* fix(flatpak): allow reading launcher version pins

* fix(flatpak): allow reading launcher version pins
2026-10-30 20:11:55 -04:00
David Mann 4380abc007 Merge PR #8725: feat(ui): Photoshop Fill/Stroke popover and full Color Picker for every colour swatch 2026-10-31 00:11:35 +01:00
d53a524334 Integration: the Ctrl+Shift+Enter Pen test starts its draft as a click does (#8015)
Since main's #3464 a Pen draft carries the owner its first click captured
(document, revision, target path). The test built a draft with no owner,
so finishing it took the target from the current UI state, where path.set
had left the old work path selected, and appended to it: the selection
became 0,0 170x80 instead of the triangle plus the square. The test now
captures the owner as main's Ctrl+Enter test does, with the work path not
selected in the Paths panel (the Pen then starts a new work path).

Co-authored-by: mahefanante <42338306+mahefanante@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 00:08:22 +01:00
David Mann 89a5b25072 Merge main at 952c328b3 into integration batch 10 2026-10-31 00:05:12 +01:00