- A face outline segment that runs along several edge segments (the
face has no corner where a crossing line splits the edge) now joins
the face to every edge segment it runs along, not only the one under
its middle, so a double-click flood no longer stops there.
- The first click of a triple-click on selected paths, which makes the
Live Paint group, takes the fill to match from the paths' closed
subpaths only, as the group's faces do; an open path in front no
longer gives the wrong fill.
livePaint.fill's description listed "not with points" as its own entry, which
the params parser reads as a parameter name, so every_description_parses
failed. The note now sits inside the samePaint value's parentheses and says
that "connected" and "samePaint" are refused with points, as lp_fill does.
With the Live Paint Bucket, a double-click on a face fills it and every
face reached across edges that are hidden or draw no stroke; a stroked
edge, a hidden face and a Gap Detection gap stop it. On an edge, a
double-click paints the edges joined to it end to end with the same
stroke paint. A triple-click fills every face of the group with the
clicked face's fill, or paints every edge with the clicked edge's
stroke. Shift and the Paint Fills and Paint Strokes options choose a
face or an edge as for a click; Alt held paints nothing.
- livePaint.fill and livePaint.strokeEdge take scope ("one", the
default, "connected" or "samePaint") and match, the paint compared,
and reply with count. A bad scope or match is an error, and scope
with a drag's points is refused.
- Each click of a double-click or triple-click paints as it arrives,
as its own undo step. For a triple-click, and for a double-click on
an edge, the tool sends as match the paint the face or edge had
before the first of those clicks, including a first click that makes
the Live Paint group from the selected paths. A double-click on a
face sends no match.
- PointerKind::TripleClick is new: the canvas sends it on egui's
triple-click unless a modal dialog is open, as for a double-click,
and ui.pointer and pointer_gesture take "tripleclick".
Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md.
With repeated names numbered when a brush library is read, a stroke that
names a repeated brush draws the first brush of that name, and a later
brush of the name is read as "Name 2". Three tests built a library with a
repeated name and expected the later brush:
- Document Info lists a name two stored brushes share with the first
brush's type (art), not the last one's.
- The two render memory tests add their own `Dots` scatter brush beside
the default library's `Dots`. They now remove the default `Dots` first,
so the stroke draws their brush.
- The .ai writer test that leaves out a Pattern brush "X" gets the
Calligraphic brush after it back as "X 2", the name it had in the
document.
With the selection as its scope, a fix that removes or unwraps objects
(Needless Groups, Stray Points, Empty Text and the others) kept the list
of selected objects current by searching it and splicing it once for each
object it changed. Removing many selected objects above a long run of
others took time that grew with the square of their number.
The list is now rebuilt in one walk after each pass: each changed object
gives way to what replaces it, in its place, and the others keep their
order. The objects found, the counts, the document and the undo step are
the same as before.
Empty Artboards deleted each empty artboard with its own Vec::remove and
walked every ruler guide again for each one. It now drops the empty
artboards in one walk and deletes their guides in one more. The same
artboards and guides are deleted as before.
Tests cover the order after unwrapping nested and empty groups, Fix All
reaching an unwrapped member on a later round, the rebuild itself, the
number of objects looked at for 150 and 300 removals, and the number of
walks over the artboards and guides when 40 empty artboards are deleted.