Commit Graph

1731 Commits

Author SHA1 Message Date
BFlat d23973de4f
Merge pull request #1046 from storytold/fix/1008-polar-zero-radial
#1008: a polar grid with no radial dividers draws none
2026-10-11 04:08:11 +07:00
BFlat bd55d66072
Merge pull request #1044 from storytold/fix/1007-gradient-reverse-midpoint
#1007: Reverse Gradient mirrors off-centre midpoints
2026-10-11 04:07:54 +07:00
BFlat 9ea05d5d45
Merge pull request #1043 from storytold/fix/1006-active-artboard-select
#1006: Select > All on Active Artboard selects on the active artboard
2026-10-11 04:07:37 +07:00
BFlat b5d25c1102
Merge pull request #1042 from storytold/fix/1005-run-broken-pipe
#1005: vectorcraft-cli run ends quietly when its reader closes early
2026-10-11 04:07:14 +07:00
BFlat c11b516d34
Merge pull request #1041 from storytold/fix/1004-connected-artboard-shot
#1004: a connected app's screenshot renders the artboard asked for
2026-10-11 04:06:52 +07:00
BFlat 2bfb0887d8
Merge pull request #1040 from storytold/fix/1003-path-text-color
#1003: MCP add_text colours type made on or in a path
2026-10-11 04:06:29 +07:00
BFlat b2800fb529
Merge pull request #1039 from storytold/fix/1002-noneditable-layer
#1002: new art is refused when no layer is shown and unlocked
2026-10-11 04:06:12 +07:00
BFlat 1b761c68c1
Merge pull request #1038 from storytold/fix/1001-style-attrs
#1001: named text styles take leading, kerning, mojikumi and other attributes left out at their defaults
2026-10-11 04:05:50 +07:00
bflatastic fd52ca32c7 #1008: a polar grid with no radial dividers draws none
shapes::polar_grid drew at least one radial divider (`radial.max(1)`), so radial 0, which
the command and the Polar Grid tool (Left arrow while dragging) accept, still drew a spoke.

Zero now draws none; the loop never divides by it.

The test checks 0, 1 and 2 radial dividers with no concentric ones give 1, 2 and 3 paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	ROADMAP.md
2026-10-11 03:51:35 +07:00
bflatastic 0497c9e46d #1007: Reverse Gradient mirrors off-centre midpoints
Reversal read the midpoints after Gradient::reverse had reordered the stops, so each stop
took the wrong segment's midpoint: red-to-blue with its midpoint at 20% reversed to a 50%
midpoint instead of 80%, moving the transition.

Gradient::reverse now mirrors each segment's midpoint with it, so a reversed gradient is the
same ramp the other way round; paint.editGradient's own (wrong) pass is gone, and the SVG
importer's reflect spread, which had a correct copy of the same mirroring, uses it too.

Tests: two- and three-stop gradients with off-centre midpoints sample the same reversed (t vs
1 - t) and come back after two reversals; paint.editGradient reverse turns a 0.2 midpoint into
0.8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	ROADMAP.md
2026-10-11 03:51:31 +07:00
bflatastic cacc9e4f36 #1006: Select > All on Active Artboard selects on the active artboard
The menu item sends no artboard, so the engine fell back to the first one even with another
active in the Artboards panel.

