Commit Graph
22 Commits
Author SHA1 Message Date
sanyamsingh001andCodex 67f9d134ed G11: Preserve gaps when deleting open-path anchors
Keep surviving drawable runs separate when Delete or Backspace removes an open-path anchor. Preserve appearance, selection and one-step Undo.

Co-authored-by: Codex <noreply@openai.com>
2026-10-16 04:44:58 +07:00
Murat Vural 1ab3940b3d feat: move and copy ruler guides and art together when selected 2026-10-16 04:19:06 +07:00
turtwig 89501d73c2 Delete removes every selected anchor and keeps the remainder selected
A fully selected object is deleted along with partial anchors on other
paths. Several anchors on one closed path are removed by their original
indexes. What remains of a path stays selected, so a second Delete
removes it.
2026-10-14 03:55:40 +07:00
bflatastic 0a16b62a22 Fix #1533: Join merges the selected anchors that lie on one another (after Average) into one 2026-10-13 08:51:34 +07:00
dotCooCoo 88bd4812e0 Part of #1429: path, Pathfinder and live-object commands add and remove many objects in one pass
Offset Path, Outline Stroke, the Pathfinder panel, Clean Up, Make
Blend, Rasterize and the other commands that #1429's table marks 3,
except Split Into Grid, added, removed or replaced their objects one at
a time, and so did Remove Anchor Points, Redefine Symbol and the
removal of Shaper groups whose source art is gone. Each insertion or
removal moved the later objects of the layer or group. The lookups by
id that followed walked the tree, and every fourth walk rebuilt the
lookup cache. On 25,000 rectangles a release build of vectorcraft-cli
took 29.1 s for Offset Path.

These commands now make their edits with Document::wrap,
Document::insert_beside and Document::remove_many, in one pass over the
children of each layer or group, and Outline Stroke and Expand write
each new object into the place of the object it replaces. A list that
holds an object twice, or an object and another inside it, and that was
edited without an error before, is still edited one object at a time.
The documents, selections and undo steps are the same. On the same
rectangles Offset Path now takes 1.3 s.

Docs: docs/target-app-parity.md.
2026-10-13 05:21:31 +07:00
bflatastic 3acc29f8e0 Fix #1442: an unknown parameter key is an error naming it and the nearest accepted key 2026-10-13 02:54:33 +07:00
bflatastic a41d59604b Fix #1408: the Transform tools and commands act on the anchors selected with Direct Selection 2026-10-12 21:01:15 +07:00
dotCooCoo ae061eacfb Part of #394: art moved whole with direct-selected anchors follows Transform Pattern Tiles
With anchors of one path direct-selected and another object selected
whole, the arrow keys (object.nudge), path.moveAnchors and a Direct
Selection drag of the selected anchors moved that object without its
pattern tiles, whatever General › Transform Pattern Tiles was set to.
When the same object was selected on its own, the arrow keys and a
Direct Selection drag followed the preference. path.moveAnchors left
the tiles in place in that case too.

path.moveAnchors now follows the preference for the objects it moves
whole, as the transforms, Align and Distribute do. path.moveAnchors
and object.nudge also take a `patterns` param for one call. When those
objects use a pattern, the journal records the choice, and a recorded
action plays back with it. Partly selected paths still move only their
selected anchors.

Docs: docs/mcp.md (transformPatternTiles), docs/target-app-parity.md.
2026-10-12 14:50:00 +07:00
Ikki Nishihara 1ac797685f fix(selection): 線分の選択と削除をアンカーから分ける (#1278) 2026-10-12 07:25:36 +07:00
bflatastic 06d3e52c24 #1180: Align aligns the selected anchor points
With anchor points selected by Direct Selection, the Align buttons moved
the whole path, so two points couldn't be lined up. As in Illustrator,
they now align the selected points: to the points' own bounds (Align To
Selection) or to the artboard. A path selected whole still aligns as an
object.
2026-10-11 22:08:01 +07:00
bflatasticandClaude Opus 5.5 57050b0987 Review #998: one strict anchor parser; build fix for path.appendAnchor
The PR added `checked_anchor_from_json` next to the lenient
`anchor_from_json` and dropped path.rs's import of the latter, which
`path.appendAnchor` still called, so the engine didn't compile.
`anchor_from_json` is now the strict parser itself (handles through
`finite_numbers`), used by path.create, path.setAnchors and
path.appendAnchor alike: the Pen's appended anchor with a malformed
handle fails too instead of losing the handle. Tests: a non-boolean
`closed` and a malformed appended handle change nothing. rustfmt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:50:30 +07:00
Nigel Ihza Firdausy 743fe2521e fix(path): remove unused legacy anchor parser import 2026-10-11 01:49:22 +07:00
Nigel Ihza Firdausy 6bf2a42e22 fix(path): reject malformed anchors before creating or replacing geometry 2026-10-11 01:49:22 +07:00
bflatasticandClaude Opus 5.5 bd8fa795ed Fix #776: the Pen continues any open path and joins two paths
As in Illustrator, the Pen shows its continue cursor over an end of any
open path, selected or not, and a click there selects the path and draws
on from that end (reversing it from its first end). While drawing, it
shows a join cursor over an end of another open path, and a click joins
the two into one path, in one undo step, which finishes the path.

