3805 Commits
Author SHA1 Message Date
tjbbjt e2580ccdb5 Tests: document the Color Sampler tests updated for pixel centres 2026-11-09 22:26:46 -08:00
tjbbjt 010fbe9e2e Tests: expect Color Sampler points on pixel centres after #12174 2026-11-09 21:44:47 -08:00
David Mann d6b97e5b4b Merge pull request #12174 from hectorviov/fix/sampler-pixel-centre
Color Sampler: points sit on the clicked pixel's centre (#11725)
2026-11-10 03:04:39 +01:00
David Mann 382ed04521 Merge pull request #12677 from RickiNano/fix/remove-history-name-12541
Remove tool: name the History step "Remove Tool" (#12541)
2026-11-10 02:24:19 +01:00
David Mann 625ea98a37 Merge pull request #10059 from tomgardenart/fix/selected-pixel-transfer-nostella
Drag selected pixels between document tabs and tiled canvases
2026-11-10 01:03:25 +01:00
David Mann e72d12106a Merge pull request #9337 from DuBearte/feat/8639-stroke-emboss
feat(compose): Stroke Emboss bevels the stroked outline (#8639)
2026-11-10 00:21:56 +01:00
David Mann 1cb42bb0bc Merge pull request #9827 from Luis-0508/fix/9754-color-lookup-lut-folder
Color Lookup: list the LUT folder in Image > Adjustments (#9754)
2026-11-09 20:44:19 +01:00
David Mann e940debe35 Merge pull request #12268 from hectorviov/fix/color-replacement-tolerance-field
Color Replacement: whole-number Tolerance 1-100 with the alert, and the bar's tooltips
2026-11-09 20:43:48 +01:00
David Mann 009b93c5ed Merge pull request #12381 from RickiNano/fix/bg-eraser-cmyk-inks-12352
Background Eraser: a CMYK document compares against the picked inks (#12352)
2026-11-09 20:24:59 +01:00
David Mann b479d94e21 Merge pull request #11895 from RickiNano/fix/11887-catch-up-on-end-default
fix(paint): Catch-up on Stroke End starts unchecked (#11887)
2026-11-09 20:24:32 +01:00
RickiNano 9533f8805a Remove tool: name the History step "Remove Tool" (#12541)
Every applied removal (one stroke, waiting strokes applied together,
Sample All Layers, Create new layer, any colour mode and depth) now adds
one History step named "Remove Tool", as the reference application does.
The command id, its params and the job's progress label are unchanged.
2026-11-09 19:57:50 +01:00
David Mann d7d93960cd Merge remote-tracking branch 'origin/main' into pr-10059
# Conflicts:
#	contributors/people.toml
2026-11-09 19:52:25 +01:00
David Mann c64708b836 Merge pull request #11836 from yoriswind/codex/recorded-displace-10705
Map recorded Windows Displace actions
2026-11-09 19:27:57 +01:00
a1a122e20e Merge origin/main into fix/9754-color-lookup-lut-folder (#9827)
Keep both contributors/people.toml entries.

Co-Authored-By: Luis-0508 <Luis-0508@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 19:03:37 +01:00
David Mann 4eb25099b7 Merge remote-tracking branch 'origin/main' into pr-9337 2026-11-09 19:01:55 +01:00
David Mann b059c1a45a Merge pull request #12438 from ljkx/atn-measurement-scale
Actions: map Image › Analysis › Set Measurement Scale › Custom (#10723)
2026-11-09 17:53:15 +01:00
David Mann 42ebea1c9f Merge main into fix/color-replacement-tolerance-field 2026-11-09 17:34:48 +01:00
David Mann 1cf3932e6f Merge pull request #12217 from hectorviov/fix/note-clear-all-confirm
Note tool: Clear All asks before deleting all notes; the step is named Delete all Notes (#11791)
2026-11-09 17:34:20 +01:00
2d6f9d172b Canvas: the redraw area covers a whole command, not just its last revision (#9329) (#10053)
* perf: add P85, the app frame after Paste Into on 24 MP (#9329)

Track-only row in the redraw area group: Paste Into a 5 % selection (untimed),
then time the next kittest frame. Guards: the command moves revision by >= 2 and
the frame records a refresh. Prints refresh px.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf: P85 re-creates the selection before each Paste Into (#9329)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf: a command's redraw area spans all its revisions; count whole redraws of small edits (#9329)

Session::dispatch is the one place damage spans revisions: a command that moved
the revision more than once reports step_damage of the document before and after
it, measured from DocState::damage_from. Deletes note_insert (Paste Into), Stroke
Path's hand-made union and the failed compound's None. Debug and test builds
count a whole-document redraw of an edit under 25 % in Session::whole_redraws.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf: the canvas redraws the damage since the revision it showed (#9329)

damage_since, the navigator and the histograms accept any cached revision within
DocState::damage_from..revision, not only the one before. The Move tool's
Auto-Select clause becomes the generic rule: no pixels changed since the cache.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf: P85 shows the selection for a frame before Paste Into (#9329)

Without that frame the canvas last showed the revision before select.rect,
two commands back, so it redrew everything whatever Paste Into reported.
The app always draws frames between a selection and the next command.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf: a newly added pattern no layer refers to changes no pixels (#9329)

Pattern Stamp copies its pattern into the document on first use, which made
a multi-subpath Stroke Path report the whole canvas. Appended patterns are
now pixel-equal unless a layer reference could resolve to one. The small-edit
sweep also covers layer.translate and layer.showOnly.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf: renumber the Paste Into frame row P85 -> P89 (#9329)

Main uses P83-P86 for #10259's open benchmarks. Regenerate docs/scorecard.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* style: rustfmt viewport_pages damage lookup

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Canvas: bound the pattern-reference walk; P89 undoes each paste

- `any_layer` stops at the same depth as the file's other layer walks,
  treating a deeper tree as referring to the pattern.
- The Paste Into frame row undoes each paste, untimed, and checks the
  layer stack is restored, so every sample pastes onto the same document.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Canvas: a same-named pattern a reference still resolves past is bounded

- `patterns_pixels_equal` compares where each reference resolves before
  and after the append, since `pattern::find` tries ids before names.
- P89 also undoes its selection each sample and checks the history
  length is restored; the timed frame is unchanged.
- Main's new `damage_since` callers take the `(damage_from, last_damage)` pair.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
2026-11-09 17:30:11 +01:00
437cd7f0fe fix: brush hints keep a feathered mask's ring and the effects' reach (#9329) (#10104)
* fix: brush hints keep a feathered mask's ring and the effects' reach (#9329)

A command's damage hint (the bare dab) was intersected with the edit's
own damage, which `tile_damage` had grown by the mask's feather and the
layer's and enclosing groups' effects. The intersection cut that growth
off, so painting on a feathered layer mask left a stale soft ring around
each dab, and a dab's drop shadow was outside the reported damage.

`hint_damage` now grows the hint by the same rule first (`grow_hint`,
sharing `grow_in_layer` and `effects_reach` with `tile_damage` and the
group walk). The hint is still checked against the changed tiles as is.

The group-shadow test now cuts a hole at a tile's right edge, so its
shadow crosses into the next tile (it passed without the group's growth
before), and the clip-base test gains a dab at a tile edge.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix: brush hints skip the effects of layers that aren't drawn (#9329)

`grow_hint` grew a dab by the effects of every layer in the document,
hidden ones included, so a large drop shadow on a hidden layer widened
every `paint.stroke` dab elsewhere to all the tiles `step_damage`
reported, and each dab recomposited and uploaded that much.

It now skips layers the compositor skips, by the same rule as
`effect_layers`: a hidden layer, a clipped layer over a hidden base, and
everything inside a hidden group. A change there shows nowhere, and
every drawn layer still grows the hint as before.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test: the group-shadow brush test goes through the hint (#9329)

`a_dab_inside_a_group_with_a_drop_shadow_damages_the_shadow` painted
with a plain `Session::edit`, so its damage came from `step_damage` and
never exercised `grow_hint`. It now paints with `paint.stroke`, and the
child carries a shadow of its own inside the shadowed group: the group's
shadow of the child's shadow lands past either shadow's reach alone, in
the next tile, so dropping the enclosing groups' reach from `grow_hint`
fails it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
2026-11-09 16:36:58 +01:00
Brennan StehlingandClaude Opus 5.5 8ba961c11a Engine: bounded redraw areas for adjustment, reorder and clipping changes (#9329) (#10052)
* perf: add P83/P84 redraw-area rows for a masked adjustment toggle and a reorder (#9329)

Track-only rows in the redraw area group that check they hit the path
they claim and print the refreshed pixel count: toggling a Curves masked
to <= 5 % of the canvas with >= 4 layers above it (so the GPU prefix
cache can't cover it), and bring forward / send backward of a <= 2 %
layer past an overlapping neighbour in the many-layer document.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf: bound adjustment, reorder and clipping damage through context-aware change_bounds_in (#9329)

An unclipped adjustment reaches only the layers beneath it in its isolation
scope (and, in a 32-bit document, only under its mask; integer documents
round the whole backdrop after each adjustment, #9033). Reorders damage only
the moved layers at both ends; clipping and channel-exclusion toggles on
non-group layers are bounded. ui-egui's move and blend previews use the
context-aware bounds. Every new bound is checked against a full composite.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix: keep Move preview on the context-free bound; cover a clip-base group's mode switch (#9329)

change_bounds_in is an in-place bound (the layers beneath an adjustment, or
its clip base, stay put), so the Move drag preview, which translates its
bound, goes back to the context-free change_bounds and its mask no longer
slides over layers with stale pixels. Hiding the last visible unclipped
adjustment in a pass-through group that is a clip base switches the group
between isolated and pass-through rendering, so its reach now joins the
group's bounds, as the clipped branch does. Doc fixes on change_bounds_in,
layer_change_bounds, one_sided_bounds and step_damage.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix: reorder damage rejects nested video and grows by enclosing effects (#9329)

A moved group holding a video layer was bounded by the group's extents; the
moved-layer guard now uses the same recursive `contained` check as
`one_sided_bounds`. A moved layer's old and new bounds now grow by the reach of
the enclosing groups' effects, as the paired-layer branch does, so a reorder
that changes a parent group's shape redraws its drop shadow.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Engine: adding or deleting a layer in a group grows by the group's effect reach (#9329)

A layer added to or removed from a group with a drop shadow (or any effect
with reach) changes the group's effect output past the layer's own extent.
The one-sided branch of step_damage added only the layer's bounds, so the
shadow pixels outside them went stale. Grow them by the enclosing groups'
reach, as the reorder and pixel branches already do, sharing one helper.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix: bound added, removed and moved layers within the effect reach of the canvas (#9329)

change_bounds_in clips to the canvas, so a layer just off the canvas inside a
group with a drop shadow had an empty bound, and growing it by the group's
reach kept it empty: deleting, adding back or reordering it left the shadow it
cast onto the canvas stale. The one-sided and reorder branches now clip to the
canvas grown by the enclosing groups' reach, then grow and clip to the canvas.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix: grow clipping and property changes inside a group by its effect reach (#9329)

A paired layer whose clipping or properties changed was bounded by its own
extents on the canvas, and so were the clipped layers above it; nothing grew
them by the enclosing groups' effects. Unclipping a layer in a group with a
drop shadow, or changing a child's opacity, left the shadow past the layer
stale. Those rectangles now bound within the canvas grown by the reach, then
grow and clip to the canvas, as added, removed and moved layers do.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf: renumber this PR's rows P87/P88 after #10259 took P83–P86 (#9329)

The masked adjustment toggle and the bring forward / send backward rows
were P83 and P84; main now uses P83–P86 for the JPEG/PNG open benchmarks.
Regenerate docs/scorecard.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test: drop deselects main's new adjustment layers no longer need (#9329)

Since #8801 a new adjustment layer takes the selection as its mask and
drops it, so Deselect after it has nothing to act on. Two damage tests and
the masked Curves perf row still deselected.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Engine: bound shapeless, off-canvas and frame-relayout group damage

- `composite_bounds` gives the canvas for a shapeless group, and bounds a
  group's children within the canvas grown by its effect reach, so a
  shadow cast onto the canvas by off-canvas pixels is kept.
- `beneath` includes a pass-through artboard's background.
- `layer_change_bounds` applies the enclosing groups' reach, as
  `step_damage` does.
- `step_damage` adds a group's whole extents when a child change moves
  its frame under a frame-spanning effect (Gradient Overlay).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-11-09 15:50:42 +01:00
2999174c6b Liquify: Forward Warp and Push Left follow the pointer; stationary tools use real time (#10690)
* Liquify: Forward Warp and Push Left follow the pointer; stationary tools use real time

Forward Warp and Push Left only changed the image once every dab spacing (a twentieth of
the brush radius), so a slow drag moved in jumps. The stationary tools (Twirl, Pucker,
Bloat, ...) ticked at a fixed 30 per second and stalled while the brush crept.

Points may now carry a fourth number, the milliseconds since the previous point. A segment
ending on such a live point applies the motion left over after the last dab as a
provisional dab that is taken back before the next segment, so a slow and a fast pointer
give the same warp. The stationary tools apply the larger of elapsed time and distance
travelled. The dialog records every point live and feeds every pointer position reported
in a frame. Points without times replay exactly as before.

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

* cargo fmt

* Liquify: correct two comments to describe the provisional dab

* Liquify: keep a pointer detour that returns to its start; skip the provisional dab at zero strength

* Liquify: also cover a zero stroke pressure in the live-segment test

* Liquify: test that the next live segment takes back the provisional dab

* Liquify: tighten the take-back test (repaint area, continuation with strength)

* Liquify: check that the take-back covers the area the first segment repainted

* Liquify: a dab far off the field touches no nodes instead of panicking

node_span converted a far-off centre to an index before checking the overlap: the lower index saturated to usize::MAX, read back as -1 it passed the check, and the provisional dab's snapshot then subtracted past zero (debug) or sliced out of range (release). The overlap is now decided in f64 before any conversion, NaN included. Tests: a timed stroke far off the field, on both axes and every side, for every brush tool; node_span on and off the grid.

* Liquify: a frame's batched pointer moves share its time evenly

The dialog handles a frame's queued moves one after another, and each read the clock: the first got nearly the whole frame and the rest only processing time, so a stationary tool's strength and where it landed depended on how the platform batched the moves. The frame's time since the last point is now shared evenly by its moves, as if they had arrived one per frame; after a stall the frame counts for at most MAX_LIVE_MS in all, as one point would. Tests: batched and one-per-frame moves give the same field (Freeze at 10 %, Twirl, Bloat, Forward Warp); a stalled frame's moves total MAX_LIVE_MS.

---------

Co-authored-by: terminalgate <351039321+terminalgate@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-09 15:50:20 +01:00
David Mann 8fb8d9b6ab Merge pull request #9303 from davidmann4/fix/artboard-shift-samplers
Artboards: Color Sampler points follow the document when a board re-bases the canvas (#9302)
2026-11-09 15:46:26 +01:00
David Mann 34c9662c6b Merge pull request #12421 from slafebre/fix/11798-perspective-crop-free-size
fix(engine): a free Perspective Crop takes the quad's perspective size (#11798)
2026-11-09 15:45:51 +01:00
719ce3cfda Merge main into #9798 (Cylinder warp editor)
Conflict only in docs/gaps.md's status line: both entries kept.

Co-Authored-By: TimothyBritt <TimothyBritt@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 14:36:07 +01:00
David Mann 1372bae3ea Merge pull request #9077 from ArjenS-LA/fix/average-smart-filters
Execute Average on Smart Objects and imported PSD smart filters
2026-11-09 14:23:56 +01:00
61aa24991a PR #11836: map a recorded Displace path only when a document may name it
Playback reads the map path a loaded action file names. An action set is
shared like a document, so the path now follows the same rule as paths
stored in documents: a local absolute file. A network share, device, URL
or relative path stays a kept step with its bytes, so playing a
downloaded set never opens a remote share. Test paths are now native to
the platform, so the round trips also hold on Linux and macOS.

Co-Authored-By: yoriswind <yoriswind@yahoo.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 14:04:12 +01:00
David Mann 24cd4a4098 Merge remote-tracking branch 'origin/main' into pr-11836 2026-11-09 13:52:38 +01:00
David Mann 24ad0083fe Merge main into fix/color-replacement-tolerance-field (conflict in retouch_ui.rs test modules: kept both) 2026-11-09 13:47:35 +01:00
David Mann 89b61333e5 Merge branch 'main' into fix/note-clear-all-confirm (merge queue) 2026-11-09 13:37:07 +01:00
David Mann ccac986a82 Merge pull request #12406 from slafebre/fix/11995-magic-eraser-tolerance
fix(engine): the Magic Eraser measures Tolerance by colour spread (#11995)
2026-11-09 13:18:40 +01:00
Sven Lafebre 0a8eb9d6c8 fix(algo): keep the edges when a pixel of click error swings a free Perspective Crop (#11798)
A corner moved one pixel could take a quad across the parallel-sides limit and the output from 602 x 400 to 719 x 289. The estimate now has to survive one pixel of error on every corner, with its proportions moving by no more than 10 %. Also test the commit path with W and H empty, and a known rectangle seen by a camera model.
2026-11-09 10:22:12 +01:00
FredApps d06ad73271 Naming: use RAW Develop for PhotoCraft's raw-processing feature (#12403)
Related to #5310. Display labels only; command ids (filter.cameraRaw, edit.preferences.rawDefaults), preference keys, serialized settings, PSD/action/XMP Adobe Camera Raw identifiers and .atn step names are unchanged.

- Camera Raw / Camera Raw Filter / Camera Raw Defaults -> RAW Develop / RAW Develop Filter / RAW Defaults in menus, preferences, filter names, diagnostics and all 34 catalogs.
- Saved Photoshop actions keep the "Camera Raw Filter" step name, so .atn files round-trip byte for byte (test extended).
- "Camera Raw" stays a command-search keyword.
- Removes dormant Adobe/Photoshop-branded catalog rows; display-name guard tests.
2026-11-09 08:30:33 +01:00
RickiNano 44a3c25a9e Background Eraser: a CMYK document compares against the picked inks (#12352)
Protect Foreground Color and Sampling Background Swatch converted the
foreground and background from their sRGB stand-ins, so a colour picked
as CMYK inks (100/0/0/0) came back as other inks and pixels painted with
exactly those inks were erased or missed. BgEraseSettings now carries the
picked inks, as BrushSettings::color_cmyk does, and a CMYK target compares
against them while the colour is still that sRGB colour. RGB, Gray and Lab
documents are unchanged.
2026-11-09 07:00:26 +01:00
RickiNano 66cbb2a117 Retouching tools: a Shift-click line isn't smoothed either (#11887)
The Shift-click override only reached the Brush, Pencil, Eraser and Mixer
Brush. The retouching tools take their brush from the engine
(`retouch_cmds::stroke_brush`, or `resolve_brush` for the Background Eraser
and Color Replacement), so with Catch-up on Stroke End off their lines
stopped short of the click.

- `stroke_brush` takes `smoothing` (0..100, the options bar's Smoothing).
- `canvas::unsmoothed_line` sends `smoothing: 0` for a Shift-click line in
  every retouching tool's live preview and in both commits, so a commit
  still takes the pixels its preview drew.
2026-11-09 06:56:00 +01:00
ljkx c2039dd0e8 Actions: map Image › Analysis › Set Measurement Scale › Custom (#10723)
The Set of the document's measurementScale property (T: pixelLength long,
logicalLength double, logicalUnits text) loads as
image.analysis.setMeasurementScale with the custom preset and saves back
with its recorded descriptor. Other forms stay kept steps; a native step
that reads, resets or partly sets the scale refuses export.
2026-11-09 05:43:34 +01:00
Tim BrittandClaude Fable 5.1 4f2be5f14d Address CodeRabbit review: keep a move shape-true, never clamp a stored depth, adopt a stored warp only with its preview (#9798)
A surface drag moves the cylinder without touching its shape, however narrow;
the bend handle shifts both arcs' depths by the same amount and a depth past
the limit is kept as it is rather than clamped by a press; a stored warp is
edited only when its source could be previewed without it, else the box keeps
a fresh mesh as before; the depths and wrap of a cylinder are compared with a
dimensionless tolerance; the parity row names the placements that keep a
stored cylinder editable. Also the explicit imports main now requires.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-09 04:36:43 +00:00
Tim BrittandClaude Fable 5.1 a65577d9be Warp: a smart object's stored cylinder reaches Warp mode as a cylinder (#4112)
`smart_warp_doc_space` returns a stored Cylinder warp as a cylinder, with its
seven values in document space, when the placement only scales and moves; under
any other placement it is its mesh, as before. `is_stored_cylinder` accepts both
forms, so an untouched Enter is still no history step. The axis-aligned mapping
is shared by both directions (`cylinder_through`).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-09 04:34:22 +00:00
David Mann 47a7147778 Merge remote-tracking branch 'origin/main' into pr-9827
# Conflicts:
#	contributors/people.toml
2026-11-09 02:31:16 +01:00
David Mann d2aa435077 Merge branch 'main' into fix/note-clear-all-confirm (merge queue) 2026-11-09 02:23:27 +01:00
David Mann bade1134b2 Merge branch 'main' into fix/11775-count-record-label (merge queue) 2026-11-09 01:45:17 +01:00
Sven Lafebre 3e81a3bcc4 fix(engine): a free Perspective Crop takes the quad's perspective size (#11798)
With W and H empty the output is the rectangle the quad shows in
perspective: the width is the largest horizontal scale at a corner and
the height follows from the recovered aspect ratio. Quads whose sides
are nearly parallel, that no camera at the document centre can see as a
rectangle, or whose estimate is implausible take their longest edges.
A size set in W or H behaves as before.
2026-11-09 01:24:13 +01:00
David Mann a76bb72b1f Merge pull request #10569 from hectorviov/feat/layer-copy-css
Layer › Copy CSS
2026-11-09 00:17:21 +01:00
David MannandClaude Opus 5.5 c571f81b1c Merge main into fix/11905-bg-eraser-transparency-lock
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-11-08 23:25:35 +01:00
Sven Lafebre f5821fa581 test(engine): check the partly transparent fringe is not empty (#11995) 2026-11-08 23:07:15 +01:00
Sven Lafebre 25d6041ab5 fix(algo): partly transparent colours keep the per-channel limit (#11995)
The spread was measured on opaque colours only, and the issue keeps
today's behaviour for partly transparent ones, in the match and in the
anti-alias fringe.
2026-11-08 22:53:30 +01:00
David Mann 0523777541 Merge origin/main into fix/average-smart-filters 2026-11-08 22:24:23 +01:00
David Mann 118fc0da6b Merge remote-tracking branch 'origin/main' into HEAD 2026-11-08 22:17:36 +01:00
Sven Lafebre e0ca582b97 fix(engine): the Magic Eraser measures Tolerance by colour spread (#11995)
On 8-bit RGB a pixel now matches the clicked colour when the spread of
{0, dR, dG, dB} is within the Tolerance, so opposite changes in two
channels count double and green and blue stay at Tolerance 255. The
anti-alias fringe uses the same distance. The Magic Wand, the Paint
Bucket and other modes and depths keep the per-channel limit.
2026-11-08 22:11:51 +01:00
RickiNano cf2f496660 Format the #11887 tests 2026-11-08 22:01:12 +01:00