mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-15 14:49:18 +00:00
Merge main into fix/blend-reversed-key-stroke-direction
This commit is contained in:
+138
-33
@@ -1,6 +1,6 @@
|
||||
# VectorCraft MCP server
|
||||
|
||||
> **Last updated:** 2026-11-13 · **Change:** Snap to Point with Smart Guides off draws no Smart Guides labels or lines, #7250; no response-shape change. Previously: Envelopes: a top object's side whose pieces are all one curve split at anchors follows that curve's parameter (#7097); existing response shapes retained.
|
||||
> **Last updated:** 2026-11-14 · **Change:** Pencil continuation, straight-line and closing cursors; scores and estimates unchanged; no response-shape change. Previously: Snap to Point with Smart Guides off draws no Smart Guides labels or lines, #7250; no response-shape change. Previously: Envelopes: a top object's side whose pieces are all one curve split at anchors follows that curve's parameter (#7097); existing response shapes retained.
|
||||
|
||||
`vectorcraft-cli mcp` runs a [Model Context Protocol](https://modelcontextprotocol.io) server on stdio
|
||||
(newline-delimited JSON-RPC 2.0; see [Protocol](#protocol) for version negotiation). Agents use it to
|
||||
@@ -667,7 +667,7 @@ sampler.
|
||||
| `transform` | `{ids?, dx?, dy?, rotate?, scale?, scaleX?, scaleY?, reflect?, shear?, origin?, copy?}` | Runs move, rotate, scale, reflect, shear in that order. `rotate` is in degrees counter-clockwise; a positive `shear` moves the top to the right. With `copy`, the first step duplicates. |
|
||||
| `create_graph` | `{type?, x, y, width, height, csv? \| series?, categories?, rows?}` | The nine Illustrator graph types: column, stacked column, bar, stacked bar, line, area, scatter, pie and radar. An empty CSV cell or a `null` in `rows` is a blank value; a number in straight quotes is a label. Edit later with `graph.setData` / `graph.setType` via `run_command`. `graph.column {design, columnType: vertical\|uniform\|repeating\|sliding, each, fractions: chop\|scale}` draws the columns or bars of the series picked with Group Selection (or `seriesIndexes`, or all of them) with a graph design saved by `graph.design`; with no `design` it returns the series' current design and options. Type in the design that holds a `%` followed by two digits shows each column's value, with at least the first digit's places before the decimal point and the second digit's places after it. |
|
||||
| `text_wrap` | `{ids?, offset?, invert?, release?}` | Area type below the objects (same layer) flows around them. |
|
||||
| `undo` / `redo` | `{}` | Many calls that change nothing record no undo step, for example `object.align` with nothing to move, `object.move` by 0 without `copy` and `object.showAll` with nothing hidden. `undo` (`edit.undo`) after such a call undoes the step before it. `inspect_document` lists the undo steps as `history`. `run_command` with `edit.clearHistory` removes every undo and redo step of the active document and returns `{cleared}`, the number of steps removed; the document stays as it is, and the command records no undo step. `run_command` with `edit.newDocumentFromState` and `{index?, created?}` makes a new document holding the art as it was at that state and makes it the active document, and returns `{index, title}`. `index` is a row of the History panel, with 0 the oldest state kept, and an omitted `index` uses the current state. An `index` that names no state is an error and changes nothing. `created` is File Info's created date in Unix seconds or null, and defaults to now. The new document takes the next `Untitled-N` name, is marked unsaved, has nothing selected and has no steps to undo or redo. It is out of symbol, opacity-mask and pattern editing, and the art drawn in a pattern's tile is stored in the pattern, as `object.pattern.done` stores it. The source document and its steps stay as they are, except that typing or a drag in progress is first kept as a step. When a command keeps a drag whose preview Real-time Drawing off had not applied yet (`edit.undo`, `edit.redo`, `edit.clearHistory`, `edit.newDocumentFromState` and the other commands that end a drag first), and applying that preview gives a warning, the command's result carries it as `previewWarning`, and as `warning` too when the command gives no warning of its own; the app's status bar shows `warning`. While the Type tool edits type, `undo` and `redo` put its caret, with no characters selected, at the end of the text the step changed: after the text it puts back or retypes, or where the text it takes out was. A step that changes no characters, such as a formatting change, leaves the caret and the selection where they are. |
|
||||
| `undo` / `redo` | `{}` | Many calls that change nothing record no undo step, for example `object.align` with nothing to move, `object.move` by 0 without `copy` and `object.showAll` with nothing hidden. `undo` (`edit.undo`) after such a call undoes the step before it. `inspect_document` lists the undo steps as `history`. `run_command` with `edit.clearHistory` removes every undo and redo step of the active document and returns `{cleared}`, the number of steps removed; the document stays as it is, and the command records no undo step. `run_command` with `edit.newDocumentFromState` and `{index?, created?}` makes a new document holding the art as it was at that state and makes it the active document, and returns `{index, title}`. `index` is a row of the History panel, with 0 the oldest state kept, and an omitted or null `index` uses the current state. An `index` that names no state fails with `no history state N`, one that is not a whole number with `` `index` must be a whole number ``, and either changes nothing. `created` is File Info's created date in Unix seconds or null, and defaults to now. The new document takes the next `Untitled-N` name, is marked unsaved, has nothing selected and has no steps to undo or redo. It is out of symbol, opacity-mask and pattern editing, and the art drawn in a pattern's tile is stored in the pattern, as `object.pattern.done` stores it. The source document and its steps stay as they are, except that typing or a drag in progress is first kept as a step. When a command keeps a drag whose preview Real-time Drawing off had not applied yet (`edit.undo`, `edit.redo`, `edit.clearHistory`, `edit.newDocumentFromState` and the other commands that end a drag first), and applying that preview gives a warning, the command's result carries it as `previewWarning`, and as `warning` too when the command gives no warning of its own; the app's status bar shows `warning`. While the Type tool edits type, `undo` and `redo` put its caret, with no characters selected, at the end of the text the step changed: after the text it puts back or retypes, or where the text it takes out was. A step that changes no characters, such as a formatting change, leaves the caret and the selection where they are. |
|
||||
|
||||
For example, create editable Japanese area type with the engine's vertical writing mode:
|
||||
|
||||
@@ -856,7 +856,8 @@ stored without its placement (its vector, aspect ratio, focal point and freeform
|
||||
own box when the graph is drawn again, so `paint.setGradientGeom` and the `paint.freeform.*` edits do not store the
|
||||
placement they set there. A stroke weight and dashes are stored as the label shows them, also on a label that was
|
||||
scaled. When the characters of labels of one kind change differently, the frontmost label sets what the kind keeps. On
|
||||
a pie with Legends in Wedges whose legend labels have no fill of their own, the legend labels' fill is stored only when
|
||||
a pie with Legends in Wedges, a fill a command sets on the legend labels is drawn on every wedge, black included, until
|
||||
that command is undone; a size, font or stroke change does not set one. Before that, their fill is stored only when
|
||||
every legend label the command reaches ends up with the same fill. Otherwise they are drawn again in black, or white on
|
||||
a dark wedge. These commands do not store the colors they give a graph's axis lines, ticks and radar rings, which are
|
||||
drawn again with their default paint.
|
||||
@@ -1085,7 +1086,15 @@ or `range`), named `<file>-<artboard>.<ext>`, and returns `{path, files}` (a PDF
|
||||
SVG writes one file per artboard of a `range`); `useArtboards: false` exports the bounds of the visible art with what
|
||||
its effects paint, the effects of groups, type and images included. `artboard.fitToArt` measures the art the same
|
||||
way. `document.exportPdf {useArtboards: false}` writes that one page as well, and ignores `artboard`, `artboards` and
|
||||
`range`. A PDF of that page, from either command, carries no Preserve Editing data; when Preserve Editing is on (as it
|
||||
`range`. A PDF or `.ai` page of the art's bounds is measured without the non-printing layers that the file leaves out
|
||||
(unless `includeNonPrinting` or `createLayers` keeps them; a `.ai` file keeps layers by default). An HP-GL plot of the
|
||||
art's bounds is measured without what the plot leaves out: non-printing layers, objects at 0% opacity, placed images,
|
||||
gradient meshes whose every point is at 0% opacity, and paths without effects whose fills and strokes paint nothing.
|
||||
An image or a mesh with a Crop Marks effect, or with a Vector Halftone effect that makes dots, is measured.
|
||||
Such objects in the art of a symbol that is not dynamic are left out of its instances too, and an instance whose
|
||||
symbol holds nothing else is left out.
|
||||
A document whose only visible art is left out is refused, and Export As refuses an HP-GL plot of it before the save
|
||||
dialog. A PDF of that page, from either command, carries no Preserve Editing data; when Preserve Editing is on (as it
|
||||
is in VectorCraft Default), the export comes back with a warning that says so. A `.ai` export with
|
||||
`useArtboards: false` writes that one page too, without the native document and without the editing copy for other
|
||||
apps (`editingData`), and always comes back with the warning `Preserve editing was left out: an .ai file of the art's
|
||||
@@ -2771,11 +2780,11 @@ nearest to the pointer.
|
||||
## Global Edit
|
||||
|
||||
Select › Start Global Edit is `select.globalEdit {appearance?, size?, artboards?, includeCanvas?}`. With one path,
|
||||
compound path or symbol instance selected, it finds the objects of the same shape (moved or scaled copies; not rotated
|
||||
ones), among those `select.all` would take and the objects in their groups, and returns `{active: true, count, ids}`,
|
||||
compound path or symbol instance selected, it finds the objects of the same shape (moved, scaled or rotated copies;
|
||||
not reflected ones), among those `select.all` would take and the objects in their groups, and returns `{active: true, count, ids}`,
|
||||
the selected object first (at most 10,000). With a group of such objects selected (nested groups and clipping paths
|
||||
included; not type or images), it finds the groups like it: as many objects, in the same order, each of the same
|
||||
shape, lying the same way relative to each other (the group moved or scaled as a whole). While Global Edit is off,
|
||||
shape, lying the same way relative to each other (the group moved, scaled or rotated as a whole). While Global Edit is off,
|
||||
the command is disabled for any other selection, including a group that holds type, an image or nothing (it is off in
|
||||
the Select menu, the Properties panel's Quick Actions do not show it, and the Control bar does not show its Global Edit
|
||||
Options). `appearance` also asks for
|
||||
@@ -2784,7 +2793,9 @@ the same fill and stroke (for groups, of each object in them), `size` for the sa
|
||||
params come from `select.globalEditOptions` (the Global Edit Options, kept for the session; it returns them with
|
||||
`count`, the objects a start would take now). The selection stays the one object. Until the next `select.globalEdit`
|
||||
(Stop Global Edit, `{active: false}`), what an edit of a selected match changed is given to the other matches, in the
|
||||
same undo step, and nothing else. A changed outline or anchors go to each match in proportion to its size. A changed
|
||||
same undo step, and nothing else. A changed outline or anchors go to each match in proportion to its size, and to a
|
||||
rotated copy turned by its angle: an anchor moved to the right on the selected object moves upward on a copy rotated
|
||||
a quarter turn counter-clockwise. A changed
|
||||
opacity or blending, and each changed setting of a fill or stroke (paint, weight, opacity, blending, effects…), are
|
||||
copied as they are to the match's fill or stroke of the same kind and rank; its other fills and strokes, and their
|
||||
unchanged settings, stay its own (a stroke weight change leaves the fills). A stroke weight set on the selected match
|
||||
@@ -2800,6 +2811,16 @@ nothing. Nothing of it is saved. Before Global Edit starts, while one object tha
|
||||
selected with the Selection tool, the canvas highlights the other objects a start would take with the current Global
|
||||
Edit Options (none while a drag is in progress, or when there are none).
|
||||
|
||||
Rotated copies are edited together as in [Design a modern geometric
|
||||
logo](https://helpx.adobe.com/vn_vi/illustrator/how-to/modern-logo-design.html), where copies of a group rotated
|
||||
around a point are edited at once from one of their objects. These rules for them are VectorCraft's own. A copy's
|
||||
angle is the one that lays each anchor and handle of the selected object on the copy's anchor and handle of the same
|
||||
order, so a square whose anchors were turned a quarter turn is a copy rotated a quarter turn. The copy is the same
|
||||
shape when, laid so, every anchor and handle lies within a millionth of the larger side of the copy's box of its own. A
|
||||
reflected copy is another shape, and so is a copy stretched along one direction. With `size`, a rotated copy has the
|
||||
same size when it is the selected object rotated without scaling: a 30 × 70 pt object and its copy rotated a quarter
|
||||
turn (70 × 30 pt by its box) have the same size.
|
||||
|
||||
`select.globalEditExclude {id}` leaves the match `id` out of the Global Edit, as a Shift-click on a highlighted match
|
||||
(or on an object inside it) with the Selection tool does: it is no longer highlighted, and later edits leave it as it
|
||||
is. It returns `{active, count, ids}`, the objects left in the Global Edit; with fewer than two left, the Global Edit
|
||||
@@ -2924,8 +2945,16 @@ tutorials, `steps` the number of a tutorial's steps, `finished` whether it is fi
|
||||
zero-based indexes of its steps marked done (every step of a finished tutorial). `learn.skills {}` shows the panel on its Skills tab with the list of
|
||||
skills, with no skill and no tutorial open, as the Quick skill guide card and Back to skills do, and answers what
|
||||
`learn.list` answers. `learn.show {tutorial}` shows the panel on its Skills tab with that
|
||||
tutorial's steps → `{skill, tutorial, title, steps: [text]}`. A missing, non-string or unknown `tutorial` is an error
|
||||
and changes nothing.
|
||||
tutorial's steps → `{skill, tutorial, title, steps: [text]}`; choosing a tutorial's row runs it. A missing, non-string
|
||||
or unknown `tutorial` is an error and changes nothing. A click on the For you or Skills tab button runs
|
||||
`learn.tab {tab}` when the panel shows the other tab, and runs no command when the panel already shows that tab.
|
||||
`learn.tab {tab}`, with `tab` set to `forYou` or `skills`, shows the panel on that tab → `{tab, skill, tutorial}`,
|
||||
with null for no skill or no tutorial open; the Skills tab keeps the skill and tutorial it had open. Choosing a skill's row runs
|
||||
`learn.skill {skill}`, which shows the panel on the Skills tab with that skill's tutorials → the skill as `learn.list`
|
||||
lists it. A missing, non-string or unknown `tab` or `skill` is an error and changes nothing. Back runs `learn.back {}`,
|
||||
which shows the panel and goes up one level on the Skills tab, from a tutorial's steps to its skill's tutorials and
|
||||
from a skill's tutorials to the list of skills, and answers what `learn.tab` answers; on the list of skills or the For
|
||||
you tab the view stays as it is.
|
||||
|
||||
Under a tutorial's steps, View more opens the tutorial's practice sample, a small drawing of VectorCraft's own with the
|
||||
art its steps work on, as a new untitled document that becomes the active one; Save asks where to save it. Once the
|
||||
@@ -2952,11 +2981,11 @@ finished and every step marked. The desktop app keeps the progress in its prefer
|
||||
when two windows change it, the one that saves last keeps its progress. The web build keeps it while the page is open.
|
||||
Marking steps by hand, keeping the progress and Reset progress are VectorCraft's own rules.
|
||||
`learn.markStep {tutorial, step, complete?}` runs a step's check box → `{tutorial, step, complete}`: `step` is the
|
||||
zero-based step number, and `complete` marks the step done (`true`, omitted or null) or not done (`false`). A missing
|
||||
`step` or one the tutorial does not have, a `complete` that is not true or false, a tutorial whose sample was not
|
||||
opened, and a finished tutorial are errors. `learn.resetProgress {}` runs Reset progress and answers what `learn.list`
|
||||
answers; open documents, opened samples and the Learn view stay as they are. For both, a missing, non-string or
|
||||
unknown `tutorial` is an error, and an error changes nothing.
|
||||
zero-based step number, and `complete` marks the step done (`true`, omitted or null) or not done (`false`). A missing,
|
||||
non-string or unknown `tutorial`, a missing `step` or one the tutorial does not have, a `complete` that is not true or
|
||||
false, a tutorial whose sample was not opened, and a finished tutorial are errors, and an error changes nothing.
|
||||
`learn.resetProgress {}` runs Reset progress and answers what `learn.list` answers; open documents, opened samples and
|
||||
the Learn view stay as they are.
|
||||
|
||||
The Home screen has a Learn section between Recent Files and the new-file presets, as
|
||||
[the help page](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/homescreen-overview.html)
|
||||
@@ -2973,6 +3002,9 @@ rules.
|
||||
{"name":"invoke_menu","arguments":{"command":"learn.finish","params":{"tutorial":"pen-paths"}}}
|
||||
{"name":"invoke_menu","arguments":{"command":"learn.next","params":{"tutorial":"pen-paths"}}}
|
||||
{"name":"invoke_menu","arguments":{"command":"learn.skills","params":{}}}
|
||||
{"name":"invoke_menu","arguments":{"command":"learn.skill","params":{"skill":"draw"}}}
|
||||
{"name":"invoke_menu","arguments":{"command":"learn.back","params":{}}}
|
||||
{"name":"invoke_menu","arguments":{"command":"learn.tab","params":{"tab":"forYou"}}}
|
||||
{"name":"invoke_menu","arguments":{"command":"learn.resetProgress","params":{}}}
|
||||
```
|
||||
|
||||
@@ -3224,8 +3256,12 @@ already walks Image Trace. Short agent entry points:
|
||||
is rejected with an error. The Pencil and the Paintbrush give Fidelity in screen pixels, 0.01 to 100 px, and send it
|
||||
divided by the zoom (0.0313 to 640) and kept within that range, so a stroke is fitted at the same tolerance on screen
|
||||
at every zoom. A stroke
|
||||
that continues a path (`extend`) closes it when it ends within four times the Fidelity of the path's other end, at
|
||||
least 6 pt and at most 400 pt. The Blob Brush's `path.blob` Fidelity stays in points, 0.01 to 100 pt.
|
||||
that continues a path (`extend`) closes it when `closed` is true: the Pencil and the Paintbrush send it when the
|
||||
stroke ends within Close Paths When Ends Are Within of the path's other end (the cursor shows the closing ring there),
|
||||
a straight Pencil line too, or with Alt held at the release. The stroke's end then joins the other end when it is
|
||||
within four times the Fidelity of it (at least 6 pt and at most 400 pt), and a straight segment closes the path from
|
||||
farther away. Without `closed`, the stroke closes the path when it ends within that four-times-Fidelity distance. The
|
||||
Blob Brush's `path.blob` Fidelity stays in points, 0.01 to 100 pt.
|
||||
- Variables: `variable.list`, `variable.define {name, kind: text|visibility|image|graph}`, `variable.bind {variable, ids?}`,
|
||||
`variable.makeTextDynamic`, `variable.makeVisibilityDynamic`, `variable.makeImageDynamic`, `variable.makeGraphDynamic`
|
||||
(`variable.bind` and `variable.makeTextDynamic` refuse type that already has another text variable and name it),
|
||||
@@ -3269,8 +3305,9 @@ already walks Image Trace. Short agent entry points:
|
||||
byte order that reads a line break (`\n` or `\r`). It is refused when fewer of its units hold a NUL byte (UTF-8 or
|
||||
Windows-1252 text with stray NUL bytes, or UTF-16 text made mostly of other characters, which needs a byte-order
|
||||
mark), when both byte orders read a line break (the text holds U+0A00 or U+0D00), when it has an odd length, and
|
||||
when it isn't valid UTF-16 in that order or holds a NUL character. A file with no line break has no data rows and is
|
||||
refused for that. `csv` and `data` are read as the text they hold.
|
||||
when it isn't valid UTF-16 in that order or holds a NUL character. A file with no line break is read big-endian when
|
||||
more of its two-byte units start with a NUL byte than end with one, and little-endian otherwise; it has no data rows,
|
||||
so the import is refused. `csv` and `data` are read as the text they hold.
|
||||
- Variable libraries: `variable.loadLibrary {path|xml|dataBase64}` (the Variables panel menu's Load Variable
|
||||
Library…) replaces the document's variables and data sets with a variable library's in one undo step. A load, like a
|
||||
`dataset.import`, adds no undo step when it leaves the variables and data sets as they were. The library
|
||||
@@ -3603,7 +3640,7 @@ already walks Image Trace. Short agent entry points:
|
||||
is changed, renamed or deleted. In the app,
|
||||
`ui.imageTracePresetDialog {params?, rename?}` opens the Image Trace panel's Save as New Preset… or Rename… dialog.
|
||||
- Live Paint: `livePaint.make`, `livePaint.merge`, `livePaint.fill {group?, point}`, `livePaint.strokeEdge`,
|
||||
`livePaint.info {group}`, `livePaint.release`, `livePaint.expand`, and `livePaint.gapOptions {ids?, detect?, size?,
|
||||
`livePaint.info {group?|id?}`, `livePaint.release`, `livePaint.expand`, and `livePaint.gapOptions {ids?, detect?, size?,
|
||||
color?, closeGaps?}` (Object › Live Paint › Gap Options). Make gives each covered face the fill of its front-most
|
||||
covering source, including compound paths with shared curved boundaries. Expand keeps those face fills.
|
||||
`livePaint.expand` keeps each face and edge that draws, with all its fill and stroke rows: it is shown, its opacity
|
||||
@@ -3612,6 +3649,13 @@ already walks Image Trace. Short agent entry points:
|
||||
row is hidden is removed. `livePaint.merge` copies the fill and stroke rows, visibility, opacity and blending mode of
|
||||
each face that draws by this rule, and of each edge, to the rebuilt parts, with their gradients kept at their fit on
|
||||
the old outline and without the strokes' pen pressure, tilt, bearing and rotation.
|
||||
`livePaint.info` lists each face's top fill as `fill` and each edge's top stroke and its weight as `stroke` and
|
||||
`width`, and lists every fill and stroke row of each face and edge in `appearance`, bottom first, as
|
||||
`{index, kind, paint, opacity, visible, width?, drawn}`: `index` counts fills and strokes together, `opacity` runs
|
||||
from 0 to 1, and `width` (strokes only) is the weight in points. `drawn` is true when the row draws by the rule
|
||||
above: the part is shown with an opacity above 0, and the row is shown, has paint and has an opacity above 0 (a
|
||||
stroke also a weight above 0). An unpainted top row can sit over a lower row that draws, so `fill`, `stroke` and
|
||||
`width` alone may not describe what the part draws.
|
||||
With `detect: true`, paint stops at the gaps that run
|
||||
from a loose end of a path to the nearest path, up to `size` wide (`small` 3 pt, `medium` 6 pt, `large` 12 pt, or a
|
||||
number of points up to 72); `closeGaps: true` adds an unpainted path across each of them. `color` (the Gap Preview
|
||||
@@ -3646,6 +3690,16 @@ already walks Image Trace. Short agent entry points:
|
||||
a locked artboard, or in isolation mode outside the isolated art. In the app, the tool's cursor shows what a click
|
||||
at the pointer selects under these rules: the arrow with a filled square for a face, with a short line for an edge,
|
||||
and with an x for nothing. It keeps the look it had at the press until the release.
|
||||
A double-click (`pointer_gesture` kind `doubleclick`, after the two clicks' `down` and `up`) on the face a click there
|
||||
picks runs `select.set {ids}` with that face and the faces of its group that a flood from it reaches across edges
|
||||
that are hidden or draw no stroke (an edge that is fully transparent, or whose strokes are each hidden, without
|
||||
paint, 0 pt wide or fully transparent); a stroked edge and a Gap Detection gap stop the flood, and hidden faces are
|
||||
left out. On the edge a click
|
||||
there picks, it runs `select.set {ids}` with that edge and the edges of its group, not hidden, joined to it end to
|
||||
end through edges that draw with the stroke paint it draws with (the paint of an edge's topmost stroke that is
|
||||
shown, with paint, above 0 pt and not fully transparent; none for an edge that draws no stroke). With Shift held it runs `select.toggle {ids}` with the same faces or edges,
|
||||
and where a click selects no face or edge it runs nothing. The same options, locks and isolation rules apply as for
|
||||
a click.
|
||||
The Live Paint Bucket's options (`tool.setOption {tool: "livePaintBucket", values}`; double-clicking the tool opens
|
||||
them, dialog `livePaintBucketOptions`) are `paintFills` (on), `paintStrokes` (off), `cursorSwatchPreview` (on),
|
||||
`highlight` (on), `color` (the
|
||||
@@ -5135,7 +5189,8 @@ The Attributes panel (`window.panel {panel: "attributes"}`, Cmd+F11) reads `attr
|
||||
objects differ) and `recentUrls`. `attributes.set {overprintFill?, overprintStroke?, showCenter?, imageMap?, url?,
|
||||
note?, ids?}` sets them in one undo step; `path.setFillRule {rule: "nonZero"|"evenOdd"}` sets the fill rule of the
|
||||
paths and compound paths, and `path.reverse {reversed?}` makes subpaths run counter-clockwise (true) or clockwise
|
||||
(false). SVG export wraps an object with a URL in `<a xlink:href>`, and SVG import reads `<a href>` links back.
|
||||
(false). When every subpath of a path turns alike, its strokes' width profiles (left and right swapped) and pen
|
||||
pressure, tilt, bearing and rotation turn with it, so the strokes draw as before. SVG export wraps an object with a URL in `<a xlink:href>`, and SVG import reads `<a href>` links back.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"attributes.set","params":{"ids":[12],"url":"https://example.com","imageMap":"rectangle"}}}
|
||||
@@ -5430,6 +5485,13 @@ keeps the segment's direction when the smoothed path there turns back by 90° or
|
||||
path, the curve keeps the direction of the part outside the drag. `object.path.smooth` and Simplify keep each end's
|
||||
direction.
|
||||
|
||||
`path.smoothRegion` keeps an anchor as a corner where the path turns by more than 57.5° (an angle inside the corner
|
||||
under 122.5°) at the anchor and also over `radius` and over twice `radius` on either side of it (on a closed path that the drag reaches all the
|
||||
way round, no more than an eighth of its length), so a jag or a bump smaller than `radius` is still smoothed. The stretches on either side of a kept corner are smoothed and refitted on their
|
||||
own, and the corner keeps its place and the directions the path arrives and leaves along, on every call and at any
|
||||
`fidelity`. A call that changes no anchor returns `{ids: [], before: 0, after: 0}` and adds no undo step. The 57.5°
|
||||
threshold is VectorCraft's own value.
|
||||
|
||||
In the desktop app, Object › Path › Smooth, the canvas context menu's Smooth… (listed while the selection holds a
|
||||
path) and the Contextual Task Bar's Smooth (with a path selected whole with the Direct Selection tool) open the
|
||||
slider (`ui.menuDialog {command: "object.path.smooth"}`, dialog `smoothSlider` with field `level`) at the
|
||||
@@ -6321,6 +6383,10 @@ Pen's second anchor at (150, 431), in line with the square's centre.
|
||||
- `highlightAlternateGlyphs` (off by default): Preferences › Type › Highlight Alternate Glyphs. On, the canvas paints
|
||||
pink behind OpenType substitutions (ligatures, contextual forms). Document Setup's Highlight Substituted Glyphs
|
||||
stays separate. Agents set it with `prefs.set`; the desktop canvas reads it on the next paint.
|
||||
- `showCharacterAlternates` (on by default): Preferences › Type › Show Character Alternates. On, the desktop canvas
|
||||
shows the alternate glyphs of the one character selected with a Type tool beside it (see
|
||||
[Alternate glyphs](#alternate-glyphs)). Off, it shows none. It is VectorCraft's own option. `prefs.set` refuses a
|
||||
value that is not a boolean.
|
||||
- `highlightSubstitutedFonts` (on by default): Preferences › Type › Highlight Substituted Fonts. On, the canvas paints
|
||||
pink behind text drawn in a substitute for a missing font, in every open document. Off, no document shows that
|
||||
highlight. `document.setup` ignores this key and adds a `warnings` entry that names `prefs.set` to its reply. A file
|
||||
@@ -6745,7 +6811,10 @@ copies in artboard order); `artboard` wins when both are given. Without either,
|
||||
several artboards selected, they paste a copy on each of those, and the journal records them as `artboards`; a
|
||||
recorded action leaves both out. Art copied from no artboard keeps its place on the first artboard named and its
|
||||
offset to that one on the others. An index the document does not have, a repeated index, a value that is not an index
|
||||
or an empty list fails, and nothing is pasted. Copied artboards come back once, where they were, whichever artboards
|
||||
or an empty list fails, and nothing is pasted. An `artboard` that is not a whole number, null included, fails with
|
||||
`` `artboard` must be a whole number ``, and an `artboards` entry that is not one with
|
||||
`` `artboards` must contain whole numbers ``; both keys are checked when both are given. Copied artboards come back
|
||||
once, where they were, whichever artboards
|
||||
are named. `layer.pasteRemembersLayers {on?}` (a document option, `document.inspect` → `pasteRemembersLayers`)
|
||||
pastes objects back into the layers and sublayers they came from: in the same document while those are still there,
|
||||
else by the names of the layer and the layers around it (the topmost chain that matches the most names, a shown and
|
||||
@@ -6788,9 +6857,15 @@ also move the pattern tiles of the copies when `patterns` is true (default: pref
|
||||
`artboard.duplicate`, `artboard.copy`, `artboard.cut`, `artboard.move` and `artboard.rearrange` take `lockedAndHidden?`
|
||||
(default: prefs `moveLockedWithArtboard`), and with the Artboard tool chosen `edit.copy` and `edit.cut` pass it on. When
|
||||
art goes along, the journal records the value, so a replay under another preference takes the same art.
|
||||
Every artboard command that takes an `index` fails with `no such artboard` when the `index` is not the
|
||||
0-based index of an artboard (past the last one, negative, fractional, a string or null), and the document and the
|
||||
clipboard stay as they were.
|
||||
Every artboard command that takes an `index` fails with `no such artboard` when the `index` is a whole number past
|
||||
the last artboard, with `` `index` must be a whole number `` when it is negative, fractional, a string or another value
|
||||
that is not a whole number, and with `missing index` when it is null, also in a command that picks an artboard when
|
||||
`index` is left out. An `indices` (or a replayed `selectedArtboards`) that is not a list fails with
|
||||
`` `indices` must be a list of artboard indices ``, an empty one with
|
||||
`` `indices` must be a non-empty list of artboard indices ``, one with an entry that is not a whole number with
|
||||
`` `indices` must contain whole numbers ``, each naming its key, and one with a whole number past the last artboard
|
||||
with `no such artboard`. `artboard.align`, `artboard.distribute` and `artboard.distributeSpacing` name `artboard` or
|
||||
`activeArtboard` the same way. The document and the clipboard stay as they were.
|
||||
These artboard commands refuse a string, a number or another value that is not true or false with
|
||||
`` `art` must be true or false ``, naming the key, and leave the document, its undo history and the clipboard as they
|
||||
were: `moveArt`, `scaleArt`, `strokes`, `corners`, `patterns`, `lockedAndHidden` and an artboard's `locked`,
|
||||
@@ -7228,9 +7303,14 @@ the document; so does `object.expand`.
|
||||
Placing a text file (`.txt`) sets it as area type: `file.place {path | name+dataBase64, text?: {characterSet?:
|
||||
"unicode" | "ansi", platform?: "windows" | "mac", removeLineReturns?, removeParagraphReturns?, replaceSpaces?: n}}`
|
||||
(Text Import Options). Unicode reads UTF-8, or UTF-16 with a byte-order mark; ANSI reads Windows-1252 (Mac Roman on
|
||||
`mac`). `removeLineReturns` joins the lines of each block into one paragraph, `removeParagraphReturns` drops blank
|
||||
lines, `replaceSpaces: 3` turns runs of 3 or more spaces into tabs. The frame fills `rect`, the replaced object's
|
||||
bounds, or the artboard less a 36 pt margin.
|
||||
`mac`). Unicode reads a file without a byte-order mark as UTF-16 by the rule `dataset.import` uses: at least half of
|
||||
its two-byte units hold a NUL byte, in the byte order that reads a line break, or for a file with one line, big-endian
|
||||
when more of its units start with a NUL byte than end with one, and little-endian otherwise. Any other file is read as
|
||||
UTF-8, else as the platform's 8-bit set: one with fewer NUL bytes, one with an odd length, one where both byte orders
|
||||
read a line break, and one that isn't valid UTF-16 in that order or holds a NUL character. `removeLineReturns` joins
|
||||
the lines of each block into one paragraph, `removeParagraphReturns` drops blank lines, `replaceSpaces: 3` turns runs
|
||||
of 3 or more spaces into tabs. The frame fills `rect`, the replaced object's bounds, or the artboard less a 36 pt
|
||||
margin.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"file.place","params":{"path":"/tmp/notes.txt","text":{"removeLineReturns":true,"removeParagraphReturns":true}}}}
|
||||
@@ -7875,7 +7955,7 @@ instructions is refused with "not an HP-GL file".
|
||||
|
||||
`document.export` (and `export`, and Export As) with format `hpgl` writes a plot file (`.plt`) of the first artboard
|
||||
(or `artboard`) for pen plotters and cutters; `useArtboards: true` writes one file per chosen artboard
|
||||
(`{stem}-{artboard}.plt`), `false` the bounds of the visible art. Each visible path is drawn once along its own line:
|
||||
(`{stem}-{artboard}.plt`), `false` the bounds of the art it plots. Each visible path is drawn once along its own line:
|
||||
a filled shape is its closed outline, also when a stroke gives its color, and a stroked path is its center line, so
|
||||
fills, stroke widths, dashes, brushes and arrowheads are not painted. Type is drawn as its glyph outlines, and a
|
||||
gradient mesh as its outline, also inside a blend (a mesh whose every point is at 0% opacity draws nothing). A
|
||||
@@ -8365,7 +8445,8 @@ undo step. Object › Transform › Scale, the Scale tool and the Transform pane
|
||||
text reflows along it.
|
||||
`text.setPathHandle {id, subpath?, anchor, which: "in"|"out", x, y, independent?}` moves a direction handle of one
|
||||
of its anchors, as `path.setHandle` moves a path's (Direct Selection dragging a handle of the path, #3565), in one
|
||||
undo step.
|
||||
undo step. A call of `text.reshapeArea`, `text.reshapePath` or `text.setPathHandle` that changes nothing (`dx` and
|
||||
`dy` both 0, or a handle moved to where it already is) adds no undo step and keeps redo.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"text.reshapeArea","params":{"id":42,"anchors":[[0,2]],"dx":40,"dy":60}}}
|
||||
@@ -8430,7 +8511,10 @@ the end of the path), and `fit`, `fitScale` and `dynamicText` (Block is on) for
|
||||
Given for several area types (`ids`, or a selection of several), `text.areaOptions` changes only the options given on
|
||||
each one: each frame keeps its other options (it used to take the first frame's), and `fitMinPercent` alone changes only
|
||||
the frames that already shrink text to fit. Options that change nothing (the vertical alignment already set, say) add
|
||||
no undo step and keep redo.
|
||||
no undo step and keep redo. The same holds for `text.setText` when no object changes (the text it already has, in one
|
||||
style, every paragraph with the first one's attributes and no ruby), `text.setStyle` when no character, paragraph or
|
||||
graph label style changes, `type.ruby` with the same reading and options again or `remove` where there is no ruby, and
|
||||
`text.fitHeadline` on a first line that already has the tracking it would set.
|
||||
|
||||
Text that doesn't fit is drawn up to the last line that does, so a one-line headline in a frame lower than its line
|
||||
draws nothing. The commands that make type or change what it holds say so in their own reply: `text.create`,
|
||||
@@ -9144,7 +9228,9 @@ send an Alignment or Level change for paragraphs that stay in no list. With no t
|
||||
with an unknown `tab`, `ui.bulletsAndNumbering` is an error.
|
||||
|
||||
Type › Bullets and Numbering › Convert to Text runs `type.convertListToText` on the selected type's paragraphs, or on
|
||||
those the Type tool's selection touches, and that runs `text.convertListToText {ids?, start?, end?}`. The marker of
|
||||
those the Type tool's selection touches, and that runs `text.convertListToText {ids?, start?, end?}`. With the
|
||||
Selection tool, a selected frame of threaded text names every frame of its story in `ids`, locked and hidden frames
|
||||
included, as Apply Bullets and Apply Numbers do. The marker of
|
||||
each list paragraph becomes characters at the start of the paragraph: the bullet, or the number and its period as the
|
||||
paragraph showed it, then a tab. They are set in the marker's font, size and color: the style of the paragraph's first
|
||||
character without the attributes the marker leaves out. The paragraph leaves its list. A paragraph at a list level
|
||||
@@ -9431,6 +9517,15 @@ and a glyph that the character's style does not draw (All Caps, Small Caps or an
|
||||
system). Choosing the glyph a character already draws is not an edit. Character styles do not take `glyphAlternate`:
|
||||
`charStyle.new`, `charStyle.edit` and `charStyle.setAttrs` refuse it.
|
||||
|
||||
On the desktop canvas, a Type tool with exactly one character selected shows up to five of that character's alternates
|
||||
in a row beside it, in the same order and without the glyph the character is drawn with; a character drawn with an
|
||||
alternate gets its default glyph first. A click on a glyph runs the same command as the panel's double-click
|
||||
(`text.setRangeStyle {featureChanges}`, or `text.setGlyphAlternate` for a glyph no feature draws there), as one undo
|
||||
step. When the character has more alternates than the row shows, an arrow at the end of the row opens the Glyphs panel
|
||||
on Alternates for Current Selection. The row has no command of its own: an agent reads the alternates with
|
||||
`text.glyphAlternates` and applies one with the commands above. The `showCharacterAlternates` preference turns the row
|
||||
off.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"text.glyphAlternates","params":{"id":7,"start":2}}}
|
||||
{"name":"run_command","arguments":{"command":"text.setGlyphAlternate","params":{"id":7,"start":2,"gid":1043}}}
|
||||
@@ -10655,6 +10750,10 @@ threaded frame, which composes them again at its own widths. Such a paragraph fa
|
||||
frame has no room for its first line, or when the search for its breaks passes VectorCraft's own limits (1,000,000
|
||||
lines tried and 2,000,000 baseline steps for one paragraph, 2,000,000 lines and 4,000,000 steps for all the
|
||||
paragraphs of a frame).
|
||||
Single-line measures each line's room the same way: a line that takes in a taller character is placed again across its
|
||||
new height and broken again in the room there. When that leaves the taller character for the next line, the line is
|
||||
set at its own height where the room there is no narrower, with the words before that character that fit there, and
|
||||
otherwise stays where it was placed.
|
||||
The UI command `type.lineComposer` (Cmd+Alt+Shift+C, in remote mode `press_key {key: "C", mods: {cmd: true, alt: true,
|
||||
shift: true}}` or `invoke_menu`) sets `singleLine` when every paragraph of the selected type (or every paragraph the
|
||||
Type tool's selection touches) uses Every-line, else `everyLine`, and returns the composer it set.
|
||||
@@ -10713,7 +10812,12 @@ and the arrow keys nudge them by the keyboard increment. The active tool lists t
|
||||
(`tool.setOption {}` returns them as `meshPoints: [{id, index}…]`). On gradient meshes a solid fill colour (`paint.setFill`, from the
|
||||
Color panel, Swatches or the Eyedropper) recolours just the picked points, and when every target of
|
||||
`transparency.set` is a gradient mesh with points picked, its `opacity` fades those points instead of the objects
|
||||
(`transparency.info` then shows their opacity, `null` when it differs). Both are one undo step.
|
||||
(`transparency.info` then shows their opacity, `null` when it differs). Both are one undo step, and neither goes to the
|
||||
points while the Appearance panel's active row takes the fill or the opacity. When the first selected object is a
|
||||
gradient mesh with points picked, the Fill proxy, the Color panel, the Color Wheel and `paint.proxies` show its first
|
||||
picked point's color, and `fillMixed` compares the picked points' colors with each other and with the fills of the other
|
||||
selected objects. The Transparency panel shows the picked points' opacity (blank when it differs), and the Control
|
||||
bar shows the first picked point's opacity.
|
||||
|
||||
`object.mesh.movePoints {id, points: [index…], dx, dy}` (or `{items: [{id, points}…], dx, dy}` over several meshes)
|
||||
moves points by (dx, dy), their handles with them; `object.mesh.setPointColor` takes `points` or `items` the same
|
||||
@@ -11842,6 +11946,7 @@ the error text. The interactive fallback applies only to ordinary File > Save, n
|
||||
|
||||
| Date | Change |
|
||||
|---|---|
|
||||
| 2026-11-13 | `path.freehand`: `closed`, when given, decides whether a stroke that continues a path (`extend`) closes it; the Pencil and the Paintbrush send it by Close Paths When Ends Are Within. |
|
||||
| 2026-11-13 | Snap to Point with Smart Guides off draws no Smart Guides labels or lines (#7250). |
|
||||
| 2026-11-13 | Envelopes: a top object's side whose pieces are all one curve split at anchors follows that curve's parameter (#7097). |
|
||||
| 2026-11-11 | Document READ_ONLY_LOCATION for saves (#6146); no response-shape change. |
|
||||
|
||||
Reference in New Issue
Block a user