Commit Graph
5471 Commits
Author SHA1 Message Date
NetterSilver 472cd812f9 Keep escaped backslash literal before U+XXXX in DXF MTEXT
Squashed from #4000 onto main.
2026-10-24 20:54:42 +07:00
vangel76andClaude Sonnet 5.5 e57773d45f refactor(scriptcheck): split analyze.rs, share the token filter
Move the declaration pass, the significant-token helpers and the feature
recognisers into analyze/declared.rs, sig.rs and features.rs without
changing their code, and replace the duplicated line-break and directive
dispatch of scan and declarations with LineBreaks::read.

Part of #4014

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 20:53:54 +07:00
vangel76andClaude Sonnet 5.5 4d2b628b9e refactor(scriptcheck): feature and outside ids as enums
FeatureId and OutsideId replace the string ids the analyzer passed around.
One table each gives the id, the need and the report order, so
catalog::FEATURES and catalog::need() are gone. Feature.id and the engine
JSON are unchanged; OUTSIDE is generated from the same table.

Fixes #4013

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 20:53:54 +07:00
vangel76andClaude Sonnet 5.5 f27b1e74e6 perf(scriptcheck): lex each file once, fewer copies
Work out the unescaped text and the declared names of each file once and
share them between the scans, keep included files as bytes and decode
them on demand, check the cheap tokens before unquoting in the '=' case,
and stop allocating a String per recorded chain.

Fixes #4010
Fixes #4012

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 20:53:53 +07:00
NetterSilverandClaude Haiku 5.5 41c26c6997 Keep the denominator of DXF MTEXT stacked fractions written with ^
Found while testing crates/cad/src/import/text.rs:14-27 (mtext calls escapes at :14, which treats `^2` as a caret escape and drops it; the `\S` branch at :25 expects the `^`)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 20:45:46 +07:00
dotCooCoo aaf336ba31 MCP: each alias tool names its pair, and ui_screenshot takes max_side
The server lists two names for several calls (command_list and
list_commands, command_run and run_command, doc_inspect and
inspect_document, ui_inspect and inspect_ui, ui_screenshot and
screenshot with window:true), but no description said so, and the two
listing and running pairs take different argument names. Each
description now names its pair and the argument that differs, and undo
and redo name each other.

ui_screenshot took no arguments and returned the window at its full
size, which can be several megapixels on a large display.
ui_screenshot and screenshot {window: true} now take an optional
max_side (1..4096) that scales the returned image down to that many
pixels on its longer side. The reply's text gives the returned size as
width/height and the capture's as capturedWidth/capturedHeight; a file
written to path keeps the full capture. max_side on an artboard render
is an error that points to scale. render_preview reads its max_side
through the same check.

docs/mcp.md describes the pairs and the new argument.
2026-10-24 20:39:55 +07:00
Angelo BernardiniandClaude Fable 5.1 9a4d97c022 G11: Shape Builder's edge-source index is a grid, so diagonal hatches are no longer quadratic
The planar map's `RectIndex` sorted rectangles narrow in x by their left
edge and those narrow in y by their top edge, and scanned the rest for
every lookup. A long diagonal segment is narrow in neither, so a hatch of
diagonals put every line in the scanned list and `Outlines::source_at`
(one lookup per edge) cost a scan of the hatch per edge: quadratic in the
hatch below the 65,536-segment cap, as CodeRabbit found on #3357.

`RectIndex` is now a grid of about one cell per item, each cell listing
the items touching it; a lookup reads the cells around the point. An item
is filed under a footprint of rectangles: its bounds (`new`), or, for a
segment, the bounds of its pieces about a cell long (`with_footprint`,
`segment_footprint`), so a diagonal is filed under the cells along it,
not under every cell its bounds cover. A footprint rectangle covering
more than 64 cells or two rows/columns (a face covering most of the art)
is scanned for every point as before; a thin stripe face is filed under
its column of cells. Cells hold `u32` indices.

