Commit Graph
17 Commits
Author SHA1 Message Date
Brian TorresandClaude Opus 5.5 7c80b286c7 Fix #2540: Object → Expand expands Intertwine groups
Expand had nothing for Intertwine groups. It reported success but left
the group live (it only dropped the members' live shapes), and its
Stroke and Fill options could not reach the members, so a second Expand
found nothing to do. Ungroup takes apart plain groups only, so it did
nothing either.

Expand's Object option now turns every Intertwine group in the selection
(inside groups too, inner ones first) into a plain group of what it
draws: its objects, keeping their ids and order, then each part drawn
over the others as a clip group. The group keeps its id, place,
transparency and appearance, everything happens in one undo step, and
the dialog enables Object for an Intertwine group. Ungroup then takes
the result apart, as with an expanded blend or repeat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:20:23 +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
arhammusheer 5beac4f122 #1244: smaller objects: Node 352 -> 152 bytes, NodeKind 200 -> 80, and a cheaper undo estimate
Rarely set fields move into one optional boxed NodeExtras, and large NodeKind payloads (images,
live shapes, blends, envelopes) are boxed. Every object, and every undo step that copies it,
shrinks: a 50k-path move keeps ~24.5 MB per step instead of ~40 MB. Files stay byte-identical
(Node keeps its flat JSON through a borrowed Serialize and a from-wire Deserialize, no flatten),
and loading is slightly faster. Undo and redo reuse their step's size estimate instead of
walking the document again (8.3 -> 5.6 ms for a 50k-path move).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VmMmc1J8XeNLxhRihWv9cc

# Conflicts:
#	crates/engine/src/cmd/graph.rs
#	crates/svg/src/export.rs
2026-10-12 11:02:32 +07:00
bflatasticandClaude Opus 5.5 d3c997329d #1111: a blend's spine bends into a curve
The Anchor Point tool drags any segment of a selected blend's spine into
a curve, straight ones too, and Direct Selection reshapes a curved spine
segment as it does a path's (a straight one it leaves, as on paths). Both
run the new `object.blend.spine.reshapeSegment`, which bends the segment
with the same math as `path.reshapeSegment`, now shared as
`SubPath::bend_segment`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 17:49:41 +07:00
bflatasticandClaude Opus 5.5 695c541f0d M8.17: Edit envelopes on the canvas: Edit Contents, mesh points and handles, Control bar
- Edit Contents: while an envelope's contents are edited, clicks hit the
  content where it sits undistorted and the Selection tool selects it; the
  menu item reads Edit Envelope then. No default shortcut: the reference
  app's (Shift+Cmd+V) is Paste in Place here.
- A selected envelope shows its mesh (a warp's surface grid, a mesh's own,
  a top object's outline) instead of its content's outlines.
- Mesh envelope points get bezier handles (append-only; none stored is the
  smooth Catmull-Rom mesh, which the first handle edit fills in exactly
  along the grid lines). setMeshPoint takes `handle`; object.mesh.movePoint,
  addLine and deletePoint edit mesh envelopes too. The Mesh tool and Direct
  Selection drag points and the clicked point's handles (shared MeshEdit);
  the Mesh tool adds rows and columns inside mesh envelopes. Reset with
  Mesh keeps the shape along the grid with handles; Release returns the
  exact mesh.
- Control bar: Edit Envelope / Edit Contents, warp style, orientation,
  bend and distortions or mesh rows and columns, Reset, Envelope Options.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:16:59 +07:00
bflatasticandClaude Opus 5.5 04fa49413c M8.16: Envelopes bend images, symbols, gradients, patterns and appearance; warps keep their frame
- Images distort as a raster mesh warp: cut by Fidelity into triangles,
  each a clipped image under the affine map of its corners (pieces overlap
  slightly, no seams; the renderer paints them without clip layers; SVG
  writes the pixels once and <use>s them).
- Symbol instances distort as their symbol's art (the renderer's cache
  follows edits to the symbol).
- Distort Appearance bakes strokes (filled outlines) and geometry effects
  before bending; Distort Linear Gradients bends linear gradients; Distort
  Pattern Fills bends the tiles. Opacity masks of the content bend too.
- Bug fix: a rotated, sheared or reflected warp envelope re-warped along
  the page axes. Envelopes now keep their own frame (append-only model
  field), so the warp turns with the art; move and scale keep it square.
- Live evaluation shares one set of hooks (vectorcraft_doc::live::Hooks,
  vectorcraft_effects::{expand_live, expanded_live_group,
  expand_live_deep}) between the canvas, Expand and every exporter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:01:47 +07:00
bflatasticandClaude Opus 5.5 98a3e15ec3 M8.20: blends interpolate strokes, gradients, groups, type and symbols faithfully
Closed shapes start where they twist least (unless the Blend tool
picked the anchors); dashes, miter limit, arrowhead scale and width
profiles interpolate (caps, joins and brushes switch halfway);
gradients with different stop counts resample to common stops; groups
with different member counts grow the extra members out of a point;
compound steps stay compound paths; type, symbol instances and images
interpolate their transforms, type its colours and sizes run by run.
New blends are knockout groups and the canvas draws them knocked out
as the exports do. Expand and Release keep the blend's name,
transparency, opacity mask and appearance, and Object > Expand expands
blends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 12:01:28 +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
bflatasticandClaude Opus 5.5 c5985b3f47 M8.18: Blend Options dialog and the Blend tool's anchor targeting
Blend Options is a dedicated dialog (Spacing dropdown with its value,
Align to Page / Align to Path buttons, live preview) opened on the
selected blend's own options, so OK no longer turns Smooth Color into
5 steps; with nothing selected it sets what new blends start with
(object.blend.info reads them). The Blend tool blends from clicked
anchor points (blend spec `starts`), adds keys to an existing blend
instead of nesting it, opens Blend Options on double-click, Alt-click
and its toolbar button, and has its own cursors and hint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 11:01:18 +07:00
bflatasticandClaude Opus 5.5 42be928367 M8.16: Enveloped type exports distorted, run by run, everywhere
Every exporter (SVG, PDF, EPS, EMF/WMF, DXF) evaluated live objects with no
text outliner, so type inside an envelope was written undistorted. They now
share vectorcraft_effects::expand_live_deep, which outlines type per run in
each run's paint, as the canvas now does too (it used the first run's paint
for the whole line).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 10:27:08 +07:00
bflatasticandClaude Opus 5.5 fe6d6640fb M8.15: Envelope dialogs, Reset with Warp/Mesh, full Envelope Options
Make with Warp and Make with Mesh open dedicated dialogs (style dropdown,
orientation, bend and distortion sliders; rows and columns) with live
preview; while an envelope is selected the menu shows Reset with Warp /
Reset with Mesh instead, which switch the envelope's kind and keep its
content (Maintain Envelope Shape samples the current surface). Envelope
Options is a full dialog prefilled from the selection (Anti-Alias,
Preserve Shape, Fidelity, Distort Appearance, Distort Linear Gradients,
Distort Pattern Fills); with nothing selected it sets the defaults for new
envelopes. object.envelope.info reads the settings. Release returns the
warp or mesh shape as a gradient mesh and keeps opacity, blend mode and
mask; Expand keeps name, knockout, isolation and mask; Object > Expand
expands envelopes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 10:11:10 +07:00
bflatasticandClaude Opus 5.5 d3d6cce917 Fix #34: Ctrl/Cmd+Shift+V pastes in place
Paste in Place is Cmd+Shift+V, but egui reports every Cmd+V chord as a
Paste event (or, for what isn't text, only the key's release), never as
the key, and the handler ran Paste for every Paste event. A paste now runs
the paste command whose V chord is held (Paste in Place, Paste on All
Artboards, Paste without Formatting; user overrides included), Paste for
the Paste key and Shift+Insert. Envelope Distort > Edit Contents also had
Cmd+Shift+V; it loses the duplicate, and a test checks that no two
commands, tools or panels share a default shortcut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:49:20 +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 705976fd96 M3.84: Object > Expand dialog; gradient fills expand to a mesh or N objects
Object > Expand… opens a purpose-built dialog (Object, Fill and Stroke
checkboxes, disabled when the selection has nothing for them; Expand
Gradient To: Gradient Mesh or Specify N Objects, default 255). Every
option now does something:
- Object: type to outlines, live shapes to paths, effects baked.
- Stroke: strokes outlined into filled paths.
- Fill: linear/radial gradient fills become N solid rectangles or
  concentric ellipses, or a gradient mesh with lines where the colour
  changes, inside a clip group shaped like the object; freeform
  gradients become a mesh shaped like the object. Colours keep their
  stops' colour model. With Fill off gradient fills stay live.
object.expand {} defaults match the dialog (stroke now defaults on);
new query object.expand.info and UI command ui.expandDialog.
Create Gradient Mesh on a gradient-filled object takes the colours the
gradient paints at each point (GradientMesh::for_path_with, from_grid,
highlight).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 03:25:33 +07: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 f8136f1e35 Live Blends/Envelopes/Gradient Mesh, Shape Builder, Live Paint, Image Trace (drawcraft-trace), Recolor Artwork, Export for Screens, Actions panel, prefs persistence, real layer thumbnails; menus bound
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 11:02:16 -04:00