Commit Graph
3466 Commits
Author SHA1 Message Date
xsvm 8fe2c74f58 perf(testkit): sample RSS from /proc/self/statm, not smaps, on Linux (#5399)
memory-stats reads /proc/self/smaps by default on Linux: every sample formats and parses one
block per mapping while holding the mmap lock. The benches' RssSampler polls it every 2 ms, so
on a profile of bevel_bench --size 4000x3000 the rss-sampler thread was ~22% of all samples
(smaps_account 14.7%, smaps_pte_entry 6.3%), contending with the measured threads.

Enable the crate's always_use_statm feature: one short read of the kernel's RSS counters, the
same number VmRSS reports. The measured code is unchanged; only the harness overhead goes.
2026-10-16 17:00:43 -06:00
wwew 93f6376c5e docs: write product name as PhotoCraft in package descriptions and comments (#5615) 2026-10-16 16:59:41 -06:00
wwew e33384c9ba docs: write product name as PhotoCraft in crate module docs (#5455) 2026-10-16 16:58:50 -06:00
PerchenkoAnton f360cb0b4a fix(engine): give artboard exports unique indexed filenames (#6655) 2026-10-16 16:57:33 -06:00
wwew 651647fdf6 docs(cli): write product name as PhotoCraft in USAGE and description (#5449) 2026-10-16 16:56:48 -06:00
Jason Xiang f1c45b887e fix(codecs): respect PAM ENDHDR line boundaries (#5874) 2026-10-16 16:38:54 -06:00
Marco Arnulfo 6a7fc88c79 Crop tool: custom ratios keep three decimals, 1.414 : 1 no longer becomes 1.4 : 1 (fixes #6487) (#6503) 2026-10-16 16:38:35 -06:00
Marco Arnulfo 97f50b4714 Pen: the path in progress stays visible while panning with Space (fixes #6592) (#6625) 2026-10-16 16:38:11 -06:00
Diego Chagas ad6463b50f Paragraph text: a word wider than the box breaks at the box edge (#6694) (#6696)
parley's default overflow wrap only breaks at UAX #14 opportunities, so
a word longer than the paragraph box ran out past its edge and resizing
the box changed nothing. Paragraph text now sets OverflowWrap::BreakWord,
so such a word wraps at the box edge as Photoshop does; a space or hyphen
still wins over a mid-word break, a box that fits the word lays out as
before, and point text is untouched.
2026-10-16 16:37:45 -06:00
Korg1ch 3c75db7a80 fix(linux): avoid duplicate AppImage desktop launcher when managed by AM / AppMan (#6392) (#6394)
* fix(linux): avoid duplicate AppImage desktop launcher when managed by AM / AppMan (#6392)

* test(linux): cover AM / AppMan launcher detection in AppRun smoke test (#6392)
2026-10-16 16:37:17 -06:00
midasmatterhorn 19227022ca Histogram: scale bar heights linearly to the tallest bin, not sorted.get(250) (#6638) 2026-10-16 16:36:58 -06:00
Nicolas Falesy 54a4782849 perf(camera-raw): Shadows/Highlights 1.9× faster, bit for bit the same (#5964) (#6247)
The local Laplacian filter behind Shadows and Highlights builds a whole
pyramid per reference value (up to 96). Three costs dominated it:

- blur_step called mirror() (an integer remainder) for every tap of every
  pixel; the source rows are now found once per row and columns mirror only
  within two pixels of an edge.
- up() blurred a zero-stuffed plane, three samples in four zero; it now adds
  only the nonzero taps, in the same order.
- the small pyramid levels were split into one-row rayon tasks, costing more
  in scheduling than the rows; planes under 32K samples run on one thread.

The output is bit for bit the same: a new test checks blur_step and up
against the plain versions on odd, even, tiny and parallel-sized planes.
2026-10-16 16:26:19 -06:00
David MannandClaude Opus 5.5 c354a25a6b Type: paragraph box handles are picked at the unsnapped press (#6819)
With View > Snap on, the canvas snapped the Type tool's press (a point
gesture) before the tool's handle hit test, with the edited text's own
glyph bounds and centre lines among the targets. The snapped press could
leave the 6 pt handle grab area, so the press placed the caret or
committed the edit instead of resizing the box.

- The Type tools pick the box handle or glyph at the raw press, as Free
  Transform already does.
- While editing, only a press on a box handle starts snapping, and the
  resize drag snaps to guides and other layers, not to the text being
  resized; caret drags are no longer snapped.

Canvas-level test drags all eight handles (at the handle and inside its
grab area) at 25-200 % zoom, 1x and 2x HiDPI, plain/scaled/rotated layer.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 00:19:26 +02:00
MarekSpodBiedry 156b27d65b Object Selection: enclosed background gaps stay unselected, only object-like holes fill (#6556) 2026-10-17 00:06:54 +02:00
David MannandClaude Opus 5.5 89339396ff Droplets: carry the actions that Conditional steps call (#6804)
called_actions only followed actions.play steps, so a droplet whose action
used actions.conditional saved neither branch and failed with "no action
named ..." when run standalone. It now also queues the then/else targets.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 23:42:36 +02:00
David MannandClaude Opus 5.5 1338d78b45 Transform: drop a fill layer's cached render when its frame changes (#6808)
Free Transform and Warp moved a fill layer's linked masks (and so the frame its
gradient is laid out in) but kept the cached render, which the compositor draws
as-is while the Fill is unchanged. Drop the cache in apply_transform and
warp_layer, as transform_layer_geometry and Perspective Crop already do.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 23:42:34 +02:00
Higgs32584andClaude Opus 5.5 cd75fa78ef PSD/PSB: a 16/32-bit file's "Transparency" channel stays the merged transparency on re-save (#4654)
Photoshop's 16-bit PSBs can mark the merged transparency only by naming it
"Transparency" in the alpha channel names (positive Lr16 layer count, no Mt16).
The importer read it as a user alpha channel, and the next save wrote a second
one. merged_has_alpha now also accepts that name when the layers sit in a
global Lr16/Lr32 block and the names cover every extra channel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 17:38:42 -04:00
David MannandClaude Opus 5.5 3afb0b1283 PSD: layered TIFF byte-order conversion swaps every smart filter section (#6802)
Tx::filter_effects converted only the first u64-length section of FEid/FXid and copied the rest as stored, so a second smart object's section kept the source byte order and FilterEffects::parse lost the whole block.
It now mirrors FilterEffects::parse: one section per smart object, each with its 4-byte padding, until only trailing zero padding remains.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 23:33:20 +02:00
nrq6993-a11yandCursor 2e8d20ca9c Fix rustfmt on snap_ui smart-target assignment.
CI Format step failed on a line break rustc-fmt does not want.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-17 00:24:53 +03:00
David MannandClaude Opus 5.5 8c6412bbb2 Plug-ins: running a filter plug-in respects layer locks (#6770)
plugin.run wrote into raster and smart object layers without checking
locks. It now refuses layers with locked pixels or Lock All like the
built-in filters, and with Lock Transparency it keeps the layer's alpha
(as built-in filters do, via filters::keep_alpha).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 23:20:35 +02:00
David MannandClaude Opus 5.5 ec83a1117f Presets: refuse renaming a group to a name another group has (#6768)
renameGroup in the shared preset group editor renamed without checking
that the new name was free, so two groups could share a name and a later
replace import of that name removed both. It now refuses like the
Swatches sibling; renaming a group to its own name stays fine.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 23:20:35 +02:00
David MannandClaude Opus 5.5 0fc5660f60 Image Size: a gradient fill's centre offset stays a fraction of the frame (#6778)
map_fill multiplied the offset by the full linear part of the canvas transform, so Image Size
(and Perspective Crop) scaled it: 200% moved a 25% offset to 50%. Each axis of the linear part
is now normalised, so scale drops out while flips and 90° turns still mirror and turn it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 23:19:40 +02:00
David MannandClaude Opus 5.5 031ab7d5b2 Apply Image: write into the targeted layer mask (#6780)
With the layer mask targeted, apply_image took the layer branch and fetched the
layer's pixel surface with the target dropped, so the mask stayed unchanged and the
pixels were overwritten. A mask target now goes through the single-plane path and
is written back over the canvas, keeping the mask's default outside it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 23:18:53 +02:00
Ian Swope 9b6a85824d Mesh warp: tiles encoded in parallel and in-bounds taps read directly, about twice as fast with identical pixels 2026-10-16 16:13:44 -05:00
David MannandClaude Opus 5.5 9ac2c08875 Actions: renaming an action updates the Conditional steps that call it (#6772)
actions.rename only rewrote the "action" param of actions.play steps, so an
actions.conditional step whose "then"/"else" named the renamed action failed
with "no action named ..." on the next play. The rename loop now also rewrites
matching then/else branches, in saved actions and the pending recording.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 23:02:33 +02:00
David MannandClaude Opus 5.5 af5e77b150 Auto-Align: warp layer masks as masks, keeping what lies outside revealed (#6776)
Auto-Align warped a moving layer's mask with the colour warp (warp_placed), which
returns a grey + alpha surface defaulting to 0, so a reveal-all mask hid everything
outside its painted area. Masks now go through warp_gray (planar placements) or
warp_mesh_gray (cylindrical/spherical), keeping one channel and the mask's default.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 23:01:14 +02:00
David MannandClaude Opus 5.5 bdf44ab18c PSD: read colours stored as HSB (#6774)
color_from_desc had no HSBC arm, so HSB descriptor colours fell through to the
RGB fallback and came back None: solid fills vanished, strokes and effects went
black. Convert HSBC (hue in degrees, saturation/brightness 0..100) with the
existing channel_map::hsb_to_rgb, now pub(crate).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:51:32 +02:00
David MannandClaude Opus 5.5 ab81052308 Fit Image: a width or height of 0 leaves that side unconstrained (#6766)
fit_image read width/height with f64_param and clamped to 1, so a 0 or
negative side (dialogs send 0 for an empty field) became a 1 px box and
shrank the document to 1x1. It now uses size_param like the rest of
file_cmds.rs, so such a side falls back to the document's own size.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:49:38 +02:00
David MannandClaude Opus 5.5 01dbccee18 Merge main into feat/tool-213-7-live-retouch
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:42:01 +02:00
David MannandClaude Opus 5.5 f5d9969803 Merge main into fix/history-brush-source
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:37:11 +02:00
David MannandClaude Opus 5.5 b01f6d33b3 PSD: layered TIFF byte-order conversion reads the class of Idnt/indx references (#6764)
The byte-order converter read Idnt/indx reference items as a bare u32, but
they are class + u32 (as descriptor.rs reads them since #4434), so a block
holding such a reference desynced and was dropped (or left unconverted).
Read the class first; regression test round-trips such an lfx2 block.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:33:54 +02:00
David MannandClaude Opus 5.5 43ade8be26 Merge main into perf/p33-cmyk-dab
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:32:33 +02:00
David MannandClaude Opus 5.5 8af5f2b880 Merge main into fix/history-panel-menu
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:28:43 +02:00
David MannandClaude Opus 5.5 e5f1ecf501 Merge main into fix/smart-filter-last-mask
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:24:50 +02:00
nanopink 4354113e73 fix: match Photoshop Gradient Fill scale limits 2026-10-16 16:23:53 -04:00
David MannandClaude Opus 5.5 221af61dea Merge main into fix/count-delete-group-active
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:22:55 +02:00
David MannandClaude Opus 5.5 48ed913526 Merge main into fix/video-fps-validate
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:19:12 +02:00
David MannandClaude Opus 5.5 824cbdb022 Merge main into docs/scorecard-stale-rows-2
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:19:08 +02:00
David MannandClaude Opus 5.5 dd6f66e3ae Merge main into fix/lens-filters-smart-locks
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:17:26 +02:00
David MannandClaude Opus 5.5 0ea2684679 Merge main into fix/adjust-smart-object-locks
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:15:01 +02:00
David MannandClaude Opus 5.5 73b0bef8a5 Merge main into fix/fill-layer-angle-finite
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:15:00 +02:00
David MannandClaude Opus 5.5 c7f5dfdbc5 Merge main into feat/file-215-18-export-resample
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:13:25 +02:00
David MannandClaude Opus 5.5 699a16e024 Merge main into fix/lock-transparency-atop
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:12:47 +02:00
David MannandClaude Opus 5.5 31df8a357b Merge main into fix/mask-from-transparency-bg-depth
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:12:45 +02:00
David MannandClaude Opus 5.5 b9d646baad Merge main into fix/multichannel-alpha
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:11:01 +02:00
David MannandClaude Opus 5.5 1bd9c7a3dc Merge main into fix/1954-overlay-opacity-stops
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:08:36 +02:00
David MannandClaude Opus 5.5 1b0e69d2f6 Merge main into feat/tool-214-12-shape-feather
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:07:55 +02:00
David MannandClaude Opus 5.5 c1f0a7522a Merge main into fix/5559-bitmap-dialog
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:06:11 +02:00
David MannandClaude Opus 5.5 83afd80a87 Merge main into feat/ui-217-4-save-in-background
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 22:01:22 +02:00
David MannandClaude Opus 5.5 1336022624 Merge main into perf/p25-blur-cancel
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 21:58:23 +02:00