Merge main into fix/read-roots-document-replies

This commit is contained in:
dotCooCoo
2026-11-12 01:13:38 -08:00
170 changed files with 11762 additions and 533 deletions
+4 -4
View File
@@ -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 |
@@ -824,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
+2 -2
View File
@@ -181,13 +181,13 @@ VectorCraft choices; an original approximation, never compared with another appl
| Revolve | initial: live, editable profile, rotation and light gizmos, default-on Cap with continuous curved rims, smooth vector shading and round seam joins, SVG/PDF output, Expand Appearance ([revolve.md](revolve.md), #846) |
| Extrude & Bevel, Inflate, Rotate | initial: live, depth, twist, taper, solid or hollow caps, five original bevel shapes, Inflate volume, both sides, twist, taper and cap, Rotate of every fill and stroke, groups and layers turned about one shared axis (#4506), contours that cross, touch or overlap merged first ([three-d.md](three-d.md)), Position presets, rotation and light gizmos, SVG/PDF output, Expand Appearance ([three-d.md](three-d.md)) |
| Materials panel, lighting, ray-traced render | Window › 3D and Materials panel with the object types (Plane, Extrude, Revolve, Inflate) and the Object, Rotation and Lighting settings of the applied effect ([three-d.md](three-d.md#3d-and-materials-panel)); one to ten directional lights with per-light Color (opaque RGB, white by default), Intensity, Rotation, Height, Softness and neutral Ambient Light, Revolve and colored Inflate use smooth vector shading; Extrude & Bevel and Rotate retain planar shading; original Standard, Diffuse, Top Left and Right lighting rigs; hard-edged shadows behind or below the object from the first light ([three-d.md](three-d.md#shadows)); no materials, soft shadows or ray tracing |
| 3D (Classic): Extrude & Bevel, Revolve, Rotate | Extrude & Bevel (Classic) initial: live, Extrude Depth, Cap, five original bevel shapes with Height and Bevel Extent In or Out, Position presets and rotation gizmo, Perspective, Wireframe, No Shading, Diffuse and Plastic surfaces with one to ten lights, Light Intensity, Ambient Light, Highlight Intensity and Size, Blend Steps, Black, Custom or no Shading Color, Draw Hidden Faces ([create 3D objects](https://helpx.adobe.com/illustrator/desktop/special-effects-styles/create-3d-graphics/create-3d-objects.html)); Revolve (Classic), Rotate (Classic) and Map Art: none |
| 3D (Classic): Extrude & Bevel, Revolve, Rotate | Extrude & Bevel (Classic) initial: live, Extrude Depth, Cap, five original bevel shapes with Height and Bevel Extent In or Out, Position presets and rotation gizmo, Perspective, Wireframe, No Shading, Diffuse and Plastic surfaces with one to ten lights, Light Intensity, Ambient Light, Highlight Intensity and Size, Blend Steps, Black, Custom or no Shading Color, Draw Hidden Faces ([create 3D objects](https://helpx.adobe.com/illustrator/desktop/special-effects-styles/create-3d-graphics/create-3d-objects.html)); Revolve (Classic) initial: live, Angle, Cap, Offset from the left or right edge, Position presets and rotation gizmo, Perspective, the same four surfaces, lights, highlight, Blend Steps and Shading Color, groups and layers revolved about one shared axis (same page); Rotate (Classic) initial: live, every fill and stroke turned as one plane, Position presets and rotation gizmo, Perspective, No Shading and Diffuse surfaces with lights, Ambient Light, Blend Steps and Shading Color ([rotate objects in 3D](https://helpx.adobe.com/illustrator/desktop/special-effects-styles/create-3d-graphics/rotate-objects-in-3d.html)); Map Art: none |
| Turntable (30.0 beta) | none |
| Export 3D objects (OBJ, USDA, glTF) | initial: Asset Export's Export 3D Object collects an object with Extrude & Bevel, Revolve, Inflate or Rotate as a 3D asset, and Export writes its solids as a USDA (the default), USDZ, glTF or OBJ mesh with a material in each solid's paint color (`assets.add3D`, `assets.set3DFormat`, `assets.export3D`); no textures, map art or shading ([3D export help](https://helpx.adobe.com/illustrator/desktop/special-effects-styles/create-3d-graphics/export-3d-vector-artwork.html)) |
The `three-d` crate (depends on `geom` and `pathops`, with no UI or GPU dependencies) builds, rotates, projects, shades and depth-sorts the surfaces;
the effects crate turns them into art. What's left (materials and shadows, ray-traced rendering,
angular cut caps, exact visibility, the rest of 3D Classic (Revolve, Rotate, Map Art), Turntable) is 25–45 h.
angular cut caps, exact visibility, the rest of 3D Classic (Map Art), Turntable) is 25–45 h.
## Revision history
+8 -6
View File
@@ -645,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).
@@ -662,7 +664,7 @@ macOS cursor delivery (#2292) is narrowed to a native host adapter using the exi
Extrude & Bevel, Inflate and Rotate with Position presets ([three-d.md](three-d.md), #1407). Colored Inflate has automatic smooth vector lighting from shared membrane normals. White-light Inflate keeps its existing appearance. All four take one to ten colored directional lights, with neutral ambient applied once, a light list and independent previewing controls. Standard, Diffuse, Top Left and Right select original rigs, shared with commands; manual settings show Custom.
- **Missing:** materials (base, Substance, graphics), shadows,
ray-traced rendering, angular cut caps, exact visibility for intersecting and concave surfaces, the rest of 3D
Classic (Revolve, Rotate, Map Art), Turntable, textures, map art and shading in 3D export.
Classic (Map Art), Turntable, textures, map art and shading in 3D export.
- **Impact:** specialist; Materials is the one menu stub left.
- **Estimate:** 25–45 h; plan in `plan/` before coding.
+197 -33
View File
@@ -123,30 +123,78 @@ 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
`file.openRecentN` for a file outside the roots ends with `no such recent file`, as an empty slot does.
- `ui_inspect` (the control channel's `ui.inspect`) leaves out the paths outside the read roots: in `opening`, the
documents still being read; in `ui.recent_files`, the recent files; a library panel's `path` in `ui.library_panels`;
and the folder preferences in `ui.engine_prefs` and in an open Preferences dialog's `ui.dialog.fields`
in a recorded action's steps in `ui.action_sets`, also in a batch step's commands, the `path`, `paths`, `file`,
`files` and `folder` params, a param whose name ends in `Path`, `Paths`, `File`, `Files` or `Folder` (`diffPath`,
`destinationFolder`), the entries of a list under such a param, and under any other param, as a key or in any
list, an absolute path or a `file:` URL outside the roots (any case of `file:`, `%XX` escapes decoded; a URL that
names another host is always left out), and `~`, a path under `~` or a path that starts with `./` or `../`
(either separator) that resolves outside the roots from the app's working folder; and the folder
preferences in `ui.engine_prefs` and in an open Preferences dialog's `ui.dialog.fields`
(`fontsFolder`, `pluginsFolder`, `scratchPrimary`, `scratchSecondary`, `recoveryFolder`, `templatesFolder`; an
empty folder and the scratch disk choices `Startup` and `None` stay). A library loaded from a file outside the
roots shows as `loaded/<file name>` wherever `ui_inspect` and `ui.docking` name it: its id, its panel's id, the
Color Guide's `ui.color_guide_limit` and a closed panel's key in `ui.docking_hidden`, also when its panel is
closed. When another hidden library has the same file name, the libraries take `loaded/<file name>`,
`loaded/<file name> (2)`, `(3)` and so on in the order of their full ids (the libraries loaded in this session
first, then those only the UI state names), and each one keeps its id in both replies and in the library
commands below. The other entries keep their order, and the app's own state is not changed.
Color Guide's `ui.color_guide_limit`, a closed panel's key in `ui.docking_hidden` and the `library` and `panel`
params of a recorded action's steps in `ui.action_sets`, and the keys of shortcut overrides (`panel:<panel id>`
in `ui.shortcut_overrides` and an open Keyboard Shortcuts dialog's `ui.dialog.fields.overrides`), also when its
panel is closed. A path written with
either separator counts as a path, also one saved on another platform, and outside Windows a path that starts
with a drive (`C:`) or a `\` counts as outside the roots. Outside Windows, any other path keeps a `\` in its
file name (`/libs/a\b.ase` shows as `loaded/a\b.ase`), and a reply matches it only as written, not with `/`
in place of the `\`. When another hidden library has the same
file name, the libraries take `loaded/<file name>`, `loaded/<file name> (2)`, `(3)` and so on in the order they
are first shown. Libraries first shown in the same reply are numbered in the order of their full ids, the
libraries loaded in this session first, then those only the UI state names. Each one keeps its id for the rest
of the session in both replies and in the library commands below, also after another library with the same
file name is loaded. A hidden library skips an id that a library loaded without a path already has, and only a
library loaded later from data under that file name, which takes the id itself, moves a hidden one to the next
free number. The other entries keep their order, and the app's own state is not changed. A request may name such a library or its panel by the id
shown in a `panel`, `library` or `panels` param, in a docking destination (`anchor`, `target`, `before`, `onto`,
`above`, `below`) and in `window.panel.layout`'s `action` (`ui.set {panel: "library:swatches:loaded/<file name>"}`
reopens its panel), and the reply to such a request shows that id and file name wherever the library's id or path
appears, an error included. Every reply under the read roots shows a hidden library's id as the id shown and its
path as the file name in every string and key, the status text (`ui.status`), dialogs, the command palette query
(`ui.palette_query`), a script's report (`scriptReport`), a screenshot's reply and the error from an internal
fault included, for the libraries hidden before the request ran and after it. The path is also matched with `%XX` escapes as a `file:`
URL writes it, and on Windows in any case of its letters. A hidden id or path stays only where it begins
another loaded library's whole id with no `.` or `..` part, so a readable library's id that begins with a hidden one stays. A reply also shows a path outside the
read roots that the request sent by its file name, whether or not a library was loaded from it and whether the
request succeeded or failed, so that the reply reads the same either way. A path param (`path`, `file`,
`destinationFolder` and the like) counts with a relative path too. The hidden libraries' ids and paths are
matched before the paths the request sent, so a sent path written over part of a hidden library's path does not
keep that path in the reply. A relative path is not replaced where it ends a longer path (`/work/data/icon.svg`
keeps `data/icon.svg`), and the absolute path it reads as from the app's working folder is replaced too. Encoded file data, a base64 string under `dataBase64`,
`pngBase64` or `thumbnailBase64`, is sent as it is.
- `swatch.library.list`, `brush.libraries`, `symbol.libraries` and `graphicStyle.libraries` list every library
but leave out the paths outside the read roots: a library's `path` and the user library folder in `userFolder`
are `null` there. A library loaded from a file outside the roots is listed as `loaded/<file name>`, numbered
`(2)`, `(3)` and so on as in `ui_inspect` when two have the same file name. That id finds the library in the
other library commands (`swatch.library.get`, `swatch.library.add`, `brush.library`, `brush.addFromLibrary`,
`symbol.library`, `symbol.addFromLibrary`, `graphicStyle.library`, `graphicStyle.addFromLibrary` and the
others that take `library`), whose replies show it too. `swatch.library.copyToUser` refuses a library whose file
is outside the read roots without naming the file, and it and the library saves with `user: true` leave out
`path` when the user library folder is outside the read roots.
others that take `library`), whose replies show it too. Over the control channel, `window.swatchLibrary` and
the other library panel commands answer with that id and its panel's id (`library:swatches:loaded/<file name>`),
and `ui.libraryPanel` and the `window.panel.*` commands take that panel id in `panel`, `anchor`, `before`,
`onto`, `above` and `below`. `swatch.library.copyToUser` refuses to copy a library file outside the read roots
without naming the file (the swatches of a document loaded from there are written from the loaded library, as
for a library loaded from data, and the document is not read again), and it and the library saves with
`user: true` leave out `path` when the user library folder is outside the read roots.
- `links.list`, `links.check`, `links.info` and the `missingLinks`, `modifiedLinks` and `updatedLinks` rows of
`document.open` leave out a linked file's path when the file is outside the read roots (a relative path is taken
from the document's folder): `path`, `found`, and in `links.info` also `link` and `location`, with the `fileSize`
@@ -1653,9 +1701,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.
@@ -1667,7 +1715,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`
@@ -2440,6 +2491,26 @@ kept with the workspace, and built-in workspaces and workspaces saved without it
{"name":"invoke_menu","arguments":{"command":"window.toolsBesideCanvas","params":{"on":true}}}
```
## Learn panel
Window › Learn and the Explore tutorials button beside the search icon at the right end of the app bar show and hide
the Learn panel. Its For you tab holds a Get started section with a Quick skill guide card; choosing the card opens
the Skills tab. The Skills tab lists VectorCraft's own skills, each with its number of tutorials and an empty progress
ring. Choosing a skill lists its tutorials, choosing a tutorial shows its numbered steps, and Back goes up one level.
The tutorial text is English. `window.learn {show?}` shows the panel (`show: true`), hides it (`show: false`) or
toggles it (`show` omitted or null), and answers whether it shows; Window › Learn and Explore tutorials run it.
The panel counts as hidden while the dock is hidden or a full screen mode hides the panels. Showing it shows a hidden
dock; in a full screen mode it makes Learn the front panel, which shows when the mode ends, and answers false. Any
other value of `show` is an error and changes nothing. `learn.list {}` → `{skills: [{id, title, tutorials: [{id, title, steps}]}]}`, in the order the Skills tab
lists them, where `steps` is the number of steps. `learn.show {tutorial}` shows the panel on its Skills tab with that
tutorial's steps → `{skill, tutorial, title, steps: [text]}`. A missing, non-string or unknown `tutorial` is an error
and changes nothing. Behavior reference:
[Quick skill guide](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/learn-skills-quick-skill-guide.html).
```json
{"name":"invoke_menu","arguments":{"command":"learn.show","params":{"tutorial":"pen-paths"}}}
```
## Ruler guides
Each ruler guide is an object of a layer or sublayer, directly in it and above its art, and takes an id from the
@@ -2945,6 +3016,30 @@ 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)".
`brush.replaceArt {name, ids?|id?, applyToStrokes?}` makes the selected art the brush's art and keeps its other
options; several objects become one group, as in `brush.new`. A pattern brush takes a group named for a tile, or a
group of such groups, tile by tile: an unpainted rectangle at the back of a tile group becomes that tile's repeat frame,
a tile group's art goes back without that group, and the tiles that are not given stay as they are. Of two groups named
for the same tile, the frontmost one counts. Other art becomes the side tile. When strokes use the brush and
`applyToStrokes` is `false`, the brush and its strokes stay as they were, and a copy of the brush with the new art,
named "`<name>` copy", goes after it and becomes the current brush. Otherwise, and for a brush no stroke uses, the brush
changes and its strokes redraw. It replies `{name}`, the brush that has the new art, and refuses a calligraphic or
bristle brush, an empty selection and art (or a tile it is given, such as a tile group left with only its frame's
rectangle) with no width. `brush.replaceArt` and `brush.new` measure a symbol instance in the art by its symbol's art.
In the app, art Alt-dragged (Option-dragged on macOS) from the canvas onto a scatter, art or pattern brush in the
Brushes panel runs it. When strokes use the brush, the app checks the art first and shows why in the status bar when
the brush cannot take it; otherwise a dialog (`brushReplaceArt`) asks: Apply to Strokes, Leave Strokes
(`applyToStrokes: false`) or Cancel.
`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
@@ -3104,8 +3199,8 @@ See [Revolve](revolve.md) for the scope and limitations.
replaces the lighting rig and ambient of an existing Revolve, Extrude & Bevel, Inflate or Rotate
effect. `item: null` addresses object-level effects; an item index addresses a fill/stroke's
effects. All targets must have a 3D effect at `index`, otherwise nothing changes. Extrude & Bevel
(Classic) has no lighting presets: a target with it at `index` is an error, nothing changes, and
`effect.setParams` sets its lights. The operation is one undo step and preserves Shading, geometry, source paint and the view.
(Classic), Revolve (Classic) and Rotate (Classic) have no lighting presets: a target with any of them at `index` is an
error, nothing changes, and `effect.setParams` sets its lights. The operation is one undo step and preserves Shading, geometry, source paint and the view.
The four original rigs use one white front light at 80% intensity. Standard keeps the existing
default; Diffuse uses 100% Softness and 35% Ambient Light, Top Left uses Rotation 135 and Height
@@ -3137,7 +3232,7 @@ art", and a loaded file draws the source path, as it does for a solid past its l
documentation names the controls and their ranges
([3D and Materials panel options](https://helpx.adobe.com/illustrator/desktop/special-effects-styles/create-3d-graphics/3d-materials-panel-options.html)).
The settings are saved in the native file; SVG and PDF exports draw the shadow, and `effect.expandAppearance` keeps
it as a path. Extrude & Bevel (Classic) has no shadow. See [three-d.md](three-d.md#shadows).
it as a path. Extrude & Bevel (Classic), Revolve (Classic) and Rotate (Classic) have no shadow. See [three-d.md](three-d.md#shadows).
```json
{"name":"run_command","arguments":{"command":"effect.setParams","params":{"index":0,"item":null,"params":{"shadow":true,"shadowPosition":"below","shadowDistance":10,"shadowBounds":150}}}}
@@ -3213,6 +3308,51 @@ an unknown surface or shading color is refused with an error and the document is
{"name":"run_command","arguments":{"command":"effect.apply","params":{"effect":"threeD.classicExtrude","item":null,"params":{"depth":40,"bevel":"rounded","bevelHeight":6,"surface":"diffuse","blendSteps":64}}}}
```
## Revolve (Classic)
`effect.apply {effect: "threeD.classicRevolve", params: {...}, ids?, item?}` is Effect › 3D and Materials ›
3D (Classic) › Revolve (Classic)…. It sweeps the profile round a vertical axis as `threeD.revolve` does, at 64 segments
for a full turn, and draws every face, back to front, with the classic surfaces. Parameters: `angle` (degrees,
0..360, default 360), `cap` (true closes the profile's open ends, false leaves the surface hollow), `offset` (points,
0..1000, default 0; the axis's distance from the profile, so a value above 0 makes a ring), `edge` (`left`, the
default, or `right`: the edge of the profile's bounds the axis is at), `rotationX/Y/Z` and `perspectiveAngle` as
above, and `surface`, the lights, `ambient`, `highlightIntensity`, `highlightSize`, `blendSteps`, `shadingColor` and
`shadingCustom` as Extrude & Bevel (Classic) takes them. It has no `drawHiddenFaces`. The effect also goes on a group
or layer, whose members turn about one shared axis, or on a fill or stroke. The public documentation describes the
dialog ([Create 3D objects](https://helpx.adobe.com/illustrator/desktop/special-effects-styles/create-3d-graphics/create-3d-objects.html))
and its Angle (0 to 360), Cap, Offset (0 to 1000) and Left Edge or Right Edge settings
([Revolve options](https://helpx.adobe.com/pdf/cs6/illustrator_reference.pdf#page=283));
the defaults are VectorCraft's own. An unknown parameter (`segments` included), a number out of range, a flag that
is not true or false, another `edge`, surface or shading color is refused with an error and the document is not
changed.
```json
{"name":"run_command","arguments":{"command":"effect.apply","params":{"effect":"threeD.classicRevolve","item":null,"params":{"angle":270,"offset":10,"surface":"diffuse","blendSteps":64}}}}
```
## Rotate (Classic)
`effect.apply {effect: "threeD.classicRotate", params: {...}, ids?, item?}` is Effect › 3D and Materials ›
3D (Classic) › Rotate (Classic)…. It turns every fill and stroke as one flat plane about the center of the object's
bounds, as `threeD.rotate` does, each in its own paint, and draws the plane from either side. Parameters:
`rotationX/Y/Z` and `perspectiveAngle` as above; `surface` (`diffuse`, the default, lights the art softly, and
`none` keeps the paint unlit); and the lights, `ambient`, `blendSteps`, `shadingColor` and `shadingCustom` as Extrude &
Bevel (Classic) takes them. It has no highlight, no `drawHiddenFaces` and no shadow. The effect also goes on a group
or layer, whose members turn about one shared center, or on a fill or stroke. The public documentation describes the
dialog's Position and Surface settings
([Rotate objects in 3D](https://helpx.adobe.com/illustrator/desktop/special-effects-styles/create-3d-graphics/rotate-objects-in-3d.html)),
the Position presets, rotations from -180 to 180 and Perspective from 0 to 160
([Set 3D rotation position options](https://help.adobe.com/archive/en_US/illustrator/cs5/illustrator_cs5_help.pdf#page=270)),
and No Shading and Diffuse Shading as the only surfaces for an object that uses only this effect
([Surface shading options](https://help.adobe.com/archive/en_US/illustrator/cs5/illustrator_cs5_help.pdf#page=271)).
The defaults and the shading are VectorCraft's own. An unknown parameter (`highlightSize` and `drawHiddenFaces`
included), a number out of range, a flag that is not true or false, a surface other than `none` or `diffuse`, or
another shading color is refused with an error and the document is not changed.
```json
{"name":"run_command","arguments":{"command":"effect.apply","params":{"effect":"threeD.classicRotate","item":null,"params":{"rotationX":0,"rotationY":40,"rotationZ":0,"surface":"diffuse","blendSteps":64}}}}
```
## Edit Colors and Recolor Artwork
@@ -3354,8 +3494,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.
@@ -3403,7 +3544,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
@@ -3416,6 +3557,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}}}
@@ -6521,7 +6669,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}}}
@@ -7765,12 +7914,12 @@ its look, in one undo step. Point type in the selection is left as it is, and ar
([Dynamic Text: Block](#dynamic-text-block)). Type on a path in a
thread is refused with an error that names it, and the menu item and the task bar item are not offered for it;
`text.thread.create` and `text.thread.add` turn Dynamic Text off on the frames they thread, at their drawn sizes, and
list them in `dynamicTextOff`. When every object already has the setting asked for, nothing changes and no undo step
list them in `dynamicTextOff`; `addon.type.releasePath` turns it off at the drawn sizes on the point type it makes. When every object already has the setting asked for, nothing changes and no undo step
is recorded. It replies `{on, ids, fitScale}` (the first object's factor, 1 when off), and the menu item is checked
while the first selected type on a path or area type has it on. `document.inspect` reports `dynamicText` and `fitScale` for type
on a path. New type and documents from before it have it off, and it is saved only when on. SVG, PDF, EPS and the
editing data for other apps write the type at its drawn sizes; the editing data does not hold the setting and says
so in a warning.
on a path. New type and documents from before it have it off, and it is saved only when on. SVG, PDF, EPS, legacy
`.ai` and the editing data for other apps write the type at its drawn sizes; legacy `.ai` and the editing data do not
hold the setting, and each says so in a warning.
```json
{"name":"run_command","arguments":{"command":"type.dynamicText","params":{"on":true}}}
@@ -7812,7 +7961,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
@@ -7829,7 +7980,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
@@ -7894,12 +8045,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` or
The `paraStyleOptions` dialog exposes `name`, `section` (`general`, `basic`, `tabs`, `composition`, `hyphenation` or
`justification`) 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
@@ -7910,15 +8068,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`, and
Justification removes `justification`. `ui.paraStyleOptions.resetPanel {}` performs that reset for the section
selected in Paragraph Style Options or New Paragraph Style; it is disabled on General.
@@ -8007,13 +8167,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`):
@@ -9613,7 +9775,9 @@ VectorCraft addition and changes no parity score.
- **The text** keeps its runs with their character attributes and its paragraph attributes, and becomes point type on
one straight line along the object's own axis, with the baseline starting where the first character sat on the path
(type with no characters starts at its start bracket). Type on a Path Options (effect, align to path, spacing, flip,
brackets) don't apply to point type and are dropped. Without `keepOriginal` the type object itself becomes the point
brackets) don't apply to point type and are dropped. Type with Dynamic Text on (`type.dynamicText`) becomes point
type with it off, at the sizes it was drawn at: each size, leading and baseline shift is multiplied by the fit factor.
Without `keepOriginal` the type object itself becomes the point
type, keeping its id, so a frame of threaded text leaves its thread with the text it holds, as
`type.convertToPointType` does for area type.
- It acts on the type on a path among `ids` (or `id`, else the selection), groups included; other objects are left
File diff suppressed because one or more lines are too long
+7 -4
View File
@@ -141,7 +141,7 @@ them all. The members stay editable: moving or editing one reshapes the solids.
## Clipping groups, blends and symbol instances
Every 3D effect (Extrude & Bevel, Extrude & Bevel (Classic), Inflate, Rotate and Revolve) also applies to a clipping
Every 3D effect (Extrude & Bevel, Extrude & Bevel (Classic), Inflate, Rotate, Rotate (Classic), Revolve and Revolve (Classic)) also applies to a clipping
group, a blend or a symbol instance, alone or inside a group or layer. The help page says that effects apply to
objects, groups or layers ([Apply and modify effects](https://helpx.adobe.com/illustrator/desktop/special-effects-styles/apply-filter-effects/apply-and-modify-effects.html)),
that a clipping mask hides everything outside its shape ([Clipping masks](https://helpx.adobe.com/illustrator/using/clipping-masks.html)),
@@ -279,7 +279,7 @@ Our reading:
command is refused with "The 3D shadow is too complex; turn Shadows off or simplify the art", and a loaded
file draws the source path.
- Canvas, SVG and PDF exports draw the shadow, the art's bounds take it in, and Expand Appearance keeps it as a
path below the faces. Extrude & Bevel (Classic) has no shadow.
path below the faces. Extrude & Bevel (Classic), Revolve (Classic) and Rotate (Classic) have no shadow.
## Parameters (`effect.apply`, `effect.setParams`)
@@ -336,8 +336,11 @@ out, perspective). No Adobe software, assets, presets or bevel shapes were used.
outline crosses. An outline of tens of thousands of points that crosses nearly every cell (a comb of 4,000 teeth
across the shape) is refused because the 3D surface is too complex; a closed path of 65,536 points round a
circle builds.
- **3D (Classic)**: Extrude & Bevel (Classic) is built, with its surface types and blend steps. Revolve (Classic),
Rotate (Classic), the track cube, map art, Turntable and 3D export are separate, unbuilt items.
- **3D (Classic)**: Extrude & Bevel (Classic), Revolve (Classic) and Rotate (Classic) are built, with their surface
types and blend steps. Revolve (Classic) sweeps the surface Revolve sweeps, at 64 segments for a full turn, and draws
every face back to front, so it has no Draw Hidden Faces setting. Rotate (Classic) turns the plane Rotate turns, seen
from either side, with the No Shading and Diffuse surfaces only. The track cube, map art, Turntable and 3D export
are separate, unbuilt items.
Release measurements and a repeatable CLI scene are in [3D lighting performance](3d-lighting-performance.md).
+4 -2
View File
@@ -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 |
@@ -373,6 +373,7 @@ next unit in the order a right-click on a ruler lists them, from Feet back to Po
|---|---|---|
| Effect > Warp Options: style previews, orientation choices and percent controls | done | #1760; focused input, mixed-style and history checks passed; original captures reviewed. No geometry or optional Properties changes. |
| Command search: Up and Down move through the results, Enter runs the highlighted one | done | #1798 (#1757) |
| Learn panel: Window › Learn and Explore tutorials on the app bar open it; For you holds a Quick skill guide card, Skills lists VectorCraft's own skills with tutorial counts and empty progress rings, a tutorial shows its numbered steps, Back goes up a level | done | [the help page](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/learn-skills-quick-skill-guide.html); `learn.list`, `learn.show`; `panels::learn::tests` |
| Pathfinder panel: a group selected alone counts its nested shapes, so an expanded stroked object keeps the Shape Modes enabled | done | #1642 (#1635) |
| Selected Grid Repeat shows row, column and corner handles and spacing sliders; bounding-box handles take priority where they meet | done | #2691, `tools/src/repeat_grid.rs`; [public behavior reference](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/create-and-edit-patterns/set-grid-repeat-options.html); drags preview and commit `object.repeat.options` as one undo step, Escape cancels; Radial Repeat has no handles yet |
| Grid Repeat Options (Object › Repeat › Options…) has a Preview checkbox: the repeat on the canvas follows the fields while the dialog is open, Cancel puts the original back without a history step, OK keeps the previewed values as one undo step | done | #2651; [public behavior reference](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/create-and-edit-patterns/set-grid-repeat-options.html) lists the Preview option for the grid options only, so Radial and Mirror Repeat Options have none; `dialogs/command.rs` tests |
@@ -520,6 +521,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. |