Commit Graph
2769 Commits
Author SHA1 Message Date
aiongg a07b87a1af Merge upstream main into integration-2
crates/engine/src/mode_cmds/tests.rs: keeps #7139's opaque-background test and main's full-precision angle test
2026-10-18 15:11:28 +00:00
aionggandGitHub 4df773e966 Merge pull request #7405 from aiongg/next
Integration batch: 19 PRs on main
2026-10-18 11:09:40 -04:00
7066497886 Keep fractional translation-only Free Transform on .atn import (#7401)
Fixes #7298

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 10:51:21 -04:00
491af6d42c Camera Raw histogram: spikes run off the top, as in Photoshop's Camera Raw (#7419)
The dialog's histogram fitted its tallest interior column to the plot, so one spike (a dark sky, a bright wall) flattened the midtones' hill to a few pixels. Camera Raw 16.1.1 scales linearly by the typical columns and lets a spike run off the top (measured on Photoshop 25.4: 49 px per 10 000 pixels in a 106 px plot, the 95th-percentile column at 14 546, the tallest at 21 600).

`rgb_histogram::Spikes`: `Fit` (the old behaviour, every other histogram keeps it) and `Clip` (the scale is at most 1.5 × the 95th-percentile column, taller columns clip at the top). The Camera Raw dialog's histogram uses `Clip`.

Test: `camera_raw_scale_lets_a_shadow_spike_run_off_the_top`.

Split out of #3816 at the reviewer's request.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-18 10:50:47 -04:00
65778c1f7e Raw tone curve: no NaN between a knot at black and the next one (#7416)
`develop::tone` interpolates the camera curve logarithmically between knots, and a curve whose first knot sits at black (0, 0) made the first segment divide by log₂ 0: every value in it came out NaN, and `retone` (the open-time Shadows/Highlights preview) propagated it into the pixels. From a knot at black the segment is now linear, where log₂ has no value; the other segments are unchanged.

Test: `retone_lifts_shadows_with_a_curve_from_black` (finite output, shadows lifted, highlights kept) fails without the fix.

Split out of #3816 at the reviewer's request.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-18 10:50:41 -04:00
713dbbed2f Save Actions ATN files atomically so a failed write keeps the old file (#7403)
Fixes #7290

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-18 10:50:37 -04:00
80553ecd93 Refuse strict ATN export of Close with an explicit document target (#7393)
Fixes #7299

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-18 10:50:32 -04:00
89fa322a3c Crop: Esc and Enter go to an open options bar popup first (#7386) (#7388)
The shortcut pass runs before the panels are drawn, and its crop/polygon
branch consumed Esc and Enter even while an egui popup of the options bar
was open (the Ratio list, the overlay and gear menus): Esc cancelled the
crop and left the list open, Enter committed the crop beneath it. Skip the
branch while `egui::Popup::is_any_open` (kept in memory from the last
frame; `ctx.any_popup_open` only sees the current pass).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 10:50:27 -04:00
4b2bee675e Spot Healing Brush trail is Photoshop's dark half-opaque tint (#7342) (#7374)
The stroke preview was white at a quarter opacity, invisible on white
and faint elsewhere. Photoshop shows the area to heal in half-opaque
dark grey; the trail now does too. Other retouch trails are unchanged.

Test: drag_preview_canvas::the_spot_healing_trail_is_a_dark_half_opaque_tint
drags the real canvas offscreen on white and mid-grey and checks the
trail darkens the pixels to 40-60 %; it fails with the old colour.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 10:39:39 -04:00
d459ca7939 Image Rotation: Arbitrary keeps Color Sampler points on their pixel (#7372) (#7373)
Sampler points are pixel indices, but rotate_arbitrary mapped them as the
pixel's top-left corner while the warp moves pixels by their centres, so
after a turn a point sat one pixel off its pixel, or fell off the canvas
(a corner point at 90° or 180°). Map the pixel centre, as #6720 does for
flips and right-angle turns; the turned Crop shares this map.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 10:39:34 -04:00
a4c7b5ef89 Rotate Canvas Arbitrary: keep the angle at full precision, so rotated crops land on the pixel (#7369) (#7370)
rotate_arbitrary read `angle` as f32. rotated_crop sizes its canvas with
rotated_size at f64 and passes the angle through JSON; near a whole-pixel
ceil boundary the f32 angle grew the canvas 1 px more (1000x1000 at
0.11470651449337071: 1003 instead of 1002), shifting the crop by 1 px.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 10:39:29 -04:00
fb6f8b4fa6 Canvas Size: growing the canvas re-renders PSD fill layers (#7362) (#7363)
A fill layer from a PSD keeps its stored pixels as a fill cache that covers
only the old canvas. Canvas Size, an extending Crop and Reveal All translated
that cache but kept it, so the added area of the fill layer stayed
transparent. Drop the fill caches whenever the canvas grows, so the fill
re-renders from its model over the whole canvas, as Photoshop does (Free
Transform and Perspective Crop already drop it).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 10:39:24 -04:00
06d4d31dd4 Tool Presets: + saves only the current tool's options (#7356) (#7357)
The + button in Window › Tool Presets stored the whole ToolOptions struct, so choosing
the preset later wrote every other tool's options back (e.g. Crop's Delete Cropped
Pixels). Reset Tool's per-tool field lists become `option_keys`, which the + button now
uses to store only the tool's own options. Brush/Pencil Clear, the Eraser's mode, the
Remove tool's options and Content-Aware Move's Transform On Drop join their tools' lists,
and a test checks that every option belongs to a tool.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 10:39:19 -04:00
5f648126c7 Crop and Straighten Photos keeps Duotone inks and is disabled for Indexed Color (#7354) (#7355)
The copies were made with Document::new and kept the mode but not the
duotone inks, so a Duotone scan came out as plain gray. Copy them, and
grey the command out for Indexed Color documents, as Photoshop does.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 10:39:15 -04:00
MarekSpodBiedryandGitHub c8c651c413 Esc leaves full screen with the Crop tool showing its default frame (#7315) (#7350) 2026-10-18 10:39:09 -04:00
MarekSpodBiedryandGitHub e04f522667 Centre stacked ruler digits and the Properties W/H/X/Y labels (#7314) (#7349) 2026-10-18 10:39:04 -04:00
MarekSpodBiedryandGitHub 2c1c6f6693 Open Photoshop guides stored in a JPEG's APP13 resources (#7300) (#7348) 2026-10-18 10:38:59 -04:00
drifteeandGitHub 6e460aab8a fix(transform): isolate nested preview siblings (#7280) 2026-10-18 10:38:54 -04:00
5b087699be Tests: fix the flaky file-lock tests and the occasional portal_save hang (#7418)
The rotation and instance-log tests in logging.rs, and two app_dirs migration-lock tests, drop a
flock and check straight away that it is free. A child that another test spawns at that moment
holds a copy of every open descriptor until its exec, the lock included, so the check sometimes
saw it still held (about 6 failures in 15 runs of the app's test binary). Tests that spawn
children (the portal mock's dbus-daemon, the display-profile helper test) now hold CHILD_SPAWNS
for reading while they spawn, and the lock tests hold it for writing.

The portal mock made its message stream inside its thread; a stream only gets messages that
arrive after it exists, so a SaveFile sent before the thread got going was lost and the test
waited forever (about 1 run in 25). The stream is now made before the thread starts.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 10:29:07 -04:00
aiongg 5a01650652 Integration: cargo fmt 2026-10-18 14:19:01 +00:00
aiongg 0b167ca259 Integration: #6476's uppercase token test writes its file owner-only (#5459 on main) 2026-10-18 14:19:01 +00:00
aiongg fac74f83e8 Integration: #6414 an unconfirmed save releases the unsaved-changes prompt 2026-10-18 14:19:01 +00:00
aiongg 0c36fbc49d Integration: #6035 move the new tests above existing tests' doc comments 2026-10-18 14:19:01 +00:00
aiongg 432c973033 Merge PR #6030: Help › Search: typed letters go to the field, not to menu mnemonics (fixes #5996) 2026-10-18 14:19:01 +00:00
aiongg 8f1eedfc36 Merge PR #6039: Window › Arrange: tiles keep their documents, and every tile has rulers (fixes #6017) 2026-10-18 14:19:00 +00: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
aiongg ccb62fcd8f Merge PR #6038: Type: Korean paragraph text wraps between words, not syllables (fixes #5959) 2026-10-18 14:18:59 +00:00
aiongg 9692eea083 Merge PR #6346: File › Open: a file type filter per format (fixes #6337) 2026-10-18 14:18:59 +00:00
aiongg 17e3490142 Merge PR #6035: Image Size: Indexed Color resamples with Nearest Neighbor only (fixes #6019) 2026-10-18 14:18:58 +00:00
aiongg b9b4a73cc0 Merge PR #6338: Smart filters: an edited filter's dialog previews again (fixes #6324) 2026-10-18 14:18:58 +00:00
aiongg dad0881247 Merge PR #6366: Type: the text caret shows on a white background (part of #6085) 2026-10-18 14:18:57 +00:00
aiongg eb2b1517a8 Merge PR #6505: Character and Paragraph panels: size, leading, baseline shift and indents follow the Type units preference 2026-10-18 14:18:57 +00:00
aiongg b5fed83c79 Merge PR #6335: Replace Color: the sample eyedropper is armed when the dialog opens (fixes #6279) 2026-10-18 14:18:56 +00:00
aiongg c5c68d5de7 Merge PR #6344: Replace Color: a Result swatch whose Color Picker sets the sliders (fixes #6278) 2026-10-18 14:18:56 +00:00
aiongg fb678d7463 Merge PR #6476: Automation: a control token authenticates in either letter case (#6425) 2026-10-18 14:18:55 +00:00
Michael HigginsandGitHub 62f94d3f9f Merge branch 'storytold:main' into fix/5713-smoothing-pressure-follows-brush 2026-10-18 10:10:31 -04:00
aiongg 19e3292c9f Merge PR #7141: perf(camera-raw): Shadows/Highlights 1.5× faster, bit for bit the same 2026-10-18 13:23:03 +00:00
aiongg 811abbc3e9 Merge PR #6333: Help › Search: ← / → and Space edit the field instead of driving the menu (#6332) 2026-10-18 13:23:02 +00:00
aiongg 94bb46f5cc Merge PR #6834: Object Selection: enclosed background gaps stay unselected, only object-like holes fill (#6556) 2026-10-18 13:23:02 +00:00
aiongg d5b9de755a Merge PR #6814: Re-saving a Photoshop 16-bit PSB no longer adds a second Transparency channel 2026-10-18 13:23:01 +00:00
aiongg 2437fc36c5 Merge PR #6046: fix(path): validate Make Selection options and guard selection state 2026-10-18 13:23:00 +00:00
aiongg 58d8d911a2 Merge PR #6003: Count: reject unknown groups instead of adding markers to the wrong group 2026-10-18 13:23:00 +00:00
aiongg eef436de45 Merge PR #5654: Count tool: deleting an earlier count group keeps the active group (#5653) 2026-10-18 13:22:59 +00:00
aiongg 785b9478d7 Merge PR #6771: Plug-ins: running a filter plug-in respects layer locks (#6770) 2026-10-18 13:22:59 +00:00
aiongg da96d71506 Merge PR #6863: Native format: refuse a .pcraft with out-of-range numbers when it is opened (#6862) 2026-10-18 13:22:58 +00:00
aiongg 45c5f41af0 Merge PR #7046: Render Video: GIF frame delay follows timelines under 1 fps (#7045) 2026-10-18 13:22:58 +00:00
aiongg c9ac35b3b1 Merge PR #7139: Perspective Crop and Rotate Arbitrary keep the Background opaque (#7138) 2026-10-18 13:22:57 +00:00
aiongg 71a5bc44be Merge PR #6499: Desktop: a control/automation flag without its value is a usage error (#6429)
apps/photocraft/src/main.rs: #6499's parse_launch_args is the one parser; it also takes main's --help/-h, -- and unknown-option errors (#6435); usage_exit_code is the one exit helper
2026-10-18 13:19:41 +00:00
aiongg e452f6ad80 Merge PR #6414: Web: a requested download no longer marks the document saved (#4962)
crates/ui-egui/src/lib.rs: Services keeps both main's file_stamp and #6414's write_unconfirmed
2026-10-18 13:16:00 +00:00
aiongg cab62b9516 Merge PR #6399: Brush: the Dual Brush tip keeps its proportion at tiny main sizes (#4809) 2026-10-18 13:15:52 +00:00