Merge main into feat/scripts-folder

This commit is contained in:
dotCooCoo
2026-11-10 19:10:00 -08:00
41 changed files with 1176 additions and 9 deletions
+3 -2
View File
@@ -1,6 +1,6 @@
# File format parity
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-10 · **Change:** minor (`.ai` save: type in a variable font's named instance names its design-space setting, #6388; `.ai` and EPS import: envelopes of type open live where they draw as their drawn art and the layers with them draw as the page, #3179; `.ai` and EPS import: a note for type in an envelope, #3179; `.ai` and EPS import: the live envelope and warped type check sees white art; PDF import: DeviceN images of one ink or of process plates keep their inks, #6348; `.ai` import: images in a spot ink's Separation space keep their ink, #6350; PDF import: Separation images keep their ink, #6314; PDF editable import preserves authored ActualText once, including empty/nested spans and authored ordering (#6165); cross-line/style layout remains approximate; scores and estimates unchanged; PDF marked-text export (#6309): compatible glyphs stay on one layout line with per-glyph offsets; scores and estimates unchanged; PDF import: image masks open colorized by the color they are painted in, #6313; EPS and `.ai` editing data: a ligature the page names by a private-use glyph matches its text object; EPS import: CIDFonts only named, over a Unicode CMap, set as live type; EPS import: CMap mappings to base-font codes and glyph names; EPS import: CID-keyed fonts in FontSets (CFF) draw their glyphs; EPS import: `kshow` procedures kern live type; EPS import: embedded Type 1 fonts' glyphs and widths; EPS import: CID-keyed fonts draw their glyphs; EPS import: Type 42 fonts' characters and widths from the font they carry, show operators' spacing kept as tracking; EPS import: an image decoder's own buffers stop counting against the memory budget once it is decoded; EPS import: sampled functions interpolate between their samples; `.ai` and EPS type from the text document keeps its tab stops; it keeps auto leading and hyphenation options, and may show more of the file's last lines in an area frame; `.ai` and EPS import: Art brushes in the older form of their objects come into the Brushes panel; EPS import: gradients drawn as abutting strips come in as one gradient, without seams; EPS import: composite fonts draw their Type 42 glyphs; SVG import: filter and mask regions clip, #5876, #5875; SVG import: Gaussian blurs keep `color-interpolation-filters`, #5877; PDF and `.ai` export: objects' URLs as links, #5785; SVG import: `color-interpolation="linearRGB"` gradients, #5878; `.ai` import: paths with a Calligraphic brush open brushed, #372) · **Target:** Adobe Illustrator 2026 (30.x)
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-11-11 · **Change:** minor (`.ai` and EPS import: stroked type keeps its stroke's cap, join and miter limit from the text document, #6472; `.ai` save: type in a variable font's named instance names its design-space setting, #6388; `.ai` and EPS import: envelopes of type open live where they draw as their drawn art and the layers with them draw as the page, #3179; `.ai` and EPS import: a note for type in an envelope, #3179; `.ai` and EPS import: the live envelope and warped type check sees white art; PDF import: DeviceN images of one ink or of process plates keep their inks, #6348; `.ai` import: images in a spot ink's Separation space keep their ink, #6350; PDF import: Separation images keep their ink, #6314; PDF editable import preserves authored ActualText once, including empty/nested spans and authored ordering (#6165); cross-line/style layout remains approximate; scores and estimates unchanged; PDF marked-text export (#6309): compatible glyphs stay on one layout line with per-glyph offsets; scores and estimates unchanged; PDF import: image masks open colorized by the color they are painted in, #6313; EPS and `.ai` editing data: a ligature the page names by a private-use glyph matches its text object; EPS import: CIDFonts only named, over a Unicode CMap, set as live type; EPS import: CMap mappings to base-font codes and glyph names; EPS import: CID-keyed fonts in FontSets (CFF) draw their glyphs; EPS import: `kshow` procedures kern live type; EPS import: embedded Type 1 fonts' glyphs and widths; EPS import: CID-keyed fonts draw their glyphs; EPS import: Type 42 fonts' characters and widths from the font they carry, show operators' spacing kept as tracking; EPS import: an image decoder's own buffers stop counting against the memory budget once it is decoded; EPS import: sampled functions interpolate between their samples; `.ai` and EPS type from the text document keeps its tab stops; it keeps auto leading and hyphenation options, and may show more of the file's last lines in an area frame; `.ai` and EPS import: Art brushes in the older form of their objects come into the Brushes panel; EPS import: gradients drawn as abutting strips come in as one gradient, without seams; EPS import: composite fonts draw their Type 42 glyphs; SVG import: filter and mask regions clip, #5876, #5875; SVG import: Gaussian blurs keep `color-interpolation-filters`, #5877; PDF and `.ai` export: objects' URLs as links, #5785; SVG import: `color-interpolation="linearRGB"` gradients, #5878; `.ai` import: paths with a Calligraphic brush open brushed, #372) · **Target:** Adobe Illustrator 2026 (30.x)
Every format Illustrator opens, places, saves or exports, against VectorCraft's format table (`FORMATS`,
`OPEN_EXTS`, `PLACE_EXTS` in `crates/engine/src/cmd/fileio/formats.rs`). Illustrator's list comes from its public
@@ -54,7 +54,7 @@ private editing data. VectorCraft:
own paints with the paint before the mask's dictionary, as the writer leaves out paint that doesn't change.
Type from the text document keeps auto leading as auto, each line taking the paragraph's share
(Auto Leading) of the largest type on it ([Line and character spacing](https://helpx.adobe.com/illustrator/using/line-character-spacing.html)),
and the paragraph's hyphenation options and tab stops. Area type of one
and the paragraph's hyphenation options and tab stops. Stroked type keeps its stroke's cap, join and miter limit. Area type of one
frame whose last lines the file sets but which don't fit here (the fallback font, or a descent
past the frame's bottom) may get a frame taller from its bottom, by its lines' deepest descent plus 0.05 pt and only when that shows more of those lines, with a warning when it does.
RGB in the PDF page's `ICCBased` spaces keeps the file's numbers in a `.ai` (the `uncalibrated_rgb`
@@ -339,6 +339,7 @@ Stop opacity on translated artboards remains outside this regression coverage.
| Date | Change | Summary |
|---|---|---|
| 2026-11-11 | minor | `.ai` and EPS import: type stroked in the text document keeps its stroke's cap, join and miter limit (keys 61, 62 and 64 of its character attributes, numbered as PostScript's `setlinecap` and `setlinejoin`: 0 butt or miter, 1 round, 2 projecting or bevel). They were left at a miter join with a limit of 10 whatever the file said, so type the file strokes with round joins, or with the usual limit of 4 or less, drew spikes at its sharp corners, some many points long. In users' files, used locally and never committed, the page strokes the type with the cap, join and miter limit these keys give; no file had a bevel join, which is read by the same numbering. A value that isn't one of theirs keeps the default, a miter limit past 500 is 500, and type without a stroke keeps the defaults. Dashes are not read: no file had dashed type to tell which keys hold them. Tests `ate::tests::a_run_keeps_its_stroke_cap_join_and_miter_limit`, `tests_native::stroked_type_keeps_its_cap_join_and_miter_limit`; scores unchanged |
| 2026-11-10 | minor | `.ai` and EPS import: an envelope of type (a warp, a mesh or a top object around type) kept its drawn art, its type hidden, because the type is laid out from the text document only after the layers are read. It now waits for that: its text slots get their type, and where VectorCraft's own envelope of that type draws as the drawn art the file saves (the same check and budget as other envelopes, seen on white and on black), it opens live in the drawn art's place, its type editable in Edit Contents, and the hidden copy goes. As with other live envelopes, the layers with one are then compared with the page, which weighs the envelope as the art it draws (not as type laid out again, which the comparison allows more for), and when they don't draw as it the drawn art and the hidden type are put back. Layers used though they don't draw as the page (the editing data trusted, or the objects that differ coming in as the page's art) leave envelopes of type their drawn art and hidden type too. A `.ai` whose layers would open alone, without its PDF part, imports the PDF part to compare them with, and should they still not draw as it, or should no envelope of type open live, they open alone as before, with the envelopes' drawn art. Type in a font that isn't available, slots without type of their own (threaded, bound to a text or a visibility variable, a wrap object, type a look draws), envelopes in a symbol's or a pattern's art, and envelopes that draw differently keep their drawn art, with the note (#3179). Tests `tests_native::an_envelope_of_type_that_draws_as_its_drawn_art_opens_live`, `an_envelope_of_type_that_draws_apart_from_its_drawn_art_keeps_it`, `an_envelope_of_white_type_that_draws_apart_from_its_drawn_art_keeps_it`, `an_envelope_of_type_waits_on_the_page_of_layers_that_would_open_alone`, `an_envelope_of_type_that_draws_apart_from_the_page_does_not_open_live`, `trusted_layers_that_draw_apart_from_the_page_leave_an_envelope_of_type_its_drawn_art`, `layers_with_objects_that_come_in_as_the_page_art_leave_an_envelope_of_type_its_drawn_art`, `an_envelope_of_type_bound_to_a_visibility_variable_keeps_its_drawn_art` |
| 2026-11-10 | minor | `.ai` save: a variable font's record in the text document's font set names the type's place in the font's design space (`/4`, each `fvar` axis as 16.16 fixed: the named instance's setting, or the run's own Variable Font setting) and the font's version (`/5`). Without them, type in a named instance such as Bold opened at the font's default instance in the app that opens the file. Two settings of one font are now two fonts of the set; a static font's record is unchanged. The record's form comes from the public report in #6388. Test `ai_editing::tests::variable_font_instances_name_their_design_space` (#6388) |
| 2026-11-10 | minor | `.ai` and EPS import: an envelope of type, which keeps its drawn art with its type hidden, now says so in the import notes ("type in an envelope comes in as the envelope's drawn art, not as editable type"); nothing said it before, while the other envelopes that keep their drawn art have a note. The type is still not editable in the envelope (part of #3179). Test `tests_native::envelope_options_keep_the_source_text_hidden_under_its_outlined_appearance` |
+28 -2
View File
@@ -3157,8 +3157,16 @@ The pattern commands (`object.pattern.make`, `object.pattern.edit`, `object.patt
`object.repeat.options`) reject a param of the wrong type, such as `"instances": "8"`, `"edit": "false"` or
`"tileType": 2`, and change nothing. `pattern.options` also rejects an `overlap` that is not an object, and an
`overlap.h` other than `left` or `right` or an `overlap.v` other than `top` or `bottom`. `object.repeat.options` rejects
a `center` that is not `[x, y]`, and `object.repeat.radial` rejects a negative `radius`. Omitting a param or giving null
keeps its default.
a `center` that is not `[x, y]`, and `object.repeat.radial` rejects a negative `radius`. In `object.pattern.make`,
`object.pattern.saveCopy`, `object.repeat.radial`, `object.repeat.grid` and `object.repeat.mirror`, omitting a param or
giving null keeps its default. In `pattern.options` and `object.repeat.options`, omitting a param or giving null keeps
the pattern's or the repeat's current value, with two exceptions. A brick `tileType` in `pattern.options` or a brick
`gridType` in `object.repeat.options` with `brickOffset` omitted or null sets the offset to 0.5. While `sizeTileToArt`
is on, each `pattern.options` call sizes the tile to the art plus `hSpacing` and `vSpacing` again and ignores `width`
and `height`, so a new `hSpacing` changes the tile's width. `pattern.options` still rejects a non-null `width` or
`height` that is not a positive number, such as `"width": 0`, and changes nothing. Without a `name`,
`object.pattern.edit` edits the pattern that fills or strokes a selected object, and `pattern.options` changes the
pattern being edited; each returns an error when there is no such pattern. `pattern.delete` requires `name`.
```json
{"name":"run_command","arguments":{"command":"pattern.options","params":{"showSwatchBounds":true}}}
@@ -4615,6 +4623,24 @@ Preferences. `prefs.reset` resets the preferences at once, without the question.
{"name":"run_command","arguments":{"command":"prefs.set","params":{"key":"unitsGeneral","value":"millimeters"}}}
```
`prefs.export {path?}` writes the preferences as a JSON file, `{"format": "vectorcraft-preferences", "version": 1,
"prefs": {…}}`, and replies `{path, count}`; without `path` it replies `{data, count}` with the file's text. The file
holds every preference `prefs.list` lists and the `eyedropper`, `perspectiveWidget`, `pathfinder` and `glyphSnap`
groups. It leaves out the folder preferences (`fontsFolder`, `pluginsFolder`, `recoveryFolder`, `templatesFolder`) and
saved presets. An export over 1 MB, the most `prefs.import` reads, is an error and writes nothing.
`prefs.import {path | data}` applies such a file and replies `{imported}`, the number of preferences it
set. It checks every value first, as `prefs.set` does: a file over 1 MB, malformed JSON, another `format`, a newer
`version`, an empty `prefs`, an unknown preference, a value of the wrong type or out of range, or a folder preference
is an error, and nothing changes. Preferences the file leaves out keep their values. An import leaves the open
document's units as they are, records no undo step, and is saved with the other preferences. An open Preferences
dialog shows the imported values. `prefs.import` is refused as a `command.batch` step. The dialog's Export Preferences… and Import Preferences… buttons run the two
commands with a save or open dialog; the web build downloads the exported file and has no Import Preferences… button.
Exporting and importing preferences is an optional VectorCraft feature.
```json
{"name":"run_command","arguments":{"command":"prefs.import","params":{"data":"{\"format\":\"vectorcraft-preferences\",\"version\":1,\"prefs\":{\"uiAccent\":\"green\"}}"}}}
```
## Document Setup
`document.setup` with no params reports the document setup: units, the bleed ([top, bottom, left, right] in pt, drawn
+1
View File
@@ -658,6 +658,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
- **Window › Arrange › Float in Window, Float All in Windows and Cascade (G7):** documents float in windows of their own, out of the tab strip ([public source](https://helpx.adobe.com/illustrator/using/customizing-workspace.html)). Float in Window (`window.arrange.floatInWindow`) floats the current document, Float All in Windows (`window.arrange.floatAllInWindows`) every tabbed one, and Cascade (`window.arrange.cascade`) floats every document and stacks the windows from the upper left to the lower right ([public source](https://helpx.adobe.com/illustrator/using/viewing-artwork.html)). On the desktop each window is an OS window; on the web and on Wayland it is a window inside the app's window. The window of the current document holds the canvas; the others draw their documents as Tile's panes do, and a press in one makes its document the current one. Closing a window closes its document, asking to save unsaved changes. Consolidate All Windows brings every document back under the tabs, and Tile brings them back into its grid. The cascade's 30 pt step, the windows' size and when the items are enabled (Cascade with two documents or more, Float in Window for a tabbed current document, Float All in Windows while a document is tabbed, Consolidate All Windows while documents are tiled or floating) are VectorCraft's own. Tests: `crates/ui-egui/src/doc_windows/tests.rs`.
- **Dragging a document tab out and a document window back (G7):** a document tab dragged more than 24 pt above or below the tab strip floats its document in a window under the pointer, and a document window dragged onto the tab strip goes back under the tabs ([public source](https://helpx.adobe.com/illustrator/using/customizing-workspace.html)). A window inside the app's window is dragged by its title bar; an OS window by the document's tab at its top, and the window follows the pointer. The 24 pt distance and the tab at the top of an OS window are VectorCraft's own. Tests: `crates/ui-egui/src/doc_windows/tests.rs`.
- **Reordering document tabs (G7, #5663):** a document tab dragged along the tab strip moves its document among the others ([public source](https://helpx.adobe.com/illustrator/using/customizing-workspace.html)); a line marks the gap it goes in. The current document stays current, each document keeps its own zoom, centre and artboard, the views Window › New Window opened move with their document, and Window › Next/Previous Document follow the new order. `document.move` (`{from?, to}`) does the same from MCP, the control channel and recordings. `crates/ui-egui/src/tests/tab_reorder.rs`, `crates/engine/src/tests/document_move.rs`.
- **Export and Import Preferences (#6435):** an optional VectorCraft feature. The Preferences dialog's Export Preferences… saves the applied preferences to a JSON file (`prefs.export`; the web build downloads it), and Import Preferences… applies such a file (`prefs.import`). The file leaves out the folder preferences. The import checks every value first and changes nothing on an error; it keeps the open document's units and records no undo step. The file format is VectorCraft's own. Tests: `crates/engine/src/tests/prefs_file.rs`, `crates/ui-egui/src/prefs_dialog/tests.rs`.
- **Preferences › User Interface › Open Documents As Tabs (G7, #394):** checked by default, documents open under tabs in one document window ([public source](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/workspace-overview.html)). With the box cleared, each document opened or created afterwards opens in a floating window of its own, at the next cascade place, as Float in Window floats it; documents already open stay where they are, and checking the box again leaves floating documents in their windows. Tests: `crates/ui-egui/src/doc_windows/tests.rs`.
- **Preferences search:** a Search Preferences field above the category list has the keyboard focus when the dialog opens, and Cmd/Ctrl+F gives it back; typing lists the settings it finds, and choosing one shows its category, as the [help page](https://helpx.adobe.com/illustrator/desktop/get-started/preferences-and-settings/set-app-preferences.html) describes. VectorCraft's own rules: the field matches a setting's label, section or category, ignoring case, in the interface language or in English; the list replaces the categories while the field has text and shows every match, or "No settings found"; the chosen setting's row is highlighted and scrolled into view; Escape in the field with text clears it, and Escape in the empty field closes the dialog. The dialog's `__search` field (`ui.dialog.set`) holds the text. Tests: `crates/ui-egui/src/prefs_dialog/tests.rs`.
- **Reset Preferences asks first (#6435):** the Preferences dialog's Reset Preferences button opens a question over the dialog (`resetPreferences`). Cancel or Escape goes back to Preferences unchanged, with its category, search and edits kept; OK goes back with every preference at its default value, which OK in Preferences applies and Cancel there discards. The question and its wording are VectorCraft's own. Tests: `crates/ui-egui/src/prefs_dialog/tests.rs`.