Files
photocraft/crates/compose
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
..