mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-13 22:21:59 +00:00
Merge main into feat/korean-line-break-anywhere
This commit is contained in:
@@ -107,7 +107,7 @@ the two can still win that race.
|
||||
| `ui.render` | `{path?, scale?, artboard?, data?, traceViews?}` | render an artboard headlessly (PNG with the pixels of `app.export {format: "png", background: "white"}` at the same scale; `artboard`: its 0-based index, default the first; `traceViews: true`: Image Trace objects draw in their View, as on the canvas, instead of their tracing result): written to `path`, else (or with `data: true` as well) sent back as `pngBase64` |
|
||||
| `ui.render` | `{path?, scale?, artboard?, data?}` | render an artboard headlessly (PNG with the pixels of `app.export {format: "png", background: "white"}` at the same scale; `artboard`: its 0-based index, default the first): written to `path`, else (or with `data: true` as well) sent back as `pngBase64` |
|
||||
| `ui.resize` / `ui.focus` | | |
|
||||
| `app.open` / `app.save` / `app.export` / `app.quit` | `{path, importer?, params?}` / `{path?}` / `{path?, format?, artboard?, range?, scale?, …}` | `app.open` reads every format `document.open` reads (see `document.formats`) and returns its result (`{index, title, format, warnings, …}`; `warnings` say what didn't come in as it was, such as an EPS shown as its preview image and why its PostScript couldn't be read), or null when a dialog asks first or a library loads. The status bar (`ui.inspect` → `ui.status`) counts the `warnings` and names the first that says reading the file left something out (the notes that make Save ask before writing over it), else the first; with several, hovering it lists them in that order, as many as fit in the window (at most 30), then how many more. With `importer` (an importer plug-in's format id, `plugin.<id>`) it runs `file.openWith`: the file opens with that importer, also when a built-in format reads its extension, with the importer's parameters `params` (their defaults when omitted; no dialog asks for them). Without `importer`, `params` go to the importer that opens the file, and a built-in format does not read them. `app.export` encodes through the engine's `document.export` (same options; the document keeps its path) and writes `path` through the host; without `path` it returns `{dataBase64, format, bytes}`, as headless mode does. It refuses a key that no format takes, and an unknown key inside a PDF or EPS option object, before it writes anything (`docs/mcp.md`, Parameter keys). `app.save` refuses a key that no save format takes, beside the path or in `options`, the same way. `app.quit`, `file.close` and `file.closeAll` first open a `saveChanges` dialog for each modified document (they return `{"pending": "saveChanges"}`): `ui.dialog.confirm` saves, `ui.dialog.set {field: "discard", value: true}` then confirm discards, `ui.dialog.cancel` cancels the whole close or quit |
|
||||
| `app.open` / `app.save` / `app.export` / `app.quit` | `{path, importer?, params?}` / `{path?}` / `{path?, format?, artboard?, range?, scale?, …}` | `app.open` reads every format `document.open` reads (see `document.formats`) and returns its result (`{index, title, format, warnings, …}`; `warnings` say what didn't come in as it was, such as an EPS shown as its preview image and why its PostScript couldn't be read), or null when a dialog asks first or a library loads. The status bar (`ui.inspect` → `ui.status`) counts the `warnings` and names the first that says reading the file left something out (the notes that make Save ask before writing over it), else the first; with several, hovering it lists them in that order, as many as fit in the window (at most 30), then how many more. After `app.save`, and `app.export` with a `path`, the status bar counts the reply's `warnings` and names the first, and with several, hovering it lists them in the reply's order (a save's notes start with what the format loses). With `importer` (an importer plug-in's format id, `plugin.<id>`) it runs `file.openWith`: the file opens with that importer, also when a built-in format reads its extension, with the importer's parameters `params` (their defaults when omitted; no dialog asks for them). Without `importer`, `params` go to the importer that opens the file, and a built-in format does not read them. `app.export` encodes through the engine's `document.export` (same options; the document keeps its path) and writes `path` through the host; without `path` it returns `{dataBase64, format, bytes}`, as headless mode does. It refuses a key that no format takes, and an unknown key inside a PDF or EPS option object, before it writes anything (`docs/mcp.md`, Parameter keys). `app.save` refuses a key that no save format takes, beside the path or in `options`, the same way. `app.quit`, `file.close` and `file.closeAll` first open a `saveChanges` dialog for each modified document (they return `{"pending": "saveChanges"}`): `ui.dialog.confirm` saves, `ui.dialog.set {field: "discard", value: true}` then confirm discards, `ui.dialog.cancel` cancels the whole close or quit |
|
||||
| `app.export` with `useArtboards` | `{path, useArtboards: true, range? \| artboards?, …}` | Export As: PNG, JPEG and WebP write one file per chosen artboard (default all; SVG does so for a `range`), `<path stem>-<artboard>.<ext>`, and return `{path, files: [path…]}`; a PDF keeps them as pages of `path`. `useArtboards: false` covers the bounds of the visible art. The menu's Export As… is `file.exportAs`: the `exportAs` dialog (`format`, `useArtboards`, `all`, `range`), then a save dialog and the format's options: `pngOptions` / `jpgOptions` / `webpOptions`, `svgOptions`, or `savePdf` for a PDF with Use Artboards |
|
||||
| `ui.dialog.*` on `gradientStop` | `{field: "color" \| "opacity" \| "location", value}` | double-clicking a stop on the Gradient tool's annotator opens its popover (fields `index`, `x`, `y`, `tab`); set `color` (hex), `opacity` or `location` (percentages) and `ui.dialog.confirm` to apply them to the selected stop. `gradient.selectStop {index}` picks the stop the annotator, the panels and Delete/←/→ (`ui.key`) act on |
|
||||
| `engine.execute` `ui.savePdfDialog` | `{path?, preset?, range?, …document.exportPdf options}` | opens the Save PDF dialog (`file.export.pdf` with no params opens it too). Its fields are the `document.exportPdf` options: set `compatibility` with `ui.dialog.set {field: "compatibility", value: "1.5"}`, a whole section with `{field: "compression", value: {…}}`, the artboards with `__allArtboards: false` and `range`, the visible section with `__section` (General, Compression, Marks and Bleeds, Output, Advanced, Security, Summary). `ui.dialog.confirm` writes `path` (else asks for one), returns `{path, bytes, warnings}` and opens the file when `viewAfterSaving` is set |
|
||||
@@ -118,13 +118,13 @@ the two can still win that race.
|
||||
| `app.export` JPEG options | `{path?, format: jpg, quality?: 0–100, colorModel?: rgb \| cmyk \| gray, method?: baseline \| optimized \| progressive, scans?: 3–5, embedIcc?, imageMap?: none \| client \| server}` | `cmyk` writes ink amounts in the working CMYK space (CMYK colours keep their inks; RGB ones are separated with the colour settings); `embedIcc` (default true) embeds sRGB, the working CMYK profile or a grey profile, generated by the CMS; `imageMap` also writes `<stem>.html` (client-side `<map>`) or `<stem>.map` (NCSA) beside the image for the objects with a URL and an Image Map shape (`attributes.set`), returned in `linked`. The `jpgOptions` dialog has these fields too (`quality` is shown 0–10; a CMYK document defaults to `cmyk`) |
|
||||
| `app.export` PNG-8 and GIF | `{path?, format: png8 \| gif, colors?: 2–256, reduction?: perceptual \| selective \| adaptive \| web \| blackWhite \| gray, dither?: none \| diffusion \| pattern \| noise, ditherAmount?: 0–100, transparency?, matte?, interlaced?, …raster options}` | a palette of at most `colors` entries (art with that many colours or fewer keeps them exactly); pixels under half opacity become one transparent entry unless `transparency` is false, partly transparent edges are blended over `matte` (`none` keeps their colour). `png8` writes an indexed `.png` (1–8 bits per pixel); Export for Screens rows take both. The `png8Options` / `gifOptions` dialogs have these fields |
|
||||
| `app.export` Text and WebP | `{path?, format: txt, encoding?: utf8 \| utf16, lineEndings?: lf \| crlf, selectionOnly?}` / `{format: webp, lossless?, quality?}` | Text writes the stories in stacking order (back to front; a thread once; hidden objects and template layers left out), each line ended by `lineEndings`; `utf16` is little-endian with a byte order mark. Export As → Text opens `txtOptions` (fields `path`, `encoding`, `lineEndings`, `selectionOnly`; OK writes the file). WebP is always lossless: `lossless: false` adds a warning |
|
||||
| `engine.execute` `document.exportForOffice` | `{}` / `{path?, ppi?: 72 \| 150 \| 300, transparent?, artboard?}` | File → Save for Office Documents…: without params opens `saveForOffice` (fields `ppi`, `transparent`, `artboard`; OK picks the file); with params writes the artboard as a PNG (`path`, else a picked file) → `{path}`, and the status bar shows the first of the export's `warnings` as Save As shows a save's notes. Headless it returns `{dataBase64, width, height, warnings}` |
|
||||
| `engine.execute` `document.exportForOffice` | `{}` / `{path?, ppi?: 72 \| 150 \| 300, transparent?, artboard?}` | File → Save for Office Documents…: without params opens `saveForOffice` (fields `ppi`, `transparent`, `artboard`; OK picks the file); with params writes the artboard as a PNG (`path`, else a picked file) → `{path}`, and the status bar shows the export's `warnings` as Save As shows a save's notes. Headless it returns `{dataBase64, width, height, warnings}` |
|
||||
| Native file dialogs | any command with no `path` that needs one (`file.open`, `file.saveAs`, `file.place`, exports…) | on macOS (a sheet on the window) and Linux the dialog doesn't hold the window: the call returns `"cancelled"` at once, `ui.inspect` reports `fileDialog`, and when the person at the computer picks a file the command runs again on the document it was asked for. While it is open another dialog is refused: that call returns `"cancelled"` too, and the status bar (`ui.inspect` → `ui.status`) says `"A file dialog is open: choose there first"`; on macOS `app.quit`, `file.close` and `file.closeAll` return that message and the menu bar does nothing (#592, #867). On Windows the dialog is shown in line: the call returns once it closes. Pass `path` to skip the dialog |
|
||||
| Background Save / Export | `app.save`, `app.export {path}`, `file.save`, `file.saveAs`, `file.saveCopy`, `file.exportForScreens {folder, …}` | with the `backgroundSave` / `backgroundExport` preferences on (the default) the desktop app writes the file from a snapshot on a worker thread: the call returns `{path, background: true, status}` at once (`file.exportForScreens`: `{background: true, status}`, and the files are written into the folder from a snapshot taken at the call), `ui.inspect` lists the jobs still running in `background` (labels such as `"Saving a.vectorcraft"`), and the document counts as saved (as of the snapshot) once its file is written. Quit and Close wait for them. A job that fails reports the error in the status bar only (`ui.inspect` → `ui.status`), a path outside `--automation-write-root` included. With the preferences off (`prefs.set`), saves return once written. `app.save {path?, wait: true}` and `app.export {path, wait: true}` wait for the jobs already running, write the file before they reply whatever the preferences are set to, and return its result or the error. When the save asks first (the question before replacing a file that opened with losses, or on macOS and Linux the file dialog for an untitled document without `path`), the reply is `{pending}` or `"cancelled"` as before, and the save that runs after the answer uses the preferences. A `wait` that is not `true`, `false` or `null` is refused with "`wait` must be true or false", and nothing is written |
|
||||
| `engine.execute` `file.exportForScreens` | `{}` / `{…document.exportForScreens params}` | without params opens `exportForScreens` on the settings the document last exported with (`document.exportSettings`). While the Artboard tool is in use, the artboards it has selected (its `selected` option, the rows the Artboards panel highlights) are checked instead, and `select` is `range`, or `all` when every artboard is selected. Fields: `tab` (`artboards` \| `assets` \| `layers` \| `selection`; OK reads Export Layer or Export Selection on those), `layers` ([layer id…] checked), `selectionMode` (`one` \| `each`), `name` (the file name pattern of `document.exportForScreens`), `counterStart`, `folders` (`none` \| `rows` \| `format` \| `item` \| `itemFormat`), `exportPreset` (the preset applied last), `__savePreset` (the name typed to save one), `select` (`all` \| `range` \| `full`), `range` ("1-3, 5"), `boards` (a bool per artboard; checking them sets `select` and `range`), `includeBleed`, `folder` (desktop; default the Desktop, else home), `openLocation`, `subfolders`, `prefix`, `preset` (`""` \| `mobile` \| `density`), `formats` (rows `{format, scale: "2x" \| "100w" \| "100h" \| "72ppi", suffix, quality?, folder?}`), `settings` (`{png \| png8 \| jpg \| webp \| gif \| svg \| pdf: {…options}}`, the gear's Format Settings; `__settings` names the format shown). `ui.dialog.confirm` exports (a bad range or no folder keeps it open); on the web OK reads "Download" and the files download (several as one `.zip`). With params it runs `document.exportForScreens`: no `folder` returns the files (or with `zip: true` one zip) as `dataBase64`; with `openLocation` the first file is shown in the file manager. When `warnings` is not empty, an export into a folder or a download shows the first in the status bar as Save As shows a save's notes |
|
||||
| Export for Screens' Assets tab, Asset Export panel | `ui.dialog.set` `tab: "assets"`, `assets: [asset id…]`; `window.panel {panel: "assetExport"}` | on the Assets tab of `exportForScreens` the `assets` field lists the checked asset ids (all of them when it opens); `ui.dialog.confirm` runs `document.exportForScreens {assets}` (nothing checked keeps it open) and OK reads "Export Asset". The Asset Export panel acts through `assets.*` and shares the format rows with the dialog (`assets.settings.set`). The dialog has the format presets menu (☰). In the dialog, `exportPreset` names the preset applied last (`ui.dialog.set` of it applies the preset it names, as picking it does; a name that is not a preset's is an error and leaves the dialog as it was), `__exportPresets` lists the presets, and `__savePreset` holds the name being typed after Save Preset…. The panel menu applies presets through `assets.settings.set {exportPreset}` and holds Save As Preset…, Save Changes, Delete Preset, Import Preset… and Export Preset…. Import and Export use picked files. |
|
||||
| `engine.execute` `file.exportSelection` | `{multiple?}` | File › Export Selection…: collects the selected objects as one asset (`assets.add`; one per object with `multiple: true`) and opens `exportForScreens` on its Assets tab with just them checked → `{assets}`. `document.exportSelection` still exports the selection in one go, without the dialog |
|
||||
| CSS Properties panel | `window.panel {panel: "cssProperties"}`; `engine.execute` `css.copy` / `css.exportFile` | the panel shows `css.selection` of the selection (after Generate CSS, while nothing is selected, `css.generate`); its menu holds the options the commands take (`units`, `position`, `dimensions`, `unnamed`, `rasterize`). `css.copy {scope?, …options}` copies the CSS to the clipboard → `{css, rules}`; `css.exportFile {path?, scope?, …options}` writes `css.export` to `path` (else a picked file; the web downloads it) with the pictures of rasterized art next to it → `{path, rules, images, warnings}`, and the status bar shows the first of `warnings` as Export As shows an export's notes |
|
||||
| CSS Properties panel | `window.panel {panel: "cssProperties"}`; `engine.execute` `css.copy` / `css.exportFile` | the panel shows `css.selection` of the selection (after Generate CSS, while nothing is selected, `css.generate`); its menu holds the options the commands take (`units`, `position`, `dimensions`, `unnamed`, `rasterize`). `css.copy {scope?, …options}` copies the CSS to the clipboard → `{css, rules}`; `css.exportFile {path?, scope?, …options}` writes `css.export` to `path` (else a picked file; the web downloads it) with the pictures of rasterized art next to it → `{path, rules, images, warnings}`, and the status bar shows `warnings` as Export As shows an export's notes |
|
||||
|
||||
| `ui.dialog.*` on `importPdf` | `{field: "page" \| "allPages" \| "range" \| "cropTo" \| "password", value}` | opening (`app.open`, `file.open`) a PDF, `.ai` or `.ait` with a password, or one with several pages unless it is a `.ai` or `.ait` with its editing data or carries its VectorCraft document (those open whole), or placing (`file.place` without `page`) any of them with several pages or a password, opens the Import PDF dialog (`mode`: `open` or `place`; `pageCount`). While `__locked` is true, set `password` and `ui.dialog.confirm` to unlock it (a one-page file then opens or is placed). Then set `allPages: false` and `range` ("2-3, 5") to open some pages, or `page` to place one, and `cropTo` (`bounding`, `art`, `crop`, `trim`, `bleed`, `media`); `ui.dialog.confirm` opens or places them (placing keeps the other `file.place` params, such as `link`, `template` and `at`, in `__place`). `document.open {pages, cropTo, password}` and `file.place {page, crop, password}` do the same without the dialog |
|
||||
|
||||
@@ -217,7 +217,9 @@ export's own parameters); `ui.dialog.confirm` writes the file. An importer plug-
|
||||
`pluginImport` dialog when `file.openWith` is given no `params`: one field per parameter, `__plugin`, and `__open`
|
||||
(`path` and `importer`); `ui.dialog.confirm` opens the file. `ui.installPlugin {path?}` installs a `.wasm` (without
|
||||
a path it asks for one); one that needs approval opens the `pluginInstall` dialog, which only a person can confirm
|
||||
(`ui.dialog.confirm` and injected input are refused); see [plugins.md](plugins.md).
|
||||
(`ui.dialog.confirm` and injected input are refused). When a control request opened it, directly or through a file
|
||||
dialog, the reply adds `approval: "personMustStartInstall"` and nobody can confirm it: the person chooses Object ›
|
||||
Plug-ins › Install Plug-in… to install the plug-in; see [plugins.md](plugins.md).
|
||||
|
||||
Overprint Black: the Edit → Edit Colors → Overprint Black… menu item opens a `command` parameter dialog for
|
||||
`edit.colors.overprintBlack` (fields `remove`, `percentage`, `fill`, `stroke`, `includeCmyBlacks`,
|
||||
@@ -711,8 +713,9 @@ with.
|
||||
DXF Options: Export As… with the DXF format (`file.exportAs {format: "dxf"}`, then the save dialog), or
|
||||
`ui.dxfOptionsDialog {path?, …document.exportDxf options}` for agents, opens the `dxfOptions` dialog. Its fields are
|
||||
`document.export` params: `dxfPreset` (`custom`, `cnc`), `version`, `unit` (a unit name such as `Millimeters`), `scale`,
|
||||
`scaleLineweights`, `colors` (`8`, `16`, `256`, `true`), `rasterFormat` (`png`, `jpeg`), `preserve` (`appearance`,
|
||||
`editability`), `selectedOnly`, `alterPaths`, `outlineText`, plus `path` and the artboard choice. Setting `dxfPreset` to
|
||||
`scaleLineweights`, `colors` (`8`, `16`, `256`, `true`), `rasterFormat` (`png`, `jpeg`), `includeImages` (Include
|
||||
Placed Images), `preserve` (`appearance`, `editability`), `selectedOnly`, `alterPaths`, `outlineText`, `includeHatches`
|
||||
(Include Fill Hatches), plus `path` and the artboard choice. Setting `dxfPreset` to
|
||||
`cnc` sets the fields it sets (see `document.exportDxf`), and `dxfPreset` reads `custom` again once one of them is
|
||||
changed; setting it to `custom` puts back the defaults. `ui.dialog.confirm` checks them (a bad value, or
|
||||
Export Selected Art Only with nothing selected, keeps the dialog open), remembers them for the next DXF Options and
|
||||
@@ -821,7 +824,7 @@ a preset) plus `__view` (`original`, `optimized`, `2up`, `4up`), `__zoom` (`fit`
|
||||
the image, or the page with HTML output; the web downloads the files); with `discard: true` it is Done: it remembers
|
||||
the settings and closes. `file.saveForWeb` with settings saves without the dialog, and `file.saveForWeb.browser`
|
||||
writes the HTML page to a temporary folder and opens it in the default browser (desktop). Both return the export's
|
||||
`warnings`, and the status bar shows the first one as Save As shows a save's notes.
|
||||
`warnings`, and the status bar shows them as Save As shows a save's notes.
|
||||
|
||||
PSD Options: Export As… with the PSD format (`file.exportAs {format: "psd"}`, then the save dialog) opens `psdOptions`:
|
||||
the raster rows of PNG Options (`ppi`, `background`, `antiAlias`), then `colorModel` (`rgb`, `cmyk`, `gray`; a CMYK
|
||||
@@ -1063,7 +1066,7 @@ app:
|
||||
| `vectorcraft.docInspect(params)` / `vectorcraft.uiInspect(params)` | `document.inspect` / `ui.inspect` |
|
||||
| `vectorcraft.inspect()` | `ui.inspect` (the name before `uiInspect`) |
|
||||
| `vectorcraft.screenshot(params)` | `ui.screenshot` (no `path`: the PNG comes back inline, as `data` and as `pngBase64`) |
|
||||
| `vectorcraft.openFile(name, bytes)` | opens the bytes the way a dropped file opens (returns `true` once queued) |
|
||||
| `vectorcraft.openFile(name, bytes)` | opens the bytes the way a dropped file opens, as automation: a plug-in install it asks for has to be started by the person (returns `true` once queued) |
|
||||
| `vectorcraft.captureDownloads(on)` | while on, a save or export is kept in the page instead of downloaded |
|
||||
| `vectorcraft.files()` / `vectorcraft.readFile(name)` | the kept files (`{path, size}`) / one of them as a `Uint8Array` |
|
||||
|
||||
|
||||
@@ -290,7 +290,7 @@ Names in the editing data that aren't UTF-8 (layers, objects, artboards, colors,
|
||||
| EPS | open, place, save | yes (own PostScript L3 interpreter, Illustrator EPS editing data structure) | yes (L2/L3, TIFF previews) | CIDFonts the file doesn't carry not drawn, but for those over a predefined Unicode CMap (`UniJIS-UCS2-H`), set as type in the font of the CIDFont's name; name-keyed fonts in a FontSet set as type by name; #505; images encoded with `CCITTFaxDecode` (ITU-T T.4 Group 3 and T.6 Group 4, with `K`, `Columns`, `Rows`, `EndOfBlock`, `EndOfLine`, `EncodedByteAlign` and `BlackIs1`) draw, and damaged data keeps the rows decoded before its first damaged row; Type 42 (TrueType) fonts set type at its size (#1553); an embedded Type 1 font's encrypted part is read for its glyphs, which space its type, outline it and draw glyphs without a character, in plain and composite fonts; a Type 42 font that carries its TrueType font gives each code its character by its glyph name or, for names that say nothing (`/g12`), by the glyph's entry in the font's own character map, spaces its type by its own widths and draws glyphs that stand for no character from its outlines; the show operators' spacing along the baseline (`ashow`, `widthshow`, `xshow`, `yshow`, `xyshow`, and the moves of `kshow`'s procedure, run between each two characters) is kept on live type as tracking, so type in a font that isn't installed keeps the file's line lengths (spacing that moves characters off the baseline, as `yshow`, `xyshow` or a `kshow` procedure can, places each character as its own text object); composite (Type 0) fonts with the 8/8 mapping, as PDF-to-PostScript converters write two-byte fonts, draw a Type 42 descendant's glyphs from the TrueType outlines it carries and an embedded Type 1 descendant's from its charstrings, and set other descendants' characters as type at the composite font's size (other mappings are still set as type in the font of their name); CID-keyed fonts (`composefont`, `FMapType` 9 over a CMap built with the CIDInit operators or `Identity-H`/`Identity-V`; `bfchar` and `bfrange` mappings give a base-font descendant its codes or glyph names) draw the glyphs of the Type 0 CIDFonts (Type 1 charstrings in their `StartData` binary data or `GlyphDirectory`) and Type 2 CIDFonts (TrueType glyphs through `CIDMap`) they carry, and the CID-keyed fonts of a FontSet's Compact Font Format data (Type 2 charstrings); a clip only counts as covering the page when its shape does (#1542); an EPS another app copied pastes as editable vector art (`clipboard.importEps`, #1499); a stitched shading keeps its hard colour changes on import (#1654); sampled functions (type 0) interpolate between their samples, multilinearly or by cubics with `Order 3`, and a sampled axial or radial gradient has a stop at each sample; a gradient the page paints as a row of abutting one-colour strips (as Level 2 writers draw smooth shades) imports as one linear gradient, without the seams the strips leave when each is drawn alone; CMYK images, CMYK JPEGs included, keep their ink amounts on import, as from PDF, and the pixels a `MaskColor` or `ImageType 3` mask hides become a grayscale opacity mask; ruzstd 0.9.1 for compressed editing data (#1807, RUSTSEC-2026-0344) |
|
||||
| PostScript `.ps` | open, place | yes (the EPS reader reads its first page; `.epsf` files open and place as EPS) | via Print to PostScript | `tests_epsimport.rs` |
|
||||
| SVG / SVGZ | open, place, save | yes | yes (SVG Options, Preserve Editing, symbols, filters, rich text) | strongest format; tests in `crates/svg/tests`; text on a path follows basic shapes as their SVG 2 equivalent paths (#1527); CSS transforms and the `font` shorthand (#1565), percentage lengths in symbols (#1596), Inkscape flowed text as area type (#1568) and Inkscape pages as artboards (#1601) import; an unsupported filter is named in its warning (#1598); an artboard exported on its own (Export As with Use Artboards, Export for Screens, Asset Export) has the artboard's name as `<title>`, Save the document's (#3544); attributes in other applications' XML namespaces (`plotter:pen="2"`) kept on their objects from import to export, as `data-*` attributes are (`crates/svg/tests/it/foreign_attributes.rs`); simple shapes export as `<rect>`, `<circle>`, `<ellipse>`, `<line>`, `<polygon>` and `<polyline>` where they draw the same as the path (#4652, `crates/svg/tests/it/basic_shapes.rs`); the regions of exported masks and filters (opacity masks, inverted masks, knockout groups) cover the art they apply to, and over type keep a region that covers any artwork (#6401, `crates/svg/tests/it/blend_export.rs`) |
|
||||
| DXF | open, export | yes | yes (R12–2018) | R13–2018 closed SPLINE flags and control-point closure on import verified (#1299); circular cubic paths export as native CIRCLE/ARC where stroke semantics permit; R12 weighted strokes remain POLYLINE while non-circular curves keep the existing fallback (`crates/cad/src/tests.rs`); [Autodesk group 70](https://help.autodesk.com/cloudhelp/2024/ENU/AutoCAD-DXF/files/GUID-E1F884F8-AA90-4864-A215-3182D47A9C74.htm). DXF 2000–2018 LAYOUT objects write the paper image origin as 148/149 (was a stray 158), the shade plot codes (2004+) and the model type flag, and the plot style placeholder carries no subclass marker (#3085; structure test `r2000_and_later_files_have_the_structure_cad_apps_require`, checked with ezdxf's audit; not yet confirmed in Autodesk Fusion). CNC preset and VCarve QA remain open |
|
||||
| DXF | open, export | yes | yes (R12–2018) | R13–2018 closed SPLINE flags and control-point closure on import verified (#1299); circular cubic paths export as native CIRCLE/ARC where stroke semantics permit; R12 weighted strokes remain POLYLINE while non-circular curves keep the existing fallback (`crates/cad/src/tests.rs`); [Autodesk group 70](https://help.autodesk.com/cloudhelp/2024/ENU/AutoCAD-DXF/files/GUID-E1F884F8-AA90-4864-A215-3182D47A9C74.htm). DXF 2000–2018 LAYOUT objects write the paper image origin as 148/149 (was a stray 158), the shade plot codes (2004+) and the model type flag, and the plot style placeholder carries no subclass marker (#3085; structure test `r2000_and_later_files_have_the_structure_cad_apps_require`, checked with ezdxf's audit; not yet confirmed in Autodesk Fusion). DXF Options' Preset menu and `document.exportDxf`'s `dxfPreset: "cnc"` set the CNC / CAM options (#5500); VCarve QA remains open |
|
||||
| HP-GL/2 `.plt`, `.hpgl`, `.hgl`, `.hpg` | — | yes (pen moves, pens and widths, line types and attributes, circles, arcs, wedges and Bézier curves, filled and edged rectangles, wedges and polygons, encoded polylines, scaling and rotation; labels, symbol mode, raster images and hatching aren't drawn) | no | recognized by its first instructions after any printer escapes, under its own extensions or one no other format reads; `crates/cad/src/hpgl/tests.rs`, `tests_hpgl.rs`, `import_fuzz.rs` |
|
||||
| DWG | open, export | no | no | no open spec; DXF instead |
|
||||
| EMF / WMF | open, export | yes | yes | an oversized embedded PNG or JPEG is refused from its header, before any pixels are decoded (#1776) |
|
||||
|
||||
+8
-7
@@ -323,8 +323,7 @@ macOS cursor delivery (#2292) is narrowed to a native host adapter using the exi
|
||||
|
||||
- **Done:** Numeric fields keep a text drag's start when the pointer gains focus and movement exceeds the click threshold (#1326, in part). A completed focus click selects the whole value; keyboard focus, double-click and numeric stepping remain regression-tested. Short movements still classified as clicks can select all; that case remains open.
|
||||
|
||||
- **Done:** DXF reads control-point SPLINE closure (#1299 follow-up after #1320); open curves keep their open state. DXF export now recognizes circular cubic paths conservatively and writes native CIRCLE/ARC where stroke semantics permit; R12 weighted strokes remain POLYLINE, and a non-circular ellipse keeps the existing fallback. Alter Paths for Appearance outlines only the strokes a CAD line can't draw (aligned, profiled, offset dashes, wider than 2.11 mm, or in R13 and R14), so a 1 pt circle or arc stays a CIRCLE or ARC. CNC preset and VCarve QA remain open. Escape leaves Artboard editing for Selection; during a drag it first cancels the gesture. Headless egui key events cover idle Escape, active-drag cancellation and a subsequent Escape in `tests/distortkeys.rs`.
|
||||
- **Done:** DXF reads control-point SPLINE closure (#1299 follow-up after #1320); open curves keep their open state. DXF export now recognizes circular cubic paths conservatively and writes native CIRCLE/ARC where stroke semantics permit; R12 weighted strokes remain POLYLINE. A closed four-cubic ellipse, or a circle scaled out of proportion, is written as a native ELLIPSE in R13 and later; R12 keeps the existing fallback. CNC preset and VCarve QA remain open. Escape leaves Artboard editing for Selection; during a drag it first cancels the gesture. Headless egui key events cover idle Escape, active-drag cancellation and a subsequent Escape in `tests/distortkeys.rs`.
|
||||
- **Done:** DXF reads control-point SPLINE closure (#1299 follow-up after #1320); open curves keep their open state. DXF export now recognizes circular cubic paths conservatively and writes native CIRCLE/ARC where stroke semantics permit; R12 weighted strokes remain POLYLINE. A closed four-cubic ellipse, or a circle scaled out of proportion, is written as a native ELLIPSE in R13 and later; R12 keeps the existing fallback. Alter Paths for Appearance outlines only the strokes a CAD line can't draw (aligned, profiled, offset dashes, wider than 2.11 mm, or in R13 and R14), so a 1 pt circle or arc stays a CIRCLE or ARC. DXF Options' Preset menu and `document.exportDxf`'s `dxfPreset: "cnc"` set the CNC / CAM options (#5500); VCarve QA remains open. Escape leaves Artboard editing for Selection; during a drag it first cancels the gesture. Headless egui key events cover idle Escape, active-drag cancellation and a subsequent Escape in `tests/distortkeys.rs`.
|
||||
|
||||
- **Done:** Simplify and Add Anchor Points clear stale component selections on rewritten paths; Simplify previews and reports original/new point counts (#1272).
|
||||
- **Done:** Object › Path › Simplify opens its slider at the Auto-Simplify level for the selection and previews that result, as the [manual-simplify page](https://helpx.adobe.com/illustrator/desktop/draw-shapes-and-paths/modify-paths/manually-simplify-paths.html) describes; simplifying only a Direct Selection part of a path is done too (G1).
|
||||
@@ -646,12 +645,14 @@ macOS cursor delivery (#2292) is narrowed to a native host adapter using the exi
|
||||
Direct Selection of a path, compound path or type inside a dynamic instance also takes opacity and blend
|
||||
(`transparency.set`) and a gradient or pattern fill or stroke (`paint.setFill` / `paint.setStroke`,
|
||||
Eyedropper), for that instance only;
|
||||
graphic style libraries (Window › Graphic Style Libraries; nine original libraries generated in code, including
|
||||
graphic style libraries (Window › Graphic Style Libraries; ten original libraries generated in code, including
|
||||
Game HUD with Health Fill, Mana Glow, Damage Flash, Quest Outline, Coin Shine and Boss Alert, Status Effects
|
||||
with Poison Tint, Freeze Edge, Burn Aura, Stun Pulse, Stealth Fade and Shield Buff, and Textures with Fine Grain,
|
||||
Canvas Weave, Burlap Sack, Cracked Glaze, Mosaic Floor, Quilted Squares, Leaded Glass and Damp Paper, painted with
|
||||
the texture effects; User Defined; Other Library…; `graphicStyle.libraries`, `graphicStyle.addFromLibrary`).
|
||||
- **Missing:** more built-in brush libraries beyond the six shipped (and further graphic-style libraries beyond the nine shipped, and further symbol libraries beyond Basic
|
||||
with Poison Tint, Freeze Edge, Burn Aura, Stun Pulse, Stealth Fade and Shield Buff, Painted and Sketched with
|
||||
Washed Blue, Bristle Ochre, Pastel Heather, Charcoal Shade, Ink Contour, Wet Ink and Fine Pen, and Textures with
|
||||
Fine Grain, Canvas Weave, Burlap Sack, Cracked Glaze, Mosaic Floor, Quilted Squares, Leaded Glass and Damp Paper,
|
||||
painted with the texture effects; User Defined; Other Library…; `graphicStyle.libraries`,
|
||||
`graphicStyle.addFromLibrary`).
|
||||
- **Missing:** more built-in brush libraries beyond the six shipped (and further graphic-style libraries beyond the ten shipped, and further symbol libraries beyond Basic
|
||||
Shapes, UI Frames, Map Markers, Inventory Icons and Skill Icons; original, generated in code, never Adobe's); dynamic symbols' `.ai` read and write;
|
||||
Global Edit of groups holding type or images, rotated copies as matches and highlighting matches before the
|
||||
start; 9-slice guides outside the symbol's art (a dragged guide stops at the art's edge).
|
||||
|
||||
+117
-23
@@ -123,6 +123,18 @@ the suite) keep the agent to the folders you give it:
|
||||
- Every file a command writes must lie inside a **write root**: `save_file`, `export`, the save and
|
||||
export commands, Export for Screens, Package, Export for Web, print to file, `screenshot {path}`,
|
||||
library and preset saves to a path, the copies `links.relink {copy}` makes.
|
||||
- A path the agent gives stays in a save or export reply, with the files written beside it. Paths it did not
|
||||
give are left out when they are outside the read roots. `save_file`, `document.save` and `file.save` without
|
||||
a `path` write the document's own file: the reply then has no `path`, and `files` and `linked` name the files
|
||||
written beside it by their file names. A save without a path known (`file.saveAs` and `file.saveCopy` without
|
||||
one, a document never saved) leaves out the suggested `folder`. `document.exportForScreens` into the `folder`
|
||||
of its `exportPreset` leaves out the ZIP's `path` and lists `files` relative to that folder, and an error
|
||||
for that export names the folder by its name alone.
|
||||
`document.exportSettings`, `document.exportPresets.list` and `document.exportPresets.export` (as data and as
|
||||
a file) leave out a kept `folder` outside the read roots. `file.package`
|
||||
names the document's file and the linked files outside the read roots by their file names in `warnings`, in
|
||||
`missingLinks` and in its report. `document.info` gives `link: null` for an image linked to a file outside them,
|
||||
and its Linked Images rows and text report name that file alone. `action.batch` returns the replies of its steps as these commands give them.
|
||||
- `file.list {path}` (through `run_command`) lists a folder's files and folders, held to the read roots like any read, so an agent can see what it was given (#1163).
|
||||
- `file.recentFiles` and the control channel's `ui.menu.list` leave out the recent files outside the read roots. The
|
||||
other File › Open Recent Files rows keep their ids (`file.openRecent3` still opens the third file), and
|
||||
@@ -153,6 +165,11 @@ the suite) keep the agent to the folders you give it:
|
||||
and `modified` the document keeps of that file. Each row keeps its id, `name` (`fileName`), status and other
|
||||
fields. This applies to every document, also one the person or a client with wider roots opened. The paths a
|
||||
client gives `links.relink` and `links.unembed` stay in their replies, and the document's links are not changed.
|
||||
- `prefs.get`, `prefs.list`, `prefs.set` and `prefs.reset` show a folder preference outside the read roots
|
||||
(`fontsFolder`, `pluginsFolder`, `scratchPrimary`, `scratchSecondary`, `recoveryFolder`, `templatesFolder`) as
|
||||
`null`; an empty folder and the scratch disk choices `Startup` and `None` stay. In `prefs.get {}` and
|
||||
`prefs.reset`, an export preset in `screenExportPresets` leaves out its `folder` when the folder is outside the
|
||||
read roots, and the preset stays. The preferences themselves are not changed.
|
||||
- Each flag may be given more than once (#3546): a path inside any of the read roots may be read, one inside any
|
||||
of the write roots written, so one session can read a project folder and a shared assets folder, or write to an
|
||||
output folder and a scratch folder, without widening a root to their common parent. A folder given twice
|
||||
@@ -1336,6 +1353,22 @@ fails with no change. A description with a `…` entry takes more keys than it l
|
||||
object can carry several formats' options). A command that takes its own reply back
|
||||
(`document.setup`, `text.areaOptions`) says so the same way.
|
||||
|
||||
The app's own commands are not checked against their descriptions, but those listed here refuse a value of the wrong
|
||||
type and change nothing: `view.setZoom` (`zoom`, `center`), `view.screenMode` (`mode`), `window.panel` (`toggle`,
|
||||
`toggleGroup`), `file.revert` (`confirmed`), `file.close` (`index`), `ui.newSwatch` (`spot`, `global`),
|
||||
`ui.symbolOptions` (`edit`), `ui.batchDialog` (`set`, `action`) and `file.exportSelection` (`multiple`). So do the
|
||||
control channel's `ui.key`, `ui.move`, `ui.wheel`, `ui.click`, `ui.drag`, `ui.pointer`, `ui.resize`, `ui.screenshot`,
|
||||
`ui.render` and `ui.set` for their numbers, switches and `mods`, and the headless session's key, pointer and screenshot
|
||||
calls. Omitting a param or giving null keeps its default, with two exceptions: `ui.click`'s `count` and `ui.drag`'s
|
||||
`count` and `steps` refuse null, and a headless pointer event needs its `x` and `y`. A pointer event's `pressure`,
|
||||
`holdMs`, `tiltX`, `tiltY` and `rotation` must be numbers and its `space` must be `doc` or `screen`. A pointer packet
|
||||
with one malformed event sends none of its events:
|
||||
|
||||
```json
|
||||
{"id": "view.setZoom", "params": {"zoom": "200"}}
|
||||
→ `zoom` must be a number
|
||||
```
|
||||
|
||||
Saved actions aren't checked this way. When the Actions panel plays an action (Play at any speed, an action's function
|
||||
key, the Batch dialog or `ui.action.play`), a key a command no longer reads, recorded by an older version, is ignored
|
||||
and the action still plays. `Session::replay` plays a journal the same way. The command still refuses an effect
|
||||
@@ -1627,9 +1660,9 @@ control character, in the first 8 KiB) or `tooLarge` (over 8 MiB). For a script,
|
||||
`menuCommand` or `e4x`), each with a count and its lines.
|
||||
- `dom.members` lists the document-model member chains as the script writes them
|
||||
(`app.activeDocument.layers[].name`, with `[]` for an index and `()` for a call); a variable assigned from a chain
|
||||
is replaced by that chain, and a name written with `\u` escapes is read as the name it spells. `dom.types` lists
|
||||
the type names the script compares with `.typename` or creates with `new`, apart from the language's, the platform's
|
||||
and the script's own functions.
|
||||
is replaced by that chain, and a name written with `\uXXXX` or `\u{…}` escapes is read as the name it spells.
|
||||
`dom.types` lists the type names the script compares with `.typename` or creates with `new`, apart from the
|
||||
language's, the platform's and the script's own functions.
|
||||
- `menuCommands.strings` lists the string literals the script passes to `executeMenuCommand`
|
||||
(`app.executeMenuCommand('…')`), each with a count and its lines, and `menuCommands.dynamic` counts the calls
|
||||
whose argument isn't a string literal.
|
||||
@@ -1641,7 +1674,10 @@ control character, in the first 8 KiB) or `tooLarge` (over 8 MiB). For a script,
|
||||
template literals and XML literals that aren't closed, brackets that don't match, syntax newer than ES3 and
|
||||
unknown directives) and notes on its text (bytes that aren't valid UTF-8, mixed line endings, and nesting deeper
|
||||
than the check follows: more than 4,096 open brackets, or XML literals and the code in their braces nested more
|
||||
than 4,096 levels deep).
|
||||
than 4,096 levels deep). Newer syntax includes a private name (`#name`, given with its escapes read, unless the
|
||||
name they spell would make the line a directive) and a `\u{…}` escape in a name (given as written). A `#` and a
|
||||
name at the start of a line is a private name, not a directive, when the name starts with an escape, or when the
|
||||
line is inside braces and the name is not a directive's.
|
||||
|
||||
Each entry of `targets`, `directives`, `includes` and `problems` has the `line` it is on (a problem with the whole
|
||||
text has none) and, when it is in an included file, that file's path as `file`. `features`, `menuCommands.strings`
|
||||
@@ -2919,6 +2955,15 @@ Brushes panel's New Brush button, its menu's New Brush… and art dropped on the
|
||||
Brush Options for the new brush; for a scatter, art or pattern brush they preview the art from `brush.selectionArt`.
|
||||
Their OK runs `brush.new {type, name, params, ids?}`, and Cancel adds no brush.
|
||||
|
||||
`brush.placeArt {name, x?, y?}` places a copy of the art a scatter, art or pattern brush is made of, centered on
|
||||
(`x`, `y`) (default: the center of the first artboard), and selects it, in one undo step. The app runs it when a
|
||||
brush is dragged from the Brushes panel onto an empty part of the canvas; dropped on a path, a brush is applied to it
|
||||
(`brush.apply`). A pattern brush places its tiles left to right, 10 pt apart, in the order side, outer corner, inner
|
||||
corner, start, end (only the tiles it has art for), each in a group named Side Tile, Outer Corner Tile, Inner Corner
|
||||
Tile, Start Tile or End Tile. A tile with a repeat frame has an unpainted rectangle at the back of its group that marks
|
||||
the frame. A symbol instance in the art is measured by its symbol's art. A calligraphic or bristle brush is refused
|
||||
with "`<name>` has no art (only scatter, art and pattern brushes do)".
|
||||
|
||||
`variable.bind`, `variable.unbind`, `variable.delete`, `dataset.set`, `dataset.update`, `dataset.delete`,
|
||||
`dataset.select`, `dataset.next` and `dataset.prev` add no undo step when they leave the document as it was, such as
|
||||
binding art to a variable it already has or applying the active data set again: the steps to redo stay, and a saved
|
||||
@@ -3328,8 +3373,9 @@ in the `swatch.list` shape (`library` is an id or a name). `swatch.library.add {
|
||||
into the document as one undo step: a colour group's name brings the whole group, a swatch's name the swatch alone,
|
||||
no names the whole library; swatches the document already has (same name and paint) are reported under `existing`
|
||||
and not added again. `apply: "fill"|"stroke"` also applies the first one, in the same undo step (what clicking a
|
||||
swatch in the library panel does). The pattern library Geometric Patterns (`geometric-patterns`, category
|
||||
`patterns`) holds pattern swatches drawn in code; adding one also adds its pattern, as pasting art painted with it does
|
||||
swatch in the library panel does). The pattern libraries Geometric Patterns (`geometric-patterns`) and Grit Textures
|
||||
(`grit-textures`: seamless black grain, grit, sand, speckle, stipple, scratch and fleck tiles), category `patterns`,
|
||||
hold pattern swatches drawn in code; adding one also adds its pattern, as pasting art painted with it does
|
||||
(the same pattern the document has is reused, and a name another pattern or swatch has gets a number).
|
||||
`swatch.resetDefaults {replace?}` brings back the missing default swatches.
|
||||
|
||||
@@ -3377,7 +3423,7 @@ as a value left out.
|
||||
## Graphic style libraries
|
||||
|
||||
Graphic style libraries are read-only sets of graphic styles generated in code (Shadows and Glows, Outlines and
|
||||
Rules, Hand-Drawn, Textures, Gradient Finishes, Shape Effects, Blends and Transparency, Game HUD, Status Effects). Textures
|
||||
Rules, Hand-Drawn, Textures, Painted and Sketched, Gradient Finishes, Shape Effects, Blends and Transparency, Game HUD, Status Effects). Textures
|
||||
(`textures`) paints its fills and strokes with the texture effects: Fine Grain (`texture.grain`), Canvas Weave and Burlap
|
||||
Sack (`texture.texturizer`), Cracked Glaze (`texture.craquelure`), Mosaic Floor (`texture.mosaicTiles`), Quilted Squares
|
||||
(`texture.patchwork`), Leaded Glass (`texture.stainedGlass`) and Damp Paper (`sketch.waterPaper`). `graphicStyle.libraries` lists them
|
||||
@@ -3390,6 +3436,13 @@ the patterns the styles paint with come along. `apply: true` also applies the fi
|
||||
does. Library styles keep placed gradients in unit-box space, so each object gets them at the same place relative to
|
||||
its bounds.
|
||||
|
||||
Painted and Sketched (`painted-sketched`) holds Washed Blue, Bristle Ochre, Pastel Heather, Charcoal Shade, Ink
|
||||
Contour, Wet Ink and Fine Pen. Each is a solid fill (Bristle Ochre and Ink Contour add a 1 pt stroke) under one object
|
||||
effect that repaints fill and stroke together: `artistic.watercolor`, `artistic.dryBrush`, `artistic.roughPastels`,
|
||||
`sketch.charcoal`, `brushStrokes.inkOutlines`, `brushStrokes.sumiE` and `sketch.graphicPen`, in that order. The
|
||||
colors and effect settings are VectorCraft's own. These are raster effects, so the document's raster effects
|
||||
resolution sets how fine they draw.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"graphicStyle.library","params":{"library":"hand-drawn"}}}
|
||||
{"name":"run_command","arguments":{"command":"graphicStyle.addFromLibrary","params":{"library":"hand-drawn","name":"Crosshatch","apply":true}}}
|
||||
@@ -5925,8 +5978,11 @@ DXF layer (hidden layers switched off, locked ones locked, non-printing ones not
|
||||
straight paths become polylines (an open path of one straight segment becomes a line, except for a stroke weight
|
||||
before 2000), curved ones cubic splines through every anchor, fills their outlines followed by
|
||||
solid hatches (laser and cutter software reads the outlines and skips hatches; R12 has no hatches: the outlines
|
||||
alone), strokes lines with their lineweight and a linetype per dash pattern, and placed images image entities linked
|
||||
to PNG or JPEG files (`rasterFormat`) written next to the drawing (`linked` in the result). Coordinates are y up
|
||||
alone; an open path's fill outline is closed, as the fill is), strokes lines with their lineweight and a linetype per dash pattern, and placed images image entities linked
|
||||
to PNG or JPEG files (`rasterFormat`) written next to the drawing (`linked` in the result). `includeImages: false`
|
||||
leaves placed images out, with no image entity, no linked file and no decoding of their pixels, and `includeHatches:
|
||||
false` writes each filled area as its outlines alone, without its solid hatch (both default to `true`; these two
|
||||
options are VectorCraft's own). Either one, when it leaves something out, adds one note to `warnings`. Coordinates are y up
|
||||
from the bottom-left corner of the first artboard (or `artboard`), in drawing units: `scale` units per `unit` (default
|
||||
1 mm = 1 unit, which sets `$INSUNITS`); `scaleLineweights` scales the lineweights with them. `colors` is `8`, `16` or
|
||||
`256` indexed colours, or `true` (default; true colour with the nearest index, DXF 2004 and later). `preserve:
|
||||
@@ -5939,7 +5995,8 @@ selected objects in their layers (every export takes it), and `useArtboards: tru
|
||||
artboard holding the art over it. `dxfPreset: "cnc"` (CNC / CAM; default `"custom"`) sets the options for cutting
|
||||
software that the call does not give: version `2000` (the oldest version that has both lightweight polylines and lineweights), `unit:
|
||||
"mm"` and `scale: 1`, `colors: 256` (all version 2000 holds), `preserve: "editability"` with `alterPaths: false` (every
|
||||
stroke a center line), `outlineText: true` (type as paths), and `rasterFormat: "png"`. DXF Options has the same choice as its Preset menu,
|
||||
stroke a center line), `outlineText: true` (type as paths), `includeImages: false` and `includeHatches: false` (the
|
||||
cutting paths alone: fills as their outlines, no image files), and `rasterFormat: "png"`. DXF Options has the same choice as its Preset menu,
|
||||
which shows Custom again once a field it sets is changed. What DXF can't hold (gradients and patterns as one colour,
|
||||
blending, opacity masks, raster effects, clipping) comes back in `warnings`. In R13 and later, an image that can't be decoded is left out with
|
||||
no linked file, and `warnings` carries "an image couldn't be decoded and is missing from the picture" once for all such
|
||||
@@ -6491,7 +6548,8 @@ point, as in SVG export), `pt`, `mm`, `cm` or `in`; `unnamed: false` leaves out
|
||||
writes the `.css` file with the PNGs of rasterized art next to it (no path: `data` and `images` as base64). Its
|
||||
`warnings` add the PNGs' notes to the CSS's, each once (an image that couldn't be decoded, type written in the
|
||||
fallback font…). In the app, `css.copy` copies the CSS and `css.exportFile` writes it through a save panel (the web
|
||||
downloads it) and shows the first note in the status bar.
|
||||
downloads it) and shows the first note in the status bar, with how many there are; resting the pointer on the
|
||||
message lists up to 30 of them, fewer when the list would not fit in the window, with how many were left out.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"css.selection","params":{"units":"px","position":true}}}
|
||||
@@ -6992,7 +7050,9 @@ the middle of its bounding box's right side, hollow on point type and filled on
|
||||
Type and Convert To Point Type. Either keeps the text and its styles and is one undo step; `ids` picks the objects
|
||||
(default: the selection). A frame of threaded text that `type.convertToPointType` converts leaves its thread with the
|
||||
text it holds, and the story flows through the other frames without that text; a thread left with one frame is no
|
||||
longer a thread.
|
||||
longer a thread. Area type with Dynamic Text (Block) on becomes point type with Dynamic Text off, at the sizes Block
|
||||
set its lines to, as `type.dynamicText {on: false}` leaves them; converting it back to area type does not turn Block
|
||||
on again.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"type.convertToAreaType","params":{"ids":[42]}}}
|
||||
@@ -7799,7 +7859,9 @@ touches (a caret, `start == end`, touches its paragraph). Without a range they c
|
||||
targeted objects, as before. With a range, the character attributes of `text.setStyle` and `text.setFormat` style
|
||||
that range of characters. When every paragraph that `text.tabs.set` or `text.tabs.clear` targets already has those
|
||||
stops, the command changes nothing and records no undo step. `text.tabs.set` rejects a supplied `align`, `leader`, or
|
||||
`alignOn` value that is not a string, and an empty `alignOn` value.
|
||||
`alignOn` value that is not a string, an empty `alignOn` value or one of more than one character, a leader of more than
|
||||
8 characters, a position outside 0 to 100000 pt, and more than 256 stops. It sorts the stops by position and keeps the
|
||||
first of stops at one position.
|
||||
|
||||
`text.tabs.get {start?}` and `paraStyle.new` / `paraStyle.redefine {id, start?}` read the
|
||||
paragraph at `start`; `paraStyle.list` counts paragraphs as uses, and `charStyle.list` counts runs; both count the type in
|
||||
@@ -7816,7 +7878,7 @@ is the document's. A loaded style that is the same as the style of
|
||||
its name, or of its name with a number (`Body 2`), is not added again; any other is added under a free name. The
|
||||
document's styles and the type that uses them keep their attributes, and the file's Normal styles are not loaded. The
|
||||
reply lists the names `added` and `existing` in the document and the names `skipped` in the file (a style whose
|
||||
attributes do not read or are out of the range `charStyle.new` takes, or whose name is empty); `textStyle.loadAll`
|
||||
attributes do not read or are out of the range `charStyle.new` or `paraStyle.new` takes, or whose name is empty); `textStyle.loadAll`
|
||||
replies `{charStyles, paraStyles}`, and `charStyle.load` and `paraStyle.load` list only the styles of their own kind. A Return the Type tool types (or `text.editRange`
|
||||
inserting `\n`) continues the style of the paragraph it splits; deleting a break keeps the first paragraph's style;
|
||||
`text.setText` gives every paragraph the first one's attributes. Threaded text keeps each paragraph's attributes as
|
||||
@@ -7881,12 +7943,19 @@ the Paragraph Styles panel, or Paragraph Style Options… in its menu, does the
|
||||
`paraStyle.edit {name, to, attrs}`, which takes the same arguments as `charStyle.edit` and replaces the style's
|
||||
name and attributes in one undo step; the paragraphs that use the style keep their local overrides. OK with no field
|
||||
changed records no undo step, and Preview updates the paragraphs while the dialog is open (Cancel restores them).
|
||||
The `paraStyleOptions` dialog exposes `name`, `section` (`general`, `basic`, `composition`, `hyphenation`,
|
||||
The `paraStyleOptions` dialog exposes `name`, `section` (`general`, `basic`, `tabs`, `composition`, `hyphenation`,
|
||||
`justification` or `eastAsian`) and `preview`, and these fields:
|
||||
|
||||
- Basic Paragraph Formats: `justify` (`Auto`, `Left`, `Center`, `Right`, `JustifyLeft`, `JustifyCenter`,
|
||||
`JustifyRight` or `JustifyAll`), and `left_indent`, `right_indent`, `first_line_indent`, `space_before` and
|
||||
`space_after`, typed in the General unit of Preferences or with a unit of their own.
|
||||
- Tabs: `tabs`, the style's stops, each `{position, align, leader, alignOn}`: `position` typed like the distances
|
||||
above, `align` `left`, `center`, `right` or `decimal`, `leader` up to 8 characters, and `alignOn` one character
|
||||
(used by decimal stops). The section edits the selected stop with Alignment, X: (Y: for vertical type), Leader:
|
||||
and Align On:. Add puts a left stop 36 pt past the furthest stop (at 36 pt when there is none, and at most at
|
||||
100000 pt); it is disabled at 256 stops or when a stop is already at that position. Delete Tab removes the selected
|
||||
stop, and Clear All Tabs leaves the style with no stops, which it then sets. OK sorts the stops by
|
||||
position; of two stops at one position it keeps the one edited last.
|
||||
- Composition: `composer` (`singleLine` or `everyLine`) and the `roman_hanging` checkbox.
|
||||
- Hyphenation: the `hyphenate` checkbox, `words_longer_than`, `after_first`, `before_last`, `hyphen_limit`,
|
||||
`hyphenation_zone` and the `hyphenate_capitalized` checkbox. The options are inactive while Hyphenation is off, and
|
||||
@@ -7899,15 +7968,17 @@ The `paraStyleOptions` dialog exposes `name`, `section` (`general`, `basic`, `co
|
||||
|
||||
A field left as it was keeps the attribute as the style has it, and an empty field leaves its attribute unset; an
|
||||
empty Hyphenation or Justification field takes its default while another field of that section is set. Attributes
|
||||
the dialog does not show, such as tabs and character attributes, stay as they are.
|
||||
the dialog does not show, such as character attributes, stay as they are.
|
||||
`paraStyle.new`, `paraStyle.setAttrs` and `paraStyle.edit` reject a changed indent, space before or space after outside
|
||||
-1296 to 1296 pt, Words Longer Than outside 1 to 25, After First or Before Last outside 1 to 15, Hyphen Limit outside
|
||||
0 to 25, Hyphenation Zone outside 0 to 1296 pt, Word Spacing outside 0 to 1000%, Letter Spacing outside -100 to 500%,
|
||||
Glyph Scaling outside 50 to 200%, Minimum, Desired and Maximum values out of that order, Auto Leading outside 0 to
|
||||
500%, and a tab position outside 0 to 100000 pt. A value the style already has is kept. An invalid value leaves the
|
||||
500%, and changed tabs with more than 256 stops, or with a changed stop whose position is outside 0 to 100000 pt or
|
||||
whose leader is longer than 8 characters. They sort changed tabs by position and keep the first of stops at one
|
||||
position. A value the style already has is kept. An invalid value leaves the
|
||||
style, its paragraphs and Undo history unchanged, and keeps the dialog open.
|
||||
Reset Panel removes the section's attributes from the definition: Basic Paragraph Formats removes `justify` and the
|
||||
five distances, Composition removes `composer` and `roman_hanging`, Hyphenation removes `hyphenate` and
|
||||
five distances, Tabs removes `tabs`, Composition removes `composer` and `roman_hanging`, Hyphenation removes `hyphenate` and
|
||||
`hyphenation`,
|
||||
Justification removes `justification`, and East Asian Composition Settings removes `korean_line_break_anywhere`.
|
||||
`ui.paraStyleOptions.resetPanel {}` performs that reset for the section
|
||||
@@ -7997,13 +8068,15 @@ drawings leave a deferred stage as it is until its input or parameters change, w
|
||||
the active document (`reason`: `budget`, `timeout`, `missing`, `failed` or `safeMode`; `item` is the fill or stroke
|
||||
whose effect it is; `objectId` can be an object in the art of a symbol, pattern, brush or opacity mask; an empty list
|
||||
when none is deferred). A stage whose object is deleted, or whose plug-in effect is
|
||||
removed, moved from its place in the list or hidden (or whose fill or stroke is hidden), is no longer listed. `effect.refreshDeferred {ids?}` (Effect › Refresh
|
||||
removed, moved from its place in the list or hidden (or whose fill or stroke is hidden), is no longer listed. `effect.refreshDeferred {ids?|id?}` (Effect › Refresh
|
||||
Deferred Effects, enabled while a stage is deferred) runs the deferred stages of those objects (default: all of them)
|
||||
again with a fresh 2,000 ms budget and returns `{refreshed, stillDeferred, failed}`: `stillDeferred` counts stages left
|
||||
out for want of time again, the stages of an object that is hidden or in a hidden group or layer, which is not drawn,
|
||||
and the stages with a part of their input too small for the drawing the refresh makes, and `failed` those that
|
||||
timed out, failed or have no plug-in. `id` names one object in place of
|
||||
`ids`, and an entry that is not an object id of the document is an error. Each document has its own budget and its own deferred stages. Exports, Expand
|
||||
`ids`. An entry can name an object in the document's layers or in the art of a symbol, pattern, brush or opacity mask;
|
||||
an object without a deferred stage adds nothing to the counts, and an entry that is not an object of the document is
|
||||
an error. Each document has its own budget and its own deferred stages. Exports, Expand
|
||||
Appearance and commands run every stage under the per-call limit, so an export never leaves out a stage that was only
|
||||
deferred for time, and the canvas then draws the result. The web build measures the budget and the per-call
|
||||
limit with the page's `performance.now()`. An exporter adds a write-only file format `plugin.<id>` (listed by `document.formats`):
|
||||
@@ -8031,7 +8104,10 @@ needs a person's approval too, and `plugin.install` refuses `grant: [permission]
|
||||
app connected, `ui.installPlugin` opens the approval dialog and returns `{pending: "pluginInstall"}`; `answer_dialog`,
|
||||
`ui.dialog.confirm` and injected input can't confirm it. Its OK takes input only once the question has been on screen
|
||||
in the focused window for half a second, counted again for every new question and after the window gets the focus
|
||||
back. A `vectorcraft-cli mcp` started with `--allow-plugin-grants`
|
||||
back. A question that a request asked, directly or through a file dialog it opened, can't be approved by the person
|
||||
either: the reply adds `approval: "personMustStartInstall"`, OK stays disabled, and the person installs the plug-in
|
||||
with Object › Plug-ins › Install Plug-in… themselves. A request's `replace: true` doesn't skip the question about
|
||||
taking another module's place. A `vectorcraft-cli mcp` started with `--allow-plugin-grants`
|
||||
accepts `grant` and `allowHeavy` from any request, in that session only (headless; it can't be combined with
|
||||
`--connect`, `--automation-read-root` or `--automation-write-root`). A server confined to folders has no plug-in
|
||||
store, so it reads no `grants.json`, and a module that lists permissions or asks for a heavy budget does not install
|
||||
@@ -8575,7 +8651,8 @@ keys without bounds make 1 step. `starts` gives, per object, the anchor of its f
|
||||
from (as the Blend tool's clicks on anchor points do; an open path's last anchor runs it the other way). With the
|
||||
Blend tool, `press_key` Escape 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. A blend
|
||||
among the objects takes the others in as more key objects, keeping its options, name and transparency:
|
||||
among the objects takes the others in as more key objects, keeping its options, name, transparency and whether it
|
||||
has a spine:
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"object.blend.make","params":{"ids":[12,15],"starts":[0,2],"steps":8}}}
|
||||
@@ -8583,6 +8660,23 @@ among the objects takes the others in as more key objects, keeping its options,
|
||||
{"name":"run_command","arguments":{"command":"object.blend.info","params":{}}}
|
||||
```
|
||||
|
||||
`object.blend.createSpine {mode?: "auto" | "always" | "never"}` is the Blend panel's Create Spine menu: whether new
|
||||
blends get a spine (the [help page](https://helpx.adobe.com/illustrator/desktop/manage-colors/apply-transparency-and-blending/blend-panel-overview.html)
|
||||
describes the three choices). Without `mode` it reads the setting; both return `{mode}`. Auto, the default, and Always
|
||||
give every new blend a straight spine between the key centers, as before, whatever its key objects are. Never makes blends without a spine: their steps sit where a straight spine puts them, and
|
||||
`object.blend.info` reports `hasSpine: false` and no `spine`. Such a blend has no easing (`easingType` and `ramp` are
|
||||
refused, and the Blend panel dims Type and Ramp), Reverse Spine and the `object.blend.spine.*` commands refuse it
|
||||
("the blend has no spine"), and Release gives back its keys with no spine path. Replace Spine gives it a spine. The
|
||||
setting is kept with the preferences, is not an undo step and does not change blends already made, and
|
||||
`object.blend.make {createSpine}` chooses for one new blend. Any other value is refused ("`mode` must be one of auto,
|
||||
always, never") and changes nothing. A blend saved without a spine keeps `noSpine` in the native file; `.ai` and
|
||||
EPS files hold its drawn steps, as they do for every blend:
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"object.blend.createSpine","params":{"mode":"never"}}}
|
||||
{"name":"run_command","arguments":{"command":"object.blend.make","params":{"ids":[20,31],"createSpine":"always"}}}
|
||||
```
|
||||
|
||||
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.
|
||||
@@ -8593,7 +8687,7 @@ the spine passes nearest, `object.blend.spine.moveAnchor {anchor, x, y}` moves a
|
||||
`handle: "in" | "out"` it places that handle), `object.blend.spine.convertAnchor {anchor, to: "smooth" | "corner", x?, y?}` converts a point's handles (a Smooth drag with `x, y` creates opposite handles; Corner retracts both), `object.blend.spine.reshapeSegment {segment, t, dx, dy, perpendicular?}` bends a segment
|
||||
so its point at `t` moves by (dx, dy), turning a straight spine into a curve (`perpendicular` works as in `path.reshapeSegment`), and `object.blend.spine.removeAnchor
|
||||
{anchor}` deletes a point no key sits on; the first edit turns the spine into a path. Moving a key moves its end of the spine. Release
|
||||
(`object.blend.release`) leaves the spine as a path that paints nothing (`spines` in the result):
|
||||
(`object.blend.release`) leaves the spine of a blend that has one as a path that paints nothing (`spines` in the result):
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"object.blend.spine.addAnchor","params":{"id":40,"x":150,"y":100}}}
|
||||
|
||||
+17
-6
@@ -217,7 +217,16 @@ capability model proposed for PhotoCraft plug-ins
|
||||
https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/security/security-considerations-for-browser-ui.md
|
||||
gives for dialog boxes), so a click, Enter or Space, or a press begun before then, installs nothing. The half second
|
||||
starts over for every new question, even one that reads the same, and when the window gets the focus back. Cancel
|
||||
and Escape work at once.
|
||||
and Escape work at once. A module that would take the place of the installed plug-in with its id asks in the same
|
||||
dialog.
|
||||
- **An install that automation asked for is not approved in its dialog.** When a control request, MCP, injected input,
|
||||
or a file dialog that one of them opened (even when the person picks the file there) leads to the approval dialog, its
|
||||
OK stays disabled, a confirm is refused even after the half second, and the dialog says that automation asked for the
|
||||
install. `ui.installPlugin` returns `{pending: "pluginInstall", approval: "personMustStartInstall"}`. Cancel still
|
||||
closes it. To install the plug-in, the person chooses Object › Plug-ins › Install Plug-in… and picks the file, or
|
||||
opens it with File › Open or drops it on the window: the module is inspected again and the new question waits its
|
||||
half second. A request's `replace: true` does not skip asking about taking another module's place. A module that
|
||||
needs no approval still installs at once from any request. This is VectorCraft's own rule.
|
||||
- `plugin.install` refuses the module, naming the permissions it needs, unless this module already has a recorded grant
|
||||
(`plugin.inspect`'s `needsApproval` tells it beforehand). A request's `grant` is refused too: `plugin.install` takes
|
||||
it only with the approval the dialog gives. A `vectorcraft-cli mcp` or `run` started with `--allow-plugin-grants`
|
||||
@@ -262,14 +271,16 @@ capability model proposed for PhotoCraft plug-ins
|
||||
write the module to the `Plug-ins` folder, or can't remove the grant from `grants.json`, the folder keeps the module
|
||||
it held and `grants.json` keeps the grant. The new module runs until the session ends. When the grant can't be
|
||||
removed and the module already stored can't be read back or written back, the new module stays in the folder, and
|
||||
the grant does not count for the rest of the session. The grant also does not count when the folder held no module
|
||||
for that id. A
|
||||
the grant stops counting. The grant also stops counting when the folder held no module for that id. A
|
||||
`grants.json` larger than 1 MiB, or one that is not a JSON list, grants nothing: the new module stays in the folder,
|
||||
and `plugin.remove` removes the plug-in. A `grants.json` that can't be opened or read counts as a grant that can't be
|
||||
removed. When VectorCraft loads the `Plug-ins` folder, it forgets any grant for an id whose stored module lists no
|
||||
permissions. When it can't remove that grant from `grants.json`, or can't read the file, the grant does not count for
|
||||
the rest of the session, or until the plug-in is granted again, including for the next load, which tries the removal
|
||||
again. In Safe Mode, and for
|
||||
permissions. When it can't remove that grant from `grants.json`, or can't read the file, the grant stops counting,
|
||||
including for the next load, which tries the removal again. A grant that stops counting in either of these cases
|
||||
does not count for any session in the same process that uses the same `Plug-ins` folder, by any path to it, until
|
||||
`grants.json` can be written for that plug-in, as when the plug-in is granted again. Another process on the same
|
||||
folder, for example `vectorcraft-cli` beside the app, still reads `grants.json` as it is written. A grant for the
|
||||
same id kept in another `Plug-ins` folder counts. In Safe Mode, and for
|
||||
a stored module that the user disabled,
|
||||
VectorCraft does not read the module, and `grants.json` keeps the grant for its id. The Additional Plug-ins Folder
|
||||
and `plugin.reload` do not change the `Plug-ins` folder: when they leave a module that lists no permissions under an
|
||||
|
||||
File diff suppressed because one or more lines are too long
+4
-3
@@ -1,6 +1,6 @@
|
||||
# UI and interaction parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-12 · **Change:** minor (Live Paint Bucket fills faces crossed in one drag (#6373); previously: #6404: transform-aware Eyedropper character copying; scores and estimates unchanged; previously: Outline view: images and gradient meshes are picked on what Outline draws, so a click inside them reaches the path behind, #6437; previously minor: a middle-click on a document tab closes it, #6506; previously minor: Blob Brush: a round tip's preview is the outline of the area it adds, round at both ends, as the stroke it commits (#4343); scores and estimates unchanged; previously:; ruler double-click adds a guide at the pointer, #5239; G5: Inventory Icons built-in symbol library (four built-ins); previously minor: files that record no units open in Preferences › Units › General, #5820; previously minor: interim macOS cursor delivery, #2292; native validation pending; scores and estimates unchanged; Control bar › Snapping includes the existing Snap to Glyph and Alignment Guides toggles (#6164); scores and estimates unchanged; floating tab groups collapse into the side icon rail and opened rail panels fold back into it, #5925 in part; numeric fields step on wheel hover without taking keyboard focus, #5949; Character Styles panel: a double-click on a style's row opens its Character Style Options; the dialog keeps a fixed width and scrolls its sections, so its buttons stay on screen; Selection QoL: marquee modes and visible feedback, #5313; #3380 deletion-only review follow-up: independent survivors keep gradient placement, owned subpaths avoid discarded copies, and contracts/status/evidence are clarified; endpoint highlighting remains open; scores and estimates unchanged; Drop Shadow and glow dialogs: spinner arrows, #5367, #5368; Stroke Weight Up and Down shortcuts, #5797; Layers: Rename (`ui.rename`) opens the name field of the selected layer, group or object, #5324; Properties in Edit Artboards: Transform section above the Artboards section, #5219; scrubby labels: the Control bar's Stroke: and Opacity: links and the Properties panel's Stroke link scrub their fields, #4088; Properties: Quick Actions has Repeat Options for one selected repeat, #5181; Direct Selection: Shift-click picks several blend spine points, which drag together, #5285; Direct Selection: Cmd/Ctrl held lends the Selection tool and shows its bounding box, #3901; Join tool trims two crossing open paths and joins them at the crossing, #5844; Control bar: Paragraph: link and Align left/center/right while type is selected, #5372; shape tools: a press on the selection's centre point moves it and one in the rotate zone outside a box corner turns it, #5477; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; Units › East Asian Type acts, with Q and Ha units; scores unchanged)
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-12 · **Change:** minor (Ruler origin: the corner drag snaps as a drawn point does; previously minor: Live Paint Bucket fills faces crossed in one drag (#6373); previously: #6404: transform-aware Eyedropper character copying; scores and estimates unchanged; previously: Outline view: images and gradient meshes are picked on what Outline draws, so a click inside them reaches the path behind, #6437; previously minor: a middle-click on a document tab closes it, #6506; previously minor: Blob Brush: a round tip's preview is the outline of the area it adds, round at both ends, as the stroke it commits (#4343); scores and estimates unchanged; previously:; ruler double-click adds a guide at the pointer, #5239; G5: Inventory Icons built-in symbol library (four built-ins); previously minor: files that record no units open in Preferences › Units › General, #5820; previously minor: interim macOS cursor delivery, #2292; native validation pending; scores and estimates unchanged; Control bar › Snapping includes the existing Snap to Glyph and Alignment Guides toggles (#6164); scores and estimates unchanged; floating tab groups collapse into the side icon rail and opened rail panels fold back into it, #5925 in part; numeric fields step on wheel hover without taking keyboard focus, #5949; Character Styles panel: a double-click on a style's row opens its Character Style Options; the dialog keeps a fixed width and scrolls its sections, so its buttons stay on screen; Selection QoL: marquee modes and visible feedback, #5313; #3380 deletion-only review follow-up: independent survivors keep gradient placement, owned subpaths avoid discarded copies, and contracts/status/evidence are clarified; endpoint highlighting remains open; scores and estimates unchanged; Drop Shadow and glow dialogs: spinner arrows, #5367, #5368; Stroke Weight Up and Down shortcuts, #5797; Layers: Rename (`ui.rename`) opens the name field of the selected layer, group or object, #5324; Properties in Edit Artboards: Transform section above the Artboards section, #5219; scrubby labels: the Control bar's Stroke: and Opacity: links and the Properties panel's Stroke link scrub their fields, #4088; Properties: Quick Actions has Repeat Options for one selected repeat, #5181; Direct Selection: Shift-click picks several blend spine points, which drag together, #5285; Direct Selection: Cmd/Ctrl held lends the Selection tool and shows its bounding box, #3901; Join tool trims two crossing open paths and joins them at the crossing, #5844; Control bar: Paragraph: link and Align left/center/right while type is selected, #5372; shape tools: a press on the selection's centre point moves it and one in the rotate zone outside a box corner turns it, #5477; scores and estimates unchanged) · **Target:** Adobe Illustrator 2026 (30.x; Units › East Asian Type acts, with Q and Ha units; scores unchanged)
|
||||
>
|
||||
> Vector Halftone preview update (2026-11-10): temporary dot selection marks are hidden, and the bounding box stays available (#6369).
|
||||
>
|
||||
@@ -240,7 +240,7 @@ tools, never checked side by side) isn't captured row by row.
|
||||
| Ruler guides: drag out, select, move, delete, lock, Make/Release Guides | done | #414, #451; marquee selects unlocked ruler guides |
|
||||
| A double-click on a ruler adds a guide at the pointer: a vertical one on the top ruler, a horizontal one on the left ruler (swapped in a view turned 90°, where the rulers read the other document axis; the nearer axis in between), exactly where the pointer is (no snapping), shown even with guides hidden, one undo step (`guide.add`); both clicks of the pair must be on that ruler, and the first adds nothing. The [public page on rulers](https://helpx.adobe.com/illustrator/desktop/measure-and-align/grids-and-guides/use-rulers.html) doesn't describe this gesture, so it follows the request in #5239 | done | #5239; an artboard guide with the Artboard tool, as a drag from a ruler makes one; `canvas/tests.rs` `double_clicking_a_ruler_adds_a_guide_at_that_position`, `a_canvas_click_then_a_ruler_click_adds_no_guide`, `a_ruler_double_click_follows_a_rotated_view` |
|
||||
| Escape cancels an existing ruler-guide press, move or copy | done | Selection and Direct/Group Selection; app-input regressions cover preselected guides, document/interaction-start selection, Undo/Redo and saved state, later on-canvas motion/release and temporary borrowing from idle Pen. All eight checks and the Direct Selection Escape control passed in current full CI. [Validation evidence](target-app-parity.md#evidence-what-ships-today-by-area) |
|
||||
| Ruler origin: corner drag with preview, double-click reset to the active artboard, relative X/Y fields, native save/reopen | done | #1212; `document.setRulerOrigin`, `document.resetRulerOrigin`; geometry and command coordinates stay absolute |
|
||||
| Ruler origin: corner drag with preview, snapped as a drawn point is (Smart Guides, Snap to Point and the ruler guides, pixels, the grid), double-click reset to the active artboard, relative X/Y fields, native save/reopen | done | #1212; `document.setRulerOrigin`, `document.resetRulerOrigin`; geometry and command coordinates stay absolute |
|
||||
| Ruler guides as Layers rows: shown, hidden, locked and deleted with their layer; rows dragged to another layer | done | `guide.setLayer`; guides from older files go on a layer |
|
||||
| Objects made into guides: drawn in the guide colour and style of Preferences; Lock Guides locks them too (no select, move or delete); a dragged selection snaps to ruler guides with Smart Guides on, by the nearest point of the path when pressed on its stroke or beside its edge, so the path lands exactly on the guide | done | #1534 (#1543, #1583); #3701 |
|
||||
| A selected ruler guide's X or Y in the Transform panel; typing a value moves it | not scored | #1659 (part of #1597); several guides move together; not in Properties or the Control bar. Not established by the documentation we could find: the help pages on guides, rulers and the Transform, Control and Properties panels (read again on 2026-10-14) don't describe it, and the one public statement is a user's [community answer](https://community.adobe.com/questions-652/adding-a-new-custom-guide-785586), which is not documentation. Kept as a convenience pending the owner's decision; no parity claim |
|
||||
@@ -436,7 +436,7 @@ next unit in the order a right-click on a ruler lists them, from Feet back to Po
|
||||
| Window › Help Bar shows or hides the tool-help strip apart from the status bar; kept with the preferences and in saved workspaces; Presentation Mode hides both bars | done | `window.helpBar`; `help_bar_toggle_is_independent_and_saved_in_workspaces`, `help_bar_and_status_bar_render_independently`, `legacy_help_bar_visibility_follows_each_layouts_status_bar` |
|
||||
| Background Export: a progress dialog with the file name, the artboard count and a bar (busy for one artboard and for formats made in one go), Cancel (Esc) and Continue in Background; it opens after 0.4 s and never over another dialog. A cancelled export writes no file | done | #2564; on the shared `vectorcraft_doc::cancel` token (#2546), so a cancelled render keeps no half-drawn pattern tile or effect raster. The bar moves between artboards, not within one. Save As, Export for Screens and Export Selection don't show it yet |
|
||||
| Swatch, graphic style and symbol library panels: each library opens in a panel of its own, several at once, that floats, groups, docks and closes like any panel; opening an open library brings its panel forward; Previous / Next Library change the library in place; the panel menu's Persistent reopens the panel at startup with its view and find field (a library loaded from a file is read again; when its file is missing the panel reopens showing the file's path with Locate Library…, and the status bar names the file) | done | #2603; panel ids `library:<kind>:<id>`, `ui.libraryPanel {panel, library?, view?, showFind?, persistent?}`, `ui.libraryPanel.locate {panel, path?}`; the library panels have no sort option, as before |
|
||||
| DXF export/import preserves intended curve closure | done | #1299; R13–2018 closed SPLINE bit set/read; an open curve ending at its start stays open; knots and control points unchanged; native CIRCLE/ARC export and CNC preset remain pending |
|
||||
| DXF export/import preserves intended curve closure | done | #1299; R13–2018 closed SPLINE bit set/read; an open curve ending at its start stays open; knots and control points unchanged; circular cubic paths export as native CIRCLE/ARC where stroke semantics permit; DXF Options' Preset menu and `document.exportDxf`'s `dxfPreset: "cnc"` set the CNC / CAM options (#5500) |
|
||||
| macOS save sheet: choose the format from a menu | done | #866; the save panel is VectorCraft's own `NSSavePanel` with its Format menu set before the sheet opens (`apps/vectorcraft/src/mac_save_format.rs`); #1855 had withdrawn the menu that was added after the sheet began, which made Save As, Save a Copy and the first Save show no sheet |
|
||||
| Preferences: every option acts | partial | 2 stored but unused (#394, audited 2026-10-30): Scratch Disks, Legacy vector clipboard; the rest act (Units › East Asian Type since 2026-10-31; Open Documents As Tabs: cleared, new documents open in floating windows). General › Corner Radius drives the Rounded Rectangle tool and follows its ↑/↓ (2026-10-24) |
|
||||
| Preferences › General › Constrain Angle | done | arrow keys and Shift drags along the turned axes; the Rectangle, Rounded Rectangle, Ellipse and grid tools, point and area type and the shape size dialogs draw along them with the bounding box turned; Shift-drawn polygons and stars keep the turned base orientation; the Line Segment tool's Shift steps count from it (#394, <https://helpx.adobe.com/illustrator/desktop/manage-objects/arrange-objects/rotate-objects-by-specific-angles.html>); arcs, spirals, flares and Pen paths are not turned |
|
||||
@@ -520,6 +520,7 @@ before release (#6373). [Paint faces and edges](https://helpx.adobe.com/illustra
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-11-12 | minor | Live Paint Bucket fills faces crossed in one drag (#6373). Scores and estimates unchanged. |
|
||||
| 2026-11-11 | minor | Ruler origin: the corner drag snaps as a drawn point does, onto the art's and the artboards' anchors, centres, edges and paths, and with Snap to Point along the ruler guides; scores and estimates unchanged |
|
||||
| 2026-11-11 | minor | Eyedropper copies effective character dimensions between transformed text objects (#6404); scores and estimates unchanged. |
|
||||
| 2026-11-11 | minor | Outline view: a click on a path's outline selects it through an image or a gradient mesh in front, which Outline draws as a frame or mesh lines (#6437). |
|
||||
| 2026-11-11 | minor | A middle-click on a document tab (or its ×) closes it as the × does; closing a document's last view with unsaved changes asks to save first (#6506). VectorCraft addition; scores and estimates unchanged. |
|
||||
|
||||
Reference in New Issue
Block a user