Commit Graph

88 Commits

Author SHA1 Message Date
bflatastic 3692b9d233 M3.24: basic appearance, Layers target dots, Mixed Appearances and Clear resets opacity
An appearance is basic with at most one fill and one stroke, none hidden or
with its own opacity, blend mode or effects, and no object effects; Reduce
to Basic keeps the topmost visible fill and stroke. The Layers panel fills
an object's target circle for any non-default transparency (blend mode,
isolation, knockout or an opacity mask: Node::has_default_transparency).
A multi-selection whose objects differ shows "Mixed Appearances" with no
rows. The Appearance panel's object row and the Control bar name the
selection from one source, and type objects are "Type". Expand Appearance
is only in the Object menu. Clear Appearance also resets the object's
opacity and blend mode. Tests cover addFill/addStroke, setItem/removeItem,
clear, reduceToBasic and graphicStyle.apply.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 17:30:03 +07:00
bflatastic b6b87ee9b6 M3.23: per-item Opacity popups and one grouped blend-mode widget
Clicking an Opacity row in the Appearance panel (a fill's or stroke's, or
the object's) opens a popup with the same blend-mode dropdown, opacity
field and slider as the Transparency panel (widgets::opacity_blend), and
edits that item through transparency.set. The blend-mode dropdown draws a
separator between the BlendMode::group() groups, also for the blend-mode
parameters of effect dialogs and inline effect editors. Fills and strokes
of type objects composite with their own opacity and blend mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 17:21:28 +07:00
bflatastic 543d09985d M3.22: effects apply to the active fill or stroke and item effect rows are editable
effect.apply, effect.remove, effect.setParams and the new effect.duplicate
take item (omitted: the Appearance panel's active item, else the object;
null: the object's own effects), so the fx button, the Effect menu, Apply
Last Effect and the effect dialogs (effect.dialog {item}) put the effect on
the selected fill or stroke. effect.list reports each object's item effects
and the active item. appearance.addEffect is an alias of effect.apply.
In the Appearance panel, item effect rows sit under their fill or stroke
with working eyes and inline editors, and can be selected for Duplicate
and Delete; a selected effect row is remembered per object.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 17:15:40 +07:00
bflatastic 018bed29db M3.21: the Appearance panel's active item drives paint, stroke, gradient and transparency edits
Clicking a fill or stroke row runs appearance.setActiveItem; the toolbar,
Control bar and Properties proxies and the Color, Swatches, Gradient,
Stroke and Transparency panels show and edit that item, and the gradient
tool's annotator follows it. paint.setFill/setStroke, stroke.set/
setAdvanced, paint.editGradient/setGradientGeom and transparency.set take
item (omitted: the active item, null: the top one). Item edits and the
appearance.* commands address the selected objects' own stacks, so a
group's own fills no longer leak into its contents. Any selection change
clears the active item.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 12:28:05 +07:00
bflatastic fb8c41d8e3 Merge wp/M1: one engine loader/encoder for every frontend and export correctness (M4.12, M4.13)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:58:07 +07:00
bflatastic 115255a7e4 Merge wp/WP-00: neutral labels, packaging metadata and vendor-name CI gate (M3.7, M4.10, M4.11)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:57:34 +07:00
bflatastic 879295dd1a M4.10: shortcut-set alias test reads the legacy name from the alias table
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:56:39 +07:00
bflatastic 7b410ecf2c M3.7: proof setup looks profiles up through the alias table; alias tests read the legacy name from it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:56:39 +07:00
bflatastic 7bc50901e4 M4.13: review fixes — template sublayers are left out of raster exports too (the check moves into draw_arc), Export Selection skips art under a template layer at any depth, Export for Screens drops @Nx suffixes on SVG/PDF rows, names files without case clashes and calls an unnamed artboard Artboard-N, oversized raster exports are refused instead of writing empty files, a named MCP artboard/range replaces the option picks, and control app.export without a path returns dataBase64 instead of opening a save dialog
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:49:45 +07:00
bflatastic 5d9b97c3bd M4.10: neutral file, preference and MCP wording; vendor-name CI gate
Edit -> "PDF Presets…"; the clipboard preferences read "Legacy vector
clipboard (no transparency)" / "Legacy vector clipboard" (keys copyAicb and
aicbMode unchanged); the second keyboard shortcut set is "Classic Defaults",
and the old set name is still accepted from saved UI preferences, imported
sets and shortcuts.preset. The MCP server instructions, the apply_effect and
create_graph tool descriptions, the text.createInPath params doc,
docs/mcp.md, the ui-egui crate description and the PDF compatibility docs
no longer name another vendor.

New `cargo xtask brands` (run by `cargo xtask ci`) fails on vendor product
or company names in Rust string literals (labels, params docs, menus,
panels, MCP definitions; comments and test code skipped), Cargo.toml
descriptions and text under docs/ and packaging/; a required legacy alias
is marked `brand-ok`. xtask shares one git file listing between the asset
and brand checks. docs/development.md describes the gate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:47:28 +07:00
bflatastic dd0bb0eefb M3.7: colour tests share the settings lock
Every colour-management test reads or changes the process-wide colour
settings or proof view, so all of them now hold the file's lock; the
legacy-profile-name test switching the RGB working space could otherwise
shift a parallel RGB/CMYK round-trip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:45:32 +07:00
bflatastic 45a7302601 M4.13: export correctness and MCP export parity — document.export/serialize honour artboard, artboards or range ("1-3, 5") for PDF (one page per artboard) and return dataBase64 without a path; Export for Screens writes one page per PDF, ignores scale and @Nx suffixes for vector formats, names duplicate artboards -2/-3 and returns bytes without a folder; raster exports, thumbnails and Export Selection leave template layers out (RenderOptions.skip_templates); file.exportForScreens with params runs the engine; the MCP export tool takes artboard/range/options, lists formats from the engine and never retargets the document; CLI convert --range
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:38:23 +07:00
bflatastic 4d503c0327 M4.12: one loader and encoder for every frontend — engine fileio (load/encode/export/save, append-only FORMATS table, OPEN_EXTS, document.formats query, typed per-format options, parse_range); document.open reads native/legacy, SVG/SVGZ, PDF/.ai, .ait (opens untitled like native templates) and PNG/JPEG/GIF/WebP/TIFF/BMP; desktop, web, control channel, headless MCP and the CLI open and encode through it; open dialogs list "All readable files" plus one filter per format
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:36:51 +07:00
bflatastic 9cabeea68b M3.8: register the split paint modules next to paint so the command palette keeps listing them (Stroke Options for "stroke")
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:32:11 +07:00
bflatastic b7969a6a5d M3.8: split the paint/panel command modules and the dialogs into per-area files
No behaviour change: every command keeps its id, label, menu, shortcut and
params doc.

- Engine: swatch.* -> cmd/swatch.rs, graphicStyle.* -> cmd/style.rs,
  appearance.* (incl. copyFrom) -> cmd/appearance.rs, stroke.set/setAdvanced
  -> cmd/stroke.rs, paint.editGradient/setGradientGeom -> cmd/gradient.rs.
  Shared helpers in cmd/mod.rs: leaf_targets/paint_targets (replacing three
  copies) and unique_name (swatch and graphic style naming).
- UI: dialogs.rs -> dialogs/ with one file per dialog and a DialogSpec
  registry (one DialogKind row per dialog); shared field widgets in
  dialogs/form.rs. Headless frame tests draw and confirm every dialog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:22:23 +07:00
bflatastic 016fcbf34e M3.7: neutral paint, effect and stroke labels
The wide-gamut RGB working space is now "Wide Gamut RGB (1998 primaries)";
its old name still resolves everywhere (cms::profile / canonical_name,
Color Settings, Assign Profile, documents and settings saved earlier).
The Effect menu section is "Vector Effects", stroke width profiles are
Lens / Taper Start / Taper End, dash, arrowhead-tip and gradient-on-stroke
tooltips are reworded, the Window library submenus hold neutral disabled
placeholders until the generated libraries land, and the Swatches menu
offers "Save Swatch Library…" (disabled).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:17:50 +07:00
bflatastic d99853ed2a M4.10: neutral New Document preset name
Rename the 'iPhone' New Document preset to 'Phone 390×844'.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 11:01:59 +07:00
bflatastic b8701977d4 M4.9: Save / Don't Save / Cancel before closing modified documents — File → Close, Close All, a tab's ×, Quit and the window's close button ask once per modified document (shown first); Cancel stops the whole close/quit, a cancelled Save As keeps the document open; closing keeps per-document views aligned; agents answer the saveChanges dialog with ui.dialog.confirm (discard: true for Don't Save) 2026-10-02 22:42:50 +07:00
bflatastic 3f1f3383d3 M11.6: middle-button drag pans the view with any tool (no tool events, grabbing cursor while panning; a left press during the pan is ignored); headless canvas test 2026-10-02 22:42:50 +07:00
bflatastic cf775072be M1.10: Rotate/Reflect/Scale/Shear reference point snaps — a click or Alt-click within 5 px of an anchor or object centre (of the selection or the object under the pointer) pivots exactly there, so Alt-clicking a corner flips/rotates from that corner; hovering shows the anchor/center label first; follows View → Snap to Point or Smart Guides (snap_to_point now reaches the tools) 2026-10-02 22:42:50 +07:00
bflatastic 8276d0a303 M2.10: Live Corners — drag a live rectangle's corner widget (Selection or Direct Selection) to round or sharpen all four corners as one undo step (object.setLiveShape preview, radius readout, follows rotated/scaled shapes, square to fully round); widgets drawn from the same geometry the tools hit-test, hidden on tiny shapes and with View → Hide Corner Widget; corner-radius cursor 2026-10-02 22:42:49 +07:00
Brandon Thomas 7b37dd1da5 M7.6: tab stops and the Tabs panel — left/center/right/decimal stops (align-on character), default stops every ½ inch, text.tabs.set/get/clear, ruler (click adds, drag moves, drag off deletes), Repeat Tab / Delete Tab / Clear All Tabs; control characters no longer draw .notdef boxes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 10:13:24 -04:00
Brandon Thomas dabd179d5a M7.4: Text Wrap flows on both sides of an object (lines split into every free span, left to right, sharing the baseline; exact interval intersection across the line band)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 09:28:04 -04:00
Brandon Thomas fa2d901a7e M2.9: Shaper tool — rough rectangles, ellipses, triangles/polygons/diamonds and lines become clean live shapes (geom::recognize), squares/circles snap; a scribble deletes the objects it crosses
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 09:10:44 -04:00
Brandon Thomas 55e24d6622 M11.4: text-thread connectors on selected threaded frames + View → Hide/Show Text Threads, Hide/Show Gradient Annotator, Type → Show Hidden Characters (spaces, ¶, #), Effect → Last Effect… (reopens the last effect's dialog)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 08:51:33 -04:00
Brandon Thomas dcc5a006a2 M3.6: opacity-mask editing mode — click the mask thumbnail to edit the mask art on a temporary isolated layer with any tool; the mask updates live after every edit; the object thumbnail (or transparency.stopEditingOpacityMask) leaves the mode
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 08:40:18 -04:00
Brandon Thomas 5026dad446 M11.5: View → New View… / Edit Views… (saved views in the document, up to 25, listed at the bottom of the View menu; view.saved.* commands)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 08:16:36 -04:00
Brandon Thomas 8e735f1de9 M11.3: View → Snap to Pixel (drawing points and moved selections land on whole pixels)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 08:16:36 -04:00
Brandon Thomas 16a73dc02a M12.7: Object → Create Object Mosaic… (trace::mosaic tile averages; columns/rows, new size, spacing, gray, delete raster; follows the image transform)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 08:16:36 -04:00
Brandon Thomas 5a36fa1a9b M6.1: a panic inside the curve sweep (rare near-degenerate input) becomes PathOpsError::Degenerate instead of crashing (found by the randomized export test)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 08:16:35 -04:00
Brandon Thomas bfa46e6cb4 M9.4: raster effects in PDF export — shadows/outer glows as images under the untouched vector object, inner glow/feather/blur as images, at the document's resolution; Effect → Document Raster Effects Settings… (document.rasterEffectsSettings: screen/medium/high/ppi); engine::export_pdf used by app, CLI and MCP
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 07:58:10 -04:00
Brandon Thomas 9b0fe0ca5d M1.9: agent integrations — MCP tools add_text, apply_effect, pathfinder, transform, create_graph, text_wrap, export {selection, outlineText}; CLI convert (IN → OUT, effects kept) and info; SVG export Convert to Outlines (text as glyph paths); TextObject pathEffect key camelCase
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 07:50:20 -04:00
Brandon Thomas 1d493c7f06 M12.6: Graphs — the nine graph tools (Column, Stacked Column, Bar, Stacked Bar, Line, Area, Scatter, Pie, Radar), Object → Graph → Type… and Data… (CSV), series groups with legend, regenerate in place keeping moves/scales
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 00:16:23 -04:00
Brandon Thomas 13d0aef57f M1.5: commands that default to the current layer validate the remembered id (reused after undo it could name a compound path: Send to Current Layer moved art into it, Delete Layer could delete it)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 00:16:23 -04:00
Brandon Thomas 1e7b4308ec M0.2: hit-test distance exact on cusp-like cubics (nearest-point accuracy 1e-9; proptest regression)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 00:16:23 -04:00
Brandon Thomas c878ac994c M11.4: View → Hide/Show Corner Widget; Type → Recent Fonts (last 10 applied fonts, persisted)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:46:20 -04:00
Brandon Thomas 69be79bbf1 M4.4: File → Export Selection… (selected art cropped to its bounds as PNG/JPG/WebP/SVG/PDF), Save as Template… and New from Template… (templates open as untitled documents)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:46:20 -04:00
Brandon Thomas 3b48776607 M5.2: render perf — drop shadows/outer glows from a cached CPU-blurred raster composited per draw (600 shadows: ~300–1500 ms → 17–70 ms/frame); object blend modes on single plain fills applied per draw instead of a full-viewport layer; effect catalogue indexed once (lookups 300× faster)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:31:22 -04:00
Brandon Thomas 4745f39c6c M7.4: Object → Text Wrap (Make, Release, Text Wrap Options: offset, invert): area type flows around wrap objects above it in the same layer, re-resolved after every edit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 22:48:49 -04:00
Brandon Thomas 0ae572be93 M7.3: Type → Type on a Path effects (Rainbow, Skew, 3D Ribbon, Stair Step, Gravity): TextObject::path_effect, type.pathOptions {effect}, checked menu items
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 22:21:58 -04:00
Brandon Thomas 8434ef4404 M2.6: Flare tool ↑/↓ add or remove rays while drawing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 22:21:58 -04:00
Brandon Thomas 09fc2eedd9 M4.3: live effects survive SVG, PDF and clipboard export (vectorcraft_effects::bake_document evaluates object, per-fill/stroke and Pathfinder effects on a copy; SVG raster effects become filters: drop shadow, outer/inner glow, Gaussian blur, feather)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 21:39:20 -04:00
Brandon Thomas 1c1fd0f139 M9.3: Effect → Pathfinder (Add, Intersect, Exclude, Subtract, Minus Back, Divide, Trim, Merge, Crop, Outline) as live effects on groups/layers; rendered via the live cache, baked by Expand Appearance
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 20:57:14 -04:00
Brandon Thomas 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 Thomas 7d95f146ce M11.4: View → Trim View (artwork clipped to the artboards; RenderOptions::trim)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 20:56:45 -04:00
Brandon Thomas f5ff9317d4 M6.7: Object → Clipping Mask → Edit Contents / Edit Clipping Path (select the clipped art or the mask of the selected clip groups, also from inside one)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 20:56:22 -04:00
Brandon Thomas 7d393add4a Community links: Help menu (Discord, ArtCraft website, app page, GitHub), Discord button in the header, links on the About and Home screens; engine help.* commands return the URLs (menu clicks open them via the host's browser service)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:37:29 -04:00
Brandon Thomas 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 Thomas deb9df299c M7.7: Type → Find Font… (fonts in document with missing ones flagged, Find, Change, Change All; engine: text.fonts, text.replaceFont, select.font)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 13:16:26 -04:00
Brandon Thomas d5aa387367 M7.5: OpenType as character attributes — per-run features (ligatures, contextual alternates, discretionary ligatures, swash, small caps, ordinals, fractions, figure styles) drive shaping; OpenType panel; SVG font-feature-settings
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 12:02:13 -04:00