mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-10 18:10:01 -06:00
Merge main into feat/native-save-precision
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Control protocol
|
||||
|
||||
> **Last updated:** 2026-10-25 · **Change:** brush library panels (`window.brushLibrary`, `window.brushLibrary.other`, `ui.saveBrushLibrary`); previously: Transform Each opens on the values it was last confirmed with; its Copy button confirms with `copy: true` (#1732); previously: panel docking on craft-ui's layout: `ui.docking`, the parameters of `window.panel.float` and `window.panel.dock`; previously: `ui.screenshot`'s 64 MiB inline-PNG cap and its path-plus-data downgrade; symbol library panels (`window.symbolLibrary`, `window.symbolLibrary.other`, `ui.saveSymbolLibrary`); synthetic input budgets (#1709); bounded transport waits (#1726).
|
||||
> **Last updated:** 2026-10-25 · **Change:** Object → Expand… dimmed while the selection has an appearance Expand Appearance expands (`object.expand.info`'s `appearance`, #3089); previously: brush library panels (`window.brushLibrary`, `window.brushLibrary.other`, `ui.saveBrushLibrary`); previously: Transform Each opens on the values it was last confirmed with; its Copy button confirms with `copy: true` (#1732); previously: panel docking on craft-ui's layout: `ui.docking`, the parameters of `window.panel.float` and `window.panel.dock`; previously: `ui.screenshot`'s 64 MiB inline-PNG cap and its path-plus-data downgrade; symbol library panels (`window.symbolLibrary`, `window.symbolLibrary.other`, `ui.saveSymbolLibrary`); synthetic input budgets (#1709); bounded transport waits (#1726).
|
||||
|
||||
`vectorcraft --control <port>` listens on `127.0.0.1:<port>` (loopback only). The port must be a number
|
||||
from 1 to 65535 (`--control=<port>` works too), given once; otherwise the app prints an error and exits
|
||||
@@ -415,7 +415,9 @@ opens the `expand` dialog for the selection. Fields: `object`, `fill`, `stroke`
|
||||
`__stroke` say which the selection has something for, as `object.expand.info` does, and the others are disabled),
|
||||
`gradient` (`objects` or `mesh`) and `steps` (1–1000, default 255), which are enabled when `fill` is on and
|
||||
`__gradient` says the selection has a gradient fill (`object.expand.info`'s `gradient`). `ui.dialog.confirm` runs `object.expand` with them as
|
||||
one undo step.
|
||||
one undo step. While the selection has an appearance Expand Appearance expands (effects, several fills or strokes, a
|
||||
brush: `object.expand.info`'s `appearance`), the menu item is dimmed with a tooltip to use Object → Expand Appearance
|
||||
first, and `ui.expandDialog` refuses with that message (#3089).
|
||||
|
||||
Attributes panel: `window.panel {panel: "attributes"}` (Cmd+F11) shows it; its controls run `attributes.set`,
|
||||
`path.reverse {reversed}` and `path.setFillRule {rule}`, and its Browser button runs the UI command
|
||||
@@ -947,6 +949,7 @@ hidden tab (whose frames the browser pauses) answers when it is shown again.
|
||||
| 2026-10-25 | minor | Panel docking on craft-ui's layout: `ui.docking`, the floating and dock parameters, native floating windows. |
|
||||
| 2026-10-24 | minor | Documented the brush library panel commands (`window.brushLibrary`, `.other`, `ui.saveBrushLibrary`, `window.userBrushLibrary1`…`10`). |
|
||||
| 2026-10-24 | minor | Documented `ui.screenshot`'s 64 MiB inline-PNG reply cap: with `path` the file is still written and `pngBase64` is omitted when over the cap; a path-less `data: true` request fails before encoding. |
|
||||
| 2026-10-25 | minor | Documented that Object → Expand… is dimmed, and `ui.expandDialog` refuses, while the selection has an appearance Expand Appearance expands (`object.expand.info`'s `appearance`, #3089). |
|
||||
| 2026-10-25 | minor | Documented that Transform Each opens on the values it was last confirmed with and that its Copy button confirms with `copy: true` (#1732). |
|
||||
| 2026-10-23 | minor | Documented the symbol library panel commands (`window.symbolLibrary`, `.other`, `ui.saveSymbolLibrary`, `window.userSymbolLibrary1`…`10`). |
|
||||
| 2026-10-13 | minor | Documented count, pending-event and per-frame request budgets (#1709). |
|
||||
|
||||
+2
-1
@@ -829,6 +829,7 @@ trap, and the defaults (0.25 pt, 100%, 40%) are VectorCraft's own, the pages giv
|
||||
| 2026-10-10 | minor | G9 evidence counted from the tracker (28 `.ai`/EPS issues, 20 fixed); impact narrowed to handing files back |
|
||||
| 2026-10-10 | minor | Alpha blockers checked against the core-workflow gate: none |
|
||||
| 2026-10-10 | major | Moved from the ROADMAP's "Where we're lacking"; kept ids G1–G8, added G9–G19 (file formats, stability, bugs, preferences, 30.x additions, pen hardware, performance, localization, ecosystem, AI, accessibility) and re-ranked |
|
||||
| 2026-10-28 | minor | Flare ray rotation follows vertical travel at one degree per document point, independent of pointer event count. Shift freezes the current orientation; Space also freezes rotation on the first update. This is the chosen application interaction rate. Scores and estimates unchanged. |
|
||||
| 2026-10-28 | minor | Drop Shadow Darkness subtracts the normalized amount from RGB source channels or adds it to CMYK/Gray black before profile conversion and blur; near-100% becomes gray black, with shadow opacity separate. SVG keeps live filters for uniform sRGB sources and renders shadows for other RGB profiles, source models and gradients. Gradient-stop adjustment is an application rule; spot/custom colors and composite-source parity remain open. Scores and estimates unchanged. |
|
||||
| 2026-10-28 | minor | Blob Brush Shift locks after clear axial movement, keeps earlier samples fixed, and waits without an off-axis trail. Activation uses raw press displacement in logical screen pixels, with exact quarter-turn boundaries. Explicit application rule; scores and estimates unchanged. |
|
||||
| 2026-10-28 | minor | Flare Tool Options opened by a canvas click previews its settings at that click. Reset refreshes the enabled preview while keeping the dialog open. Cancel discards preview art and tentative options; OK accepts one flare in one Undo step. Editing existing flare artwork remains outside this dialog scope. Scores and estimates unchanged. |
|
||||
@@ -842,6 +843,6 @@ trap, and the defaults (0.25 pt, 100%, 40%) are VectorCraft's own, the pages giv
|
||||
| 2026-10-22 | minor | Tab-drag follow-up: reconcile upstream progress updates and document drag lifecycle, insertion behavior and regression contracts; behavior, scores and estimates unchanged. |
|
||||
| 2026-10-22 | minor | Artwork dragged with Selection switches visible document tabs after a 400 ms hover, then copies editable artwork on canvas release; source and clipboard stay intact; scores and hours unchanged |
|
||||
|
||||
2026-10-28 behavior correction: Flare ray rotation follows vertical travel at one degree per document point, independent of pointer event count. Shift freezes the current orientation; Space also freezes rotation on the first update. This is the chosen application interaction rate. Scores and estimates unchanged.
|
||||
## EPS Save evidence (2026-10-26)
|
||||
|
||||
Ordinary Save and Save As keep EPS as EPS, with the chosen page frame, transparent margins and the complete editable VectorCraft document. Existing import-loss confirmation and transparency warnings remain; the Save TIFF preview is capped at 1024 pixels, while Export retains 2048. See [file-format-parity.md](file-format-parity.md#eps-save-and-source-protection) for limits and regression evidence. This narrows G9 save-back workflow coverage; native Illustrator editing-data fidelity, parity scores and hour estimates are unchanged.
|
||||
|
||||
@@ -46,6 +46,11 @@ most `colors` of its colors are used. A missing group and a group with no solid
|
||||
mode, palette or library in the panel clears the group. A group the active document does not have shows as All
|
||||
and traces as All.
|
||||
|
||||
**Document Library linked colors.** With Library › Document Swatches, with or without a color group,
|
||||
a traced fill or stroke whose color comes from a global or spot swatch is linked to that swatch, and
|
||||
one whose color comes from a tint swatch is linked to its base at the tint. Editing the swatch
|
||||
recolors the trace. Colors from process swatches and from swatch libraries are not linked.
|
||||
|
||||
**Document Library** traces with the library's colors as they are. Each pixel takes the library
|
||||
color nearest to it in lightness and hue, with a difference in hue or chroma counted three times
|
||||
as much as one in lightness, so a gray or a muted brown takes a black, white or other neutral
|
||||
|
||||
+90
-25
@@ -588,7 +588,8 @@ it replaced by the template's extension, and any other path that does not end in
|
||||
`card.png` is saved as `card.vctemplate` and `card` as `card.vctemplate`; the suggested name and the Templates folder
|
||||
come back without a path), `file.newFromTemplate {path}`, `file.revert` and `file.formatOptions {format?}` (a format's options
|
||||
with the values a save would use). Without a path the save commands return `{dataBase64, name, folder?, warnings}`. A document saved as SVG or PDF
|
||||
remembers its options, so the next save reuses them. A PDF opened with `pages`, `cropTo` or `password` is only part
|
||||
remembers its options, so the next save reuses them; a document not yet saved as a native file is offered the
|
||||
VectorCraft Options the last native Save or Save As used (not its artboards, nor Use Compression). A PDF opened with `pages`, `cropTo` or `password` is only part
|
||||
of the file, so Save asks for a new name instead of writing it back.
|
||||
`file.documentColorMode {mode, convert?, intent?, grays?}` switches the document color mode, converting the colors of
|
||||
the art (opacity masks included), symbols, graph designs, pattern tiles (with the tile that pattern editing's Cancel
|
||||
@@ -1144,8 +1145,8 @@ and `type.fractionalWidths`; `remove` and `overhang` in `type.ruby`; `expandInst
|
||||
These commands refuse a string or another value that is not a number with `` `radius` must be a number, not "2" ``,
|
||||
naming the key, and change nothing: `radius` in `shape.rectangle`; `sides` and `rotation` in `shape.polygon`;
|
||||
`radius2`, `points` and `rotation` in `shape.star`; `diameter`, `opacity`, `brightness`, `growth`, `fuzziness`,
|
||||
`rays`, `longest`, `rayFuzziness`, `rings`, `largest`, `x2`, `y2`, `direction`, `pathLength` and `seed` in
|
||||
`shape.flare`; `decay` and `segments` in `shape.spiral`; `rows` and `columns` in `shape.rectangularGrid`; `concentric`
|
||||
`rays`, `longest`, `rayFuzziness`, `rotation`, `rings`, `largest`, `x2`, `y2`, `direction`, `pathLength` and `seed`
|
||||
in `shape.flare`; `decay` and `segments` in `shape.spiral`; `rows` and `columns` in `shape.rectangularGrid`; `concentric`
|
||||
and `radial` in `shape.polarGrid`; `size` and the `width`, `height` and `fitMinPercent` of `area` in `text.create`;
|
||||
`size` and `fitMinPercent` in `text.createInPath`; `start`, `end`, `size`, `tracking`,
|
||||
`baselineShift`, `hScale`, `vScale`, `rotation` and `strokeWidth` in `text.setRangeStyle`; `start` and `end` in
|
||||
@@ -1245,7 +1246,9 @@ Transparency and opacity-mask commands take `ids` (or `id`), so they need no sel
|
||||
(0..100) in every command (`transparency.set`, `object.setProps`, `appearance.setItem`). `transparency.info` returns
|
||||
the Transparency panel's values, with `null` where the objects differ. Making a mask from one object gives it an
|
||||
empty mask and enters mask editing: art drawn then becomes the mask, and the mask commands act on the masked object
|
||||
until `transparency.stopEditingOpacityMask`. Saves and exports never include the editing layer.
|
||||
until `transparency.stopEditingOpacityMask`. While a mask is edited, `object.exitIsolation` (Esc, the isolation bar's
|
||||
back arrow, Exit Isolation Mode) leaves mask editing the same way, in one undo step. Saves and exports never include
|
||||
the editing layer.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"transparency.set","params":{"ids":[12],"opacity":40,"blend":"Multiply"}}}
|
||||
@@ -1376,8 +1379,8 @@ is one of them, and `edit.undo` selects them again with the key object.
|
||||
`object.hide.unselected` (Object › Hide › Unselected Artwork, Cmd+Alt+Shift+3) hides, in one undo step, every
|
||||
object that `select.all` takes and that is neither selected nor holds a selected object, and returns `{count}`. In a
|
||||
group that holds a selected object it hides the group's other members one by one; a clip group, a compound path or
|
||||
another object that holds a selected object stays as it is with its members. While Lock Guides is on it leaves the
|
||||
guide paths as they are. The selection stays as it is, and `object.showAll` shows the objects again. With nothing to
|
||||
another object that holds a selected object stays as it is with its members. The objects of a selected layer count as
|
||||
selected. While Lock Guides is on, the guide paths count as selected and stay as they are. The selection stays as it is, and `object.showAll` shows the objects again. With nothing to
|
||||
hide it records no undo step. In isolation mode the menu item is disabled, and the command returns the error "exit
|
||||
isolation mode first" and changes nothing.
|
||||
|
||||
@@ -1584,6 +1587,16 @@ already walks Image Trace. Short agent entry points:
|
||||
- Image Trace: `imageTrace.presets`, `imageTrace.make {id?, preset?, params?, view?}` (or `imageTrace.makeAndExpand`),
|
||||
`imageTrace.setView`, `imageTrace.expand`, `imageTrace.release`. A key inside `params` that is not one of the trace
|
||||
settings, such as `colours`, is an error that names it and the nearest setting (`colors`), as for a command's own keys.
|
||||
`imageTrace.presets.save {name?, newName?, preset?, enhanced?, params?}` saves tracing settings as a preset kept with
|
||||
the preferences: `params` over `preset`'s (default: the saved preset `name`, else Default), checked as `imageTrace.make`
|
||||
checks them; without `name` it is a new "Tracing Preset N", and `newName` renames a saved preset (the reply's
|
||||
`renamedFrom` holds the old name). `imageTrace.presets.delete {name}` deletes one. Built-in presets and the name
|
||||
`Custom` can't be saved over, renamed or deleted. `imageTrace.presets` lists the built-in presets with
|
||||
`builtIn: true`, then the saved ones with `builtIn: false`, and returns a `revision` that grows each time the saved
|
||||
presets change. `imageTrace.make {preset}` takes a saved preset's name, with ASCII letters matching in either case.
|
||||
Its journal entry records the saved preset's settings as `savedPreset`, so a replay traces with them after the preset
|
||||
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?,
|
||||
color?, closeGaps?}` (Object › Live Paint › Gap Options). With `detect: true`, paint stops at the gaps that run
|
||||
@@ -2016,7 +2029,8 @@ they answer its file's name without the extension and `count: 0`.
|
||||
|
||||
## Libraries
|
||||
|
||||
The Libraries panel's libraries hold graphics, colours and character and paragraph styles that any document can use.
|
||||
The Libraries panel's libraries hold graphics, colours, gradients, patterns and character and paragraph styles that any
|
||||
document can use.
|
||||
They are kept on this machine: each is a `.vclibrary` file (JSON) named after the library (`CON-.vclibrary` for a
|
||||
library named after a Windows device such as `CON`) in the `Libraries` folder next to the preferences
|
||||
(none in the web app and headless sessions, where they last for the session). `library.list` lists them (`id`, `name`,
|
||||
@@ -2026,7 +2040,7 @@ size and a PNG `thumbnail` in base64; colours with `name`, `hex` and `color`; st
|
||||
`library.setCurrent {library}` manage them; `library` is an id or a name, and without it the current library (the one
|
||||
the panel shows) is meant.
|
||||
|
||||
`library.add {library?, kind, ids?, name?, color?}` adds from the selection: `graphic` (a copy of the objects with the
|
||||
`library.add {library?, kind, ids?, name?, color?, swatch?}` adds from the selection: `graphic` (a copy of the objects with the
|
||||
images, symbols, patterns, swatches, styles and brushes they use, as Copy takes them), `fillColor` / `strokeColor` (the
|
||||
first selected object's solid colour, else the default one, or `color`), `charStyle` / `paraStyle` (the selected
|
||||
text's attributes). An item the library already has is reported as `existing`. `library.use {library?, kind, item,
|
||||
@@ -2036,6 +2050,18 @@ to the document under its name without the white space around it (numbered when
|
||||
attributes) and applied to the selected text, each as one undo step. `library.removeItem {library?, kind, item}` removes
|
||||
one.
|
||||
|
||||
Gradients and patterns are kinds of their own (the panel's + button lists Fill Gradient, Stroke Gradient, Fill Pattern
|
||||
and Stroke Pattern, and a gradient or pattern swatch dragged from the Swatches panel onto the list is added).
|
||||
`library.add {kind: "fillGradient" | "strokeGradient", swatch?}` adds the first selected object's fill or stroke
|
||||
gradient (else the default one, or the gradient swatch `swatch`) without its placement or swatch links, named after its
|
||||
swatch, else `Gradient`; `library.use` paints the selection's fill or stroke with it, fitted to each object.
|
||||
`library.add {kind: "fillPattern" | "strokePattern", swatch?}` adds the first selected object's fill or stroke pattern
|
||||
(else the default one, or the pattern swatch `swatch`) with the images, symbols, patterns, swatches, styles and brushes
|
||||
its art uses, and a thumbnail of one swatch's worth of it; `library.use` adds the pattern and its swatch to the document (the
|
||||
same pattern there is reused, and a name the document gives another pattern gets a number) and paints the selection's
|
||||
fill or stroke with it, as one undo step, and returns the pattern's name in the document as `pattern`. `library.get`
|
||||
lists them as `gradients: [{name, gradient}]` and `patterns: [{name, pattern, thumbnail}]`.
|
||||
|
||||
Items can be put in user-named groups, which the panel shows as collapsible sections after the ungrouped items (its
|
||||
search field filters every item by name; `library.get` lists them all to filter). `library.createGroup {library?,
|
||||
name?, items?: [{kind, item}]}` makes one (a name another group has, ignoring case, gets a number) with those items
|
||||
@@ -2045,15 +2071,17 @@ deletes one, its items staying in the library ungrouped; and `library.moveItem {
|
||||
of its kind), just before or after that item in the order its kind is listed and shown in. `library.moveGroup
|
||||
{library?, group, to}` moves a group to place `to` of the list (0: first; past the end: last). Dragging items and
|
||||
group headers in the panel runs these. An item is in one group at most; `library.get` lists the groups as `groups:
|
||||
[{name, items: [{kind: "color"|"charStyle"|"paraStyle"|"graphic", item}]}]` (a graphic by its id), and each kind's
|
||||
[{name, items: [{kind: "color"|"gradient"|"pattern"|"charStyle"|"paraStyle"|"graphic", item}]}]` (a graphic by its id), and each kind's
|
||||
items in the order the panel shows them.
|
||||
|
||||
`library.export {library?, path?}` writes a library (its colours, styles, graphics with their art and thumbnails, and
|
||||
its groups) as a `.vclibrary` file, the JSON the library folder keeps (without `path`: `{data}`, the file's text).
|
||||
`library.export {library?, path?}` writes a library (its colours, gradients, patterns, styles, graphics with their art
|
||||
and thumbnails, and its groups) as a `.vclibrary` file, the JSON the library folder keeps (without `path`: `{data}`, the file's text).
|
||||
`library.import {path? | data? | dataBase64?, name?}` adds the library of such a file as a new library and makes it
|
||||
the current one; a name another library has gets a number (`Brand (2)`). Imported files are checked: at most 10,000
|
||||
items of each kind and 1,000 groups, names clipped and made unique, thumbnails kept only when they are small PNGs, and
|
||||
groups naming items that aren't there dropped. Files written before groups load as they are.
|
||||
items of each kind and 1,000 groups, names clipped and made unique, thumbnails kept only when they are small PNGs,
|
||||
gradients with fewer than 2 or more than 1,024 stops dropped and the others' offsets, opacities and midpoints put in
|
||||
range, and groups naming items that aren't there dropped. Files written before groups load as they are. Using a
|
||||
pattern whose data is damaged fails with an error and leaves the document as it was.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"library.add","params":{"kind":"graphic","name":"Logo"}}}
|
||||
@@ -2122,7 +2150,8 @@ couldn't be decoded and is missing from the picture", the note raster exports gi
|
||||
|
||||
In pattern editing mode the tile edge (`pattern.options {showTileEdge}`) and the swatch bounds (`pattern.options
|
||||
{showSwatchBounds}`: the part of the tiling the swatch repeats, dashed) are drawn in the preference
|
||||
`patternTileEdgeColor`.
|
||||
`patternTileEdgeColor`. There `object.exitIsolation` (the Exit Isolation Mode item of the canvas context menu and of the
|
||||
Layers panel menu) saves the tile art into the pattern and leaves the mode, as `object.pattern.done` does.
|
||||
|
||||
`object.pattern.make {name?}`, `object.pattern.saveCopy {name?}` and `pattern.options {newName?}` trim the white space
|
||||
around the name they are given. The first two number a name that a pattern, a swatch or a color group has ("Dots 2"),
|
||||
@@ -2137,6 +2166,12 @@ old name keeps it. A blank name gives "New Pattern N" in `object.pattern.make` a
|
||||
{"name":"run_command","arguments":{"command":"prefs.set","params":{"key":"patternTileEdgeColor","value":"#ff4f4f"}}}
|
||||
```
|
||||
|
||||
Pattern editing mode and opacity mask editing exclude each other. In pattern editing mode
|
||||
`transparency.editOpacityMask` and `transparency.viewOpacityMask` are off, and `transparency.makeOpacityMask` refuses
|
||||
one target, an object or a layer, which it would take into mask editing; a call returns an error that ends "finish
|
||||
editing the pattern first". While a mask is edited, `object.pattern.edit` and `object.pattern.make` (also with
|
||||
`edit: false`) are off, and a call returns an error that ends "stop editing the opacity mask first".
|
||||
|
||||
Pathfinder Options: `object.pathfinder.options {precision?, removeRedundantPoints?, removeUnpainted?}` (or
|
||||
`prefs.get`/`prefs.set` with key `pathfinder`) reads and sets the options every later Shape Mode and Pathfinder
|
||||
operation uses: `precision` (0.001–10 pt, default 0.01; a string with a unit also reads) is how closely results follow
|
||||
@@ -2152,7 +2187,8 @@ whatever the options are then.
|
||||
```
|
||||
|
||||
The Eyedropper: `appearance.copyFrom {source}` copies what the Eyedropper Options pick up and apply from `source` to the
|
||||
selection (`ids`); `reverse: true` copies the selection's attributes onto `source` (Alt-click) and `append: true` adds
|
||||
selection (`ids`); `reverse: true` copies the selection's attributes onto `source` (Alt-click), or with nothing selected
|
||||
what the last copy without `reverse` picked up (a copy made then, kept for the session), and `append: true` adds
|
||||
the source's fills and strokes on top of each target's stack (Shift+Alt-click). The options live in the preferences:
|
||||
`eyedropper.setOptions {sampleSize?, pickUp?, apply?}` (or `prefs.get`/`prefs.set` with key `eyedropper`) reads and
|
||||
sets them; a tree names flags under `appearance` (`transparency`, `fill` `{color, transparency, overprint}`, `stroke`
|
||||
@@ -2195,7 +2231,8 @@ and `layerRows`, the rows highlighted in the panel.
|
||||
- **Buttons**: `layer.new {name?, top?, below?, …options}` (above the current layer at its level; `top` with
|
||||
Ctrl/Cmd; `below`, directly below the current layer at its level, with Ctrl/Cmd+Alt),
|
||||
`layer.newSublayer {parent?, bottom?, name?, …options}` (on top of the parent's contents; `bottom`, under them but
|
||||
above a clipping layer's clipping path, with Ctrl/Cmd+Alt), `layer.delete {ids?}` (rows with what they hold; the
|
||||
above a clipping layer's clipping path, with Ctrl/Cmd+Alt; both refused while an opacity mask is edited),
|
||||
`layer.delete {ids?}` (rows with what they hold; the
|
||||
last layer stays), `layer.locate {id?}` (highlights the selected object's row; the panel opens the rows around it)
|
||||
and `layer.clippingMask.toggle`.
|
||||
- **Panel menu**: `layer.duplicate {ids?}`, `layer.merge {ids?}` (into the layer highlighted last, keeping the
|
||||
@@ -2270,7 +2307,8 @@ is edited the panel lists only an `<Opacity Mask>` entry and the document tab sa
|
||||
|
||||
`effect.expandAppearance {ids?, target?}` (Object → Expand Appearance, enabled when a selected or targeted object's appearance isn't basic)
|
||||
turns appearances into plain objects in one undo step: each visible fill becomes a copy of the path painted by that
|
||||
fill alone and each stroke its outline filled with its paint (a brushed stroke: its brush art), grouped in paint order
|
||||
fill alone and each stroke a copy of the path stroked by that stroke alone, its weight, caps, joins, dashes, arrowheads,
|
||||
alignment and width profile kept as stroke attributes (a brushed stroke: its brush art), grouped in paint order
|
||||
under the object's id; each piece takes its fill's or stroke's opacity and blend mode, and the group keeps the
|
||||
object's transparency and opacity mask. Geometry effects are baked; raster effects become an embedded image at the
|
||||
document's raster effects resolution (shadows and outer glows under the art; a blur, feather or inner glow replaces
|
||||
@@ -2279,6 +2317,12 @@ is outlined; type that has no fills or strokes of its own and whose only effects
|
||||
type, with the image under it. A group's or layer's own fills and strokes become objects among its members, and its
|
||||
members are expanded too. The result is `{ids}`; when an image in the art can't be decoded, the images made from
|
||||
raster effects do not show it, and the result also carries the `warning` that Flatten Transparency gives.
|
||||
A path's strokes stay strokes, as the
|
||||
[Expand objects](https://helpx.adobe.com/illustrator/desktop/manage-objects/arrange-objects/expand-objects.html) help
|
||||
page's two steps imply (Expand Appearance first, then Expand, whose Stroke option outlines strokes): `object.expand`
|
||||
or `object.path.outlineStroke` outline them (#3089). Object → Expand… in the menus is dimmed while the selection has
|
||||
an appearance Expand Appearance expands (`object.expand.info`'s `appearance`); `object.expand` itself still bakes
|
||||
effects and outlines strokes in one step.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"effect.expandAppearance","params":{"ids":[12]}}}
|
||||
@@ -2395,7 +2439,8 @@ an instance when the effects in the symbol's art, or the instance's own, paint o
|
||||
|
||||
`object.expand {object?, fill?, stroke?, gradient?, steps?}` (Object → Expand…) turns the selection into plain art in
|
||||
one undo step. `object` (on by default) outlines type, turns live shapes into paths and bakes effects; `stroke` (on)
|
||||
outlines strokes into filled paths; `fill` (on) expands gradient fills: with `gradient: "objects"` (the default) into
|
||||
outlines strokes into filled paths, the stroked paths that baking effects leaves included (a group's own stroke among
|
||||
them, #3089); `fill` (on) expands gradient fills: with `gradient: "objects"` (the default) into
|
||||
`steps` (1–1000, default 255) solid objects (rectangles across a linear gradient, each from its band to the far end so
|
||||
no seams show; concentric ellipses for a radial one, largest first; just the bands when stops are translucent), with
|
||||
`gradient: "mesh"` into a gradient mesh that paints the gradient (columns or rings where its colour changes, sharp at
|
||||
@@ -2421,9 +2466,10 @@ or a geometry effect on a group or type, which the canvas draws turned or scaled
|
||||
and those of the object shape the outline of the clip group, the gradient fits that outline and the tiles reach its
|
||||
box, as the canvas paints the fill; the expanded art does not keep them. With `fill: false` gradient and pattern fills
|
||||
stay live. `object.expand.info` answers which options have something to expand in the selection
|
||||
(`{object, fill, stroke, gradient}`; `gradient` says whether Fill has a gradient fill, which Expand Gradient To
|
||||
applies to), and `object.mesh.create` on a gradient-filled object colours the mesh points as the
|
||||
gradient paints them, with the colors Object › Expand gives them.
|
||||
(`{object, fill, stroke, gradient, appearance}`; `gradient` says whether Fill has a gradient fill, which Expand
|
||||
Gradient To applies to; `appearance` whether the selection has appearance attributes Expand Appearance expands first,
|
||||
for which Object → Expand… is dimmed in the menus), and `object.mesh.create` on a gradient-filled object colours the
|
||||
mesh points as the gradient paints them, with the colors Object › Expand gives them.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"object.expand","params":{"stroke":false,"gradient":"mesh"}}}
|
||||
@@ -3053,7 +3099,11 @@ Pen's second anchor at (150, 431), in line with the square's centre.
|
||||
kerning to Auto in the type objects in `ids`, the Type tool's selected text or the selected type objects; at a caret
|
||||
it resets only the kerning of the character before it. `type.resetHorizontalScale` (Cmd+Shift+X,
|
||||
`press_key {key: "X", mods: {cmd: true, shift: true}}`) sets the horizontal scale to 100%, as the Character panel
|
||||
shows it, in the same text; at a caret it leaves the text as it is.
|
||||
shows it, in the same text; at a caret it leaves the text as it is. In the app, `type.highlightKerning` (Cmd+Alt+K),
|
||||
`type.highlightTracking` (no default key) and `type.highlightFontName` (Cmd+Alt+Shift+F) show the Character panel and
|
||||
give its Kerning or Tracking field the keyboard focus with the value selected, or open its font family menu with the
|
||||
search field focused; each replies `{field: "kerning" | "tracking" | "fontName"}`. Without selected type or text the
|
||||
Type tool edits, the panel shows and the command fails.
|
||||
- `missingGlyphProtection` (on by default): `text.setStyle` and `text.setRangeStyle` changing the font leave the
|
||||
characters the new font has no glyph for in the font that had one.
|
||||
- `typeSelectionByPathOnly` (off by default): on, the Selection tools (`pointer_gesture` with `selection`, and the
|
||||
@@ -3245,6 +3295,11 @@ The art's bounds are the bounds of the art that shows, with its strokes and effe
|
||||
hidden objects, guides and template layers do not count, and symbol instances are measured by their art. A page or artboard holds the objects
|
||||
whose shown art lies on it; a hidden object on it is still placed and stays hidden, as do the hidden members of the groups placed.
|
||||
`replace` and the `width` and `height` that `file.place` answers also measure symbol instances by their art.
|
||||
`file.place` decodes the pixels of a PNG, JPEG, GIF or WebP file within the decode allowance before placing it. When
|
||||
they can't be read, as with a PNG cut short by a download or a sync still running, it fails with "the image's pixels
|
||||
can't be read" and places nothing; `clipboard.importImage` fails the same way. A JPEG cut short is placed when its
|
||||
pixels still decode. Both keep the decoded pixels (except a CMYK JPEG's) in the image store the renderers share, so the first render
|
||||
that draws the image does not decode the file again.
|
||||
`file.place.info` describes a file without placing it and `image.info` reports a placed image's link, colour mode and
|
||||
effective ppi. `file.place.queue` loads the place cursor (the `place` tool) with several files: headless, drive it
|
||||
with `pointer_gesture` (a click places at 100% with the top-left corner there, a drag at the dragged size) and
|
||||
@@ -3528,8 +3583,10 @@ The result lists `missingLinks`
|
||||
path isn't followed) when it isn't. The desktop app also checks the active document's links when its window
|
||||
comes back to the front, following the same preference. `links.check` reports every link's `status` (`ok`, `modified`,
|
||||
`missing`), `links.update {ids?}` reads modified files again and `links.relink {ids?, path | folder}` points images at
|
||||
another file (or each at the file of its name in a folder); images keep their bounds, one undo step each. Without a
|
||||
file system (the web), linked images show their previews.
|
||||
another file (or each at the file of its name in a folder); images keep their bounds, one undo step each. A PNG, JPEG,
|
||||
GIF or WebP file whose pixels can't be read is not shown: `links.relink` fails with "the image's pixels can't be
|
||||
read", and `links.update`, or `document.open` when it reads the file, lists it as missing, its images keeping what they
|
||||
showed. Without a file system (the web), linked images show their previews.
|
||||
|
||||
`links.findFiles {folder}` looks in an absolute folder and its subfolders, on separate threads, for the files of the
|
||||
active document's missing links, or of the images and placed documents `ids` whatever their status, and returns at once
|
||||
@@ -5084,7 +5141,11 @@ desktop app. The Flare tool's are its Flare Tool Options (dialog `flareOptions`)
|
||||
(Option on macOS) is held, the dialog's Cancel button reads Reset. Reset puts every option back to the tool's default,
|
||||
leaves a click's `x` and `y` unchanged and keeps the dialog open; `ui.dialogReset` does the same. OK keeps the options
|
||||
(`tool.setOption {tool: "flare", values}`) and the next flare dragged out uses them; a click with the tool opens the
|
||||
same dialog, and its OK also draws a flare there. The Artboard tool's are the active artboard's Artboard Options
|
||||
same dialog, and its OK also draws a flare there. While the center is dragged out, each drag update in which the
|
||||
pointer's document y grows adds one degree per document point to `shape.flare`'s `rotation` (it turns
|
||||
only the rays), decreasing y subtracts the same rate, and unchanged y leaves it. This application rate is independent of event frequency; Shift held keeps
|
||||
the turn as it is. Space held keeps the turn as well. Once the center drag has passed its starting distance, and in the
|
||||
drag that places the rings' end point, Space held moves the flare at its current size. The Artboard tool's are the active artboard's Artboard Options
|
||||
(dialog `artboardOptions`; the Artboard tool's active artboard while it is in use, else the window's; its `x` and `y`
|
||||
are the artboard's top-left corner in document points, while the dialog shows X and Y at the reference point the
|
||||
Transform panel uses, counted from the ruler origin), a graph tool's
|
||||
@@ -5359,6 +5420,10 @@ among the objects takes the others in as more key objects, keeping its options,
|
||||
{"name":"run_command","arguments":{"command":"object.blend.info","params":{}}}
|
||||
```
|
||||
|
||||
With the Blend tool active, `tool.select {tool: "blend"}` finishes the blend, as a click on the tool's button or W
|
||||
does: it drops the object clicked first and stops the next click adding to the blend just made. The document and the
|
||||
selection stay as they are. Choosing any other tool that is already active leaves its work as it is.
|
||||
|
||||
A blend's spine is the straight lines between its key centres until it is edited. `object.blend.info` lists it
|
||||
(`spine.anchors`, `keyAnchors`: the point each key sits on). `object.blend.spine.addAnchor {x, y}` adds a point where
|
||||
the spine passes nearest, `object.blend.spine.moveAnchor {anchor, x, y}` moves a point (a key on it moves along; with
|
||||
|
||||
+2
-1
@@ -278,6 +278,7 @@ separate. Scores and hours unchanged. [Behavior and command details](development
|
||||
| 2026-10-10 | minor | M9 row from main: initial Revolve |
|
||||
| 2026-10-10 | minor | Added the Alpha gate table (core-workflow gate): all six workflows work end to end, `.ai` exchange partial but not blocking; stage stays alpha |
|
||||
| 2026-10-10 | major | Created from ROADMAP.md's milestone table and "Where we're going"; added Current focus and the beta list |
|
||||
| 2026-10-28 | minor | Flare ray rotation follows vertical travel at one degree per document point, independent of pointer event count. Shift freezes the current orientation; Space also freezes rotation on the first update. This is the chosen application interaction rate. Scores and estimates unchanged. |
|
||||
| 2026-10-28 | minor | Drop Shadow Darkness subtracts the normalized amount from RGB source channels or adds it to CMYK/Gray black before profile conversion and blur; near-100% becomes gray black, with shadow opacity separate. SVG keeps live filters for uniform sRGB sources and renders shadows for other RGB profiles, source models and gradients. Gradient-stop adjustment is an application rule; spot/custom colors and composite-source parity remain open. Scores and estimates unchanged. |
|
||||
| 2026-10-28 | minor | Blob Brush Shift locks after clear axial movement, keeps earlier samples fixed, and waits without an off-axis trail. Activation uses raw press displacement in logical screen pixels, with exact quarter-turn boundaries. Explicit application rule; scores and estimates unchanged. |
|
||||
| 2026-10-28 | minor | Flare Tool Options opened by a canvas click previews its settings at that click. Reset refreshes the enabled preview while keeping the dialog open. Cancel discards preview art and tentative options; OK accepts one flare in one Undo step. Editing existing flare artwork remains outside this dialog scope. Scores and estimates unchanged. |
|
||||
@@ -291,6 +292,6 @@ separate. Scores and hours unchanged. [Behavior and command details](development
|
||||
| 2026-10-22 | minor | Tab-drag follow-up: reconcile upstream progress updates and document drag lifecycle, insertion behavior and regression contracts; behavior, scores and estimates unchanged. |
|
||||
| 2026-10-22 | minor | Artwork dragged with Selection switches visible document tabs after a 400 ms hover, then copies editable artwork on canvas release; source and clipboard stay intact; scores and hours unchanged |
|
||||
|
||||
2026-10-28 behavior correction: Flare ray rotation follows vertical travel at one degree per document point, independent of pointer event count. Shift freezes the current orientation; Space also freezes rotation on the first update. This is the chosen application interaction rate. Scores and estimates unchanged.
|
||||
## EPS Save evidence (2026-10-26)
|
||||
|
||||
Ordinary Save and Save As keep EPS as EPS, with the chosen page frame, transparent margins and the complete editable VectorCraft document. Existing import-loss confirmation and transparency warnings remain; the Save TIFF preview is capped at 1024 pixels, while Export retains 2048. See [file-format-parity.md](file-format-parity.md#eps-save-and-source-protection) for limits and regression evidence. This narrows G9 save-back workflow coverage; native Illustrator editing-data fidelity, parity scores and hour estimates are unchanged.
|
||||
|
||||
File diff suppressed because one or more lines are too long
+2
-1
File diff suppressed because one or more lines are too long
+4
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user