Fix #122: Mirror & Cut, Line Cut and Rectangle Cut tools

The issue asked for one-step symmetric shapes, splitting all selected art
along a line and cropping art to a rectangle as real geometry. Only the
freehand Knife and the Scissors existed, and neither works on compound
paths as one shape.

New commands path.mirrorCut, path.lineCut and path.rectCut cut the
selected paths and compound paths (inside groups too) with pathops
booleans against a half-plane or rectangle, and split open paths with
the Knife/Path Eraser helpers. Mirror & Cut reflects the kept half and
unites it with itself (open halves are joined on the axis). The draw2
piece helpers now rebuild compound paths too. Three tools (Eraser group,
original icons) preview the cut live while dragging and commit it as one
undo step; Mirror & Cut's axis and kept side are tool options shown in
the Control bar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bflatastic
2026-10-06 00:42:26 +07:00
co-authored by Claude Opus 5.5
parent 1c46c4c654
commit a844503e4c
20 changed files with 1101 additions and 12 deletions
+7
View File
@@ -429,3 +429,10 @@ macOS, Ctrl elsewhere), and the app holds them for the frames the input spans, a
press, its `text` and its release; a click's press and release; a drag from the press through every move to the
release. Every handler sees them (Shift+arrow nudges by the big increment, Alt+arrow nudges a copy, Shift-clicking a
Layers selection square adds to the selection); the keyboard's own modifiers apply again afterwards.
Cutting tools: Mirror & Cut (`mirrorCut`), Line Cut (`lineCut`) and Rectangle Cut (`rectCut`) cut the selected paths
and compound paths. `ui.tool.select` one, then drag with `ui.pointer`: the cut previews live and the release keeps it
as one undo step (`ui.key` Escape cancels). They run `path.mirrorCut`, `path.lineCut` and `path.rectCut`, which an
agent can call directly. Mirror & Cut's tool options (`tool.setOption`, shown in the Control bar) are `axis`
(`free` | `vertical` | `horizontal`; a constrained axis follows the pointer and a click places it) and `keep`
(`left` | `right` | `top` | `bottom`); Alt on release keeps the other side.