Tests: `rect_index_reads_a_diagonal_hatch_only_near_the_point` (2,000
diagonals a tenth of a point apart: a lookup got 1,001 candidates with
the old index, now at most n/4, and still every line through the point;
a hatch of stripe faces is filed, not scanned; a collinear, degenerate
grid). `rect_index_finds_every_rectangle_holding_a_point` keeps the
bounds-only contract.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014gCpjL3yUhaH3jRp7ksufh
2026-10-24 20:39:53 +07:00
BFlat ad7cb44a6f Merge pull request #4018 from vangel76/test/scriptcheck-case-tables
test(scriptcheck): table the held-value tests
2026-10-24 20:39:10 +07:00
BFlat 499d205e08 Merge pull request #4016 from dotCooCoo/fix/undo-group-follows-new-documents
Undo groups: an open undo group also groups the edits in a document opened or created before its end
2026-10-24 20:38:35 +07:00
vangel76andClaude Sonnet 5.5 bdd26580fc test(scriptcheck): table the held-value tests
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 20:31:55 +07:00
BFlat c56e6e6db1 Merge pull request #3996 from lehni/update/text-stroke-cache
Renderer: character strokes are expanded once, not every frame
2026-10-24 20:23:37 +07:00
dotCooCoo 6cd57cfa1b Undo groups: an open undo group also groups the edits in a document opened or created before its end
A document opened or created between edit.undoGroup.begin and
edit.undoGroup.end opens an undo group of its own with the begun
group's name, so an atomic command_batch that starts with file.new or
document.open is one undo step in the new document. The group opens
after the command that opens the document: when that command also
edits it (a command.batch), those edits stay the command's own undo
step, and a canceled group keeps them, so the journal still replays.
Both commands also run with no document open, and a command.batch that
fails rolls back a begun group. Switching to a document that was
already open does not open a group in it.
2026-10-24 20:10:04 +07:00
BFlat 8dc4f7ec6b Merge pull request #4009 from dotCooCoo/fix/mcp-docs-start-installed-app
MCP docs: start an installed app with the control port
2026-10-24 20:08:34 +07:00
BFlat 293dbcd534 Merge pull request #4008 from dotCooCoo/fix/trace-two-pixel-bar
Image Trace: Flat Logo finds a bar two pixels wide in its own color
2026-10-24 20:08:17 +07:00
Jürg Lehni 0776323e27 Renderer: character strokes are expanded once, not every frame
The outlines of a run's character stroke are kept with the glyph geometry the renderer keeps for the type, in a byte-limited cache swept by frame, so type that changes in every frame (an animation) frees them within a few frames.
2026-10-24 20:04:10 +07:00
dotCooCoo eb4c5e7bf8 MCP docs: start an installed app with the control port
The installed-release section of docs/mcp.md said how to register the
server but not how to start an installed app for a live session; the
only start command in the setup steps was the cargo run from a
checkout.

It now gives the command that starts the installed app with
--control 7979 on macOS, Windows and Linux, and says that the
launchers open no control port, that the flagless server checks for
the app once when it starts, and what --connect prints when no app
is listening.
2026-10-24 19:58:11 +07:00
dotCooCoo 465ddfded9 Image Trace: Flat Logo finds a bar two pixels wide in its own color
When Flat Logo finds the colors itself (no colors named), a flat bar
two pixels wide (whole pixels of one color) on a ground beside other
art was lost or traced in another color. No bar pixel has a uniform
3 x 3 neighborhood, so neither the first clustering nor the check for
unexplained colors took it. A gray bar on white beside black art was
traced as white, and a red or green bar was traced as black. Bars
three pixels wide or more were already found.

