Commit Graph
3509 Commits
Author SHA1 Message Date
David Mann fa71e04f10 Merge PR #5769: PSD smart objects: keep Photoshop's Cylinder warp when re-rendered (#4112)
Integration: resolve docs conflicts (file-format-parity, gaps status lines) with main
2026-10-21 23:24:11 +02:00
David Mann e0457b2f4e Merge PR #7922: Create Rectangle and the other shape dialogs: right-click Width or Height to pick their unit (#7786) 2026-10-21 23:23:17 +02:00
David Mann 2c625d986f Merge PR #7838: Free Transform: a result may take what Memory Usage allows, not 2^30 px (#7807) 2026-10-21 23:23:13 +02:00
David Mann c7585e0ee8 Merge main 2026-10-21 23:22:56 +02:00
skylar taylor-barrick 6d8cbac7dc Merge pull request #2945 from diegochagas/feat/xcf-read
Open GIMP XCF files: layers, groups, masks, blend modes, channels and selection
2026-10-21 14:35:32 -06:00
skylar taylor-barrick 18e2d45420 Merge pull request #6318 from robertoffmoura/fix/floating-selection-move-lag
Fix lag when dragging a floating selection with the Move tool
2026-10-21 14:25:55 -06:00
David Mann 9c3a0bbfec Merge remote-tracking branch 'origin/main' into integration-batch-6-fix 2026-10-21 22:05:27 +02:00
David MannandClaude Opus 5.5 c7ef3676af Integration: snapshot selection and History follow share one history identity (#5940)
At the history limit a new state can keep the count and the name, so a
selected snapshot stayed selected after it. The newest past state now
belongs to HistorySpot, used by both checks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 22:05:27 +02:00
Dylan M. Taylor 87fa191818 ci: add sonar-project.properties for CI-based analysis
Marks the project ineligible for SonarCloud Automatic Analysis, resolving the
CI-vs-automatic-analysis conflict so the SonarCloud workflow succeeds.
2026-10-21 16:00:47 -04:00
Diego Chagas ca18689304 Open GIMP XCF files: layers, groups, masks, modes, channels and selection (#1076)
PhotoCraft reads GIMP's .xcf (and .xcf.gz) files, read only, through a new
reader in photocraft-io written from the public XCF specification: versions
0 to 26, uncompressed, RLE and zlib tiles, 8/16/32-bit integer and
16/32/64-bit float precisions (linear precisions get a linear profile),
pixel layers at any position, groups by item path with pass-through,
layer masks applied or disabled, opacity, visibility, locks, colour tags,
the 2.10 and legacy blend modes mapped to Photoshop's (modes without an
equivalent open as Normal with a note), the ICC profile, resolution,
guides, the comment, extra channels and the saved selection; indexed
images open as RGB. Text, vector and link layers open as their pixels;
layer effects, paths and floating selections are reported.

Fixtures are written by GIMP 3.2 itself (scripts/xcf_fixtures.py), each
with GIMP's merged rendering as a PNG. In gamma-encoded blend and
composite spaces our composite matches GIMP within 0.5/255; GIMP's
linear-light default, its Clip to backdrop and its clamp-after-alpha
for unbounded modes are documented and measured in docs/xcf.md.
2026-10-21 16:57:22 -03:00
Dylan M. Taylor 8e518d8169 ci: add SonarCloud scan via shared reusable workflow
Calls storytold/craft-common-actions/.github/workflows/sonarcloud.yml@main
with secrets: inherit. Adds SonarCloud badge to README where missing and
removes the redundant sonar-project.properties (config now passed by the
reusable workflow).
2026-10-21 15:47:04 -04:00
Brandon ThomasandClaude Opus 5.5 6a2d027ee2 Release: version 0.12.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.12.0
2026-10-21 13:59:16 -04:00
Roberto Moura f4ea3139d7 Keep selection snap targets when dragging a guide with the Move tool 2026-10-21 16:37:54 +00:00
David Mann c3f282d837 Merge PR #6472: fix(ui): preserve shape stroke settings at zero width 2026-10-21 17:48:06 +02:00
David Mann 3d64af4aec Merge PR #5940: History panel: scroll to the current state on document change (#5909) 2026-10-21 17:48:02 +02:00
David Mann 1d72d6e17d Merge PR #3356: CMYK documents keep their exact inks: export, PSD merged image and Flatten (follow-up to #4199) 2026-10-21 17:47:55 +02:00
aiongg 68348dcafc Merge pull request #8271 from aiongg/integration-8
Integration batch: 86 PRs on main
2026-10-21 11:02:54 -04:00
27c525c079 Integration: a unit per field, no Percent, not remembered, as in Photoshop (#7922)
Photoshop's Create Rectangle switches only the right-clicked field
(Width 35.28 mm, Height still 100 px), lists the six length units
without Percent, and opens in pixels again after OK. The PR shared one
unit between both fields, offered Percent, and saved the unit on every
OK, so after one use with the rulers in px the dialog stayed in px even
after the rulers changed to cm, though no unit was ever picked.

Now each field has its own widthUnit / heightUnit (set only by the
menu, never remembered), and the menu is rulers::unit_menu_of with
LENGTH_UNITS. The new test right-clicks the real field and clicks the
menu item through egui input.

Co-authored-by: Korg1ch <57859048+Korg1ch@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 16:08:43 +02:00
f18e6189c7 Integration: History follows the history, not every revision, and never moves a visible row (#5940)
The panel scrolled with `scroll_to_rect(current, Some(Align::BOTTOM))` on every revision
change. In egui an explicit alignment always realigns, and the revision also changes when
nothing in the history does (selecting a layer, a channel eye). So clicking a visible older
state slid it to the bottom under the pointer, Undo hid the greyed redo states, a layer click
threw a user who had scrolled up back to the bottom, and selecting a snapshot scrolled it out
of view.

Now the panel follows the history position (document, past/redo counts, current name, and the
newest past state, which also changes at the state limit), skips it while a snapshot is
selected, and scrolls without alignment, so only a hidden current row moves into view. New
tests: a clicked visible state stays put, Undo keeps the redo state in view, a layer click keeps
the scroll, a selected snapshot stays in view, a new state at the limit is revealed; the first
three fail on the PR head, the others without the snapshot guard / the newest-state key.

Co-authored-by: nrq6993-a11y <342501791+nrq6993-a11y@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 15:38:53 +02:00
962539607d Integration: keep a strokeless shape strokeless on a 0 px width step (#6472)
The width field reports a change for an arrow-key step that clamps at
0 px. With the stroke now kept at width 0, Down in the options-bar or
Properties width field of a shape without a stroke added an invisible
0 px stroke (bg colour in the options bar, black in Properties), which
enabled Copy Stroke and exported strokeEnabled to PSD. Skip the edit
when the shape has no stroke and the width is still 0.

Test: arrow_down_at_zero_width_keeps_a_strokeless_shape_strokeless.

Co-authored-by: denstu473 <63150090+denstu473@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 15:37:36 +02:00
Roberto Moura 8352b26c1a Fix lag when dragging a floating selection with the Move tool
- Replace whole-region Vec<f32> read_region/write_region in CutParts::new
  with tile-parallel cut_piece + try_fill_surface/try_clear_surface,
  sharing interior Arc<Tile> allocations in O(1) and activating the
  solid_tile hole-fill fast path on Background and mask targets.
- Cache piece_bounds on CutParts so CutParts::place avoids scanning tile
  content bounds on every drag frame.
- Parallelize composite_over across top tiles with Rayon and share fully
  opaque top tiles by Arc<Tile> clone in O(1), preserving COW tile
  identity for GPU canvas uploads.
- Parallelize Surface::translated across target tiles with Rayon and
  prune cleared tiles in-place inside edit_tiles.
- Skip zero-offset floating preview generation on pointer-down in
  move_ui::floating_doc.
- Exclude SnapKind::Selection when moving selected pixels with the Move
  tool so small initial drags do not snap back to (0, 0).
- Keep navigator_plain active during Move/Brush/Patch drags on a GPU
  canvas so navigator_gpu is not evicted into a synchronous full-document
  CPU thumbnail composite on the first drag frame.
- Parallelize row normalization in compose::render_reduced_in_bands and
  add a direct read_rgba_into fast path for unmasked Normal layers over
  an empty backdrop.
2026-10-21 13:21:10 +00:00
9a6b3cb3bc Integration: merge main, resolve conflicts with #6913's split warps (#5769)
Main's quiltWarp support (#6913) rewrote the same placed-warp code the
cylinder warp touches. Kept main's split-warp read and write
(warp_head, quiltWarp, sold_warp) and added the cylinder to it:
warp_head writes `warpValues` for a cylinder, placed_frame frames a
cylinder's mesh as well as any valid custom mesh, quad_points uses
perspective_frame of the warp the block stores, and parse_smart_perspective
reads `quiltWarp` before `warp`, as parse_placed_warp does, so a projective
placement is framed by the warp that is imported.

Co-authored-by: alvarohn <32224796+alvarohn@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 14:29:59 +02:00
Dylan M. Taylor 04d0212c7a Merge pull request #6448 from dylanmtaylor/ci/shared-nix-workflow
ci: switch to shared nix workflow from craft-common-actions
2026-10-21 03:40:26 -04:00
aiongg abd0582add Integration: the Type units test makes its type after the resolution change, for #7125
#7125 keeps existing type's pixel size across Image Size, so the #6491 test's 12 pt layer, made before the change to 144 ppi, became 6 pt. The test now creates its layer at 144 ppi; its assertions are unchanged.
2026-10-21 05:04:04 +00:00
aiongg 194dfcf0ec Integration: Clear History resets the History Brush source and Undo brings it back, for #3534 and #3536 2026-10-21 05:04:04 +00:00
aiongg c5176efd93 Integration: a scale beyond f32 range is refused, not clamped, for #7048
Main's 3f216a0cd1 rejects numeric overflow before document edits; #7048's test predates it and expected 1e39 to clamp to 150 %.
2026-10-21 05:04:04 +00:00
aiongg b1e408d28f Merge the smart-filter track (#7066 #6398 #6397 #6297 #6299 #6301 #6303 #6315 #6305 #6317)
# Conflicts:
#	docs/file-format-parity.md
2026-10-21 05:04:04 +00:00
aiongg a2c56f960f Integration: gaps.md preferences count from the regenerated scorecard, for #6208 and #6211 2026-10-21 05:04:04 +00:00
aiongg 8e04e6f21e Integration: regenerate docs/scorecard.md for the batch 2026-10-21 05:04:04 +00:00
aiongg cb8bea1636 Merge PR #7044: Conditional Mode Change: "gray" as a single source mode matches Grayscale (#7042)
# Conflicts:
#	crates/engine/src/file_cmds/tests.rs
2026-10-21 05:04:04 +00:00
aiongg 1d567a115f Merge PR #7015: Actions: deleting an action removes its function key (#7014)
# Conflicts:
#	crates/engine/src/actions_cmds.rs
2026-10-21 05:04:04 +00:00
aiongg 2a1ac6a6fb Merge PR #6208: Preferences: Save in Background off saves in the foreground (#6207)
# Conflicts:
#	docs/gaps.md
#	docs/scorecard.md
2026-10-21 05:04:04 +00:00
aiongg 050caf9ecd Merge PR #6681: Content-Aware Move: live preview for large selections (TOOL-213-4, #6680)
# Conflicts:
#	docs/gaps.md
#	docs/scorecard.md
#	docs/target-app-parity.md
2026-10-21 05:04:04 +00:00
aiongg 4804148ff9 Merge PR #3759: Pattern Stamp and Background Eraser draw live; Spot Healing shows its heal area (TOOL-213-7, #3754)
# Conflicts:
#	docs/gaps.md
#	docs/target-app-parity.md
2026-10-21 05:04:04 +00:00
aiongg f163e3ce0b Merge PR #6211: Zoom tool: hold to zoom continuously with Animated Zoom on (#6210)
# Conflicts:
#	docs/gaps.md
#	docs/scorecard.md
#	docs/ui-parity.md
2026-10-21 05:04:03 +00:00
aiongg 1a5d22ca94 Merge PR #6708: Paths: the path selected in the Paths panel is drawn on the canvas (#6550)
# Conflicts:
#	crates/ui-egui/src/vector_ui.rs
2026-10-21 05:04:03 +00:00
aiongg fc371711e6 Merge PR #5847: Shapes: Density and Feather on shape layers (#5846)
# Conflicts:
#	docs/scorecard.md
#	docs/target-app-parity.md
#	docs/ui-parity.md
2026-10-21 05:04:03 +00:00
aiongg cd710ca898 Merge PR #5622: Filters: Lens Correction, Adaptive Wide Angle and Camera Raw Filter respect locks on smart objects (#5621)
# Conflicts:
#	crates/engine/src/lens_cmds.rs
2026-10-21 05:04:02 +00:00
aiongg 34c5e7d49e Merge PR #3536: History: set the History Brush source from the panel (history.setSource) (#2966)
# Conflicts:
#	crates/engine/src/commands.rs
#	crates/ops/src/lib.rs
2026-10-21 05:04:02 +00:00
aiongg c23a6c9b90 Merge PR #6206: Performance: a cancelled Gaussian Blur job stops within budget (#6205)
# Conflicts:
#	docs/gaps.md
2026-10-21 05:04:02 +00:00
aiongg 375c5e1517 Merge PR #7085: Actions: an imported Crop step in a unit other than pixels is not applied as pixels (#7084) 2026-10-21 05:04:02 +00:00
aiongg 3d233afd31 Merge PR #7028: Transform Selection: an unknown reference point is an error (#7027) 2026-10-21 05:04:02 +00:00
aiongg 4699d3605c Merge PR #7026: Automation: place and layer/data-set export by index keep the active document (#7025) 2026-10-21 05:04:01 +00:00
aiongg 7db7f847c4 Merge PR #7024: Automation: doc.save rejects a bad quality instead of ignoring or clamping it (#7023) 2026-10-21 05:04:01 +00:00
aiongg 26844944b9 Merge PR #7005: Keyboard Shortcuts: switching sets keeps action function keys (#7004) 2026-10-21 05:04:01 +00:00
aiongg de03dd43f1 Merge PR #6861: CLI batch: skip shell-only Save and view steps inside played action sets (#6860) 2026-10-21 05:04:01 +00:00
aiongg 1637ae25e1 Merge PR #6805: Droplets: carry the actions that Conditional steps call (#6804) 2026-10-21 05:04:01 +00:00
aiongg 9d5bf2a82c Merge PR #6773: Actions: renaming an action updates the Conditional steps that call it (#6772) 2026-10-21 05:04:01 +00:00
aiongg dc8b8834e0 Merge PR #5889: Image: Bitmap dialog with Output resolution and per-method settings (#5559) 2026-10-21 05:04:01 +00:00
aiongg 40895532aa Merge PR #5840: Export As: Resample menu, incl. Nearest Neighbor (#5838)
# Conflicts:
#	docs/scorecard.md
2026-10-21 05:04:01 +00:00