The frontend fills in the active artboard (the view's, as the Artboards panel and navigator
show it) for select.allOnArtboard, as it already did for Paste in Place / in Front / in Back
(#693); the two now share one block, and the index is kept within the artboards. An explicit
artboard still wins; the engine is unchanged.

The test makes artboard 2 active, then 1, and invokes the menu item each time, then passes
artboard 1 explicitly with artboard 1 active.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	ROADMAP.md
2026-10-11 03:51:27 +07:00
bflatastic 33b6a6323d #1005: vectorcraft-cli run ends quietly when its reader closes early
`run` reported "Broken pipe" (on Windows "The pipe is being closed") and exited 1 when the
reader of its stdout went away, unlike `commands` and the other subcommands, which end quietly.

Its step printer now treats a closed pipe as the end of output, not an error: the remaining
steps still run (an export is still written), unprinted, and the run exits 0. Other write
errors and failing steps still fail.

The test runs document.json, a rectangle and an SVG export with stdout closed: status 0, empty
stderr, the SVG written; `run --cmd not-a-command` still fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	ROADMAP.md
2026-10-11 03:51:23 +07:00
bflatastic 148ef1870a #1004: a connected app's screenshot renders the artboard asked for
The desktop app's ui.render (MCP `screenshot` when connected) always rendered the first
artboard and ignored `artboard`, which the headless backend honours.

It now renders the 0-based `artboard` (the first without one, an error for one that doesn't
exist), as headless does. control-protocol.md and the control.rs list show the parameter.

The test drives ui.render through the control channel on a 64 x 64 and a 96 x 48 artboard:
no index and 0 give 64 x 64, 1 gives 96 x 48 (48 x 24 at scale 0.5), 2 is an error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	ROADMAP.md
2026-10-11 03:51:19 +07:00
bflatastic 7f17d980d4 #1003: MCP add_text colours type made on or in a path
add_text passed `color` to text.create only, and text.createInPath built its own character
style without a colour, so type on a path and path-based area type took the current fill.

text.createInPath now uses the same new-type style as text.create (size, font, style, color,
else the current fill), and add_text sends `color` on both routes.

The MCP test draws a blue rectangle (the current fill), turns it into on-path and area type
with color #ff0000, and reads red back through inspect_document.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	ROADMAP.md
2026-10-11 03:51:15 +07:00
bflatastic eeb213e5a8 #1002: new art is refused when no layer is shown and unlocked
With every layer hidden or locked, the insertion layer fell back to the top layer anyway, so
drawing a shape, typing, pasting, making a graph, a flare, a grid, trim marks or a symbol put
the art on a hidden or locked layer: invisible, or unselectable by Select All. Illustrator
refuses to draw on a locked or hidden target layer (public forum answers, e.g.
https://community.adobe.com/t5/illustrator/can-t-draw-a-new-object-in-my-document/m-p/11107182).

DocState::target_parent is insertion_parent for new art, failing with "the target layer is
locked or hidden" when it would be a layer that isn't editable; those creation paths use it.
Another layer that is shown and unlocked still takes the art, as before. The message is in the
de, es, fr, it, ja, ru and uk catalogs. File > Place is left as it is (another branch reworks
it).

The test hides, then locks, the only layer: an ellipse, a polar grid, text and a paste each
fail with the message and leave the document unchanged; a new layer then takes a rectangle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	ROADMAP.md
2026-10-11 03:51:11 +07:00
bflatastic e77d15c70d #1001: named text styles take leading, kerning, mojikumi and other attributes left out at their defaults
Character and paragraph styles checked a new attribute against the keys its base style
serializes, and the JSON leaves out Auto leading and kerning, no mojikumi and other defaults.
So charStyle.new / setAttrs refused leading or kerning, paraStyle.new refused mojikumi, and a
style captured from text with explicit leading failed to apply to Auto-leading text, to
duplicate or to come back out of a library.

The check now also accepts every field name the style type deserializes (read from serde's
derive), still refusing unknown keys and the file-only justify_auto.

The test creates and edits styles with kerning, leading, small caps, mojikumi and direction,
applies a captured leading style to fresh text with and without Clear Overrides, duplicates it,
uses it from a library, and checks `nope` and `justify_auto` are still refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	ROADMAP.md
2026-10-11 03:51:06 +07:00
BFlat 3416bf49cd
Merge pull request #1037 from storytold/fix/983-supersampled-export
#983: supersample Art Optimized edges in exports
2026-10-11 03:48:46 +07:00
bflatastic 178f99d60e #983: supersample Art Optimized edges in exports
Asset Export, File › Export, Save for Web and Object › Rasterize drew
each shape with its own smoothed edge, so where two shapes met edge to
edge (Divide, Shape Builder, abutting art) both half-covered the pixels
on the line and the background showed through as a thin ghost border.

With Art Optimized (the default) these now supersample, as the option's
name in Illustrator says: the art is drawn with hard edges at four times
the size (three or two times for large images, within a 40-megapixel
budget and the renderer's 65,535-pixel side) and each block averaged
into one pixel. Pixels shared by two shapes are fully owned by one or
the other at the finer size, so no seam is left, and the outer edges
are still smooth. The canvas keeps shape-by-shape smoothing for speed;
None and Type Optimized are unchanged.

RenderOptions::supersample turns it on (exports and Rasterize set it).
A render test checks two triangles sharing a diagonal: a seam with
shape-by-shape smoothing, none supersampled, and the factor's limits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 03:48:03 +07:00
BFlat c403e57d2a
Merge pull request #1013 from Ni-zav/fix/991-shift-stepper-s20261010T1758Z-a74b
fix(widgets): apply Shift and Ctrl modifiers to numeric stepper buttons
2026-10-11 03:45:43 +07:00
BFlat e606c56064
Merge pull request #1012 from Ni-zav/fix/1000-object-mosaic-input-s20261010T1758Z-a74b
fix(dialogs): preserve integer counts in command parameter fields
2026-10-11 03:45:27 +07:00
BFlat d15bc61818
Merge pull request #988 from Ni-zav/fix/noissue-crop-box-option-s20261010T1630Z-c8d2e1
fix(crop): reject malformed crop rectangles without shifting coordinates
2026-10-11 03:45:10 +07:00
BFlat 428894df22
Merge pull request #999 from Ni-zav/fix/noissue-distort-geometry-validation-s20261010T1654Z-8d74ec
fix(distort): reject malformed warp geometry and explicit targets
2026-10-11 03:44:54 +07:00
BFlat 0cb1beaf21
Merge pull request #998 from Ni-zav/fix/noissue-path-anchor-validation-s20261010T1654Z-8d74ec
Fix/noissue path anchor validation s20261010 t1654 z 8d74ec
2026-10-11 03:44:37 +07:00
BFlat c05ad3985c
Merge pull request #997 from Ni-zav/fix/noissue-anchor-selection-input-s20261010T1654Z-8d74ec
fix(selection): reject malformed anchor references without changing selection
2026-10-11 03:44:20 +07:00
BFlat 05bb1ac97f
Merge pull request #996 from Ni-zav/fix/noissue-assets-explicit-targets-s20261010T1654Z-8d74ec
fix(assets): reject invalid object IDs before collecting export assets
2026-10-11 03:44:04 +07:00
BFlat 7915bfc0e1
Merge pull request #987 from Ni-zav/fix/noissue-stroke-input-atomic-s20261010T1630Z-c8d2e1
fix(stroke): reject invalid dash entries and keep defaults atomic
2026-10-11 03:43:47 +07:00
BFlat 219b9da346
Merge pull request #986 from Ni-zav/fix/noissue-rect-cut-input-s20261010T1630Z-c8d2e1
fix(cut): reject malformed rectangle cut bounds
2026-10-11 03:43:30 +07:00
BFlat 683f6439ca
Merge pull request #985 from Ni-zav/fix/noissue-place-coordinates-s20261010T1630Z-c8d2e1
fix(place): reject malformed rectangle and position parameters
2026-10-11 03:43:14 +07:00
BFlat 67a0ffca4d
Merge pull request #984 from Ni-zav/fix/noissue-paint-proxy-atomic-s20261010T1630Z-c8d2e1
fix(paint): preserve fill and stroke defaults when edits fail
2026-10-11 03:42:57 +07:00
bflatastic e0d494b2eb ROADMAP: the validation batch, Object Mosaic counts and stepper modifiers
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:24:31 +07:00
bflatastic 9e09d53fd9 Review #1013: the stepper test from #1015 compiles and hits the spinner
The headless test taken from #1015 set `RawInput::modifiers`, which egui
0.36 doesn't have, and clicked left of the spinner (the right-aligned
label's text ends before its box). Modifiers now come as
`ModifiersChanged` events, as the Appearance panel tests send them, and
the click is placed from the field's text. It also checks Ctrl/Cmd steps
a tenth. It fails with the spinner ignoring modifiers (15 pt for 24).
rustfmt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:14:00 +07:00
Nigel Ihza Firdausy 6d5fdc8a2a test(ui): Shift-click on the Stroke weight stepper steps 10 pt (#991)
The headless panel test of #1015, kept on top of #1013's fix (#1015's
own change to the spinner is superseded by it).
2026-10-11 02:06:41 +07:00
Nigel Ihza Firdausy 057c2ee2c1 fix(widgets): honor Shift on numeric spinner buttons (#991) 2026-10-11 02:06:20 +07:00
bflatastic 5a9c6e2e06 Review #1012: whole numbers typed in command dialogs are integers
The PR kept a field's integer kind only while its value had been an
integer: typing 2.5 in Columns and then 3 sent 3.0, and the mosaic fell
back to 10 × 10 again. A whole number typed in any command dialog is now
an integer (`typed_number`) whatever the field held before; commands
that take any number read integers as well, and a fraction stays one.

Test: Object › Create Object Mosaic… opened from its menu item, 3 typed
over Columns and Enter makes a 3 × 10 mosaic (it made 10 × 10 before,
#1000).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 02:06:19 +07:00
Nigel Ihza Firdausy 130bacde12 fix(dialogs): preserve integral command parameters in numeric fields (#1000) 2026-10-11 01:59:54 +07:00
bflatastic 311d75fc97 Review #988: rustfmt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:58:43 +07:00
Nigel Ihza Firdausy c845c7f9e0 fix(crop): reject malformed crop rectangles without shifting coordinates 2026-10-11 01:58:31 +07:00
bflatastic 2ff5688511 Review #999: corners and from through finite_numbers; rustfmt
Same checks in a third of the code; the corners destructure into the
four points instead of being indexed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:51:12 +07:00
Nigel Ihza Firdausy 0d697ed79d fix(distort): validate the full corner quad, source bounds and targets 2026-10-11 01:50:31 +07:00
bflatastic 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
bflatastic 93cadc8994 Review #997: one anchor-reference parser, for Reshape area type too
`text.reshapeArea` read its anchors with the lenient `parse_refs`, so a
malformed reference among good ones moved only the good ones. It now
uses `checked_refs` as well, and `parse_refs` (no other user) goes.
Test: a mixed list fails without moving anything.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:48:17 +07:00
Nigel Ihza Firdausy 2f984f2e7a fix(selection): reject malformed anchor references before selection changes 2026-10-11 01:47:03 +07:00
bflatastic 2f458842ae Review #996: rustfmt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:46:59 +07:00
Nigel Ihza Firdausy 3b742b6c0c fix(assets): validate all explicit export object ids before collecting 2026-10-11 01:46:24 +07:00
bflatastic de17a00eb2 Review #987: test the next-object stroke with nothing selected; rustfmt
A rejected Stroke panel edit with nothing selected leaves the next
object's stroke as it was; an accepted one sets its weight and dashes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:46:22 +07:00
Nigel Ihza Firdausy 059bd82676 fix(stroke): reject malformed dashes and keep defaults atomic 2026-10-11 01:45:19 +07:00
bflatastic 6eeabcd742 Review #986: the rect through finite_numbers; rustfmt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 01:45:18 +07:00
Nigel Ihza Firdausy bfbe9e1eb6 fix(cut): reject malformed rectangle cut bounds 2026-10-11 01:44:43 +07:00