The check for unexplained colors now also takes the pixels of such a
bar: two rows or columns of one color (within about 3.5 in RGB
distance), three pixels long, with the same ground on both sides. They
count when the known colors do not explain them, and also when their
color lies less than two thirds as far from the ground's known color
as from every other known color, where the bar would otherwise be
traced as the ground. A gray bar darker than about #9B9B9B on white
beside black art stays black, #808080 included, because a black stroke
1 to 1.6 px wide on the pixel grid gives the same pixels. Named colors
are unchanged.
2026-10-24 19:52:18 +07:00
BFlat 8f3cbca390 Merge pull request #3671 from pat26-dotcom/fix/3621-function-shading
Fix #3621: function-based PDF shadings keep their colours instead of a flat grey
2026-10-24 19:51:22 +07:00
BFlat ce9db1a15c Merge pull request #4006 from Taha-Mahmoodi/docs/catch-up-2026-10
Docs: G11, G2 and parity tables drop missing items that shipped (Effect Gallery, Relative rounding, Hard/Soft Mix, #834, #937, #722)
2026-10-24 19:51:07 +07:00
BFlat b07c43b058 Merge pull request #4005 from Silvertree2010/fix/h2002-source-date-epoch-accepts-a-lead
Reject a leading plus sign in SOURCE_DATE_EPOCH
2026-10-24 19:50:51 +07:00
BFlat ce400ac615 Merge pull request #4003 from dotCooCoo/fix/trace-outline-without-area
Image Trace: Flat Logo leaves out a traced outline that has no area
2026-10-24 19:50:36 +07:00
Patrick LenzenandClaude Opus 5.5 504b549a78 Fix #3621: bound function-based shading reads per import
Review follow-up. A function-based shading is read once per import (kept
per shading pattern and inks), and all of them draw on one budget of
200,000 function evaluations; past it a shading comes in as its average
colour, then flat grey, each with a warning that names the cause. A
gradient read leaves enough of the budget to average another shading.

A colour that changes in step with the sampling grid is checked across
the middle of the domain before an axis is chosen, so it isn't read
along the wrong one. The grey fallback warning for other shadings names
only them.

Tests: the same shading on 2,000 paths is read once; 40 distinct
shadings stay within the budget; a hostile file (5,000 fills, 20
shadings with 500-step functions) opens in 0.8 s, 253 s before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 19:27:44 +07:00
Patrick LenzenandClaude Opus 5.5 095d2bd2fd Fix #3621: function-based PDF shadings keep their colours
PDF import turned every function-based shading (ShadingType 1) into a
flat mid-grey. Chromium writes a CSS repeating-linear-gradient this way,
so a red and white hatch came in as a grey bar.

A function-based shading whose colour changes along one axis of its
domain only now becomes a linear gradient across the domain: stops
sampled along that axis, each hard colour change (found by halving the
interval between two samples) two stops at one offset. One whose colour
changes in two directions comes in as its average colour, with a
warning. Either paints only over the shading's domain.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 19:27:44 +07:00
Taha-Mahmoodi 95436e7212 Docs: G11, G2 and parity tables drop missing items that shipped (Effect Gallery, Relative rounding, Hard/Soft Mix, #834, #937, #722) 2026-10-24 19:21:32 +07:00
NetterSilverandClaude Haiku 5.5 34e17ff13b Reject a leading plus sign in SOURCE_DATE_EPOCH
Found while testing crates/doc/src/metadata.rs:108 (stamp_from_env)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 19:21:31 +07:00
dotCooCoo 6010dae0f0 Image Trace: Flat Logo leaves out a traced outline that has no area
The fit of a thin outline can lose all its area. Its two sides can
straighten onto one line, which leaves two anchors whose segments run
back and forth along it. Or the fit can be a single cubic, which becomes
one anchor and has no segment. Both occur when Flat Logo traces noise
whose cells are one pixel in size. The trace kept such an outline as a
selectable path that paints nothing.

Flat Logo now leaves out an outline whose area is below 1e-6 px^2,
together with its holes, and a hole whose area is below 1e-6 px^2. The
area is summed about the outline's first anchor, as the other trace
modes already do for a filled loop (crates/trace/src/lib.rs:996-1001).
Outlines with an area of 1e-6 px^2 or more, thin slivers included, are
kept as before.

One test traces a black and cream noise with both colors named exactly
and checks that no subpath of the result lacks an area. Two more build
shapes from straight cubics: a hole without area is left out, and an
outline without area is left out with its hole.
2026-10-24 19:15:08 +07:00
BFlat 21a648d850 Merge pull request #3999 from dotCooCoo/fix/flat-logo-near-colors-full-size
Image Trace: Flat Logo traces named colors a few levels off at the image's own size
2026-10-24 19:07:39 +07:00
BFlat e8215ea878 Merge pull request #3944 from dotCooCoo/fix/flat-logo-traced-size-warning
Image Trace: Flat Logo says when it traces a large image at a reduced size
2026-10-24 19:07:22 +07:00
BFlat b00381408d Merge pull request #3950 from Taha-Mahmoodi/feat/properties-contextual-controls
Properties: Blend Options, Merge Live Paint, Width Profile, an effect's Delete icon and Direct-Selected corners
2026-10-24 19:07:05 +07:00
BFlat ab717530ed Merge pull request #3993 from dotCooCoo/fix/save-errors-name-save-command
Save: option errors name the save command that was run
2026-10-24 19:06:48 +07:00
BFlat d842e2f323 Merge pull request #3998 from dotCooCoo/fix/mcp-docs-duplicate-tool-rows
MCP docs: export and add_text each have one row
2026-10-24 19:06:33 +07:00
BFlat 9a41215d25 Merge pull request #3991 from Silvertree2010/fix/h1955-logo-trace-palette-hex-parser-ac
Reject plus signs in logo palette hex parser
2026-10-24 19:06:18 +07:00
BFlat 574a707e47 Merge pull request #3986 from Silvertree2010/fix/h1951-dxf-text-u-xxxx-escape-accepts-a
Require four hex digits in DXF text \U+XXXX escape
2026-10-24 19:06:02 +07:00
BFlat f709c0ff3b Merge pull request #3960 from dotCooCoo/feat/paragraph-numbered-lists
Type: the Numbered List button numbers paragraphs 1, 2, 3
2026-10-24 19:05:45 +07:00
BFlat 5ff9412ece Merge pull request #3997 from dotCooCoo/fix/native-pretty-save-size
Native format: a document is saved pretty-printed only when its pretty-printed JSON is at most 1 MiB
2026-10-24 19:05:28 +07:00
BFlat 6e194f5431 Merge pull request #3989 from dotCooCoo/feat/image-trace-hold-source
Image Trace: pressing and holding the eye button shows the source image
2026-10-24 19:05:06 +07:00
BFlat 7c5bcc43c4 Merge pull request #3988 from dotCooCoo/fix/pdf-line-break-hyphen-as-text
PDF export: the hyphen that ends a hyphenated line is written as text
2026-10-24 19:04:39 +07:00
BFlat badac3fcc8 Merge pull request #3969 from dotCooCoo/fix/save-file-waits-for-app-save
MCP: save_file against the running app waits for the save and reports its result
2026-10-24 19:04:17 +07:00
BFlat 70b93f5aa2 Merge pull request #3984 from dotCooCoo/feat/pencil-straight-line-cursor
Pencil: the pointer shows a straight-line cursor while Shift or Alt is held before a press
2026-10-24 19:04:01 +07:00
dotCooCoo 76c014b732 Image Trace: Flat Logo traces named colors a few levels off at the image's own size
Squashed from #3999 onto main.
2026-10-24 19:02:09 +07:00
dotCooCoo d0644e5eb9 Image Trace: docs say Flat Logo averages down the decoded raster
An image over 64 megapixels is decoded at a smaller size first, and Flat
Logo averages that raster down in whole-number blocks.
2026-10-24 19:02:09 +07:00
Taha-MahmoodiandClaude Opus 5.5 ff5919f416 Live Paint: Make and Merge refuse type, images and other objects that aren't paths
Live Paint builds its faces and edges from path outlines alone. Make,
Merge and the Live Paint Bucket put every selected object among the
group's hidden sources, so type, an image, a symbol, a blend or a group
holding one of them vanished from the canvas. They now refuse such a
selection before changing anything ("Live Paint takes paths and compound
paths: convert type, images and other objects to paths first"), as type
and raster images can't go into a Live Paint group directly
(https://helpx.adobe.com/illustrator/desktop/paint-and-fill/learn-painting-basics/create-live-paint-groups.html).
One predicate, vectorcraft_tools::builder::live_paint_takes (Live Paint
groups, paths, compound paths and groups of them), decides it for Make,
Merge and the Properties panel's Merge Live Paint, which no longer shows
for a selection Merge refuses. The message has an @msg row in every
catalog.

Tests: tests_build::live_paint_refuses_type_and_images_and_changes_nothing
(Merge, Make and the Bucket with type, an image or a group holding type:
refused, document, selection and undo history unchanged; a group of
paths and a path still merge) and
panels::properties::tests::merge_live_paint_is_a_quick_action_for_a_live_paint_group_and_more
(hidden with type selected). Both fail without the change.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-24 19:02:09 +07:00
dotCooCoo d2de74e12a Save: option errors name the save command that was run
A save (document.save, file.saveAs, file.saveCopy) passes its options to
the export encoders, so an option an encoder refused was reported under
document.export: file.saveCopy with format pdf and range "5" on a
document of three artboards, or with format ai and compress "yes", or
document.save to a .vectorcraft path with compress "yes", failed with
"invalid parameters for `document.export`". The error now names the
save command that was run, for PDF, SVG, .ai, .ait and native files.
document.export's own errors are unchanged.
2026-10-24 19:02:09 +07:00
dotCooCoo b0e88bddf9 MCP docs: export and add_text each have one row
The tool table in docs/mcp.md listed export and add_text twice. The first
export row omitted the ai format, the per-artboard files of SVG, SVGZ and
EPS, options.useArtboards and options.rect, and said that every format but
PDF writes one artboard. The second add_text row omitted vertical.

Each tool now has one row: export keeps the complete row, and add_text
keeps the row with vertical.
2026-10-24 19:02:09 +07:00
NetterSilverandClaude Haiku 5.5 5068dfc73f Reject plus signs in logo palette hex parser
Found while testing crates/trace/src/logo/palette.rs:9-15 (parse_hex)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 19:02:09 +07:00
NetterSilverandClaude Haiku 5.5 2a4aafe346 Require four hex digits in DXF text \U+XXXX escape
Found while testing crates/cad/src/import/text.rs:73-74 (escapes)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 19:02:09 +07:00
dotCooCoo 68e4392491 Image Trace: Flat Logo says when it traces a large image at a reduced size
Flat Logo traces a copy of the image at most 1024 pixels on a side,
averaged down by a whole factor, so a 1025-pixel image is traced at
513 pixels. The trace's warnings did not say so, because they compared
the image only with the decoded raster. For an image over 1500 pixels
they said instead that it is traced more slowly, which Flat Logo does
not do.

The trace result now carries Flat Logo's working size when it averaged
the image down. imageTrace.make and imageTrace.makeAndExpand then name
both sizes in their warnings, and the status bar shows that note, in
place of the slower-trace and megapixel notes. Other modes keep their
warnings. The message has a row in each catalog that translates the
other Image Trace warnings.
2026-10-24 19:02:09 +07:00
Taha-MahmoodiandClaude Opus 5.5 aa35783f47 G1: Properties: Blend Options, Merge Live Paint, Width Profile, an effect's Delete icon and Direct-Selected corners
The Properties panel has the additional contextual controls the public
Properties panel overview lists
(https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/properties-panel-overview.html),
each running the existing command:

- Quick Actions: Blend Options for one selected blend while the Blend
  tool is in use (the Blend Options dialog; OK is one undo step), and
  Merge Live Paint when a Live Paint group is selected with more objects
  (livePaint.merge).
- Appearance: the stroke's Variable Width Profile list (the Control
  bar's) with the Width tool or when the stroke has a variable width
  (stroke.set {profile}); beside fx, with one effect on the one selected
  object (its own, or a fill's or stroke's), its name and a Delete icon
  that removes it (effect.remove); with several, the icon opens the
  Appearance panel, as the overview describes.
- With Direct Selection and corners of one path selected, Corner and
  Corner Radius set those corners' kind and radius
  (object.setLiveShape); a live rectangle's and polygon's own rows
  already do, so they get no second row.

The overview's Variable Font icon was already in Character. Every label
is already in every catalog.

Tests in panels::properties::tests:
blend_options_is_a_quick_action_for_one_blend_with_the_blend_tool,
merge_live_paint_is_a_quick_action_for_a_live_paint_group_and_more,
the_width_profile_shows_for_a_variable_width_or_the_width_tool,
direct_selected_corners_show_their_kind_and_radius,
one_effect_has_a_delete_icon_in_appearance (shown for the right
selection and tool, hidden otherwise, the right command in one undo
step). Documented in docs/target-app-parity.md, docs/ui-parity.md and
docs/gaps.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-24 19:02:09 +07:00
dotCooCoo bc041e15ef Type: the Numbered List button numbers paragraphs 1, 2, 3
Squashed from #3960 onto main.
2026-10-24 19:02:08 +07:00
dotCooCoo 0635357eb9 Native format: a document is saved pretty-printed only when its pretty-printed JSON is at most 1 MiB
A native save was pretty-printed when the document had at most 2,000
layers and objects and its compact JSON was at most 1 MiB. Pretty
printing puts every coordinate on its own indented line, so traced art
with few paths and many anchors could pass that check and be written at
about five times the size of its compact JSON.

The 1 MiB limit now applies to the pretty-printed document, indented as
the file holds it and in the form the save writes: version 1 anchors,
and placed documents expanded for older versions or Include Linked
Files. Documents whose pretty-printed JSON is over 1 MiB are saved as
compact JSON, even when their compact JSON is under it. The 2,000-object
rule and compressed saves are unchanged. docs/mcp.md describes the rule.
2026-10-24 19:02:08 +07:00