path.join takes {ids: [a, b], ends: ["first"|"last", "first"|"last"]}
to join the ends asked for (the Pen's join); without them it joins the
selected paths' nearest ends as before. Joining a path with itself, or
anything that isn't a path, is an error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 23:59:50 +07:00
bflatasticandClaude Opus 5.5 253249717b Pen and anchors: Alt edits one handle, cut and convert selected anchors from the Control bar
Discord feedback: Alt with the Pen didn't move a direction handle on its own, and there was no
way to break a path at an anchor and pull the ends apart.

- Pen: Alt held over a handle end or an anchor of a selected path (the one being drawn too) hands
  the gesture to the Anchor Point tool, with the convert cursor: dragging a handle moves it alone,
  clicking a smooth anchor makes it a corner, dragging an anchor pulls out symmetric handles.
  Drawing goes on afterwards. Handles hidden by a partial anchor selection aren't grabbed.
- path.cutAtAnchors cuts at the direct-selected anchors in one undo step: a closed path opens
  there, an open one becomes one path per piece, and one anchor of each cut stays selected so a
  drag pulls the path apart. It answers {ids} and refuses (no undo step) when only open ends are
  selected. path.convertAnchors checks `to`, skips stale anchor refs instead of indexing past
  them, and keeps a smooth anchor's handles when converting to smooth.
- SubPath::cut_at and SubPath::smooth_anchor (geom) now back path.split, path.cutAtAnchors,
  path.convertAnchor and path.convertAnchors, replacing three copies of that logic.
- Control bar and Properties panel: "Convert:" corner/smooth and "Anchors:" remove, connect
  (Join), cut buttons when anchors are selected; Cut Path on the task bar and the context menu.
  New original icon dc-anchor-smooth.svg (ASSETS.md row).
- ja, zh-hans, zh-hant and es strings (cs for the context menu item), es @msg rows; docs/mcp.md
  section; ROADMAP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 17:16:12 +07:00
bflatasticandClaude Opus 5.5 d5a060a009 Path: Remove Anchor Points is Object › Path's one item and shares the Delete Anchor Point refit (review of #241)
- Parity: Object › Path › Remove Anchor Points now runs the new command (`path.removeAnchors`,
  the menu's feature name) instead of `path.deleteAnchors`, which deleted the anchors with their
  segments and opened closed paths; that stays the Delete key's command ("Delete Anchor Points",
  off the menu). No second "Smart" item.
- Geometry: the refit moves to `vectorcraft_pathops::remove_anchor` on the existing least-squares
  fitter (fixed end tangents, a golden-section search for where the curve passes the removed
  point) instead of a ~1,000-candidate grid search in geom (about 4 ms per anchor, now well under
  0.1 ms). Two straight sides stay one straight side (a rectangle loses a corner and becomes a
  triangle), as Illustrator does; non-finite input leaves the handles alone.
- The Delete Anchor Point tool (`path.removeAnchor`) uses the same function, replacing its
  heuristic handle stretch; the explicit id/anchor and `fit` params of the new command are dropped
  as duplicates of it. The command is enabled by direct-selected anchors (`has_anchors`), not a
  UI override.
- The Control bar shows an icon button (the Delete Anchor Point icon, tooltip "Remove Anchor
  Points") instead of a 204 pt text button; the labels reuse the translated "Remove Anchor
  Points"; zh-hant gains "Delete Anchor Points". The Pen test that pinned Alt-click as plain Pen
  (Illustrator's Alt over an anchor is Convert Anchor Point) is dropped.
- Tests for the refit, closed paths, straight sides and bad input; docs/mcp.md and ROADMAP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 03:27:07 +07:00
bflatasticandClaude Opus 5.5 3d35b8518f M8.19: blend spine and keys editable on the canvas
A selected blend shows its spine. Direct Selection drags spine points
and handles, the Pen tool adds and deletes points on a selected
blend's spine (object.blend.spine.moveAnchor/addAnchor/removeAnchor).
The straight spine becomes a path on the first edit, its points pinned
to the key objects (append-only BlendSpec.key_anchors): moving a key
moves its end of the spine and the other way round; spines from older
files and Replace Spine still spread the keys evenly. Direct and Group
Selection pick blend keys on the canvas, edits redraw the blend live,
and Release leaves the spine as a path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 11:12:58 +07:00
Brandon ThomasandClaude Opus 5.5 3e323bfa2a Robustness: VectorCraft never crashes — no panics in shipped code
Shipped code no longer unwraps, expects or panics: every one of the 124
unwrap()/expect()/panic!/unreachable! sites outside tests now handles the
failure (Result/Option, ?, let-else, defaults) and reports errors to the user.

- Lints: workspace clippy denies unwrap_used, expect_used, panic, todo,
  unimplemented and unreachable; clippy.toml allows them in tests, and
  integration tests, examples and testkit opt out explicitly.
- Safety net (vectorcraft_engine::guard): a panic in a top-level command rolls
  the document back and returns EngineError::Internal; a panicking tool is
  reset; the MCP server answers with an internal error and keeps serving; the
  UI frame and each control request are guarded.
- APIs that hid failures now return them: Rendered::to_png/to_jpeg/to_webp
  return Result (JPEG/WebP errors used to write empty files),
  FontDb::face returns Option, Region::top returns Option.
- Fuzzing: engine/tests/import_fuzz.rs feeds garbage, hostile and mutated SVG
  and PDF through import → render → export (30k cases locally, no panics).
- Docs: AGENTS.md/CLAUDE.md rule, docs/development.md "Robustness" section,
  README pointer and a PR template checklist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 06:28:59 +07:00
bflatasticandClaude Opus 5.5 4591c85845 M3.76: Attributes panel with overprint, centre point, path direction, fill rule, image map, URL and note
Window > Attributes (Cmd+F11) shows Overprint Fill/Stroke, Show/Don't Show
Center, Reverse Path Direction Off/On, the non-zero / even-odd fill rule,
Image Map, a URL field with recent URLs and a Browser button, and a note.
New commands attributes.set and path.setFillRule; path.reverse takes ids and
reversed; attributes.info reports every value. Objects keep the attributes in
Node.attrs. SVG export wraps linked objects in <a>, and import reads links
back. The canvas draws the centre point of selected objects that show it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 03:46:04 +07:00
Brandon ThomasandClaude Opus 5.5 71d43421f5 M2.6: Flare tool (centre drag, then click for the rings; click → Flare Tool Options; shape.flare builds centre/halo/rays/rings from radial gradients in Screen mode) and Reshape tool (path.reshape: grab a point of a selected path, neighbourhood follows with a smooth falloff)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 20:57:02 -04:00
Brandon ThomasandClaude Opus 5.5 4878f1c5dd Rename DrawCraft → VectorCraft: crates (vectorcraft-*), apps, binaries, types, env vars, docs, examples (.vectorcraft); old .drawcraft files and preferences still load. Fix: text bounds exact after opening a file; selection no longer marks a document modified (dirty = content differs from the saved document). Screenshots and renders regenerated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:30:09 -04:00
Brandon ThomasandClaude Opus 5.5 bfee80a22c M0: workspace skeleton — geom, color, doc, render, text, pathops, svg, tools, engine
Engine-first Cargo workspace for DrawCraft (clean-room Illustrator):
- geom: anchor-based path model, shapes, hit testing, snapping
- color: colours, paints, gradients, swatches, blend modes, harmonies
- doc: persistent Arc document tree, appearance stacks, text model, selection
- render: vello_cpu renderer (appearance, gradients, clip groups, blend modes)
- text: font DB, harfrust shaping, point/area/path layout
- pathops: curve booleans (linesweeper), Pathfinder, offset, simplify
- svg: import (usvg) and export
- tools: selection/direct/pen/shape tools emitting commands
- engine: Session, history with interactions, ~110 commands

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 05:53:29 -04:00