Every click and hover measured each path and compound path along its
curves to cull it (Node::reach_bounds_with), and a compound path was
then assembled whole to test its outline and fill. For a compound path
of thousands of members that took milliseconds per click.
Hit testing now culls paths and compound paths by the box of their
control points (which holds the curves), grown by their strokes' reach,
so the box is never smaller than the reach box it replaces. A compound
path's outline and fill are tested against only the members whose
control box, grown by the tolerance, holds the point: a member outside
that box is farther than the tolerance and winds zero times round the
point. Painted strokes still follow the whole compound path (alignment,
dashes, width profiles) and are measured along all of it, as before.
Tests (crates/doc/src/hit/tests.rs):
- a 2,000-member compound path hits exactly as the whole-path test did,
at random points, on and next to anchors and on the edges of the
members' boxes, for both fill rules, in Outline view and with Object
Selection by Path Only;
- wide strokes painting past the control points are still hit, for a
path and a compound path;
- the cull box holds the reach box for paths and compound paths.
Measured in a debug test build (one run, machine not idle): a click on
a 20,000-member compound path went from about 18 ms to about 1 ms.
vectorcraft-cli perf was not rerun.
The check of a selected object's masked art looked at its own place
only. A click goes down from the layer (or the isolated container) and
never reaches a Shaper group's original shapes outside Construction
mode, however deep the object lies in them; and below a layer whose
Preview is off it hits art in outline. A press inside such a path's
fill, or on a path in a Shaper group's hidden shapes, started a move.
The way down to the selected object is now checked as a click goes:
a Shaper group's part a click can't reach on it rules the object out,
and a Preview-off layer on it (below the isolated container) makes the
object count by its outline.
Tests also cover Shift with Direct and Group Selection (a marquee) and
an object a click hits over the masked art (it is selected).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EjfPR4a1jPek7r3nyFFNYv
The selected object itself was checked for being hidden, locked or a
template, but not as a click checks it: a selected guide path was
grabbed where a mask hid it while guides were locked or hidden, though
a click on it there hits nothing.
The selected object now passes the same test a click applies to it
before its art is tried: guides while guides are locked or hidden, and
a Shaper group's hidden part, don't count.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EjfPR4a1jPek7r3nyFFNYv
A selected group was grabbed by any of its contents under the pointer
where an outer mask hides them, including a hidden or locked child and
art the group's own clipping mask leaves out: none of these is drawn or
hit by a click.
A container's art now counts as a click would hit it: its contents as
the hit test tries them, through its own mask and without its hidden,
locked or template contents. The check for locked objects shares it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EjfPR4a1jPek7r3nyFFNYv
An image in a clipping mask, picked in the Layers panel, shows its
whole frame, but a press on the part the mask hides hit nothing: the
Selection, Direct Selection and Group Selection tools started a marquee
there, which dropped the selection, so the image could be dragged only
by the part that shows.
Such a press now grabs the selection by that art, as a press on its
visible part does: a drag moves the selected object (the image, not its
clip group) and a click keeps it selected. With nothing of it selected
there, or with Shift, a press there starts a marquee as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EjfPR4a1jPek7r3nyFFNYv