Merge main into feat/ai-save-graph-records

This commit is contained in:
dotCooCoo
2026-11-14 13:27:39 -08:00
179 changed files with 9758 additions and 1203 deletions
+1 -1
View File
@@ -122,7 +122,7 @@ the two can still win that race.
| 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; an `app.export` given an option the format doesn't read: also `warnings`, naming the option), `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. |
| 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. Its Create Sub-folders and Open Location after Export run `assets.settings.set {subfolders}` and `{openLocation}`; its Format Settings… opens the dialog on the Assets tab with `__settings` set to the first row's format. |
| `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` with params still exports the selection in one go, without the dialog; with no params or `{}` the save panel picks the file and its format's options dialog follows, as after Export As, and the call returns `null` while the dialog is open (OK returns what `file.exportAs` returns, without `format` or `bounds`). `file.exportAs {path, exportSelection: true, …options}` writes the selection without a 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 `warnings` as Export As shows an export's notes |
+1 -1
View File
@@ -297,7 +297,7 @@ other `sv-*` locale resolve to it), Georgian (`ka`, complete; `ka-GE` and `ka_GE
placeholders are translated in turn (the reason after `: {e}` is often a message too). A literal brace in a
row is written `{{` or `}}`, in the English and in the translation: a message made with `format!` keeps the
doubled braces of its format string, and a plain string literal has each of its braces doubled, so the row for
`"expected {\"objects\": [...]}"` is `expected {{"objects": [...]}}`. Czech, German, Greek, Spanish, French, Georgian, Hindi, Hungarian, Italian, Japanese, Korean, Polish, Brazilian Portuguese, Russian, Simplified Chinese, Traditional Chinese, Swedish, Ukrainian, Vietnamese, Finnish, Turkish, Catalan and Dutch
`"expected {\"objects\": [...]}"` is `expected {{"objects": [...]}}`. Czech, German, Greek, Spanish, French, Georgian, Hindi, Hungarian, Italian, Japanese, Korean, Polish, Brazilian Portuguese, Russian, Simplified Chinese, Traditional Chinese, Swedish, Ukrainian, Vietnamese, Finnish, Turkish, Catalan, Dutch and Danish
translate status and error messages (`COMPLETE_MESSAGES` in `i18n::tests`); the untranslated report lists the
message literals the scan finds, and the phrases a parameter schema's error builds at run time
(`SCHEMA_PHRASES`), that one of them has no row for. The scan covers the crates in `MESSAGE_CRATES`, the
+1 -1
View File
@@ -283,7 +283,7 @@ Names in the editing data that aren't UTF-8 (layers, objects, artboards, colors,
| Illustrator template `.ait` | open, save | yes | PDF-compatible only, from Save as Template (`.vctemplate` stays its default) | New from Template opens a saved `.ait` untitled with its layers and art (`tests_pdfedit.rs`) |
| Illustrator `.ai` | open, save | yes (PDF-compatible + editing-data structure with template layers and ruler guides, File Info) | PDF-compatible, or legacy version 7 (layers and groups) | see above; no real-file corpus |
| PDF | open, place, save | yes (authored ActualText in editable import, #6165; layers, masks, editable text, security, overprint, File Info from the XMP packet and the document information dictionary; Crop To › Trim takes the bleed box as the document's bleed) | yes (presets, PDF/X-1a/3/4, layers, marks and bleed, ICC, fast web view, 1.3+; objects' URLs as link annotations, not in PDF/X) | fuzzed import; shared guarded writer and windowed reader ([pdf-backend.md](pdf-backend.md)), metadata, incomplete-content and dependency-source regressions; PDF text opens where the file draws it, glyph by glyph (#722: kerning or none, spacing per character, text rise as baseline shift, vertical writing, justified text boxes); alpha soft masks drawn as images import with the mask (#1551); a clip only counts as covering the page when its shape does (#1542); a PDF another app copied pastes as editable vector art (#1499); letter-spaced type on a path keeps its length and its glyph-by-glyph stroke comes in as one text object (#1586, #1585); a crafted name tree with shared nodes no longer takes exponential time on open (#1781); fonts named with hyphens (`Noto-Sans-Bold`) or with a composite font's CMap (`Name-Identity-H`) find the installed family; invisible text (rendering mode 3: a scanned page's recognized text) opens as type with no fill or stroke and saves back as invisible, searchable text (#2675); PDF/X-1a and X-3 flattening in a CMYK document keeps CMYK inks where it rasterizes (#2160); an image mask (`/ImageMask true`) painted in a solid color opens as a grayscale image colorized by that color, a spot color keeping its swatch and tint, so Fill and Recolor Artwork reach it, and the same mask painted again in another color keeps that color (#6313); an image in a Separation space opens as a grayscale image of its tints colorized by its ink at 100 % (a spot swatch, a process plate or Registration), its soft mask as its opacity mask (#6314); a DeviceN image of one colorant opens the same way, and one of process plates only (the ink `None` may be among them) opens in CMYK with each colorant's tint in its plate (#6348) PDF export keeps harakat and zero-advance Noto Arabic dot glyphs in one compatible batch per layout line, with per-glyph vertical offsets (#6309). `crates/pdf/src/tests/realtext.rs` (`mark_text_*`) checks decoded cluster mappings, mixed Arabic/Latin/digits, contour placement against outline export, vertical columns, differing path rotations and PDF/X-1a/3/4. Editable-text import preserves authored ActualText separately (#6165), with cross-line/style layout limits; separately styled or differently rotated clusters and external viewer search/copy remain outside this export-only evidence. |
| 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 CMap (`UniJIS-UCS2-H`, `90ms-RKSJ-H`, `GBK-EUC-H`, `KSCms-UHC-H`, `ETen-B5-H`), set as type in the font of the CIDFont's name, vertical over a `-V` CMap; a name that ends in the row-and-cell CMap `H` or `V` splits off the CMap only when the file defines the CIDFont of that name, or the name has a hyphen and an installed face that covers Japanese has it; 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) |
| 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 CMap (`UniJIS-UCS2-H`, `90ms-RKSJ-H`, `GBK-EUC-H`, `KSCms-UHC-H`, `ETen-B5-H`), set as type in the font of the CIDFont's name, vertical over a `-V` CMap; a name that ends in the row-and-cell CMap `H` or `V` splits off the CMap only when the file defines the CIDFont of that name, the CIDFont is `Ryumin-Light` or `GothicBBB-Medium` (the Japanese CIDFonts a printer carries), or the name has a hyphen and an installed face that covers Japanese has it; 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` |
| DCS 1.0 / 2.0 | place linked | place linked only (one image of the plates; spot plates as spot swatches; the composite's clipping path; each plate on its own ink in Separations Preview and print separations) | no | `crates/eps/src/dcs/tests.rs`, `crates/engine/src/tests/dcs.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`); a masked group, or a knockout group's masked group, whose content has a shadow, glow, blur or feather starts with a hidden, unpainted rectangle over the mask's region, so readers that draw a masked group only inside the box of its shapes draw those effects too (`crates/svg/tests/it/blend_export.rs`); SVG Options › Include Variable Data writes the text variables, data sets and bound type objects, and opening the SVG reads them back (`tests::variables::an_svg_with_variable_data_opens_with_its_variables_data_sets_and_bindings`) |
+6 -2
View File
@@ -34,6 +34,7 @@ Artboard Options forwards the active Artboard tool's Scale Artwork with Artboard
| Date | Change | Summary |
|---|---|---|
| 2026-11-14 | minor | G12: Symbols panel context menu: right-click on a symbol in thumbnail or list view displays a context menu (Place Symbol Instance, Edit Symbol, Duplicate Symbol, Delete Symbol, Break Link to Symbol, Select All Instances), selecting the symbol first if unselected; scores and estimates unchanged. |
| 2026-11-14 | minor | G5: Weather Icons joins Basic Shapes, UI Frames, Map Markers, Inventory Icons and Skill Icons as a sixth built-in symbol library (Sun, Moon, Cloud, Rain, Thunder, Snow; original procedural vector symbols generated in code, no default 9-slice); estimate decremented (5–15 → 4–14 h). |
| 2026-11-14 | minor | G12: Layers panel row context menu (Options…, Duplicate, Delete, Lock Others/Show All/Hide Others/Unlock All, Locate Object, Collect for Export) with selection handling and undo tracking. Scores and estimates unchanged. |
| 2026-11-13 | minor | PDF import: preserve Type 3 font text runs as named groups `<g>`, or as live text in `TextAs::Text` mode if `/ToUnicode` exists on non-colour fonts (`TextAs::Outlines` produces grouped outlines) (#6740); scores and estimates unchanged. |
@@ -465,6 +466,7 @@ macOS cursor delivery (#2292) is narrowed to a native host adapter using the exi
## G12 Preferences and panels that don't act yet
- **Done (2026-11-14):** Symbols panel context menu: right-click on a symbol in thumbnail or list view displays a context menu with Place Symbol Instance, Edit Symbol, Duplicate Symbol, Delete Symbol, Break Link to Symbol (enabled when canvas selection includes instances of the symbol), and Select All Instances, selecting the symbol if unselected. Estimate unchanged.
- **Done (2026-10-29, #4522):** the Pathfinder panel menu's Make, Release and Expand Compound Shape, which were dimmed placeholders, and the panel's Expand button act on live compound shapes ([Create compound shapes with Pathfinder](https://helpx.adobe.com/illustrator/desktop/manage-objects/reshape-transform-objects/create-compound-shapes-with-pathfinder.html)): Alt-clicking a Shape Mode makes one in that mode, a Shape Mode sets the mode of the members selected, and the compound shape draws, exports and saves as the area its members' modes make (`object.compoundShape.*`, `crates/engine/src/tests/compound_shape.rs`). Left: blends, envelopes and warps as members, question marks on the buttons for mixed member modes, clicks that hit the area rather than the members. Estimate unchanged.
- **Done (2026-10-25, #3426):** Pathfinder panel › Pathfinder Options… ([Pathfinder panel overview](https://helpx.adobe.com/illustrator/desktop/manage-objects/reshape-transform-objects/pathfinder-panel-overview.html)): Precision (0.001–10 pt; results are refit to within it and pieces thinner than it are dropped), Remove Redundant Points and Divide and Outline Will Remove Unpainted Artwork (pieces of objects with no fill), kept in the preferences (`object.pathfinder.options`, group `pathfinder`) and used by every Shape Mode and Pathfinder button and Repeat; the page gives no defaults, so ours (0.01 pt, both off) keep the earlier results byte for byte. Trap is left as it was. Estimate unchanged.
- **Done (2026-10-25):** Artboards panel › Delete Empty Artboards ([Delete artboards](https://helpx.adobe.com/illustrator/desktop/create-manage-artboards/add-edit-artboards/delete-artboards.html), [artboard context menu](https://helpx.adobe.com/illustrator/desktop/create-manage-artboards/organize-manage-artboards/use-artboard-context-menu.html)): `artboard.deleteEmpty` deletes every unlocked artboard with no artwork, with its guides, in one undo step, and keeps artboard 1 when every artboard is empty and none is locked; an artboard is empty when no object (hidden, locked and template art included; guides not) has visual bounds that meet or touch it, a group counting by its members and a clip group or clipping layer by its members inside the clip (our reading of "no artwork"; the pages give no finer rule). The Artboard tool's canvas context menu lists it too. Estimate unchanged.
@@ -632,6 +634,9 @@ macOS cursor delivery (#2292) is narrowed to a native host adapter using the exi
made to an object inside it at the object in the same place ([public source](https://helpx.adobe.com/illustrator/desktop/manage-objects/edit-objects/edit-groups-with-similar-objects.html));
a group that holds type or an image is not taken, as Global Edit does not take images or text
([public source](https://helpx.adobe.com/illustrator/desktop/manage-objects/edit-objects/edit-similar-objects.html));
rotated copies of the object or group are taken too, and an edit reaches each turned by its angle
([public source](https://helpx.adobe.com/vn_vi/illustrator/how-to/modern-logo-design.html); reflected copies are not
taken, VectorCraft's own rule);
with one such object or group selected with the Selection tool, the objects Start Global Edit would take are
highlighted on the canvas before it starts (`selecting_one_object_highlights_the_similar_objects_before_global_edit_starts`);
dynamic symbols (#4938): Symbol Options › Symbol Type (Dynamic Symbol / Static Symbol; `type` on
@@ -677,8 +682,7 @@ macOS cursor delivery (#2292) is narrowed to a native host adapter using the exi
painted with the texture effects; User Defined; Other Library…; `graphicStyle.libraries`,
`graphicStyle.addFromLibrary`).
- **Missing:** more built-in brush libraries beyond the eight shipped (and further graphic-style libraries beyond the ten shipped, and further symbol libraries beyond Basic
Shapes, UI Frames, Map Markers, Inventory Icons, Skill Icons and Weather Icons; original, generated in code, never Adobe's); dynamic symbols' `.ai` read and write;
Global Edit of rotated copies as matches.
Shapes, UI Frames, Map Markers, Inventory Icons, Skill Icons and Weather Icons; original, generated in code, never Adobe's); dynamic symbols' `.ai` read and write.
- **Estimate:** 4–14 h.
## G3 3D and Materials
+5 -6
View File
@@ -15,7 +15,7 @@ translation never fails a test or a build: the interface shows the English text
`cargo xtask ci` prints the untranslated report (`cargo xtask i18n-report` alone), which lists per language the
strings missing from each catalog with the `complete_menus` flag and the messages missing from each language in
the `COMPLETE_MESSAGES` list. Every non-English language marked "full" has the flag, and all of them except
Bosnian, Bulgarian, Danish and Indonesian are in the list. No language has help content: there is no translated (or
Bosnian, Bulgarian and Indonesian are in the list. No language has help content: there is no translated (or
English) in-app help, and the docs are English.
**Native review:** every catalog was written clean-room from the English meaning, most of it by agents
@@ -36,11 +36,11 @@ Chinese by `imachus`). Georgian and the original Gujarati catalog are recorded a
| Arabic | `ar` | 0 | none | document text: bidi layout and Paragraph Direction; interface: no right-to-left layout, no Arabic shaping in egui | no | none | 25–40 |
| French | `fr` | 9,166 rows, 3,436 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 178 missing messages for it | all | Latin | no | full | — (review) |
| Portuguese | `pt-br` | 9,378 rows, 3,563 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 55 missing messages for it, which open #7116, #7211, #7330, #7378 and #7405 translate; one/other plurals | all | Latin | contributor is a Brazilian Portuguese speaker; further native review welcome | full | — (review) |
| Indonesian | `id` | 5,279 rows, 750 of them `@msg` (counted 2026-10-21): menus and `tl!` literals complete when counted; its messages are partial; one plural form | dialogs and tooltips all; 750 message rows (French has 796) | Latin | no | full | — (review) |
| Indonesian | `id` | 6,825 rows, 1,036 of them `@msg` and 47 `@msgplural` (counted 2026-11-14 on `main` at `676f0524cc`): the untranslated report lists 60 missing menu strings, 35 `tl!` literals and 13 undo labels for it; not in `COMPLETE_MESSAGES`, and checked against the same scanned messages it lacks 2,508; one plural form | most dialogs and tooltips; status and error messages partial | Latin | no | full | — (review) |
| Japanese | `ja` | 4,004 / 4,020 (99.6%) | all | CJK UI font as above; Japanese IME; vertical type partial; Japanese crop marks and composition settings | no | full | — (review) |
| German | `de` | 3,952 / 4,020 (98%; menus, literals and messages complete when counted) | all (3,563 `@msg` and 48 `@msgplural` rows, counted 2026-11-13: the untranslated report lists 52 missing messages for it, which open #7116, #7211 and #7378 translate) | Latin | contributor-written, not reviewed | full | — (review) |
| Korean | `ko` | 4,870 rows (counted 2026-10-21): menus, `tl!` literals and messages complete when counted; one plural form | all (3,438 `@msg` and 48 `@msgplural` rows, counted 2026-11-13: the untranslated report lists 39 missing messages for it) | Hangul from an installed system font on the desktop (Apple SD Gothic Neo, Malgun Gothic, Noto Sans CJK KR…); the web build has no Korean UI font yet (craft-fonts); IME path exists | no (AI-drafted) | full | — (review; web font) |
| Vietnamese | `vi` | 4,886 rows (counted 2026-10-21): menus, `tl!` literals and messages complete when counted; one plural form; 4,046 plain + 18 `@plural` + 28 contextual + 794 `@msg` | all | Latin with Vietnamese diacritics (stacked marks attach in precomposed, decomposed and keyboard forms, #4491; glyph tests pass) | contributor is a Vietnamese speaker; AI-assisted draft, further native review welcome | full | — (review) |
| Vietnamese | `vi` | 4,886 rows (counted 2026-10-21): menus, `tl!` literals and messages complete when counted; one plural form; 4,046 plain + 18 `@plural` + 28 contextual + 794 `@msg` | dialogs and tooltips all; messages partial (1,750 `@msg` and 49 `@msgplural` rows, counted 2026-11-14: the untranslated report lists 1,875 messages without a Vietnamese row, 53 of which open #7211, #7378, #7405 and #7434 translate) | Latin with Vietnamese diacritics (stacked marks attach in precomposed, decomposed and keyboard forms, #4491; glyph tests pass) | contributor is a Vietnamese speaker; AI-assisted draft, further native review welcome | full | — (review) |
**Historical 12-language score: ~82%** (equal weights: 100 + 85 + 100 + 0 + 0 + 100 + 100 + 100 + 100 + 98 + 100 + 100, over 12).
**To `full` for all twelve: ~50–85 h** (historical estimate, not re-scored here). Hindi now has
@@ -55,20 +55,19 @@ plus review. Native-speaker review is human work and isn't in the hours.
| Traditional Chinese (Taiwan) | `zh-hant` | 8,820 rows, 3,438 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 40 missing messages for it; menus, `tl!` literals and messages were complete when counted on 2026-10-21 (80% overall) | partial |
| Italian | `it` | 8,924 rows, 3,560 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 54 missing messages for it, which open #7116, #7211, #7378 and #7405 translate | full |
| Dutch | `nl` | 3,447 `@msg` and 48 `@msgplural` rows (counted 2026-11-13): in `COMPLETE_MESSAGES`, and the untranslated report lists 41 missing messages for it; one/other plurals | full |
| Danish | `da` | 5,279 rows, 750 of them `@msg` (counted 2026-10-21): menus and `tl!` literals complete when counted; its messages are partial; one/other plurals | full |
| Danish | `da` | 7,422 rows, 1,636 of them `@msg` and 48 `@msgplural` (counted 2026-11-14 on `main` at `edb228ac3`): in `COMPLETE_MESSAGES`, and the untranslated report lists the same missing messages for it as for Greek, Spanish and Finnish; one/other plurals | full |
| Russian | `ru` | 4,009 / 4,020 | full |
| Ukrainian | `uk` | 8,802 rows, 3,439 of them `@msg` and 48 `@msgplural` (counted 2026-11-13); one/few/many plurals | full |
| Hungarian | `hu` | 9,166 rows, 3,444 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 40 missing messages for it, and lists 47 menu strings, 25 `tl!` strings, 11 undo labels and 45 swatch names without a row; one plural form | full |
| Polish | `pl` | 9,044 rows, 3,439 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 46 missing messages for it, and 47 menu strings, 26 `tl!` literals, 11 undo labels and 45 swatch names; one/few/many plurals | full; native review pending |
| Finnish | `fi` | 5,318 rows (counted 2026-10-21): menus, `tl!` literals and messages complete when counted; one/other plurals, 797 `@msg` rows | full; AI-assisted, native proofreading pending |
| Czech | `cs` | 9,273 rows, 3,560 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 2 missing Czech messages, and 54 messages that no language has a row for | catalog complete; render-site gaps reduced; native review pending |
| Bosnian | `bs` | 5,841 rows (counted 2026-10-30): menus, `tl!` literals and messages complete when counted; one/few/other plurals | full; AI-assisted, native review pending |
| Bosnian | `bs` | 6,887 rows, 1,144 of them `@msg` and 47 `@msgplural` (counted 2026-11-14 on `main` at `676f0524cc`): the untranslated report lists 97 missing menu strings, 53 `tl!` literals and 27 undo labels for it; not in `COMPLETE_MESSAGES`, and checked against the same scanned messages it lacks 2,416; one/few/other plurals | full; AI-assisted, native review pending |
| Swedish | `sv` | 8,991 rows, 3,106 of them `@msg` and 48 `@msgplural` (counted 2026-11-14): the untranslated report lists 518 missing messages for it, and 12 menu strings, 1 `tl!` literal and 3 undo labels; one/other plurals | full; native review welcome |
| Bulgarian | `bg` | 5,245 rows, 763 of them `@msg` (counted 2026-10-21): menus and `tl!` literals complete when counted; its messages are partial | full; AI-drafted, native review pending |
| Greek | `el` | 5,251 rows, 795 of them `@msg` (counted 2026-10-21): menus, `tl!` literals and messages complete when counted | full; native review welcome |
| Georgian | `ka` | 5,200 rows (counted 2026-10-21): menus, panels, dialogs, plurals (one count-neutral form) and messages, tested complete; reviewed by a native speaker | full |
| Turkish | `tr` | 5,558 rows, 880 of them `@msg` (counted 2026-10-28); 6 menu strings and the default swatch names still fall back to English | full |
| Indonesian | `id` | 5,531 rows, 788 of them `@msg` (counted 2026-10-28): menus and `tl!` literals complete when counted; its messages are partial; one plural form | full |
| Catalan | `ca` | 5,626 rows, 881 of them `@msg` (counted 2026-10-28): menus, `tl!` literals and messages complete when counted; one/other plurals; every `ca-*` locale resolves here | full; AI-drafted, native review welcome |
Twenty-seven non-English catalogs in all (registry count, 2026-11-06). Illustrator, as its public documentation lists, ships around two dozen
+151 -27
View File
@@ -667,7 +667,7 @@ sampler.
| `transform` | `{ids?, dx?, dy?, rotate?, scale?, scaleX?, scaleY?, reflect?, shear?, origin?, copy?}` | Runs move, rotate, scale, reflect, shear in that order. `rotate` is in degrees counter-clockwise; a positive `shear` moves the top to the right. With `copy`, the first step duplicates. |
| `create_graph` | `{type?, x, y, width, height, csv? \| series?, categories?, rows?}` | The nine Illustrator graph types: column, stacked column, bar, stacked bar, line, area, scatter, pie and radar. An empty CSV cell or a `null` in `rows` is a blank value; a number in straight quotes is a label. Edit later with `graph.setData` / `graph.setType` via `run_command`. `graph.column {design, columnType: vertical\|uniform\|repeating\|sliding, each, fractions: chop\|scale}` draws the columns or bars of the series picked with Group Selection (or `seriesIndexes`, or all of them) with a graph design saved by `graph.design`; with no `design` it returns the series' current design and options. Type in the design that holds a `%` followed by two digits shows each column's value, with at least the first digit's places before the decimal point and the second digit's places after it. |
| `text_wrap` | `{ids?, offset?, invert?, release?}` | Area type below the objects (same layer) flows around them. |
| `undo` / `redo` | `{}` | Many calls that change nothing record no undo step, for example `object.align` with nothing to move, `object.move` by 0 without `copy` and `object.showAll` with nothing hidden. `undo` (`edit.undo`) after such a call undoes the step before it. `inspect_document` lists the undo steps as `history`. `run_command` with `edit.clearHistory` removes every undo and redo step of the active document and returns `{cleared}`, the number of steps removed; the document stays as it is, and the command records no undo step. `run_command` with `edit.newDocumentFromState` and `{index?, created?}` makes a new document holding the art as it was at that state and makes it the active document, and returns `{index, title}`. `index` is a row of the History panel, with 0 the oldest state kept, and an omitted `index` uses the current state. An `index` that names no state is an error and changes nothing. `created` is File Info's created date in Unix seconds or null, and defaults to now. The new document takes the next `Untitled-N` name, is marked unsaved, has nothing selected and has no steps to undo or redo. It is out of symbol, opacity-mask and pattern editing, and the art drawn in a pattern's tile is stored in the pattern, as `object.pattern.done` stores it. The source document and its steps stay as they are, except that typing or a drag in progress is first kept as a step. When a command keeps a drag whose preview Real-time Drawing off had not applied yet (`edit.undo`, `edit.redo`, `edit.clearHistory`, `edit.newDocumentFromState` and the other commands that end a drag first), and applying that preview gives a warning, the command's result carries it as `previewWarning`, and as `warning` too when the command gives no warning of its own; the app's status bar shows `warning`. While the Type tool edits type, `undo` and `redo` put its caret, with no characters selected, at the end of the text the step changed: after the text it puts back or retypes, or where the text it takes out was. A step that changes no characters, such as a formatting change, leaves the caret and the selection where they are. |
| `undo` / `redo` | `{}` | Many calls that change nothing record no undo step, for example `object.align` with nothing to move, `object.move` by 0 without `copy` and `object.showAll` with nothing hidden. `undo` (`edit.undo`) after such a call undoes the step before it. `inspect_document` lists the undo steps as `history`. `run_command` with `edit.clearHistory` removes every undo and redo step of the active document and returns `{cleared}`, the number of steps removed; the document stays as it is, and the command records no undo step. `run_command` with `edit.newDocumentFromState` and `{index?, created?}` makes a new document holding the art as it was at that state and makes it the active document, and returns `{index, title}`. `index` is a row of the History panel, with 0 the oldest state kept, and an omitted or null `index` uses the current state. An `index` that names no state fails with `no history state N`, one that is not a whole number with `` `index` must be a whole number ``, and either changes nothing. `created` is File Info's created date in Unix seconds or null, and defaults to now. The new document takes the next `Untitled-N` name, is marked unsaved, has nothing selected and has no steps to undo or redo. It is out of symbol, opacity-mask and pattern editing, and the art drawn in a pattern's tile is stored in the pattern, as `object.pattern.done` stores it. The source document and its steps stay as they are, except that typing or a drag in progress is first kept as a step. When a command keeps a drag whose preview Real-time Drawing off had not applied yet (`edit.undo`, `edit.redo`, `edit.clearHistory`, `edit.newDocumentFromState` and the other commands that end a drag first), and applying that preview gives a warning, the command's result carries it as `previewWarning`, and as `warning` too when the command gives no warning of its own; the app's status bar shows `warning`. While the Type tool edits type, `undo` and `redo` put its caret, with no characters selected, at the end of the text the step changed: after the text it puts back or retypes, or where the text it takes out was. A step that changes no characters, such as a formatting change, leaves the caret and the selection where they are. |
For example, create editable Japanese area type with the engine's vertical writing mode:
@@ -856,7 +856,8 @@ stored without its placement (its vector, aspect ratio, focal point and freeform
own box when the graph is drawn again, so `paint.setGradientGeom` and the `paint.freeform.*` edits do not store the
placement they set there. A stroke weight and dashes are stored as the label shows them, also on a label that was
scaled. When the characters of labels of one kind change differently, the frontmost label sets what the kind keeps. On
a pie with Legends in Wedges whose legend labels have no fill of their own, the legend labels' fill is stored only when
a pie with Legends in Wedges, a fill a command sets on the legend labels is drawn on every wedge, black included, until
that command is undone; a size, font or stroke change does not set one. Before that, their fill is stored only when
every legend label the command reaches ends up with the same fill. Otherwise they are drawn again in black, or white on
a dark wedge. These commands do not store the colors they give a graph's axis lines, ticks and radar rings, which are
drawn again with their default paint.
@@ -867,6 +868,13 @@ kind takes them when the graph is drawn again. The graph saves the paragraph att
`categoriesPara` and `legendPara` in its label styles, and still sets each label's alignment for its place. The legend
leaves room for a legend label's stored indents, spacing and leading.
When a graph is drawn again, its plot moves and scales with any move or scale of the graph made since it was last
drawn. The graph saves the bounds of its art other than type as `placedArt` (and the bounds of all of its art as
`placed`), and measures the move or scale on those. Changing the size, indents or spacing of the labels, moving a label
on its own and `type.createOutlines` on labels do not move or scale the plot. A graph opened from a `.ai` file saves
`placedArt` too. A graph saved without `placedArt`, or with a `placedArt` that has no width or height, is measured on
`placed`.
The `appearance.*` commands, `graphicStyle.apply` and `graphicStyle.redefine`, and the paint, stroke, gradient and
transparency commands given an `item` (or the Appearance panel's active row) store a graph label's object rows for its
kind of label: the paint, weight, opacity and blend mode of its topmost visible fill and stroke row, their order and
@@ -1085,7 +1093,15 @@ or `range`), named `<file>-<artboard>.<ext>`, and returns `{path, files}` (a PDF
SVG writes one file per artboard of a `range`); `useArtboards: false` exports the bounds of the visible art with what
its effects paint, the effects of groups, type and images included. `artboard.fitToArt` measures the art the same
way. `document.exportPdf {useArtboards: false}` writes that one page as well, and ignores `artboard`, `artboards` and
`range`. A PDF of that page, from either command, carries no Preserve Editing data; when Preserve Editing is on (as it
`range`. A PDF or `.ai` page of the art's bounds is measured without the non-printing layers that the file leaves out
(unless `includeNonPrinting` or `createLayers` keeps them; a `.ai` file keeps layers by default). An HP-GL plot of the
art's bounds is measured without what the plot leaves out: non-printing layers, objects at 0% opacity, placed images,
gradient meshes whose every point is at 0% opacity, and paths without effects whose fills and strokes paint nothing.
An image or a mesh with a Crop Marks effect, or with a Vector Halftone effect that makes dots, is measured.
Such objects in the art of a symbol that is not dynamic are left out of its instances too, and an instance whose
symbol holds nothing else is left out.
A document whose only visible art is left out is refused, and Export As refuses an HP-GL plot of it before the save
dialog. A PDF of that page, from either command, carries no Preserve Editing data; when Preserve Editing is on (as it
is in VectorCraft Default), the export comes back with a warning that says so. A `.ai` export with
`useArtboards: false` writes that one page too, without the native document and without the editing copy for other
apps (`editingData`), and always comes back with the warning `Preserve editing was left out: an .ai file of the art's
@@ -2771,11 +2787,11 @@ nearest to the pointer.
## Global Edit
Select › Start Global Edit is `select.globalEdit {appearance?, size?, artboards?, includeCanvas?}`. With one path,
compound path or symbol instance selected, it finds the objects of the same shape (moved or scaled copies; not rotated
ones), among those `select.all` would take and the objects in their groups, and returns `{active: true, count, ids}`,
compound path or symbol instance selected, it finds the objects of the same shape (moved, scaled or rotated copies;
not reflected ones), among those `select.all` would take and the objects in their groups, and returns `{active: true, count, ids}`,
the selected object first (at most 10,000). With a group of such objects selected (nested groups and clipping paths
included; not type or images), it finds the groups like it: as many objects, in the same order, each of the same
shape, lying the same way relative to each other (the group moved or scaled as a whole). While Global Edit is off,
shape, lying the same way relative to each other (the group moved, scaled or rotated as a whole). While Global Edit is off,
the command is disabled for any other selection, including a group that holds type, an image or nothing (it is off in
the Select menu, the Properties panel's Quick Actions do not show it, and the Control bar does not show its Global Edit
Options). `appearance` also asks for
@@ -2784,7 +2800,9 @@ the same fill and stroke (for groups, of each object in them), `size` for the sa
params come from `select.globalEditOptions` (the Global Edit Options, kept for the session; it returns them with
`count`, the objects a start would take now). The selection stays the one object. Until the next `select.globalEdit`
(Stop Global Edit, `{active: false}`), what an edit of a selected match changed is given to the other matches, in the
same undo step, and nothing else. A changed outline or anchors go to each match in proportion to its size. A changed
same undo step, and nothing else. A changed outline or anchors go to each match in proportion to its size, and to a
rotated copy turned by its angle: an anchor moved to the right on the selected object moves upward on a copy rotated
a quarter turn counter-clockwise. A changed
opacity or blending, and each changed setting of a fill or stroke (paint, weight, opacity, blending, effects…), are
copied as they are to the match's fill or stroke of the same kind and rank; its other fills and strokes, and their
unchanged settings, stay its own (a stroke weight change leaves the fills). A stroke weight set on the selected match
@@ -2800,6 +2818,16 @@ nothing. Nothing of it is saved. Before Global Edit starts, while one object tha
selected with the Selection tool, the canvas highlights the other objects a start would take with the current Global
Edit Options (none while a drag is in progress, or when there are none).
Rotated copies are edited together as in [Design a modern geometric
logo](https://helpx.adobe.com/vn_vi/illustrator/how-to/modern-logo-design.html), where copies of a group rotated
around a point are edited at once from one of their objects. These rules for them are VectorCraft's own. A copy's
angle is the one that lays each anchor and handle of the selected object on the copy's anchor and handle of the same
order, so a square whose anchors were turned a quarter turn is a copy rotated a quarter turn. The copy is the same
shape when, laid so, every anchor and handle lies within a millionth of the larger side of the copy's box of its own. A
reflected copy is another shape, and so is a copy stretched along one direction. With `size`, a rotated copy has the
same size when it is the selected object rotated without scaling: a 30 × 70 pt object and its copy rotated a quarter
turn (70 × 30 pt by its box) have the same size.
`select.globalEditExclude {id}` leaves the match `id` out of the Global Edit, as a Shift-click on a highlighted match
(or on an object inside it) with the Selection tool does: it is no longer highlighted, and later edits leave it as it
is. It returns `{active, count, ids}`, the objects left in the Global Edit; with fewer than two left, the Global Edit
@@ -2924,8 +2952,16 @@ tutorials, `steps` the number of a tutorial's steps, `finished` whether it is fi
zero-based indexes of its steps marked done (every step of a finished tutorial). `learn.skills {}` shows the panel on its Skills tab with the list of
skills, with no skill and no tutorial open, as the Quick skill guide card and Back to skills do, and answers what
`learn.list` answers. `learn.show {tutorial}` shows the panel on its Skills tab with that
tutorial's steps → `{skill, tutorial, title, steps: [text]}`. A missing, non-string or unknown `tutorial` is an error
and changes nothing.
tutorial's steps → `{skill, tutorial, title, steps: [text]}`; choosing a tutorial's row runs it. A missing, non-string
or unknown `tutorial` is an error and changes nothing. A click on the For you or Skills tab button runs
`learn.tab {tab}` when the panel shows the other tab, and runs no command when the panel already shows that tab.
`learn.tab {tab}`, with `tab` set to `forYou` or `skills`, shows the panel on that tab → `{tab, skill, tutorial}`,
with null for no skill or no tutorial open; the Skills tab keeps the skill and tutorial it had open. Choosing a skill's row runs
`learn.skill {skill}`, which shows the panel on the Skills tab with that skill's tutorials → the skill as `learn.list`
lists it. A missing, non-string or unknown `tab` or `skill` is an error and changes nothing. Back runs `learn.back {}`,
which shows the panel and goes up one level on the Skills tab, from a tutorial's steps to its skill's tutorials and
from a skill's tutorials to the list of skills, and answers what `learn.tab` answers; on the list of skills or the For
you tab the view stays as it is.
Under a tutorial's steps, View more opens the tutorial's practice sample, a small drawing of VectorCraft's own with the
art its steps work on, as a new untitled document that becomes the active one; Save asks where to save it. Once the
@@ -2952,11 +2988,11 @@ finished and every step marked. The desktop app keeps the progress in its prefer
when two windows change it, the one that saves last keeps its progress. The web build keeps it while the page is open.
Marking steps by hand, keeping the progress and Reset progress are VectorCraft's own rules.
`learn.markStep {tutorial, step, complete?}` runs a step's check box → `{tutorial, step, complete}`: `step` is the
zero-based step number, and `complete` marks the step done (`true`, omitted or null) or not done (`false`). A missing
`step` or one the tutorial does not have, a `complete` that is not true or false, a tutorial whose sample was not
opened, and a finished tutorial are errors. `learn.resetProgress {}` runs Reset progress and answers what `learn.list`
answers; open documents, opened samples and the Learn view stay as they are. For both, a missing, non-string or
unknown `tutorial` is an error, and an error changes nothing.
zero-based step number, and `complete` marks the step done (`true`, omitted or null) or not done (`false`). A missing,
non-string or unknown `tutorial`, a missing `step` or one the tutorial does not have, a `complete` that is not true or
false, a tutorial whose sample was not opened, and a finished tutorial are errors, and an error changes nothing.
`learn.resetProgress {}` runs Reset progress and answers what `learn.list` answers; open documents, opened samples and
the Learn view stay as they are.
The Home screen has a Learn section between Recent Files and the new-file presets, as
[the help page](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/homescreen-overview.html)
@@ -2973,6 +3009,9 @@ rules.
{"name":"invoke_menu","arguments":{"command":"learn.finish","params":{"tutorial":"pen-paths"}}}
{"name":"invoke_menu","arguments":{"command":"learn.next","params":{"tutorial":"pen-paths"}}}
{"name":"invoke_menu","arguments":{"command":"learn.skills","params":{}}}
{"name":"invoke_menu","arguments":{"command":"learn.skill","params":{"skill":"draw"}}}
{"name":"invoke_menu","arguments":{"command":"learn.back","params":{}}}
{"name":"invoke_menu","arguments":{"command":"learn.tab","params":{"tab":"forYou"}}}
{"name":"invoke_menu","arguments":{"command":"learn.resetProgress","params":{}}}
```
@@ -3608,7 +3647,7 @@ already walks Image Trace. Short agent entry points:
is changed, renamed or deleted. In the app,
`ui.imageTracePresetDialog {params?, rename?}` opens the Image Trace panel's Save as New Preset… or Rename… dialog.
- Live Paint: `livePaint.make`, `livePaint.merge`, `livePaint.fill {group?, point}`, `livePaint.strokeEdge`,
`livePaint.info {group}`, `livePaint.release`, `livePaint.expand`, and `livePaint.gapOptions {ids?, detect?, size?,
`livePaint.info {group?|id?}`, `livePaint.release`, `livePaint.expand`, and `livePaint.gapOptions {ids?, detect?, size?,
color?, closeGaps?}` (Object › Live Paint › Gap Options). Make gives each covered face the fill of its front-most
covering source, including compound paths with shared curved boundaries. Expand keeps those face fills.
`livePaint.expand` keeps each face and edge that draws, with all its fill and stroke rows: it is shown, its opacity
@@ -3617,6 +3656,13 @@ already walks Image Trace. Short agent entry points:
row is hidden is removed. `livePaint.merge` copies the fill and stroke rows, visibility, opacity and blending mode of
each face that draws by this rule, and of each edge, to the rebuilt parts, with their gradients kept at their fit on
the old outline and without the strokes' pen pressure, tilt, bearing and rotation.
`livePaint.info` lists each face's top fill as `fill` and each edge's top stroke and its weight as `stroke` and
`width`, and lists every fill and stroke row of each face and edge in `appearance`, bottom first, as
`{index, kind, paint, opacity, visible, width?, drawn}`: `index` counts fills and strokes together, `opacity` runs
from 0 to 1, and `width` (strokes only) is the weight in points. `drawn` is true when the row draws by the rule
above: the part is shown with an opacity above 0, and the row is shown, has paint and has an opacity above 0 (a
stroke also a weight above 0). An unpainted top row can sit over a lower row that draws, so `fill`, `stroke` and
`width` alone may not describe what the part draws.
With `detect: true`, paint stops at the gaps that run
from a loose end of a path to the nearest path, up to `size` wide (`small` 3 pt, `medium` 6 pt, `large` 12 pt, or a
number of points up to 72); `closeGaps: true` adds an unpainted path across each of them. `color` (the Gap Preview
@@ -5446,6 +5492,13 @@ keeps the segment's direction when the smoothed path there turns back by 90° or
path, the curve keeps the direction of the part outside the drag. `object.path.smooth` and Simplify keep each end's
direction.
`path.smoothRegion` keeps an anchor as a corner where the path turns by more than 57.5° (an angle inside the corner
under 122.5°) at the anchor and also over `radius` and over twice `radius` on either side of it (on a closed path that the drag reaches all the
way round, no more than an eighth of its length), so a jag or a bump smaller than `radius` is still smoothed. The stretches on either side of a kept corner are smoothed and refitted on their
own, and the corner keeps its place and the directions the path arrives and leaves along, on every call and at any
`fidelity`. A call that changes no anchor returns `{ids: [], before: 0, after: 0}` and adds no undo step. The 57.5°
threshold is VectorCraft's own value.
In the desktop app, Object › Path › Smooth, the canvas context menu's Smooth… (listed while the selection holds a
path) and the Contextual Task Bar's Smooth (with a path selected whole with the Direct Selection tool) open the
slider (`ui.menuDialog {command: "object.path.smooth"}`, dialog `smoothSlider` with field `level`) at the
@@ -6337,6 +6390,10 @@ Pen's second anchor at (150, 431), in line with the square's centre.
- `highlightAlternateGlyphs` (off by default): Preferences › Type › Highlight Alternate Glyphs. On, the canvas paints
pink behind OpenType substitutions (ligatures, contextual forms). Document Setup's Highlight Substituted Glyphs
stays separate. Agents set it with `prefs.set`; the desktop canvas reads it on the next paint.
- `showCharacterAlternates` (on by default): Preferences › Type › Show Character Alternates. On, the desktop canvas
shows the alternate glyphs of the one character selected with a Type tool beside it (see
[Alternate glyphs](#alternate-glyphs)). Off, it shows none. It is VectorCraft's own option. `prefs.set` refuses a
value that is not a boolean.
- `highlightSubstitutedFonts` (on by default): Preferences › Type › Highlight Substituted Fonts. On, the canvas paints
pink behind text drawn in a substitute for a missing font, in every open document. Off, no document shows that
highlight. `document.setup` ignores this key and adds a `warnings` entry that names `prefs.set` to its reply. A file
@@ -6761,7 +6818,10 @@ copies in artboard order); `artboard` wins when both are given. Without either,
several artboards selected, they paste a copy on each of those, and the journal records them as `artboards`; a
recorded action leaves both out. Art copied from no artboard keeps its place on the first artboard named and its
offset to that one on the others. An index the document does not have, a repeated index, a value that is not an index
or an empty list fails, and nothing is pasted. Copied artboards come back once, where they were, whichever artboards
or an empty list fails, and nothing is pasted. An `artboard` that is not a whole number, null included, fails with
`` `artboard` must be a whole number ``, and an `artboards` entry that is not one with
`` `artboards` must contain whole numbers ``; both keys are checked when both are given. Copied artboards come back
once, where they were, whichever artboards
are named. `layer.pasteRemembersLayers {on?}` (a document option, `document.inspect` → `pasteRemembersLayers`)
pastes objects back into the layers and sublayers they came from: in the same document while those are still there,
else by the names of the layer and the layers around it (the topmost chain that matches the most names, a shown and
@@ -6804,9 +6864,15 @@ also move the pattern tiles of the copies when `patterns` is true (default: pref
`artboard.duplicate`, `artboard.copy`, `artboard.cut`, `artboard.move` and `artboard.rearrange` take `lockedAndHidden?`
(default: prefs `moveLockedWithArtboard`), and with the Artboard tool chosen `edit.copy` and `edit.cut` pass it on. When
art goes along, the journal records the value, so a replay under another preference takes the same art.
Every artboard command that takes an `index` fails with `no such artboard` when the `index` is not the
0-based index of an artboard (past the last one, negative, fractional, a string or null), and the document and the
clipboard stay as they were.
Every artboard command that takes an `index` fails with `no such artboard` when the `index` is a whole number past
the last artboard, with `` `index` must be a whole number `` when it is negative, fractional, a string or another value
that is not a whole number, and with `missing index` when it is null, also in a command that picks an artboard when
`index` is left out. An `indices` (or a replayed `selectedArtboards`) that is not a list fails with
`` `indices` must be a list of artboard indices ``, an empty one with
`` `indices` must be a non-empty list of artboard indices ``, one with an entry that is not a whole number with
`` `indices` must contain whole numbers ``, each naming its key, and one with a whole number past the last artboard
with `no such artboard`. `artboard.align`, `artboard.distribute` and `artboard.distributeSpacing` name `artboard` or
`activeArtboard` the same way. The document and the clipboard stay as they were.
These artboard commands refuse a string, a number or another value that is not true or false with
`` `art` must be true or false ``, naming the key, and leave the document, its undo history and the clipboard as they
were: `moveArt`, `scaleArt`, `strokes`, `corners`, `patterns`, `lockedAndHidden` and an artboard's `locked`,
@@ -7896,7 +7962,7 @@ instructions is refused with "not an HP-GL file".
`document.export` (and `export`, and Export As) with format `hpgl` writes a plot file (`.plt`) of the first artboard
(or `artboard`) for pen plotters and cutters; `useArtboards: true` writes one file per chosen artboard
(`{stem}-{artboard}.plt`), `false` the bounds of the visible art. Each visible path is drawn once along its own line:
(`{stem}-{artboard}.plt`), `false` the bounds of the art it plots. Each visible path is drawn once along its own line:
a filled shape is its closed outline, also when a stroke gives its color, and a stroked path is its center line, so
fills, stroke widths, dashes, brushes and arrowheads are not painted. Type is drawn as its glyph outlines, and a
gradient mesh as its outline, also inside a blend (a mesh whose every point is at 0% opacity draws nothing). A
@@ -8016,7 +8082,12 @@ moving the art moves the crop, and deleting it removes it from its asset (an ass
format row of the document's export settings, the ones Export for Screens remembers (`document.exportSettings`); any
`formats`, `preset`, `settings`, `prefix` or `subfolders` given win for that export. `assets.settings.set` changes
those shared settings (not an undo step); its `subfolders: true` sets Export for Screens' Folders to a folder per row,
and `subfolders: false` sets a folder per row back to All in One Folder. `document.exportForScreens {assets: [id…]}` does the same with its own params
and `subfolders: false` sets a folder per row (without `exportPreset`, also a folder per format or item) back to All
in One Folder. Its `openLocation: true|false`
is Open Location after Export, kept in `document.exportSettings` (not in presets). The panel menu's Create Sub-folders and
Open Location after Export run these two (sub-folders sort the pictures; `assets.export3D` writes mesh files in the
folder itself), and its Format Settings… opens Export for Screens on the first row's format
settings. `document.exportForScreens {assets: [id…]}` does the same with its own params
(the dialog's Assets tab). An asset's crop, and the crop of `export` with `selection: true`, is the bounds the
renderer measures for what the art draws, its effects included.
@@ -8386,7 +8457,8 @@ undo step. Object › Transform › Scale, the Scale tool and the Transform pane
text reflows along it.
`text.setPathHandle {id, subpath?, anchor, which: "in"|"out", x, y, independent?}` moves a direction handle of one
of its anchors, as `path.setHandle` moves a path's (Direct Selection dragging a handle of the path, #3565), in one
undo step.
undo step. A call of `text.reshapeArea`, `text.reshapePath` or `text.setPathHandle` that changes nothing (`dx` and
`dy` both 0, or a handle moved to where it already is) adds no undo step and keeps redo.
```json
{"name":"run_command","arguments":{"command":"text.reshapeArea","params":{"id":42,"anchors":[[0,2]],"dx":40,"dy":60}}}
@@ -8451,7 +8523,10 @@ the end of the path), and `fit`, `fitScale` and `dynamicText` (Block is on) for
Given for several area types (`ids`, or a selection of several), `text.areaOptions` changes only the options given on
each one: each frame keeps its other options (it used to take the first frame's), and `fitMinPercent` alone changes only
the frames that already shrink text to fit. Options that change nothing (the vertical alignment already set, say) add
no undo step and keep redo.
no undo step and keep redo. The same holds for `text.setText` when no object changes (the text it already has, in one
style, every paragraph with the first one's attributes and no ruby), `text.setStyle` when no character, paragraph or
graph label style changes, `type.ruby` with the same reading and options again or `remove` where there is no ruby, and
`text.fitHeadline` on a first line that already has the tracking it would set.
Text that doesn't fit is drawn up to the last line that does, so a one-line headline in a frame lower than its line
draws nothing. The commands that make type or change what it holds say so in their own reply: `text.create`,
@@ -9165,7 +9240,9 @@ send an Alignment or Level change for paragraphs that stay in no list. With no t
with an unknown `tab`, `ui.bulletsAndNumbering` is an error.
Type › Bullets and Numbering › Convert to Text runs `type.convertListToText` on the selected type's paragraphs, or on
those the Type tool's selection touches, and that runs `text.convertListToText {ids?, start?, end?}`. The marker of
those the Type tool's selection touches, and that runs `text.convertListToText {ids?, start?, end?}`. With the
Selection tool, a selected frame of threaded text names every frame of its story in `ids`, locked and hidden frames
included, as Apply Bullets and Apply Numbers do. The marker of
each list paragraph becomes characters at the start of the paragraph: the bullet, or the number and its period as the
paragraph showed it, then a tab. They are set in the marker's font, size and color: the style of the paragraph's first
character without the attributes the marker leaves out. The paragraph leaves its list. A paragraph at a list level
@@ -9452,6 +9529,15 @@ and a glyph that the character's style does not draw (All Caps, Small Caps or an
system). Choosing the glyph a character already draws is not an edit. Character styles do not take `glyphAlternate`:
`charStyle.new`, `charStyle.edit` and `charStyle.setAttrs` refuse it.
On the desktop canvas, a Type tool with exactly one character selected shows up to five of that character's alternates
in a row beside it, in the same order and without the glyph the character is drawn with; a character drawn with an
alternate gets its default glyph first. A click on a glyph runs the same command as the panel's double-click
(`text.setRangeStyle {featureChanges}`, or `text.setGlyphAlternate` for a glyph no feature draws there), as one undo
step. When the character has more alternates than the row shows, an arrow at the end of the row opens the Glyphs panel
on Alternates for Current Selection. The row has no command of its own: an agent reads the alternates with
`text.glyphAlternates` and applies one with the commands above. The `showCharacterAlternates` preference turns the row
off.
```json
{"name":"run_command","arguments":{"command":"text.glyphAlternates","params":{"id":7,"start":2}}}
{"name":"run_command","arguments":{"command":"text.setGlyphAlternate","params":{"id":7,"start":2,"gid":1043}}}
@@ -10738,7 +10824,12 @@ and the arrow keys nudge them by the keyboard increment. The active tool lists t
(`tool.setOption {}` returns them as `meshPoints: [{id, index}…]`). On gradient meshes a solid fill colour (`paint.setFill`, from the
Color panel, Swatches or the Eyedropper) recolours just the picked points, and when every target of
`transparency.set` is a gradient mesh with points picked, its `opacity` fades those points instead of the objects
(`transparency.info` then shows their opacity, `null` when it differs). Both are one undo step.
(`transparency.info` then shows their opacity, `null` when it differs). Both are one undo step, and neither goes to the
points while the Appearance panel's active row takes the fill or the opacity. When the first selected object is a
gradient mesh with points picked, the Fill proxy, the Color panel, the Color Wheel and `paint.proxies` show its first
picked point's color, and `fillMixed` compares the picked points' colors with each other and with the fills of the other
selected objects. The Transparency panel shows the picked points' opacity (blank when it differs), and the Control
bar shows the first picked point's opacity.
`object.mesh.movePoints {id, points: [index…], dx, dy}` (or `{items: [{id, points}…], dx, dy}` over several meshes)
moves points by (dx, dy), their handles with them; `object.mesh.setPointColor` takes `points` or `items` the same
@@ -11275,8 +11366,8 @@ A `configure` call that changes no shape records no undo step and returns `{upda
## Cutting Tools add-on
Cutting Tools is a built-in add-on that prepares art for cutting. Its commands are `addon.cutting.bridges`,
`addon.cutting.weed` and `addon.cutting.banner`; in the desktop app they are Object › Plug-ins › Cutting Tools › Stencil
Bridges…, Weed Box and Lines… and Banner Hems and Grommets….
`addon.cutting.weed`, `addon.cutting.banner` and `addon.cutting.nest`; in the desktop app they are Object › Plug-ins ›
Cutting Tools › Stencil Bridges…, Weed Box and Lines…, Banner Hems and Grommets… and Nest Shapes….
### Stencil Bridges
@@ -11397,6 +11488,39 @@ Banner Hems and Grommets… opens the command dialog with Preview.
{"name":"run_command","arguments":{"command":"addon.cutting.banner","params":{"hem":"1 in","grommetInset":"0.5 in","spacing":"2 ft"}}}
```
### Nest Shapes
`addon.cutting.nest {roll?, width?, height?, margin?, spacing?, rotate?, usePreviewBounds?, artboard?, patterns?}` moves
the selected objects close together onto a sheet or a roll of material
([packing problems](https://en.wikipedia.org/wiki/Packing_problems)). The ranges, defaults and rules below are
VectorCraft's own. The sheet starts at the top-left corner of artboard `artboard` (0-based; by default the artboard
under the center of the selection, else the first). It is `width` × `height` points (0 to 1000000 each; 0, the default,
takes the artboard's width or height). With `roll` true it is a roll `width` wide with no end, and `height` is not used.
`margin` (0 to 100000, default 18) is kept clear inside each edge of the sheet; on a roll, inside the sides and the
start. `spacing` (0 to 100000, default 9) is kept between two objects.
Each selected object is packed by its bounding box: with its strokes and effects, including the reach of shadows, glows
and blurs, when `usePreviewBounds` is true (the default), else by its geometry. A group is one object. The tallest
objects go first, each where its bottom edge is highest and then furthest left. With `rotate` true (false by default),
an object may turn 90° clockwise where that puts its bottom edge higher, or where only the turned object fits; the
longest side then decides the order, and a turned object is measured as it is after the turn. A path of a
pixel-aligned compound path is not turned. Objects are moved, and turned with `rotate`, never resized. An object on the
pixel grid moves by whole points and takes 1 pt more room across and down. Objects that do not fit go in a column to
the right of the sheet, from its top, `spacing` from its edge and from each other, in stacking order (back to front).
Objects without bounds, such as an empty group, are not moved. `patterns` moves pattern fills and strokes with the art
(default: General › Transform Pattern Tiles).
All of it is one undo step, and nothing changes when no object moves. The command fails when nothing selected can be
measured, when the margin leaves no room on the sheet, when no selected object fits, with more than 10000 objects
selected, and with bad params. Result: `{placed, unplaced, rotated, skipped, length}`: the number of objects placed,
the ids of the objects put beside the sheet, the ids of the objects turned, the ids of the objects without bounds, and
the length of material used in points, from the sheet's top edge to the margin below the lowest object placed. Nest
Shapes… opens the command dialog with Preview.
```json
{"name":"run_command","arguments":{"command":"addon.cutting.nest","params":{"roll":true,"width":"24 in","margin":"0.25 in","spacing":"0.125 in","rotate":true}}}
```
## Color Effects add-on
Color Effects is a built-in add-on: its effects are colour adjustments in Effect › Color Effects, its command is
File diff suppressed because one or more lines are too long
+7 -3
View File
@@ -163,7 +163,8 @@ The rest is our reading:
depths where they overlap, with caps on or off. A fill wall in a gap stays in its own depth order. Inflate's
curved surfaces follow this only as closely as their flat facets do. A solid painted with a gradient that has
transparent stops under a light that is not white is drawn with an opacity mask: its faces keep their places in
this order, in runs that each carry the mask, and so do its graphics. A member of a 3D group with its own opacity
this order, in runs that each carry the mask, and a graphic drawn after one of its faces carries the mask too
([Graphics](#graphics)). A member of a 3D group with its own opacity
mask or blending mode draws its fill's and strokes' faces in this order inside that mask or blending mode when
they are opaque with Normal blending. Otherwise each solid is drawn on its own with its opacity and blending, the
lower item's first. With a light that is not white, a puffed, shaded Inflate surface in a solid color takes its
@@ -389,8 +390,11 @@ These rules are VectorCraft's own:
turned, foreshortened by the perspective and twisted and tapered with the face, and clipped to it. It is shaded
with the face's light: each color is multiplied by the light that falls on the face, except in pattern tiles,
which keep their own colors. It is drawn with the
opacity and blending mode of the fill or stroke the face is painted with. A graphic on a face turned away from
the viewer is not drawn.
opacity and blending mode of the fill or stroke the face is painted with. Solids whose fills and strokes have the
same opacity and blending mode share one graphic on each face, clipped to their faces there and drawn after the
last of them. An object's fill and stroke share it when the fill is drawn with an opacity mask too, and the
graphic takes the mask of the solid it is drawn after; members of a 3D group drawn with a mask keep graphics of
their own. A graphic on a face turned away from the viewer is not drawn.
- On the back cap, X runs to the right as the back is seen from behind, so the graphic reads the right way round
there.
- On Revolve a graphic lies on the swept side, which has one face (Front), unrolled flat. X runs around the axis:
+3 -3
View File
@@ -252,7 +252,7 @@ tools, never checked side by side) isn't captured row by row.
| 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, 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; each row's own eye and lock; a row dropped on the trash deletes its guide | done | `guide.setLayer`; guides from older files go on a layer; `layer.setProps` on a guide's id hides or locks it alone; Object › Lock/Hide › Selection, Unlock All and Show All reach guides; `guide.remove {indexes}` |
| Ruler guides as Layers rows: shown, hidden, locked and deleted with their layer; rows dragged to another layer; each row's own eye and lock; a row dropped on the trash deletes its guide; a plain click on another row lets go of the guide | done | `guide.setLayer`; guides from older files go on a layer; `layer.setProps` on a guide's id hides or locks it alone; Object › Lock/Hide › Selection, Unlock All and Show All reach guides; `guide.remove {indexes}`; #7340 |
| 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 |
| Alt swaps a ruler guide's orientation while dragging | missing | Alt-drag copies the selected guides ([Use rulers](https://helpx.adobe.com/illustrator/desktop/measure-and-align/grids-and-guides/use-rulers.html)); `guide.move` `{copy: true}` |
@@ -385,7 +385,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 progress rings that fill and counts of tutorials finished, a tutorial shows its numbered steps with a check box each that marks the step done once its sample is open, a finished tutorial has a check mark, Back goes up a level; a tool's name in a step is a link that marks the tool where the toolbars show it (its button, its group's flyout, a torn-off strip, a toolbar made with New Toolbar or the All Tools drawer) without choosing it; View more opens the tutorial's practice sample as a new untitled document, Finish tutorial then marks it finished with all its steps, and Next Up shows the next tutorial in the same skill; Reset progress clears the progress (no video) | done | [the help page](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/learn-skills-quick-skill-guide.html); `learn.list`, `learn.skills`, `learn.show`, `learn.locateTool`, `learn.openSample`, `learn.markStep`, `learn.finish`, `learn.next`, `learn.resetProgress`; the mark's look and 3-second lifetime, marking steps by hand, keeping the progress in the preferences and Reset progress are VectorCraft's own rules; `panels::learn::tests`, `toolbar::tests` |
| 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 progress rings that fill and counts of tutorials finished, a tutorial shows its numbered steps with a check box each that marks the step done once its sample is open, a finished tutorial has a check mark, Back goes up a level; a tool's name in a step is a link that marks the tool where the toolbars show it (its button, its group's flyout, a torn-off strip, a toolbar made with New Toolbar or the All Tools drawer) without choosing it; View more opens the tutorial's practice sample as a new untitled document, Finish tutorial then marks it finished with all its steps, and Next Up shows the next tutorial in the same skill; Reset progress clears the progress (no video) | done | [the help page](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/learn-skills-quick-skill-guide.html); `learn.list`, `learn.tab`, `learn.skills`, `learn.skill`, `learn.show`, `learn.back`, `learn.locateTool`, `learn.openSample`, `learn.markStep`, `learn.finish`, `learn.next`, `learn.resetProgress`; the mark's look and 3-second lifetime, marking steps by hand, keeping the progress in the preferences and Reset progress are VectorCraft's own rules; `panels::learn::tests`, `toolbar::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 |
@@ -419,7 +419,7 @@ next unit in the order a right-click on a ruler lists them, from Feet back to Po
| Actions panel: Delete Selection (bottom bar) deletes the selected set with its actions and keeps the other sets ([Actions panel overview](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/actions-panel-overview.html)) | partial | `ui.actionSet.delete`; `panels/actions.rs` tests. VectorCraft's own rules, which the overview does not cover: deleting a set asks first (a selected action is still deleted at once), Shift-click on a set's name selects a range of sets, ≡ › Delete does the same as the button, and Default Actions and the last set can be deleted. Undo does not restore a deleted set, and recorded commands cannot be selected or deleted |
| Actions panel: ≡ › Duplicate copies the selected action or set ([Actions panel overview](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/actions-panel-overview.html)) | partial | `ui.actionSet.duplicate`; `panels/actions.rs` tests. VectorCraft's own rules, which the overview does not cover: the copy goes right after the original, is named after it with " copy" added and is selected, and a copied set holds copies of all its actions. Undo does not remove the copy, and recorded commands cannot be duplicated |
| Properties panel per context (every selection type's Quick Actions) | partial | one clip group: Edit Clipping Path and Edit Contents, at the top of the panel rather than in Quick Actions (G1); the overview's additional controls ([Properties panel overview](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/properties-panel-overview.html)): Blend Options (one blend selected, with any tool, #4817), Repeat Options (one radial, grid or mirror repeat selected: Object › Repeat › Options, #5181; the overview does not list it) and Merge Live Paint (a Live Paint group with more) in Quick Actions, the Width Profile list (Width tool or a variable-width stroke) and an applied effect's Delete icon in Appearance, Corner and Corner Radius for corners selected with Direct Selection; Variable Font was already there; Edit Artboards: a Transform section (reference point, X, Y, W, H, preset, orientation) above the Artboards section (#5219) |
| Select › Start Global Edit / Stop Global Edit; Properties › Quick Actions with the Global Edit Options popover (Match: Appearance, Size; On Artboards: All Artboards or a range, Include Objects On Canvas; Result(s)); Escape stops it; the matched objects are highlighted in their layer colour while it runs; a Shift-click on a highlighted match leaves it out | partial | #3521, `select.globalEdit` / `select.globalEditOptions` / `select.globalEditExclude`, `crates/engine/src/tests/globaledit.rs`; paths, compound paths, symbol instances and groups of them (similar groups, #4939: edits inside one group reach the same object in the others; [public source](https://helpx.adobe.com/illustrator/desktop/manage-objects/edit-objects/edit-groups-with-similar-objects.html)); a group holding type or an image is not taken, as Global Edit does not take images or text; Shift-click to leave a match out ([public source](https://helpx.adobe.com/ph_fil/illustrator/how-to/global-editing-sensei.html)); the Control bar's Global Edit Options dropdown opens the same options; the matches are highlighted before the start (`selecting_one_object_highlights_the_similar_objects_before_global_edit_starts`); rotated copies remain ([public source](https://helpx.adobe.com/illustrator/desktop/manage-objects/edit-objects/edit-similar-objects.html)) |
| Select › Start Global Edit / Stop Global Edit; Properties › Quick Actions with the Global Edit Options popover (Match: Appearance, Size; On Artboards: All Artboards or a range, Include Objects On Canvas; Result(s)); Escape stops it; the matched objects are highlighted in their layer colour while it runs; a Shift-click on a highlighted match leaves it out | partial | #3521, `select.globalEdit` / `select.globalEditOptions` / `select.globalEditExclude`, `crates/engine/src/tests/globaledit.rs`; paths, compound paths, symbol instances and groups of them (similar groups, #4939: edits inside one group reach the same object in the others; [public source](https://helpx.adobe.com/illustrator/desktop/manage-objects/edit-objects/edit-groups-with-similar-objects.html)); a group holding type or an image is not taken, as Global Edit does not take images or text; Shift-click to leave a match out ([public source](https://helpx.adobe.com/ph_fil/illustrator/how-to/global-editing-sensei.html)); the Control bar's Global Edit Options dropdown opens the same options; the matches are highlighted before the start (`selecting_one_object_highlights_the_similar_objects_before_global_edit_starts`); rotated copies are matched and take an edit turned by their angle ([public source](https://helpx.adobe.com/vn_vi/illustrator/how-to/modern-logo-design.html); `start_global_edit_takes_rotated_copies_and_an_edit_reaches_each_turned_by_its_angle`); reflected copies are not matched (VectorCraft's own rule) |
| Contextual task bar | done | |
| Control bar with Transform and Stroke popovers | done | |
| Stroke panel: custom arrowheads after the built-in ones in both arrowhead menus, from the arrowheads file that the panel menu's Edit Arrowheads… opens; saving the file reloads the menus, and a stroke keeps a copy of its custom head's art | done | [Apply stroke on an object](https://helpx.adobe.com/illustrator/using/stroke-object.html) (Customize arrowheads); the file's layout (one symbol per head, pointing right, tip at the registration point, height drawn as wide as the built-in heads) is VectorCraft's own; `stroke.arrowheads.edit`, `stroke.arrowheads.list`, `stroke.arrowheads.reload`, `stroke.set` `{custom: name}`; engine `tests::arrowheads`, `stroke::tests_arrows::custom_heads_draw_their_own_art_at_the_tip` |