mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-14 15:57:49 +00:00
Merge main into fix/graph-series-gradient-per-mark
This commit is contained in:
@@ -345,7 +345,10 @@ Tile Edge Color: Object → Pattern → Tile Edge Color… (`ui.tileEdgeColor`)
|
||||
`patternTileEdgeColor` (`prefs.set`), the colour pattern editing mode draws the tile edge and the swatch bounds in.
|
||||
A `color` with an alpha part (`#rrggbbaa` or `#rgba`) is an error, and the preference does not change.
|
||||
|
||||
Window title bar: on Windows and Linux the window has no OS decorations and the app bar is the title bar. Its
|
||||
Window title bar: on Windows the window has no OS decorations and the app bar is the title bar. On Linux and the BSDs
|
||||
the app bar is the title bar by default only on a Wayland session without server-side decorations, such as GNOME, in a
|
||||
window not opened through XWayland. Elsewhere the desktop draws the frame and the app bar has no caption buttons,
|
||||
unless VectorCraft Title Bar on Every Desktop or `VECTORCRAFT_TITLEBAR=app` turns the app frame on (see below). The
|
||||
caption buttons (Minimize, Maximize/Restore, Close) are 46 pt each. By default all three sit at the bar's right end.
|
||||
On Linux and the BSDs, when the desktop leaves the window's frame to the app (a Wayland session without server-side
|
||||
decorations, such as GNOME), the window is not opened through XWayland and `VECTORCRAFT_TITLEBAR` is unset, they
|
||||
|
||||
+7
-3
@@ -121,7 +121,7 @@ A file opened from the file manager (double-click, Open With, a drop on the exec
|
||||
|
||||
## Linux: Wayland and X11
|
||||
|
||||
On GNOME/Wayland, enable **Preferences › User Interface › System Title Bar** and restart to use winit's font-free Adwaita window controls (`wayland-csd-adwaita-notitle`); the existing custom title bar remains the Linux default. On X11, on a Wayland compositor that draws server-side decorations such as KDE Plasma, and in a window opened through XWayland, enable **Preferences › User Interface › VectorCraft Title Bar on Every Desktop** and restart to use the app bar as the title bar instead of the desktop's frame. `VECTORCRAFT_TITLEBAR=app`, `=system` or `=desktop` chooses the frame for one run and takes precedence over System Title Bar and VectorCraft Title Bar on Every Desktop. The variable is case-sensitive and surrounding spaces are ignored; any other value, such as `unknown`, is ignored and does not override System Title Bar.
|
||||
On GNOME/Wayland, enable **Preferences › User Interface › System Title Bar** and restart to use winit's font-free Adwaita window controls (`wayland-csd-adwaita-notitle`); the app bar is the title bar by default only on a Wayland compositor that leaves the window's frame to the app, such as GNOME's, in a window not opened through XWayland (see the drop and pen items below). On X11, on a Wayland compositor that draws server-side decorations such as KDE Plasma, and in a window opened through XWayland, enable **Preferences › User Interface › VectorCraft Title Bar on Every Desktop** and restart to use the app bar as the title bar instead of the desktop's frame. `VECTORCRAFT_TITLEBAR=app`, `=system` or `=desktop` chooses the frame for one run and takes precedence over System Title Bar and VectorCraft Title Bar on Every Desktop. The variable is case-sensitive and surrounding spaces are ignored; any other value, such as `unknown`, is ignored and does not override System Title Bar.
|
||||
|
||||
The window runs natively on Wayland (eframe's `wayland` feature) and on X11. On machines with two GPUs it renders on the one the desktop runs on unless Preferences say otherwise; see [Desktop graphics processor](#desktop-graphics-processor) (#502). The system clipboard (`apps/vectorcraft/src/clipboard.rs`) is arboard with its `wayland-data-control` feature:
|
||||
|
||||
@@ -296,10 +296,14 @@ other `sv-*` locale resolve to it), Georgian (`ka`, complete; `ka-GE` and `ka_GE
|
||||
`Couldn't open {name}: {e}`; `{_1}`, `{_2}` … stand for the format string's `{}`, and the values in the
|
||||
placeholders are translated in turn (the reason after `: {e}` is often a message too). Czech, German, Greek, Spanish, French, Georgian, Hungarian, Italian, Japanese, Korean, Polish, Brazilian Portuguese, Russian, Simplified Chinese, Traditional Chinese, Swedish, Ukrainian, Vietnamese, Finnish, Turkish, Catalan and Dutch
|
||||
translate status and error messages (`COMPLETE_MESSAGES` in `i18n::tests`); the untranslated report lists the
|
||||
message literals the scan finds that one of them has no row for. The scan reads `Err("…")`, `Other(…)`,
|
||||
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
|
||||
effects and the crates whose errors the engine passes on included. It reads `Err("…")`, `Other(…)`,
|
||||
`#[error(…)]` and `status(…)` messages, messages given to an error enum's variant (`PsError::Limit(…)`, the reason
|
||||
in `EngineError::Disabled(id, …)`), to the engine's `bad(cmd, …)`, `err(…)` or `error(…)`, and to the PDF writer's
|
||||
`bad(…)` or `failed(…)`, and skips calls inside comments
|
||||
`bad(…)` or `failed(…)`, and the messages a `.map_err(|e| …)` closure returns (from each `if` branch,
|
||||
`match` arm and statement of a block) or the handler a `.map_err(name)` names returns (a closure bound with `let name = |e| …;` or a
|
||||
function `fn name(…)`), and skips calls inside comments
|
||||
(`VECTORCRAFT_I18N_DUMP_MESSAGES=messages.txt cargo test -p vectorcraft-ui-egui dump_source_strings` lists them
|
||||
all). A missing row shows the English message. Other languages show messages in English until they add `@msg`
|
||||
rows.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -7,7 +7,7 @@ Per-language status of VectorCraft's interface. How the catalogs work and how to
|
||||
[target-app-parity.md](target-app-parity.md).
|
||||
|
||||
**How it is measured:** rows with a translation in each `crates/ui-egui/src/i18n/<code>.tsv`, counted on
|
||||
origin/main `01e165af`, except the rows that give a count date: those were counted on the `main` commit named in the row (the other dated rows on `main` at `cb0a7d9`, 2026-10-21; the Portuguese row on `main` at `d26dd933a`, 2026-10-31).
|
||||
origin/main `01e165af`, except the rows that give a count date: those were counted on the `main` commit named in the row (the rows dated 2026-10-21 on `main` at `cb0a7d9`).
|
||||
The reference is the French catalog, which was complete when counted: 3,416 interface
|
||||
strings (menus, command labels, `tl!` literals: panels, dialogs, tooltips, Preferences) plus 604 `@msg` status and
|
||||
error messages, 4,020 in all. A language's % is its rows over 4,020 (capped at 100% per part). A missing
|
||||
@@ -27,15 +27,15 @@ Chinese by `imachus`). Only Georgian is recorded as reviewed by a native speaker
|
||||
| Language | Code | UI strings translated | Dialogs / tooltips / messages | Script support | Native review | Status | To `full` (h) |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| English | `en` | source, 100% | all | Latin | — | full | — |
|
||||
| Simplified Chinese (Mandarin) | `zh-hans` | 5,102 rows, 791 of them `@msg` (counted 2026-10-21): menus, `tl!` literals and messages complete when counted | all | CJK UI font from craft-fonts (BIZ UDPGothic) when embedded, else a system font; IME with marked text at the caret; vertical type partial ([type-parity.md](type-parity.md)) | no | full | — (review) |
|
||||
| Simplified Chinese (Mandarin) | `zh-hans` | 5,102 rows, 791 of them `@msg` (counted 2026-10-21): menus, `tl!` literals and messages complete when counted | all (3,439 `@msg` and 48 `@msgplural` rows, counted 2026-11-13: the untranslated report lists 40 missing messages for it) | CJK UI font from craft-fonts (BIZ UDPGothic) when embedded, else a system font; IME with marked text at the caret; vertical type partial ([type-parity.md](type-parity.md)) | no | full | — (review) |
|
||||
| Spanish | `es` | 4,009 / 4,020 (99.7%) | all (604 messages) | Latin | no | full | — (review) |
|
||||
| Hindi | `hi` | 8,782 rows (2026-11-13): 3,014 `@msg`, 47 `@msgplural`, 41 `@plural`; no gaps in the untranslated report | menus, dialogs, tooltips and scanned messages; contributor-approved loanword terminology; agent wording pass | UI and document text shape with HarfRust; installed desktop Devanagari fallback, or a `Deva` craft-fonts face; web font still needed | contributor terminology review; 2026-11-13 wording pass on messages and longer labels, with a glossary-term test; wider proofread welcome | complete catalog, machine-assisted draft | native review, layout and web font |
|
||||
| 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` | 4,020 / 4,020 (100%) | all | Latin | no | full | — (review) |
|
||||
| Portuguese | `pt-br` | 6,106 catalog entries (counted 2026-10-31 on `main` at `d26dd933a`): menus, `tl!` literals and messages complete when counted; one/other plurals | all | Latin | contributor is a Brazilian Portuguese speaker; further native review welcome | full | — (review) |
|
||||
| Portuguese | `pt-br` | 9,260 rows, 3,445 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 39 missing messages for it; 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) |
|
||||
| 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 (602 of 604 message rows; landed 2026-10-10) | Latin | contributor-written, not reviewed | full | — (review) |
|
||||
| German | `de` | 3,952 / 4,020 (98%; menus, literals and messages complete when counted) | all (3,433 `@msg` and 48 `@msgplural` rows, counted 2026-11-13: the untranslated report lists 48 missing messages for it) | 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 | 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) |
|
||||
|
||||
@@ -50,13 +50,13 @@ plus review. Native-speaker review is human work and isn't in the hours.
|
||||
| Language | Code | Translated | Status |
|
||||
|---|---|---|---|
|
||||
| Traditional Chinese (Taiwan) | `zh-hant` | 4,892 rows, 790 of them `@msg` (counted 2026-10-21): menus, `tl!` literals and messages complete when counted (80% overall) | partial |
|
||||
| Italian | `it` | 4,011 / 4,020 | full |
|
||||
| Italian | `it` | 8,757 rows, 3,422 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 40 missing messages for it | full |
|
||||
| Dutch | `nl` | 7,299 rows, 1,609 of them `@msg` and 47 `@msgplural` (counted 2026-11-13 on `main` at `9a1a158a3`): in `COMPLETE_MESSAGES`, and the untranslated report lists the same missing messages for it as for German; 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 |
|
||||
| Russian | `ru` | 4,009 / 4,020 | full |
|
||||
| Ukrainian | `uk` | 4,009 / 4,020 (one/few/many plurals) | 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` | 5,253 rows (counted 2026-10-21): menus, `tl!` literals and messages complete when counted; one plural form | full |
|
||||
| Polish | `pl` | 5,130 rows (counted 2026-10-21): menus, `tl!` literals and messages complete when counted; one/few/many plurals | full; native review pending |
|
||||
| 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` | 5,240 catalog entries, including 795 `@msg` rows (counted 2026-10-21); menus, literals and messages complete when counted | 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 |
|
||||
|
||||
+60
-19
@@ -148,12 +148,14 @@ the suite) keep the agent to the folders you give it:
|
||||
in a recorded action's steps in `ui.action_sets`, also in a batch step's commands, the `path`, `paths`, `file`,
|
||||
`files` and `folder` params, a param whose name ends in `Path`, `Paths`, `File`, `Files` or `Folder` (`diffPath`,
|
||||
`destinationFolder`), the entries of a list under such a param, and under any other param, as a key or in any
|
||||
list, an absolute path or a `file:` URL outside the roots (any case of `file:`, `%XX` escapes decoded; a URL that
|
||||
list, an absolute path or a `file:` URL outside the roots, also with whitespace around it (any case of `file:`, `%XX` escapes decoded; a URL that
|
||||
names another host is always left out), and `~`, a path under `~` or a path that starts with `./` or `../`
|
||||
(either separator) that resolves outside the roots from the app's working folder; and the folder
|
||||
preferences in `ui.engine_prefs` and in an open Preferences dialog's `ui.dialog.fields`
|
||||
(`fontsFolder`, `pluginsFolder`, `scratchPrimary`, `scratchSecondary`, `recoveryFolder`, `templatesFolder`; an
|
||||
empty folder and the scratch disk choices `Startup` and `None` stay). A library loaded from a file outside the
|
||||
preferences in `ui.engine_prefs`, in an open Preferences dialog's `ui.dialog.fields` and in a recorded
|
||||
`prefs.set` step (its `value` for such a `key`, and the entries of `values`), also in a batch step's commands
|
||||
(`fontsFolder`, `pluginsFolder`, `scratchPrimary`, `scratchSecondary`, `recoveryFolder`, `templatesFolder`, checked
|
||||
as written and trimmed, a bare name or a subfolder from the app's working folder; an empty folder and the scratch
|
||||
disk choices `Startup` and `None` stay). A library loaded from a file outside the
|
||||
roots shows as `loaded/<file name>` wherever `ui_inspect` and `ui.docking` name it: its id, its panel's id, the
|
||||
Color Guide's `ui.color_guide_limit`, a closed panel's key in `ui.docking_hidden` and the `library` and `panel`
|
||||
params of a recorded action's steps in `ui.action_sets`, and the keys of shortcut overrides (`panel:<panel id>`
|
||||
@@ -3172,8 +3174,13 @@ already walks Image Trace. Short agent entry points:
|
||||
reply's `defined` lists the variables the import defined. While the variables are
|
||||
locked, an import whose header would define a variable fails with "variables are locked".
|
||||
A `dataset.import` file that isn't UTF-8 is read as Windows-1252, unless it starts with the UTF-8 byte-order mark.
|
||||
A file that starts with a UTF-16 byte-order mark is read as UTF-16, and a file without one that holds NUL bytes is
|
||||
refused. `csv` and `data` are read as the text they hold.
|
||||
A file that starts with a UTF-16 byte-order mark is read as UTF-16. A file without one that holds NUL bytes is read
|
||||
as UTF-16 when at least half of its two-byte units hold a NUL byte, as characters from U+0001 to U+00FF do, in the
|
||||
byte order that reads a line break (`\n` or `\r`). It is refused when fewer of its units hold a NUL byte (UTF-8 or
|
||||
Windows-1252 text with stray NUL bytes, or UTF-16 text made mostly of other characters, which needs a byte-order
|
||||
mark), when both byte orders read a line break (the text holds U+0A00 or U+0D00), when it has an odd length, and
|
||||
when it isn't valid UTF-16 in that order or holds a NUL character. A file with no line break has no data rows and is
|
||||
refused for that. `csv` and `data` are read as the text they hold.
|
||||
- Variable libraries: `variable.loadLibrary {path|xml|dataBase64}` (the Variables panel menu's Load Variable
|
||||
Library…) replaces the document's variables and data sets with a variable library's in one undo step. A load, like a
|
||||
`dataset.import`, adds no undo step when it leaves the variables and data sets as they were. The library
|
||||
@@ -3230,7 +3237,11 @@ already walks Image Trace. Short agent entry points:
|
||||
after the set (the web downloads it), and returns `{path}`. `id` holds the panel's own set id, which the panel menu
|
||||
passes: the set with this id is saved wherever it is when the file dialog answers, and `set` is not read. A set that
|
||||
would be larger than 8 MiB as a file, has more than 1,000 actions or has an action of more than 10,000 steps is not
|
||||
written, and the command returns the same error as a load of such a file. `ui.actionSet.load {path? | data?}` reads
|
||||
written, and the command returns the same error as a load of such a file. Nor is a set with a `prefs.set` step, also
|
||||
in a batch step's commands, that sets a folder preference (`fontsFolder`, `pluginsFolder`, `scratchPrimary`,
|
||||
`scratchSecondary`, `recoveryFolder`, `templatesFolder`) to a folder, which names a folder on this computer: the
|
||||
error `the action “<name>” sets the folder preference <key>; delete that step to save the set` names the first such
|
||||
action and preference. An empty folder and the scratch disk choices `Startup` and `None` save. `ui.actionSet.load {path? | data?}` reads
|
||||
the file at `path`, else a picked one, or the file's text `data`, adds its set after the other sets and returns
|
||||
`{set, name, actions}`. A set named like one already in the panel gets the next free number (`Print 2`), and the
|
||||
other sets and the current set stay as they are. An action set file (`.vcactions`) is JSON:
|
||||
@@ -3514,7 +3525,8 @@ already walks Image Trace. Short agent entry points:
|
||||
at the pointer selects under these rules: the arrow with a filled square for a face, with a short line for an edge,
|
||||
and with an x for nothing. It keeps the look it had at the press until the release.
|
||||
The Live Paint Bucket's options (`tool.setOption {tool: "livePaintBucket", values}`; double-clicking the tool opens
|
||||
them, dialog `livePaintBucketOptions`) are `paintFills` (on), `paintStrokes` (off), `highlight` (on), `color` (the
|
||||
them, dialog `livePaintBucketOptions`) are `paintFills` (on), `paintStrokes` (off), `cursorSwatchPreview` (on),
|
||||
`highlight` (on), `color` (the
|
||||
highlight color, `#rrggbb` or a layer color's name; `#ff2a2a`) and `width` (the face highlight's width, 1 to 20 screen
|
||||
pixels; 4; an edge's highlight is half as wide). The dialog's OK gives an error for a `color` with an alpha part
|
||||
(`#rrggbbaa` or `#rgba`) and changes nothing. `tool.setOption` gives an error that names the option and sets none of
|
||||
@@ -3527,12 +3539,26 @@ already walks Image Trace. Short agent entry points:
|
||||
`livePaint.strokeEdge` when an edge is within 4 screen pixels of the pointer and `livePaint.fill` otherwise, and
|
||||
Shift-click runs `livePaint.fill`. With both off, a click runs nothing. With `highlight` off, the face or edge under
|
||||
the pointer is not outlined.
|
||||
With the Live Paint Bucket selected and no drag in progress, Left and Right without Shift, Alt or Cmd/Ctrl (which
|
||||
keep their shortcuts) run `paint.setFill {swatch, ids: []}` (or
|
||||
`paint.setStroke` when the Stroke proxy is in front) with the color swatch before or after the active paint in the
|
||||
Swatches panel, wrapping around at the ends; from a color that is no swatch, Right picks the first swatch and Left
|
||||
the last, and with no color swatch the tool does not take the keys. The selected art keeps its paint. With
|
||||
`cursorSwatchPreview` on, the active paint shows as a ringed chip above the pointer between the swatches before and
|
||||
after it, except during a fill drag or with Alt held; a solid color that is no swatch shows alone, and a paint that is not a solid color shows no chip. Left and
|
||||
Right step the swatches with `cursorSwatchPreview` off too.
|
||||
`livePaint.merge` keeps the bottom Live Paint group's id, name, lock, visibility, transparency, appearance, opacity
|
||||
mask and graphic style link. With a Live Paint group among the objects, `livePaint.make` adds the others to it as
|
||||
`livePaint.merge` does, and so does `livePaint.fill {ids}` when `point` is outside that group's faces.
|
||||
`livePaint.fill` does not fill a face that is hidden on its own. With `group`, a point on a hidden face is an
|
||||
error. With `ids`, at a point on a hidden face it fills the face there of another Live Paint group among the
|
||||
objects; otherwise it returns an error and does not merge the objects.
|
||||
A Live Paint command that changes nothing records no undo step, keeps the redo steps, leaves a saved document saved
|
||||
and replies as usual: `livePaint.fill` (a click, or a Bucket drag) when every face it reaches already has the paint,
|
||||
`livePaint.strokeEdge` when the edge already has the paint and the width, `livePaint.gapOptions` (and the Gap Options
|
||||
dialog's OK) when every group already has the options and `closeGaps` finds no gap, and `livePaint.make` or
|
||||
`livePaint.merge` given one Live Paint group alone, which they select. Such a fill or stroke also leaves the recent
|
||||
colors and the last color as they are. `livePaint.gapOptions` makes a group's faces again, with new ids, only when it adds a path or when Gap Detection is turned on or off or given a new size while it is on.
|
||||
|
||||
`brush.selectionArt {ids?|id?}` (a query) replies `{art}`: the object that `brush.new` given the same `ids` or `id`,
|
||||
or the same selection, takes as a new scatter or art brush's art and as a new pattern brush's side tile. Several
|
||||
@@ -3942,6 +3968,9 @@ For `edit.colors.*`, `fill: false` leaves colorized image fills unchanged. `reco
|
||||
`edit.colors.toGrayscale` and `edit.colors.adjustBalance` with `mode: "gray"` and `convert: true` store an embedded image
|
||||
with one gray channel, so a PDF writes it in gray.
|
||||
`includePatterns: false` leaves patterns out. The Blend commands also grade gradient meshes, which keep their shading.
|
||||
The `edit.colors.*` commands, including the Blend commands, and `recolor.apply`, `paint.invert`, `paint.complement`,
|
||||
`addon.color.filter` and `addon.color.applyNearestSwatch` record no undo step when they change nothing, for example
|
||||
`edit.colors.invert` with `fill: false` and `stroke: false`, or a Blend whose objects already have the graded fills.
|
||||
`edit.colors.saturate` needs `intensity`, a number from -100 to 100 (a number outside the range counts as its nearest
|
||||
end). Without one, or with `null`, it answers `` missing number `intensity` ``; with a value that is not a number, such as
|
||||
`"40"`, it answers `` `intensity` must be a number, not "40" ``. Either way it changes nothing.
|
||||
@@ -4933,7 +4962,9 @@ stay live. `object.expand.info` answers which options have something to expand i
|
||||
(`{object, fill, stroke, gradient, appearance, symbolArt?}`; `gradient` says whether Fill has a gradient fill, which Expand
|
||||
Gradient To applies to, that it turns into art: it is false when every such fill repeats or reflects in more than 256
|
||||
runs across the box it fills, which for type, symbol art included, is the box of each outline Object makes of a character,
|
||||
ruby character, underline or strikethrough; `appearance` whether the selection has appearance attributes Expand Appearance expands first,
|
||||
ruby character, underline or strikethrough, and for a fill of the type object itself the box of its whole outline;
|
||||
`stroke` and `fill` count the type object's own strokes and pattern fills as well as its characters' (its own
|
||||
only when the type has an outline, which type of only spaces does not); `appearance` whether the selection has appearance attributes Expand Appearance expands first,
|
||||
for which Object → Expand… is dimmed in the menus; `symbolArt: {fill, stroke, gradient}`, present when the selection
|
||||
holds symbol instances that `object` expands, whether only their art holds it, which Fill and Stroke reach only with
|
||||
`object` on), and `object.mesh.create` on a gradient-filled object colours the
|
||||
@@ -6269,12 +6300,13 @@ Preferences. `prefs.reset` resets the preferences at once, without the question.
|
||||
`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`, `glyphSnap` and
|
||||
`pixelSnap` 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.
|
||||
`pixelSnap` groups. It leaves out the folder preferences (`fontsFolder`, `pluginsFolder`, `scratchPrimary`, `scratchSecondary`,
|
||||
`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
|
||||
is an error, and nothing changes. For `scratchPrimary` and `scratchSecondary` only a folder is an error: an empty
|
||||
value and the choices `Startup` and `None` are read. 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.
|
||||
@@ -7204,7 +7236,7 @@ hatches filled, pattern hatches as their boundaries), text and multiline text po
|
||||
(one per look when their art takes colour "by block"), anonymous blocks such as dimensions groups. Indexed colours
|
||||
(7 is black on paper), true colour, lineweights (`scaleLineweights` scales them with the art), linetypes and
|
||||
transparency resolve through layers and blocks. What is left out (viewports, images, meshes, unknown entities) is
|
||||
listed in `warnings`. Binary DXF and DWG files answer an error saying to save them as ASCII DXF.
|
||||
listed in `warnings`. ASCII and binary DXF files are read; DWG files answer an error saying to save them as DXF.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"document.dxfInfo","params":{"path":"/tmp/plan.dxf"}}}
|
||||
@@ -8351,6 +8383,14 @@ indent and bullet or number again.
|
||||
{"name":"run_command","arguments":{"command":"text.thread.add","params":{"from":42,"at":[300,120]}}}
|
||||
```
|
||||
|
||||
`type.createOutlines` (Type › Create Outlines) makes a group with a path per glyph, ruby glyph and underline or
|
||||
strikethrough bar, each painted as its characters are. The type object's own fills and strokes (the items around the
|
||||
Appearance panel's Characters row, not the characters' formatting) go on paths of the type's whole outline: the items
|
||||
below the Characters row on one path under the glyph paths, the others on one path over them, in their order and with
|
||||
their opacity, blend mode, effects and stroke settings. Their gradients that are not placed are fixed to the type's
|
||||
layout box, as the canvas paints them, so one gradient spans every glyph. The group itself has no fills or strokes.
|
||||
`object.expand` outlines type with this command, so Fill and Stroke expand those paths' gradients, patterns and strokes.
|
||||
|
||||
`type.createOutlines` (Type › Create Outlines) and `effect.expandAppearance` (when it outlines type, as Expand
|
||||
Appearance describes) take an outlined frame of threaded text out of its thread with the text it shows, and the other
|
||||
frames keep the text they hold. When the thread's last frame is outlined, the text it has no room for, which its
|
||||
@@ -9875,8 +9915,8 @@ The Shape Builder tool's options are its Shape Builder Tool Options (dialog `sha
|
||||
`openFilledAsClosed` (on: a filled open path bounds a region as if an invisible edge closed it; off: it cuts regions
|
||||
as an unfilled path does), `pickColorFrom` (`artwork`, the default: a merged shape takes the appearance, opacity and
|
||||
blending mode of the front-most selected object under the drag's first point, else of the one under its last point,
|
||||
else of the front-most selected object; `swatches`: the current fill, and the Left and Right arrow keys step the
|
||||
current fill through the document's color swatches), `cursorSwatchPreview` (off; with `swatches`, chips above the
|
||||
else of the front-most selected object; `swatches`: the current fill, and the Left and Right arrow keys without
|
||||
Shift, Alt or Cmd/Ctrl step the current fill through the document's color swatches), `cursorSwatchPreview` (off; with `swatches`, chips above the
|
||||
pointer show the current fill and the swatches before and after it), `selection` (`freeform`, the default, or
|
||||
`straightLine`: a drag touches what the line from its first point to the pointer crosses), `highlightFill` (on by
|
||||
default; when it is off, merge mode shades no regions), `gapDetection` (off) with `gapLength` (pt, 0 to 72; 3), `clickStrokeSplitsPath` (In Merge Mode,
|
||||
@@ -10776,7 +10816,8 @@ Commands:
|
||||
- `addon.pathtools.cornerSet {ids?, anchors?, items?, radius, kind?, every?, minAngle?, maxAngle?}` cuts live corners, the ones Direct Selection's
|
||||
corner widgets and the Corners dialog edit, as one undo step. `ids` (default: the selection) are the paths and
|
||||
`anchors` the anchor indices of each path's outline with no corners cut; without `anchors`, a path's direct-selected
|
||||
anchors, or all of them. `items: [{id, anchors?}…]` gives each path its own instead. Only anchors where two sides meet
|
||||
anchors, or all of them. `items: [{id, anchors?}…]` gives each path its own instead; a member key other than `id`
|
||||
and `anchors`, or `items` given with `ids`, is an error. Only anchors where two sides meet
|
||||
at an angle take a corner: smooth anchors and open ends are skipped, and it is an error if none is left. `radius` is
|
||||
0 to 1,000,000 pt, drawn no larger than fits; `kind` is `round`, `invertedRound` or `chamfer` (default: each corner's
|
||||
own). `every` (`all`, `odd` or `even`; default `all`) keeps, of those anchors, only the odd- or even-numbered ones,
|
||||
@@ -10786,7 +10827,7 @@ Commands:
|
||||
be more than `maxAngle`, and it is an error, saying so, if no chosen corner is in the range. Object › Plug-ins › Path Precision Tools › Set Corners… (also in the Anchor Inspector's
|
||||
Corners section) sets these with Preview. → `{ids, corners}`.
|
||||
- `addon.pathtools.cornerRemove {ids?, anchors?, items?}` makes those corners sharp again, as one undo step; a plain path
|
||||
with none left is plain again. → `{ids, corners}`.
|
||||
with none left is plain again. Its `items` take the same keys as `cornerSet`'s. → `{ids, corners}`.
|
||||
- `addon.pathtools.slideAnchor {id, subpath?, anchor, t}` moves an anchor along its path, the segments beside it refitted
|
||||
so the outline stays (the anchor count and index stay). `t`, -0.98 to 0.98, says where: positive, a curve parameter on
|
||||
the segment after the anchor; negative, back from the end of the one before. An anchor at a sharp corner loses it, as
|
||||
@@ -11114,7 +11155,7 @@ the other colour adjustments (Effect › Color Adjustments); each colour keeps i
|
||||
`addon.color.filter {effect, params?, fill?, stroke?, includeImages?, includePatterns?, ids?}` applies any colour
|
||||
adjustment, the add-on's or one of Effect › Color Adjustments', to the colours themselves instead of as a live effect:
|
||||
fills, strokes, type, gradient meshes, embedded images and pattern tiles, as `edit.colors.invert` reaches them, as one
|
||||
undo step. Missing `params` take the effect's dialog defaults; the objects' own effects stay as they are.
|
||||
undo step (none when nothing changes). Missing `params` take the effect's dialog defaults; the objects' own effects stay as they are.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"effect.apply","params":{"effect":"addon.color.exposure","params":{"exposure":1.5}}}}
|
||||
@@ -11281,7 +11322,7 @@ spot, deltaE}]}]}` (`values` as a default swatch name reads them: `C=10 M=20 Y=3
|
||||
`addon.color.applyNearestSwatch {library?, fill?, stroke?, ids?}` (Object › Plug-ins › Color Effects › Find Nearest
|
||||
Swatch…, whose dialog lists each colour's three closest swatches with their difference; Apply runs it) gives each solid
|
||||
colour and gradient stop of the selected objects' fills and strokes (and gradient meshes) the colour of its nearest
|
||||
swatch, as one undo step. A global or spot swatch's colour links to it. The library's swatches the colours take are
|
||||
swatch, as one undo step (none when nothing changes). A global or spot swatch's colour links to it. The library's swatches the colours take are
|
||||
added to the document's first, as `swatch.library.add` adds them, so a spot colour from a colour book stays spot;
|
||||
images and patterns keep their colours. → `{changed, swatches: [the document swatches the colours took], added}`
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
>
|
||||
> Numeric spinner update (2026-11-10): held mouse arrows repeat past the click timeout; scores and estimates unchanged (#6307).
|
||||
|
||||
> **PDF import status (2026-11-14, #6957):** Outlined Indic glyphs retain their full stroke properties; translucent glyphs stay separate, and a soft mask attaches to each glyph separately. Scores and estimates unchanged.
|
||||
|
||||
## Feature submission evidence
|
||||
|
||||
M4: Explicitly requested editing data keeps a single artboard larger than its 14,400 pt capped PDF page (#6865). Scores and estimates unchanged.
|
||||
@@ -56,6 +58,7 @@ M7 type: Touch Type moves a right-to-left character along its line and up from i
|
||||
| 2026-11-13 | minor | PDF import: glyphs inside a marked-content span with an empty `ActualText` come in as outlines in their fill and stroke instead of being left out, adding no text (#6971; `empty_actual_text_keeps_the_glyphs_art` in `crates/pdf/src/tests/actual_text.rs`). Scores and estimates unchanged. |
|
||||
| 2026-11-13 | minor | Library panels (swatch, Color Book, brush, symbol and graphic style libraries): in a panel made taller the list fills the space above the footer instead of scrolling inside 220 or 280 pt (#2992; `the_list_fills_a_tall_panel_above_its_footer` in `crates/ui-egui/src/panels/library_panel/tests.rs`). Scores and estimates unchanged. |
|
||||
| 2026-11-13 | minor | Swatches: in a panel made taller the swatch list fills the space above the footer instead of scrolling inside 150 or 200 pt (#1638; `the_list_fills_a_tall_panel_above_its_footer` in `crates/ui-egui/src/panels/swatches/tests.rs`). Scores and estimates unchanged. |
|
||||
| 2026-11-13 | minor | M4: PDF import (#5235, #6906): Indic type keeps its marks on their line, and a line whose type would not draw as the file does keeps the file's glyphs as outlines (opaque, alike-stroked ones share a path except under a soft mask, where each glyph keeps its own path and mask; translucent ones keep their own). Scores and estimates unchanged. Evidence: `crates/pdf/src/tests/reshaped.rs`. |
|
||||
| 2026-11-10 | minor | M13 / G6: MCP catalogue (#6460): headless lists UI commands, eight prompts, 33 tools, effect vs command ids; scores and estimates unchanged. |
|
||||
| 2026-11-08 | minor | Character Styles panel: a double-click on a user style's row opens its Character Style Options (`ui.charStyleOptions`); the dialog keeps a fixed width and scrolls its sections in a shorter window, so OK and Cancel stay on screen. Tests `panels::text_styles::tests::double_clicking_a_character_style_row_opens_its_options` and `dialogs::char_style_options::tests::the_sections_scroll_in_a_window_shorter_than_the_general_list`. Scores and estimates unchanged. |
|
||||
| 2026-11-08 | minor | #3380, deletion only: preserve gradient placement and exact surviving geometry; consume owned subpaths with a shared original-node snapshot; consolidate status/evidence and document command/helper contracts. Compound behavior and the existing M2 status entry are retained. Endpoint highlighting remains open; scores and estimates unchanged. |
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
>
|
||||
> **Flyout update:** 2026-11-06 — resizable icon-strip flyouts and bottom-aligned panel footers (#5713); scores and estimates unchanged.
|
||||
|
||||
> **PDF import status (2026-11-14, #6957):** Outlined Indic glyphs retain their full stroke properties; translucent glyphs stay separate, and a soft mask attaches to each glyph separately. Scores and estimates unchanged.
|
||||
|
||||
## Feature submission evidence
|
||||
|
||||
EPS embedded fonts, 2026-11-09 (#6023–#6067): the fonts an EPS carries draw their glyphs instead of being set as type in an installed font: composite (Type 0) fonts with the 8/8 mapping, plain Type 42 fonts (characters from their glyph names or character map, widths from the font), CID-keyed fonts over CMaps (Type 0 and Type 2 CIDFonts, CIDFonts in a FontSet's Compact Font Format data, base-font CMaps, named CIDFonts over predefined Unicode CMaps set as type) and embedded Type 1 fonts; the show operators' spacing along the baseline is kept as tracking, `kshow` included. Each step is charged to the interpreter's budgets. Hand-written test files only (no corpus file uses these fonts); scores and estimates unchanged. Evidence: `crates/eps/src/import/tests_composite.rs`, `tests_type42.rs`, `tests_cid.rs`, `tests_type1.rs`; details in [file-format-parity.md](file-format-parity.md).
|
||||
@@ -60,6 +62,7 @@ Artboard Options forwards the active Artboard tool's Scale Artwork with Artboard
|
||||
| 2026-11-13 | minor | Library panels (swatch, Color Book, brush, symbol and graphic style libraries): in a panel made taller the list fills the space above the footer instead of scrolling inside 220 or 280 pt (#2992; `the_list_fills_a_tall_panel_above_its_footer` in `crates/ui-egui/src/panels/library_panel/tests.rs`). Scores and estimates unchanged. |
|
||||
| 2026-11-13 | minor | Swatches: in a panel made taller the swatch list fills the space above the footer instead of scrolling inside 150 or 200 pt (#1638; `the_list_fills_a_tall_panel_above_its_footer` in `crates/ui-egui/src/panels/swatches/tests.rs`). Scores and estimates unchanged. |
|
||||
| 2026-11-13 | minor | Swatches panel: its menu's Show Recent Colors hides and shows the panel's Recent Colors row, checked by default and kept between sessions apart from the Color panel's (#6617); scores unchanged. |
|
||||
| 2026-11-13 | minor | M4: PDF import (#5235, #6906): Indic type keeps its marks on their line, and a line whose type would not draw as the file does keeps the file's glyphs as outlines (opaque, alike-stroked ones share a path except under a soft mask, where each glyph keeps its own path and mask; translucent ones keep their own). Scores and estimates unchanged. Evidence: `crates/pdf/src/tests/reshaped.rs`. |
|
||||
| 2026-11-09 | minor | Stroke panel: Line Arrow, a 41st generated arrowhead: two arms of the head's weight (stroke weight × arrowhead scale, at least 0.25 pt: the line's weight at 100 % for lines of 0.25 pt or more) at right angles, a sharp tip and square-cut ends, twice as wide as the other heads; bounds and clicks follow each head's own reach (`stroke.set` `LineArrow`, #5421); scores and estimates unchanged |
|
||||
| 2026-11-09 | minor | Canvas: a 3D effect (Extrude & Bevel, Inflate, Rotate, Revolve) changed on type or a group draws again where its art was and is, measured by that art; the canvas measures through its renderer and draws the part with the art it made to measure it. Exports and Object › Rasterize take the solid of 3D type. Fit to Artwork Bounds and per-artboard SVG export measure every artboard through one renderer, building each solid once. A 3D effect on a fill or stroke that builds nothing (Revolve after Roughen) no longer overflows the stack on the canvas, in Object › Rasterize and in raster and EPS exports: the fill or stroke draws as without it. Tests `tests::changed::a_3d_effect_changed_on_type_or_a_group_changes_where_its_solid_was`, `fx::tests::a_renderer_measures_the_art_on_each_artboard_building_each_solid_once`, `canvas::tests::an_edit_to_a_3d_effect_redraws_with_the_art_measured`, `fx::tests::a_3d_effect_that_builds_nothing_draws_the_item_as_without_it`. Scores and estimates unchanged. |
|
||||
| 2026-11-08 | minor | Style panels: a double-click on a user character style's row opens its Character Style Options (`ui.charStyleOptions`), and on a paragraph style's row its Paragraph Style Options (rename); the Character Style Options dialog keeps a fixed width and scrolls its sections in a shorter window, so OK and Cancel stay on screen. Tests `panels::text_styles::tests::double_clicking_a_character_style_row_opens_its_options` and `dialogs::char_style_options::tests::the_sections_scroll_in_a_window_shorter_than_the_general_list`. Scores and estimates unchanged. |
|
||||
@@ -568,6 +571,7 @@ since 2026-10-01.
|
||||
- **Save refusal (#6146):** ordinary File > Save to its own location offers Save As after a terminal permission/read-only refusal, suggesting the original name and format, preserving options for the unchanged format and opening the chosen format’s Save options on a change. Cancel keeps the failed-save state. Busy pickers, recovery-copy errors, other failures, explicit destinations and Close/Quit keep the existing dialog. Engine, UI and MCP regression cases are in `cmd/fileio/tests_readonly.rs`, `io/tests_read_only_save.rs` and MCP `tests/fileio.rs`; focused UI regressions passed; engine regression execution and native panel acceptance pending. Scores and hours unchanged.
|
||||
|
||||
- **PDF authored replacement text (#6165):** `crates/pdf/src/tests/actual_text.rs` covers replacement once with suffix placement, PDF text-string decoding, empty and nested owners, sibling spans, page reset, multiple text-show operations, style/line changes, fill-and-stroke, reader windows and bounded input. Authored logical-order stretches are protected while adjacent ordinary text still undergoes reconstruction. The replacement takes its first placed glyph's style and line; its characters are not redistributed over later lines/styles. Exact mixed-direction paragraph layout is not claimed. No export changes; scores and hours stay at 75% / 10–20 h.
|
||||
- **PDF Indic type (#5235, #6906):** `crates/pdf/src/tests/reshaped.rs` covers a vowel sign the file draws before its consonant (the line keeps the file's glyphs as outlines, with a note), text in reading order (stays type), a mark with no advance (stays on its line, not vertical type of its own), outlined glyphs stroked with different dashes and translucent outlined glyphs (each keeps its own path). Synthetic font only; one real Gujarati file checked by eye on page 1. Indic type in an uninstalled font keeps the file's glyphs as outlines; reordering signs so more lines stay editable is not done. Scores and hours stay at 75% / 10-20 h.
|
||||
|
||||
|
||||
- **Selection — disconnected path deletion (#3380, deletion only):** Clear/Delete and Cut turn surviving disconnected pieces of an ordinary contour into independent selected sibling objects. The first keeps its ID; all keep appearance, baked transforms and stacking order. `deletion_split_preserves_gradient_placement` compares rendered survivors with the original paint space and checks linear/radial fill/stroke vectors, already placed gradients and atomic Undo/Redo; connected remainders keep automatic fitting. Existing multi-subpath paths and explicit compound members retain their semantics. Original synthetic regressions in `crates/engine/tests/it/delete_path_pieces.rs` cover styled/transformed rectangles, cubic handles, compound preservation and atomic Undo/Redo; `crates/ui-egui/src/tests/removeanchors.rs` covers real-frame Delete/Backspace and a second Delete removing all survivors. Segment endpoint highlighting remains open. Scores and hours unchanged.
|
||||
@@ -667,6 +671,7 @@ since 2026-10-01.
|
||||
- **Colour emoji with bitmap glyphs:** `sbix` (Apple Color Emoji) and `CBDT` (Noto Color Emoji) glyphs draw as their largest strike's PNG, placed with the type and unpainted by its fill; PDF writes them in Type 3 glyphs or as images, SVG as images with outlined text, EPS and legacy `.ai` as images, and Create Outlines makes embedded images. Synthetic test fonts in `crates/text/src/test_fonts.rs`; tests `crates/text/src/tests/bitmaps.rs`, `crates/render/src/tests/bitmapglyphs.rs`, `crates/svg/tests/it/colour_glyphs.rs`, `pdf::tests::colour_bitmap_glyphs_export_as_images`, the `eps` `colour_bitmap_glyphs_*` tests and `tests_pathops::create_outlines_turns_bitmap_glyphs_into_images`. COLR and OpenType SVG fonts remain.
|
||||
- **COLR colour fonts:** v0 and v1 glyphs draw as vector layers (solid colours, linear and radial gradients, clips, blend modes, the foreground colour from the run's fill) on the canvas, as paths in SVG, EPS, legacy `.ai` and PDF with outlined text, as Type 3 text in PDF, and as editable groups with Create Outlines; sweep gradients and Porter-Duff compositing draw the glyph as an image. Measured by `tests_colr`, `render::tests_colrglyphs`, `pdf::tests::colr_glyphs_export_as_vector_art`, `svg/tests/it/colour_glyphs.rs`, `eps` `colr_glyphs_*`, `tests_pathops::create_outlines_turns_colr_glyphs_into_layer_groups`. Scores unchanged (estimated).
|
||||
- **OpenType SVG colour fonts:** each glyph's SVG document is read by the SVG importer (registered by the engine) into vector art in the run's colours, then drawn, exported and outlined as COLR glyphs are; PDF real text writes them as text that draws nothing and draws their art where they sit. Measured by `tests_svg_glyphs`, `svg/tests/it/svg_glyphs.rs`, `tests_colourfonts::create_outlines_turns_svg_glyphs_into_groups`, `tests_colourfonts::pdf_real_text_draws_svg_glyphs_as_art_and_keeps_their_characters`. Scores unchanged (estimated).
|
||||
- **Create Outlines keeps the type object's own appearance:** Type › Create Outlines and Object › Expand put the type object's own fills and strokes (the Appearance panel's items around its Characters row) on paths of the whole outline, below or above the glyph paths as that row places them, with one gradient across every glyph, so the outlines draw what the type drew; `object.expand.info` reports those strokes, pattern fills and gradient fills. Outlined characters keep their stroke and fill (the help page, <https://help.adobe.com/archive/en_US/illustrator/cs5/illustrator_cs5_help.pdf#page=337>); a type object's appearance is separate from its characters' (the help page, <https://helpx.adobe.com/illustrator/using/appearance-attributes.html>); where the object's items go is VectorCraft's own rule. Measured by `tests::pathops::create_outlines_keeps_the_objects_own_fills_and_strokes`, `tests::objexpand::create_outlines_draws_the_type_objects_own_paint`, `tests::objexpand::type_objects_own_stroke_pattern_and_gradient_are_reported`, `tests::objexpand::type_without_an_outline_reports_no_own_stroke_or_fill`, `tests::objexpand::a_stroke_under_an_unpainted_stroke_is_reported_and_outlined` and `tests::objexpand::expand_keeps_the_type_objects_own_paint`. Scores unchanged (estimated).
|
||||
- **Composite fonts that two documents define differently:** when two open documents each define a composite font (Type › Composite Fonts…) by the same name with different parts, each document draws and exports its type in its own definition: in a tiled or floating window drawn while the front document draws, when it is placed in a document that defines the name differently, and in an export made while another document is in front. Evidence: `tests::composite::nested_loans_of_one_name_use_each_documents_definition` and `threads_lending_one_name_at_once_use_their_own_definitions` (`crates/text`), `tests::fontchange::a_placed_document_draws_its_own_definition_of_a_name_the_page_defines` (`crates/render`). Scores unchanged (estimated).
|
||||
- **Character-style Auto leading:** capture and explicit style attributes retain Auto as a reset, distinct from omitted leading. Redefine and later numeric updates preserve local leading overrides; the Character Styles marker recognizes Auto correctly. Regression assertions cover partial definitions, Undo/Redo and native save/load serialization. Public references: [Character and paragraph styles](https://helpx.adobe.com/illustrator/using/character-paragraph-styles.html) and [Leading](https://helpx.adobe.com/illustrator/using/line-character-spacing.html).
|
||||
- **Character-style numeric bounds:** `charStyle.new`, `charStyle.edit`, and `charStyle.setAttrs` accept size from 0.1 to 1296 pt, explicit leading from 0.1 to 5000 pt, horizontal and vertical scale from 1% to 10,000%, and baseline shift and Tate-chu-yoko offsets from -1296 to 1296 pt. Out-of-range input leaves the style and Undo history unchanged; Auto leading remains available. These limits match the Character panel controls.
|
||||
@@ -758,6 +763,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- Batch…: Override Save and Override Export name each file with the extension of the format the step writes, however the step spells the format (`.svg` and `SVG` give `.svg`, `png8` gives `.png`), in `action.batch`.
|
||||
- Batch…: Override Export writes the files of an Export for Screens or Export Assets step into a folder for each source file or data set inside the destination folder, under the names the export gives them (`action.batch`). The folder and file names drop trailing periods and spaces (`a..svg` gives `a`). When two source files would get the same name that way (compared without case), or a later file's folder or file would take the name of an output an earlier file wrote, of a source file in the destination folder or, for data sets, of a file already there, Batch adds `-2`, `-3`… to the later one's name.
|
||||
- Actions panel menu: Save Actions… writes the current action set with all its actions to a file, and Load Actions… adds the set from such a file to the panel ([Manage a set of actions](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/manage-a-set-of-actions.html); `ui.actionSet.save`, `ui.actionSet.load`). The file is VectorCraft's own action set file (`.vcactions`); a loaded set named like one in the panel gets the next free number.
|
||||
- Actions panel menu: Save Actions… does not write a set with a step that sets a folder preference (the Fonts, Plug-ins, Templates and Recovery folders and the two scratch disks) to a folder, and names the action and the preference instead; an empty folder and the scratch disk choices Startup and None save. Export Preferences leaves out both scratch disks, and `ui.inspect` under automation read roots leaves such a folder outside them out of recorded steps. These are VectorCraft's own rules (`ui.actionSet.save`, `prefs.export`).
|
||||
- Actions panel menu: Load Actions… also reads action sets saved as `.aia` files ([Actions panel overview](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/actions-panel-overview.html); `actionSet.read`, `ui.actionSet.load`). VectorCraft's own rules: the set comes in with all its actions. A step with a label and no recorded values comes in as the one menu command with the step's label, when that command is directly in a top menu, is what its menu bar item runs with no values and opens no dialog. A step that is off in the file stays excluded from playback. The other steps, recorded menu items included, are left out, and the status bar says how many.
|
||||
- Actions panel: the panel menu's Action Options… renames the selected action and keeps its steps ([Actions panel overview](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/actions-panel-overview.html): the menu item opens a dialog that renames the action or gives it a function key and color; `ui.action.options`). It also sets the action's function key and color.
|
||||
- Actions panel: Create New Action (bottom bar) and the panel menu's New Action… ask for the new action's name, set, function key and color, and Record adds the action and starts recording into it ([Create new actions](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/record-actions.html): the New Action dialog takes the action's name and the set it goes in; `ui.action.new`, `ui.action.play`). The function key (F1 to F15, with Ctrl or Command and Shift) plays the action. An action's function key plays the action even when a command has the same shortcut, and the command keeps it. VectorCraft's own rules, which the page does not cover: when several actions have the same key the first in panel order plays; a copied action has no key; New Action does not open while an action is recording. The color is kept with the action for Button Mode, which VectorCraft does not have yet.
|
||||
@@ -786,6 +792,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- Variables (data merge): text, visibility and image variables bound to objects (an object may carry several), dataset rows applied in one undo step (`variable.*`, `dataset.*`) from a Variables panel and Window › Variables, with dialogs to define, bind and edit, Make Text/Visibility/Image Dynamic, Capture/Update Data Set, CSV import/export (`dataset.import` / `dataset.export`), and a row in italics when an edit leaves the art not matching it; an image dataset value is a file path and apply keeps the object's bounds; bindings let go of deleted art and locked art is left alone except by visibility values; every command, like the rest, is drivable over MCP and the CLI.
|
||||
- Export for Screens numbers distinct row files whose names collide, compared without case, as `-2`, `-3`… instead of leaving them out; identical rows still write one file. It puts row folders that differ only in case into one folder (`document.exportForScreens`).
|
||||
- Variables: Import Data Sets… (`dataset.import`) reads tab-separated files as well as comma-separated ones. Every header cell is a variable, and the rows replace the document's data sets as Data Set 1, Data Set 2 and so on. An import error about a row's values gives the file line the row starts on.
|
||||
- Variables: Import Data Sets… (`dataset.import`) reads a UTF-16 file without a byte-order mark, instead of refusing it, when at least half of its two-byte units hold a NUL byte; it uses the byte order that reads its line breaks.
|
||||
- Variables: Import Data Sets… (`dataset.import`) defines the variables a file's header names that the document lacks, unbound. `#Shown` defines a visibility variable, `@Photo` defines an image variable, and a header without a prefix defines a text variable. A header that is a variable's exact name keeps naming it, and any other `%` header (graph data files) is refused.
|
||||
- Variables: Load Variable Library… in the Variables panel menu (`variable.loadLibrary`) replaces the document's variables and data sets with a variable library's, read from its XML file, in one undo step: every data set is deleted, and every variable is deleted with its bindings and values, except a text variable the library also declares, which stays bound so the library's data sets change its objects (#4136); then the library's other text variables are defined, unbound, and its data sets take the text of each value's `p` elements, one paragraph each. Variables of other kinds are left out with a warning that names their kinds.
|
||||
- Variables: Save Variable Library… in the Variables panel menu (`variable.saveLibrary`) writes the document's text variables and data sets as a variable library's XML file, which Load Variable Library reads back with the same text variables, data set names and text values. Variables of other kinds are left out with a warning that names their kinds.
|
||||
@@ -853,6 +860,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- With the Artboard tool, the contextual task bar sits under the selected artboards and offers Resize (Artboard Options for the active artboard), Duplicate (each selected artboard, in one undo step, the copies then selected), Rearrange All (with two or more artboards) and Export (Export for Screens with the selected artboards checked). This follows Illustrator's bar: while the Artboard tool is in use, it has options for resizing, duplicating and exporting artboards (the [Contextual Task Bar announcement](https://community.adobe.com/questions-652/contextual-task-bar-in-illustrator-2025-quick-actions-when-you-need-them-1546580); Rearrange and Export on the bar: [Managing Artboards in Illustrator](https://creativepro.com/managing-artboards-in-illustrator/)).
|
||||
- The contextual task bar offers more next steps by selection (<https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/contextual-task-bar-overview.html>): an open path Join and Edit Path (the Direct Selection tool), a closed path Edit Path, a compound path Edit Path and Release Compound Path, a clipping group Edit Clipping Path and Release Clipping Mask instead of Ungroup and Isolate, an image selected with vector art Make Clipping Mask instead of Unite, point or area type Convert To Area Type or Convert To Point Type beside Create Outlines, and type on a path, for which the overview names an item to add an effect and rearrange the text, Type on a Path Options (`type.pathOptions`; its options: <https://helpx.adobe.com/illustrator/using/creating-type-path.html>) beside Create Outlines. Evidence: `crates/ui-egui/src/tests/taskbar.rs`.
|
||||
- While a Type tool (Type, Area Type, Type on a Path and their vertical versions) adds or edits type, the contextual task bar shows the font family menu, the font style menu, the Font Size combo and the Fill chip (<https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/contextual-task-bar-overview.html>); the Touch Type tool shows no bar, as the same page describes. Type selected with a selection tool shows the same three font controls beside its Create Outlines, conversion and Type on a Path items (<https://helpx.adobe.com/illustrator/desktop/design-with-text/fonts-and-scripts/font-options-overview.html>). The controls act as the Character panel's do: on the characters a Type tool selects, else on every selected type object, with the size left blank where the sizes differ. VectorCraft's own rules: a Type tool's bar leaves out the object actions, the Stroke chip, Recolor Artwork and Lock; a Type tool shows no bar before it adds type or with other art selected; type selected with other art shows no font controls; the font controls go on a second row when one row would be wider than the canvas, and narrow to fit a canvas narrower than they are; while a Type tool edits type, the Fill chip shows the edited characters' fill ("?" where it differs). Evidence: `the_type_tools_show_font_and_fill_controls`, `the_type_tools_show_no_bar_without_type`, `selected_type_shows_font_controls_beside_its_actions`, `the_task_bars_font_size_sets_what_the_character_panel_would`, `the_type_tools_fill_chip_activates_the_fill`, `the_type_tools_bar_is_named_and_stays_on_the_canvas`, `selected_types_font_controls_take_a_second_row_on_a_narrow_canvas` and `the_type_tools_fill_chip_shows_the_edited_characters_fill` in `crates/ui-egui/src/tests/taskbar.rs`.
|
||||
- The help page describes the contextual task bar as one horizontal row (<https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/workspace-overview.html>) and gives no rule for a canvas narrower than that row. VectorCraft's own rule: the bar stays whole on the canvas. When its actions don't fit in one row, they wrap, in order, onto rows under the row with the handle, the chips and More Options; an action wider than any row, or one that would need a row past the canvas's height, is listed in More Options instead; when the chips don't fit beside the handle and More Options, they take rows after the actions; with no row to spare for the font controls, the bar leaves them out; a canvas too small for the handle and More Options shows no bar. Evidence: `a_task_bars_actions_wrap_on_a_narrow_canvas` and `a_task_bar_action_wider_than_the_canvas_goes_in_more_options` in `crates/ui-egui/src/tests/taskbar.rs`.
|
||||
- With a live rectangle, rounded rectangle, ellipse or polygon selected with the Selection tool, the contextual task bar shows a Shape Properties button in place of Lock. It opens a popup with the shape's rows from the Transform panel (corner radius, pie angles, or sides, angle, corner and radius), which edit it through `object.setLiveShape`. The overview describes this: when a shape drawn with a shape tool (Rectangle, Star) is selected, the bar offers to change its properties where Lock Object would be ([Contextual Task Bar overview](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/contextual-task-bar-overview.html)). Object › Lock and ⌘2 still lock the shape. Not done: stars, which the app draws as plain paths. Evidence: `a_basic_shape_shows_its_properties_in_place_of_lock`, `the_shape_properties_popup_edits_the_shape` and `other_selections_keep_lock` in `crates/ui-egui/src/tests/taskbar.rs`.
|
||||
- The contextual task bar has a Stroke chip beside the Fill chip, drawn with the paint the Stroke proxy shows (a "?" when the selected objects' strokes differ, as on the Fill chip); a click brings the Stroke proxy forward and shows the Swatches panel wherever it is docked, floating or closed, as a click on the Fill chip does for the Fill proxy. The reference app's bar has Fill and Stroke controls for changing an object's colors ([Contextual Task Bar overview](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/contextual-task-bar-overview.html)). Evidence: `the_task_bar_shows_a_stroke_chip_beside_fill` and `the_task_bar_chips_follow_the_proxies_and_show_swatches_anywhere` in `crates/ui-egui/src/canvas/tests.rs`.
|
||||
- With anchor points selected with Direct Selection, the contextual task bar offers Remove Anchor Points, Connect (`path.join`), Cut Path, Corner and Smooth (`path.convertAnchors` with `to` set to `corner` or `smooth`), the commands of the Control bar's anchor buttons. As in Illustrator, whose bar has items that delete the selected anchors, join selected end points, split the path at the selected anchors, and make the selected anchors corner or smooth points ([Contextual Task Bar overview](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/contextual-task-bar-overview.html)). Not done: Simplify, which the bar offers only while no anchors are selected, and the bar's Smooth item that adjusts a path's curvature, a command the app doesn't have (Object › Path › Smooth).
|
||||
@@ -879,9 +887,11 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- Hindi wording (2026-11-13): rows outside the plug-in messages keep their English's meaning, quantities and clauses, and use the catalog's save, swatch, crop, resolution, path and type terms; a test checks those terms and the point unit in every row; native review remains; scores and estimates unchanged.
|
||||
- Hindi terms (2026-11-13): every row that names a variable (data merge, variable fonts and widths, environment variables) says वेरिएबल, and joining paths, anchor points, point type and lines says जोड़ें instead of शामिल हों, which stays for joining the community; a test checks both terms in every row; scores and estimates unchanged.
|
||||
- Hindi English words (2026-11-13): 264 rows no longer keep English words in their sentences, repeat a parameter's name in Hindi or garble them, among them "unknown align", which now names the alignment; lists of accepted values such as `(left|right|top|bottom)` stay as their English writes them; two tests check every row; native review remains; scores and estimates unchanged.
|
||||
- Italian messages (2026-11-13): the Italian catalog (`it`) has 1,802 more status and error message rows, and the untranslated report's missing Italian messages go from 1,842 to 40; the translations are VectorCraft's own and await native review; scores and estimates unchanged. See [localization-parity.md](localization-parity.md).
|
||||
- Window › Help Bar shows or hides the tool-help strip at the bottom of the window apart from the status bar (`window.helpBar`). Each setting is kept with the UI preferences and in saved workspaces, and Presentation Mode hides both bars. Layouts saved before the setting existed show the Help Bar where they show the status bar (`help_bar_toggle_is_independent_and_saved_in_workspaces`, `help_bar_and_status_bar_render_independently`, `legacy_help_bar_visibility_follows_each_layouts_status_bar`, `a_help_bar_setting_the_file_lacks_is_saved`).
|
||||
- Czech render-site labels: desktop/web file filters, diagnostics, suggested preset names and contributor tooltips/plurals now use catalog lookups; gradients have Czech adjective agreement and printer marks have a separate context (PDF/Print and Summary). Search, Home, toolbar/panel tooltips and Preferences already look up their labels. Every complete catalog has rows for these labels and for the Roman and Japanese printer mark styles. Evidence: `i18n::tests::czech_render_site_follow_up`, `i18n::tests::complete_catalogs_translate_render_site_labels`, `dialogs::tests_modal::printer_mark_labels_are_distinct_from_language_names`; see [localization-parity.md](localization-parity.md).
|
||||
- The History panel, Edit › Undo and Edit › Redo translate the names of the steps that apply or redefine a character or paragraph style and of the step that redefines a graphic style: each such step keeps its template (`Apply {name}`, `Redefine {name}`, `Redefine Graphic Style “{name}”`) and the style's name, every complete catalog has a row for each template, and the panel and the menu show the style's name as the document holds it, except the Normal styles' names, which they show in the interface language (`steps_named_after_a_style_list_the_template_around_the_name`, `undo_and_redo_name_a_style_step_around_the_style_name`).
|
||||
- The Polish catalog (`crates/ui-egui/src/i18n/pl.tsv`) has an `@msg` row for the status and error messages the untranslated report (`untranslated_report`) finds in the sources, 3,439 `@msg` rows in all: the errors of commands, scripts, file import and export and plug-ins. The report lists 46 Polish messages: 44 that open #7211, #7214, #7116, #7330 and #1931 translate, and 2 that no language has a row for. A message with two placeholders in a row (`Template::parse` in `crates/ui-egui/src/i18n/catalog.rs`) is still shown in English.
|
||||
- The status bar translates the limits a plug-in run can exceed (its instruction, time and memory budgets and its output size) and the error of a plug-in removal that leaves the plug-in's grant in the plug-in store, in every language that translates every message. The untranslated-strings report also lists messages that an error or a status takes from a `&str` constant (`plugin_limit_errors_are_translated`, `message_scan_reads_messages_held_in_constants`).
|
||||
- The status bar translates the plug-in host's other errors (manifest, module and run checks, the output an importer, exporter or effect returns, and the approval a plug-in's permissions need) in every language that translates every message. A JSON object or array inside a message stays as written, and a message that wraps another one, such as `plug-in manifest: {0}`, is matched by its own row before a row that starts with a placeholder. The reasons inside these errors (what is wrong with a parameter's spec or dialog keys, the value a parameter needs, what is wrong with an object, stroke, paint or effect in a plug-in's output) are translated with them, and the untranslated-strings report lists the reasons the plug-in host's error helpers take (`plugin_messages_are_translated_in_every_complete_catalog`, `plugin_errors_translate_with_their_values`, `plugin_error_reasons_are_translated_with_the_error`, `message_scan_reads_plugin_helpers`, `templates_that_start_with_text_match_first`).
|
||||
- The status bar translates the errors a script's `File` and `Folder` objects, `vc.run`, `$.evalFile`, the `$` object's properties and functions, `alert`, `confirm` and `prompt`, `vc.document` and `vc.log` raise, the limits a run can pass, and the errors of Drop Script Engine, and the line for a run that fails (a syntax error, a thrown error, a limit, a stop or an internal error, with the script's name, the line and column, the included file it is in and the files left written), in every language that translates every message. The script's name, paths, numbers, command ids and the text a script throws itself are shown as they are. A failure with no line and column, such as an error in code `eval` compiled, is shown with one colon after the script's name (`an_error_without_a_place_names_the_script_and_kind`). A message template that names a value twice matches only when both places hold the same text, so the line for a failed run is not taken for the message inside it (`a_repeated_placeholder_matches_the_same_text`). The untranslated-strings report also lists the messages the script host's `fail`, `value` and `over` helpers take and the errors the script interpreter throws, and a constant's text comes from the file or crate that declares it, so the Scripts menu's headers are not listed as messages (`script_errors_are_translated`, `script_host_errors_are_translated`, `message_scan_reads_script_interpreter_errors`, `message_scan_reads_constants_of_the_file_and_its_crate`, `message_scan_skips_test_modules_with_any_test_cfg`).
|
||||
@@ -889,8 +899,10 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
The counts that Package's status and question, the folder search of Missing Fonts and Find Linked Files, the modified and missing linked file prompts and the CSS Properties panel's notes show use the interface language's plural forms instead of a fixed "(s)" form. Evidence: `the_missing_links_note_uses_each_count_form` in `crates/ui-egui/src/dialogs/tests_package.rs`, `the_modified_links_question_uses_each_count_form` in `crates/ui-egui/src/dialogs/missing_links.rs`, `search_counts_use_each_count_form` in `crates/ui-egui/src/dialogs/missing_fonts/tests.rs` and `the_unnamed_objects_note_uses_each_count_form` in `crates/ui-egui/src/panels/tests_css_properties.rs`.
|
||||
The status bar's messages for relinked, replaced, updated and embedded images, broken links, linked files that can't be read or changed on disk, images that can't be decoded, added and unavailable fonts, copied CSS, downloads and exports with their notes name one item in the singular and more in the plural, in English and in each language's plural forms (`counted_status_messages_take_the_plural_form` in `crates/ui-egui/src/i18n/tests.rs`).
|
||||
The status bar's messages for documents opened or saved with notes and for discarded or restored recovered documents, and the Global Edit options' Results line, do the same (`open_save_and_recovery_messages_take_the_plural_form` in `crates/ui-egui/src/i18n/tests.rs`); the warnings for linked images and placed documents output as their previews and the errors for a page past a placed file's last page or artboard name their counts in the singular or the plural in English.
|
||||
- The Simplified Chinese catalog (`crates/ui-egui/src/i18n/zh-hans.tsv`) has an `@msg` row for the status and error messages the untranslated report (`untranslated_report`) finds in the sources, 3,439 `@msg` rows in all: the errors of commands, scripts, file import and export and plug-ins. The report lists 40 Simplified Chinese messages: the composite font, justification order and Blob Brush connect end errors that open #7211, #7116 and #7330 translate, and two messages that no catalog has a row for yet. A message with two placeholders in a row (`Template::parse` in `crates/ui-egui/src/i18n/catalog.rs`) is still shown in English.
|
||||
- Edit › Undo and Edit › Redo, in the in-window and native menus, name the step in the interface language as the History panel lists it (`panels::history::step_name`), so when the catalog has no plain row for a step named after an effect, such as Feather, the menu shows the translation of the effect's menu row without its ellipsis (`undo_and_redo_name_the_step_as_the_history_panel_does`).
|
||||
- The History panel translates the undo step names the engine, the tools and the shell write as literals: the untranslated report (`untranslated_report`) lists any a complete catalog lacks, and a step whose catalog row exists only with an ellipsis (such as an effect's menu name) shows that row without the ellipsis.
|
||||
- The German catalog (`crates/ui-egui/src/i18n/de.tsv`) has an `@msg` row for the status and error messages the untranslated report (`untranslated_report`) finds in the sources, 3,433 `@msg` rows in all: the errors of commands, scripts, file import and export and plug-ins. The report lists 48 German messages; 38 of them are the composite font, select-a-path and justification order errors that open #7211, #7214 and #7116 translate. A message with two placeholders in a row (`Template::parse` in `crates/ui-egui/src/i18n/catalog.rs`) is still shown in English.
|
||||
- The History panel menu has Step Backward and Step Forward, which run Edit › Undo and Edit › Redo and are disabled when there is no step to undo or redo, and Set History Limit…, which opens Preferences at Performance, where History States is set.
|
||||
- The History panel menu's Clear History (`edit.clearHistory`) removes every step to undo and to redo and leaves the document as it is; it is not an undo step itself, and it is disabled when there is no step to clear.
|
||||
- The New Document from State button at the bottom of the History panel (`edit.newDocumentFromState`) makes a new document, which becomes active, from the state the panel has selected ([public source](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/undo-edits-and-manage-design-history.html)). VectorCraft's own rules: the new document takes the next Untitled-N name, is marked unsaved, has nothing selected and has no steps to undo or redo, and the source document and its steps stay as they are.
|
||||
@@ -909,6 +921,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- The errors of the 3D effects (Extrude & Bevel, Revolve, Inflate, Rotate and their Classic forms) show in the status bar in the interface language: the art a 3D effect cannot build a solid from, invalid light, graphics and surface settings, and the notes for an object that draws no 3D faces or more wireframe edges than the limit. Each has a row in every catalog that translates all status and error messages, and the effect's name and the values in the message are translated or kept as written (`three_d_refusals_are_translated_in_every_complete_catalog`, `three_d_refusals_translate_with_their_values`).
|
||||
- The errors of the parameter checks that many commands share show in the status bar in the interface language: a value that is not a number where a number goes (`object.move` with `"dx": "60 mm"`, and `object.rotate`, `object.setBounds` and the other commands that call `check_numbers`), a missing number or index, `ids` that are not a list of object ids, an object id that is not a non-negative integer or names no object, and a date that is not Unix seconds. Each has a row in every catalog that translates all status and error messages, and in Bulgarian, Danish, Indonesian and Dutch (`shared_param_check_errors_are_translated`).
|
||||
- A parameter schema's errors show in the status bar with what the value must be in the interface language, for every type a schema has (a number with each kind of range and with a unit, an integer and its range, true or false, a string, a list of names, an object id, a list of object ids, a color, a point, an object and a list), in every catalog that translates all status and error messages; the path, the refused value, the bounds, the unit and the names stay as the English gives them. The error for a value that is not one of its names is also translated in Bulgarian, Bosnian, Danish, Indonesian and Dutch (`parameter_schema_expected_phrases_are_translated`, `bracketed_message_parts_translate_only_as_exact_messages`).
|
||||
- The untranslated report lists the status and error messages of the effects, swatch libraries, raster sizes and encoders, 3D solids and path operations that a catalog lacks, the messages that a `.map_err` closure or a named error handler returns, and the phrases a parameter schema's error builds for what a value must be (`untranslated_report_checks_every_message_crate_and_schema_phrase`, `message_scan_reads_map_err_closures`, `message_scan_reads_named_map_err_handlers`).
|
||||
- Export commands run through MCP, the control channel or the CLI refuse a key that no format takes, and warn about a key that only another format takes (`{"format": "pdf", "quality": 80}` writes the PDF with the warning "`quality` was not used: PDF files don't read it"; `an_option_only_another_format_reads_gets_a_note`, `control_export_notes_an_option_the_format_does_not_read`, `convert_warns_about_an_unused_option_only_when_one_was_given`), and a command that writes one format (`document.exportPdf`, `document.exportEps`, `document.exportDxf`) or takes one format's options (`document.pdfSettings`, `pdf.preset.save`) refuses a key that format doesn't take. An unknown key inside `marks`, `bleed`, `compression`, `output`, `advanced`, `security` or `flattener` is refused by its path.
|
||||
- Save commands run through MCP, the control channel or the CLI (`document.save`, `file.saveAs`, `file.saveCopy`, `file.saveAsTemplate`, `app.save`) refuse a key that no save format takes, beside the path or in `options`. Export for Screens refuses a key it doesn't take, and a key that no format takes in a format row or in a format's settings, by its path (`formats[1].marks.useDocumentBleed`); Export Assets (`assets.export`, `assets.settings.set`) checks the rows and settings it is given the same way.
|
||||
- Commands that read their `ids` (or `slices`) list themselves refuse a list with an entry that is not a non-negative integer, and a value that is not a list, and change nothing; they no longer drop the entry and act on the rest (Copy Appearance From, the Edit Colors commands and Overprint Black, Find and Replace, `layer.highlight`, `layer.move`, `library.add`, the Links panel commands, `object.transform`, Make Pattern, the Repeat commands, the slice commands, Join, Average and Join, `plugin.run`, `symbol.edit`, Make Opacity Mask; `tests::ids_without_selection::an_ids_entry_that_is_not_an_id_is_refused_and_changes_nothing`). The error for an entry of an object id list names the key, the entry and its value ("`ids` entry 1 is true, not a non-negative integer object id"), with a row in every catalog that has the other object id errors.
|
||||
@@ -1291,6 +1304,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
In area type of a shape other than a rectangle, each line's whole band, ascent to descent, stays inside the frame: where an edge pinches in within the band, the line ends at the narrowest point, and a line runs beside a hole that starts and ends within its band, not across it. In area type of any shape, a line also stays clear of a text wrap object that reaches into any part of its band, and inside an Invert Wrap object over its whole band (`crates/text/src/layout/region.rs` tests).
|
||||
In area type whose frame has several contours, a line runs across an edge two contours share only when their edges lie exactly on one line, so a gap between contours keeps lines from crossing it, even a gap one unit in the last place wide near the edge of the canvas; an edge divided by an anchor exactly on it still lets lines cross (`layout::region::separate_slanted_contours_keep_a_four_ulp_gap_near_canvas_limit`, `shared_slanted_edge_still_joins_near_canvas_limit`, `area_type_sets_no_line_across_a_four_ulp_gap_between_slanted_contours`).
|
||||
With Invert Wrap, the spans a line keeps inside a wrap shape of many parts (a comb of 500 teeth) are found by stepping through the line's spans and the shape's spans once for each piece of the band, so the work grows with the number of spans, not with its square (`crates/text/src/layout/region.rs` tests).
|
||||
Text Wrap Options › Offset is a distance field in the document's units: a bare number is in those units, a typed unit ("12 pt") is read as typed, and OK sends points. In a document in picas, a bare number follows Preferences › Units › Numbers Without Units Are Points as the other length fields do: it is in points while that preference is on (the default) and in picas while it is off (`dialogs::command::tests::text_wrap_offset_in_picas_follows_numbers_without_units_are_points`). An Offset typed outside -1000 to 1000 pt, VectorCraft's own range for the command, or text that doesn't read, is refused: the field flashes and the dialog stays open, whether Enter or a click on OK ends the entry; in every dialog drawn by the shared dialog window, a click on OK no longer confirms it when the distance field it takes the focus from refuses its text (`dialogs::command::tests::text_wrap_offset_field_takes_document_units_and_refuses_values_outside_its_range`). Behavior reference: [the help page](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/enter-values-in-panels-and-dialog-boxes.html).
|
||||
The Character panel's Small Caps, Superscript and Subscript buttons and the panel menu's items of the same names turn small caps and the superscript or subscript position on and off for the selected type, or for the text the Type tool has selected (`text.setFormat` or `text.setRangeStyle` `{smallCaps, position}`), in Document Setup's proportions. Turning Superscript on turns Subscript off, and turning Subscript on turns Superscript off. A button or item shows as on when the first selected character (at a caret, the character before it) has its attribute.
|
||||
The Character panel's Anti-aliasing Method dropdown, under Character Rotation, sets how the edges of the selected type objects are drawn as pixels (`text.setFormat {antiAlias}`), for the whole object, with each frame of a thread keeping its own method and graph labels keeping it when the graph is drawn again, on the canvas, in raster exports and when the type is rasterized. VectorCraft defines the methods: Sharp, the default, draws edges as before; None paints a pixel only where the type covers at least half of it; Crisp shows a pixel covered by a share c at `2c - 0.5`, and Strong shows it at `2c`, each kept between 0 and 1. SVG, PDF and EPS export are unchanged. Scores and hours unchanged.
|
||||
The OpenType panel's Stylistic Alternates and Titling Alternates checkboxes turn `salt` and `titl` on and off for the selected type, and its Figure menu lists Default Figure, Tabular Lining, Proportional Lining, Proportional Oldstyle and Tabular Oldstyle; Proportional Lining sets `pnum` and `lnum` and turns `tnum` and `onum` off, Tabular Lining turns `pnum` off and keeps `lnum`, Proportional Oldstyle turns `lnum` off and keeps `pnum`, and Default Figure and Tabular Oldstyle turn `pnum` and `lnum` off. Behavior reference: [Format text with OpenType features](https://helpx.adobe.com/illustrator/desktop/design-with-text/special-characters-glyphs/format-text-with-opentype-features.html) and [Use swashes, titling alternates, or stylistic alternates](https://helpx.adobe.com/illustrator/desktop/design-with-text/special-characters-glyphs/use-swashes-titling-alternates-or-stylistic-alternates.html) (public documentation). Tests: `panels::opentype::tests`.
|
||||
@@ -1377,6 +1391,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- **Image Trace, curve fitting tolerance:** the outline fitter keeps cutting a run while a point stays farther than the tolerance from its curve, so a run of fewer than six points or one cut 14 times no longer keeps a piece over the tolerance. Pieces already within the tolerance do not change, and noisy art can get more anchors. Tests: `logo::bezier::tests`, `logo::outline::tests`. Scores and hours unchanged.
|
||||
- **Image Trace, gray photos:** Color and Grayscale smooth a gray photo within its tones before choosing its colors, as they do a color photo. A picture with at least 95% of its opaque pixels within 8 levels across their channels counts as continuous tone when 8 colors leave an error of more than 6 levels and more than 0.065 of the error of one color, instead of 0.1, unless 16 colors leave at most a fifth of the error of 8 (VectorCraft's own values). That exception keeps gray flat art of up to 16 clean levels on its old route; anti-aliased or noisy gray flat art can now count as continuous tone too. Most gray photos the change reaches, and very noisy gray scans of flat art, trace with fewer specks and fewer staircase edges. Some 16 Colors and High Fidelity Photo palettes of gray photos grow toward the requested count, with more anchors and regions. Some gray illustrations and sketches get more anchors and staircase edges at 16 Colors and High Fidelity Photo, and some 6 Colors traces get more staircase edges. Tests: `tests::a_gray_photo_is_continuous_tone_as_its_color_original_is`, `tests::a_gray_photo_is_smoothed_before_it_is_traced`. Scores and hours unchanged.
|
||||
- **Image Trace, tinted photos:** Color and Grayscale smooth a sepia, single-hue or duotone photo within its tones before choosing its colors, as they do a gray photo. A picture with at least 95% of its opaque pixels within 6 levels of its tone curve counts as continuous tone under the same 0.065 rule as a neutral picture. The tone curve runs through the median color of each 8-level stretch along the direction in which the picture's colors spread the most, and a pixel on it must also lie within 6 levels of the plane the colors spread along most, so art in several unrelated colors is not counted (VectorCraft's own rule and values). The neutral rule's exception for 16 colors leaving at most a fifth of the error of 8 applies to it too. Clean tinted bands of 2, 3 and 9 levels and tinted scans of flat art with up to 8 levels of noise stay on the flat-art route. On the synthetic tinted photos the 16 Colors trace keeps 12 to 15 colors instead of 6 to 13, with 525 to 708 anchors instead of up to 1,402. A duotone with strong noise on each channel can still miss the curve and stay unsmoothed. Tests: `tests::a_tinted_photo_is_continuous_tone_as_a_gray_photo_is`, `tests::small_accents_of_other_colors_leave_a_tinted_photo_continuous_tone`, `tests::tinted_flat_art_stays_flat_art`, `tests::pictures_without_tones_are_not_continuous_tone`, `tests::a_tinted_photo_is_smoothed_before_it_is_traced`. Scores and hours unchanged.
|
||||
- **Image Trace, JPEG blocks:** Color, Grayscale and Black and White traces smooth the edges of a JPEG's 8 × 8 blocks before tracing, so a dark ground whose tone changes slowly is no longer traced as staircases along the block edges. The block grid is found in the image itself: the mean step between neighboring pixels must peak at one position in eight, across and down. A cropped JPEG and a JPEG saved in another format are smoothed too. A picture of flat 8 × 8 cells is left as it is, and art made of 8 × 8 cells with slight texture inside each cell is smoothed as a JPEG copy would be. A small step at a block edge, with no edge in the eight pixels around it, is spread over those eight pixels, and larger steps are kept, as the deblocking filters of ITU-T H.263 Annex J and MPEG-4 Part 2 Annex F.3.1 do. Black and White smooths only the smallest steps, and traces of more than 16 colors move every row of a stretch of eight by the same amount (VectorCraft's own rule and values). On a 4000 × 3000 photo saved as JPEG, the straight outline segments that lie on the block grid fall from 52% and 51% (across and down) to 24% and 29% at 16 Colors, and from 54% and 51% to 43% and 42% at High Fidelity Photo; staircase runs fall from 83 to 67 (16 Colors), 11 to 1 (6 Colors), 30 to 13 (Black and White Logo) and 428 to 403 (High Fidelity Photo). A 600 px photo saved as a quality-40 JPEG has 4 staircase runs instead of 2 at 16 Colors. Images without a block grid trace as before. Tests: `tests::a_jpegs_blocks_are_not_traced_as_steps`, `deblock::tests`. Scores and hours unchanged.
|
||||
- **Image Trace, Document Library color groups:** with Document Swatches, the panel's Colors menu and `"colorGroup"` trace with one color group's colors instead of every swatch, as the public panel documentation describes Document Library; code-drawn tests in `crates/engine` and the panel.
|
||||
- **Image Trace, Document Library colors:** with Document Swatches, traced fills and strokes use the displayed colors of process, global, spot and tint swatches without links, so editing a swatch leaves the trace unchanged; swatch-library colors are also unlinked; code-drawn tests in `crates/engine`.
|
||||
- **Image Trace, flattened slivers:** in a Color, Grayscale or Black and White trace with Fills, a traced region whose outline straightens onto one line (a single pixel, or a one-pixel row along an edge, its pieces shared with the regions beside it) is left out instead of becoming a selectable path with no area, which paints nothing. Snap Curves To Lines straightens more outlines, so it leaves out more of these. Without Fills, the region's 1 px stroke draws it, and it is kept. Code-drawn tests in `crates/trace`.
|
||||
@@ -1430,11 +1445,13 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
Object › Live Paint › Merge adds the other selected paths and Live Paint groups to the bottom selected Live Paint group ([Live Paint groups](https://web.archive.org/web/20241230205225/https://helpx.adobe.com/illustrator/using/live-paint-groups.html)), which keeps its id, the paint of its faces and edges, and its name, lock, visibility, transparency, appearance, opacity mask and graphic style link. Object › Live Paint › Make with a Live Paint group selected, and a Live Paint Bucket click on a selected path beside a selected Live Paint group, add the paths to that group the same way. Make, Merge and the Live Paint Bucket take paths, compound paths and groups of them; with type, an image or another object among the selection they report that it has to be converted to paths first and change nothing, as type and raster images can't go into a Live Paint group directly ([Create Live Paint groups](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/learn-painting-basics/create-live-paint-groups.html)); before, such an object went among the group's hidden sources and vanished from the canvas. Evidence: `tests_build::live_paint_refuses_type_and_images_and_changes_nothing`.
|
||||
With the Live Paint Bucket selected, Alt-click on vector art samples its fill, stroke and stroke weight into the paint defaults ([Paint with the Live Paint Bucket tool](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/learn-painting-basics/paint-with-the-live-paint-bucket-tool.html)). On a placed image it samples the image pixel as a solid fill with no stroke. Alt+Shift-click samples only the color under the pointer, including an intermediate gradient color or image pixels, into the active fill or stroke ([Default keyboard shortcuts](https://helpx.adobe.com/illustrator/using/default-keyboard-shortcuts.html)). Neither click paints or changes the selection or selected art, and the next Bucket click paints with the sampled paint. Evidence: `tests_build::live_paint_bucket_alt_sample_paints_next_face_without_changing_selection`.
|
||||
Double-clicking the Live Paint Bucket opens Live Paint Bucket Options ([Paint with the Live Paint Bucket tool](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/learn-painting-basics/paint-with-the-live-paint-bucket-tool.html)): Paint Fills (on) and Paint Strokes (off) set whether a click paints faces, edges or both, Highlight turns the outline of the face or edge under the pointer on or off, and Color and Width set it (red and 4 px by default). Faces are outlined at the Width and edges at half of it, as the page says faces are highlighted with a thick line and edges with a thin line. With both on, a click paints the edge within 4 px of the pointer, else the face, and Shift switches to Paint Fills only; with one on, Shift switches to the other. The options last across tool switches and are saved with the preferences (`tool.setOption {tool: "livePaintBucket"}`). Evidence: `builder::tests::{bucket_options_choose_what_a_click_paints, bucket_options_set_the_highlight, bucket_highlights_an_edge_thinner_than_a_face}`, `dialogs::live_paint_bucket::tests::double_clicking_the_tool_opens_its_options_and_ok_sets_them`.
|
||||
Live Paint Bucket Options has Cursor Swatch Preview, as the [help page](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/learn-painting-basics/paint-with-the-live-paint-bucket-tool.html) lists: with the Bucket selected, the active fill or stroke shows above the pointer between the color swatches before and after it in the Swatches panel, and the Left and Right arrow keys pick the swatch before or after it, as the page describes. The selected art keeps its paint. As VectorCraft's own rules, the option is on at first, the arrows step the stroke when the Stroke proxy is in front, they wrap around at the ends and still step with the preview off, a color that is no swatch shows alone until Right picks the first swatch or Left the last, and the arrows do nothing during a fill drag or with no color swatch. Evidence: `tests::build::{live_paint_bucket_arrow_keys_step_the_active_paint_through_the_swatches, live_paint_bucket_arrow_keys_handle_unmatched_paint_few_swatches_and_drags, live_paint_bucket_arrow_keys_pass_swatches_of_the_same_color_for_fill_and_stroke, swatch_arrow_keys_leave_modified_arrows_to_the_shortcuts}`.
|
||||
Live Paint Make preserves the front-most covering source's fill when compound paths share a curved boundary, and Expand keeps the face fills. Regression evidence: `planar::tests::coincident_curves_keep_their_source_faces` checks source order, winding, fill rules and nearby boundaries; `tests::build::live_paint_make_and_expand_keep_abutting_compound_colors` checks native compound paths, Make, Expand and Undo/Redo. This preserves VectorCraft's source-fill rule without changing arrangement precision.
|
||||
Live Paint Gap Options (Object › Live Paint › Gap Options…, `livePaint.gapOptions`): with Gap Detection on, paint stops at the gaps that run from a loose end of a path to the nearest path, up to Small (3 pt), Medium (6 pt), Large (12 pt) or a custom size; Close Gaps With Paths adds an unpainted path across each gap; Preview applies the options live and draws the gaps in the Gap Preview Color. The options are saved, copied and undone with the group, and Merge keeps the bottom group's options when its Gap Detection is on, or else turns Gap Detection on with Small when another merged group has it on. When Gap Detection is off in every merged group, it stays off.
|
||||
View › Show Live Paint Gaps (`view.livePaintGaps`) draws the gaps of the selected Live Paint groups up to their Paint Stops At size, each in its group's Gap Preview Color, until Hide Live Paint Gaps or Hide Edges hides them ([Live Paint gaps](https://web.archive.org/web/20260105111201/https://helpx.adobe.com/illustrator/desktop/paint-and-fill/learn-painting-basics/find-and-close-gaps-in-live-paint-groups.html)).
|
||||
Double-clicking the Live Paint Selection tool opens its Tool Options ([Live Paint Selection tool options](https://web.archive.org/web/20250904012025/https://helpx.adobe.com/illustrator/using/selecting-objects.html)): with Select Fills off, a click selects an edge instead of a face; with Select Strokes off, Alt-click selects a face instead of an edge; Color and Width set the color and width of the highlight on the face or edge under the pointer (red and 4 px by default). The options last across tool switches and are saved with the preferences (`tool.setOption {tool: "livePaintSelection"}`).
|
||||
As VectorCraft's own rule, OK in Live Paint Selection Tool Options, Live Paint Bucket Options, Gap Options and Tile Edge Color gives an error for a color with an alpha part (`#rrggbbaa` or `#rgba`) and changes nothing.
|
||||
As VectorCraft's own rule, a Live Paint edit that changes nothing records no undo step, keeps the redo steps and leaves a saved document saved: a Live Paint Bucket click or drag over faces that already have the fill, a stroke on an edge that already has the paint and weight, Gap Options OK with the options the groups have and no gap to close, and Make or Merge with one Live Paint group alone. Such a fill or stroke also leaves the recent colors as they are. Regression tests: `live_paint_fill_same_paint_is_no_op`, `live_paint_bucket_click_with_the_face_paint_is_no_op`, `live_paint_stroke_edge_same_paint_and_width_is_no_op`, `live_paint_gap_options_same_values_are_no_op`, `live_paint_gap_options_close_without_gaps_is_no_op`, `live_paint_make_existing_group_is_no_op` and `live_paint_merge_single_group_is_no_op` in `crates/engine/src/tests/build.rs`, and `ok_on_unchanged_options_records_no_undo_step` in `crates/ui-egui/src/dialogs/live_paint_gaps.rs`.
|
||||
As VectorCraft's own rule, `tool.setOption` for the Live Paint Bucket and the Live Paint Selection tool, chosen or not, checks every value before it sets any: a switch that is not `true` or `false`, a `color` that is not an RGB color or a layer color's name, or that has an alpha part, a `width` that is not a number and an option the tool does not have give an error naming the option, and nothing is set or saved. A `width` outside 1 to 20 px is still set to the nearest end of that range. Saved settings that hold an invalid value still load, and the tool keeps its default for that option. Evidence: `tests::build::{live_paint_tool_options_refuse_invalid_values_and_change_nothing, live_paint_tool_options_take_rgb_colors_and_clamp_the_width, live_paint_tools_load_saved_settings_with_invalid_values}`.
|
||||
As VectorCraft's own rule, `tool.setOption` for the Shape Builder, chosen or not, checks every value the same way: a switch that is not `true` or `false`, a `pickColorFrom` or `selection` that is not one of its names, a `gapLength` that is not a number, a `highlightColor` that is not an RGB color or a layer color's name, or that has an alpha part, and an option the tool does not have give an error naming the option, and nothing is set or saved. A `gapLength` outside 0 to 72 pt is still set to the nearest end of that range. Evidence: `tests::build::{shape_builder_tool_options_refuse_invalid_values_and_change_nothing, shape_builder_tool_options_take_valid_values_and_clamp_the_gap}`.
|
||||
A drag of 3 screen pixels or more with the Live Paint Selection tool draws a marquee and selects the faces and edges it touches, partly enclosed ones included, and a Shift-drag adds them to the selection or removes them from it ([Modify Live Paint groups](https://web.archive.org/web/20261006115247/https://helpx.adobe.com/illustrator/desktop/paint-and-fill/learn-painting-basics/modify-live-paint-groups.html)). A click and a marquee change the selection on release, and Escape before the release leaves the selection as it was. Locked Live Paint groups, those on a locked layer or artboard, and in isolation mode those outside the isolated art are not highlighted or selected.
|
||||
@@ -1647,12 +1664,13 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
A `.ai` opened from its editing data opens its Objects on Path groups live, with their path, their objects in order along it, Pivot and Rotate, and their art where the file draws it; a group whose spacing has been dragged, or with options an Objects on Path group doesn't hold, opens as a plain group (`crates/eps/src/import/ai/tests.rs`).
|
||||
`.ai` symbol definitions and placed instances open as live symbols, in the Symbols panel's order; an instance of a symbol that isn't read, or whose appearance differs from its symbol's, comes in as the page draws it (`crates/eps/src/import/ai/tests.rs`).
|
||||
In a `.ai` opened from its editing data, an object in a pattern's art or a brush's art with an art style VectorCraft reads opens as itself with its effects live, as an object on a layer does, and an object in a pattern's art keeps the id of a graphic style in the file's list (`crates/eps/src/import/ai/tests.rs`).
|
||||
A graph in a `.ai` whose records have the shape and values the published version 7 specification gives ([the specification](https://13thmonkey.org/documentation/fonts/AI7FileFormat.pdf), printed pp. 109–112 and 146–158) opens as a live grouped column, stacked column, line or area graph with its saved art, table, axes and settings, and Graph Data edits it ([the help page](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/visualize-data/add-graph-data.html)); other graphs keep their art as plain objects with a note, and saving a graph to `.ai` warns that its data and settings aren't written (`crates/eps/src/import/ai/tests.rs`, `crates/engine/src/cmd/graph/tests.rs`).
|
||||
Blends and envelopes in the definitions of a `.ai`'s symbols, patterns and brushes' art count against the same per-file limits on blend layout and envelope checks as the layers' art, so a file with many definitions does not get those limits again for each one (`crates/eps/src/import/ai/read/directives.rs`).
|
||||
A `.ai` or EPS whose editing data has brushes opens with the file's Calligraphic, Scatter, Art and Bristle brushes in the Brushes panel in place of the default ones, in the file's order: the Calligraphic size, roundness and angle with their variation, the Scatter size, spacing, scatter and rotation, the Bristle settings, and the Scatter and Art brushes' art (Art brushes in the older and newer forms of their objects). A brush library `.ai` (brushes and no layers) opens from its PDF part with its brushes, so Other Library lists them. An Art brush in Tints keeps that colorization. Pattern brushes and brushes that can't be read are left out with a note. Paths with a Calligraphic brush, and paths with an Art brush in the newer form at 100% in Tints that stretches art of solid-filled paths unflipped, open as the path with the brush on its stroke. Paths with an Art brush in the older form, and other brushed paths, still come in as their drawn look (part of #372 and #637; `crates/eps/src/import/ai/tests.rs`, `crates/eps/src/import/tests_native.rs`).
|
||||
In a `.ai` opened from its editing data, a path or type object with Offset Path, Outline Object or Outline Stroke on the whole object opens as itself with those effects live, in their order and shown or hidden; on a fill or stroke of type they stay on that fill or stroke. Offset Path keeps its Offset, Joins and Miter Limit, and Outline Stroke takes its width from the stroke. An Offset Path with a setting missing, out of range or not read keeps the drawn art, as does a path with a Path effect on one fill or stroke (`crates/eps/src/import/ai/style/tests.rs`, `crates/eps/src/import/ai/tests.rs`, `crates/eps/src/import/tests_native.rs`).
|
||||
In a `.ai` or EPS opened from its editing data, a Scatter brush whose last 15 numbers start with 1 comes into the Brushes panel in Tints, and each brush art section is read without its frame, an unnamed, unpainted rectangle with no settings of its own at the art's bounds (within 1/1000 pt). A wider frame stays in the art, and an art group with a state or look of its own (hidden, locked, isolated, knockout, an opacity, a blend mode, a name, a mask, a note or an appearance) stays a group (`crates/eps/src/import/ai/tests.rs`).
|
||||
In a `.ai` opened from its editing data, type with Warp on the object or on one of its fills or strokes opens as type with the effect live when the live warp draws as the art saved with it. When it draws differently, or when the file's limit of checks has no check left for it, it opens as that art, and one note says how many did. Type stays live without a comparison when the saved art paints nothing or draws type of its own, in frames of threaded type, when a text variable binds it, and when its text object doesn't come in as one text object (`crates/eps/src/import/ai/envelope.rs`, `crates/eps/src/import/tests_native.rs`).
|
||||
In a `.ai` opened from its editing data, an object with a Tweak that moves nothing or Pucker & Bloat at 0 opens as itself with the effect live. A path, compound path or group whose only effect is Transform without copies, or a Free Distort whose corners make a parallelogram, opens as itself with it live, and so does an object with nothing stroked whose only effect is Twist: a path or compound path with straight segments at up to 180° either way, and another path, compound path or group with no guide in it at up to 90° either way (limits VectorCraft sets); one twisted further keeps the drawn art. A gradient or pattern, an image, type, a clipping group, an opacity mask or effects inside the object, or a stroke with a Transform that scales, rotates or reflects, keep the drawn art (`crates/eps/src/import/ai/style/tests.rs`, `crates/eps/src/import/ai/tests.rs`, `crates/eps/src/import/ai/read/ops.rs`).
|
||||
In a `.ai` opened from its editing data, an object with a Tweak that moves nothing or Pucker & Bloat at 0 opens as itself with the effect live. A path, compound path or group whose only effect is Transform without copies, or a Free Distort whose corners make a parallelogram, opens as itself with it live, and so does an object with nothing stroked whose only effect is Twist: a path or compound path with straight segments at up to 180° either way, unless it is a compound path with a guide member that reaches past its other members and the angle is not 0°, and another path, compound path or group with no guide in it at up to 90° either way (limits VectorCraft sets); one twisted further keeps the drawn art. A gradient or pattern, an image, type, a clipping group, an opacity mask or effects inside the object, or a stroke with a Transform that scales, rotates or reflects, keep the drawn art (`crates/eps/src/import/ai/style/tests.rs`, `crates/eps/src/import/ai/tests.rs`, `crates/eps/src/import/ai/read/ops.rs`).
|
||||
A PDF page whose `UserUnit` (PDF 1.6) is above 1 opens at its size in points, its numbers times the `UserUnit` (one above 75,000 counts as 75,000), and `document.pdfInfo` gives its size and boxes in points too. A `.ai` whose editing data has its artboards in the units of such a page opens from that data at the page's size, with its layers, and when the layers can't be read its pages still take the artboard layout of the data, scaled the same way (part of #1482).
|
||||
`document.open`, `file.place` and `document.pdfInfo` reject a `cropTo`, `crop`, `password`, `colorMode` or `textAs` that is not a string, such as `"textAs": true`, and `document.pdfInfo` rejects a `thumbnailSize` that is not a number; the error names the param, and nothing opens or is placed. A param left out or given as null keeps its default (`crates/engine/src/cmd/fileio/tests_pdfimport.rs`).
|
||||
When the PDF content of a `.ai` has a page for each artboard, the layers are compared with every page on its artboard (until the pages compared take 8,388,608 pixels at the comparison's scale, about 67 letter-size pages, or number 128): art that only the layers or only a later page draws is handled as art that differs on the first page is, and a text object that a later page doesn't draw is left out unless its layer doesn't print (`crates/eps/src/import/tests_native.rs`).
|
||||
@@ -1844,6 +1862,8 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
|
||||
- **Brush art of copies:** symbol instances, inline graphics and repeat copies of a brushed path keep their own brush art between frames, as the same path on the page does. The renderer also keeps the stroke outlines of brush art and the evaluation of a live object in it, such as an envelope that a scatter brush places. The brush art is made again when the path, its stroke or the brush changes, and when the art of a symbol or pattern that the brush art can show changes. On one thread at 1000 × 1000 pixels (the median frame, with the median fastest frame in brackets), 2,000 paths on the page whose scatter brush art is an envelope take 94 ms (80 ms) a frame instead of 400 ms (306 ms), and 2,000 instances of a symbol whose art is a brushed path take 13.4 ms (12.0 ms) instead of 19.3 ms (15.6 ms), with the same pixels.
|
||||
|
||||
- **Two brushes with one name:** when a document stores two brushes with the same name, a stroke that names it draws on the canvas with the first of them, as `brush.get`, Brush Options, expanding, outlining and the SVG, PDF, EPS and `.ai` exports take it. Document Info gives that brush's type, and the Brushes panel's row of that name previews and drags the first brush. Reading the library numbers the second brush ("Name 2"), so the panel lists it in a row of its own that shows it.
|
||||
|
||||
- **Live objects in symbols and masks:** symbol instances and inline graphics whose symbol is a blend, an envelope, a repeat, an Intertwine object or a gradient mesh, or a group that holds one, draw the evaluation the renderer keeps for that object between frames, as the same object on the page does. So do opacity masks whose art is such an object, and such objects in clip groups in Outline view. The object is evaluated again when the symbols, patterns, fonts or color settings it shows change. Symbol art with effects of its own, or that holds a symbol instance, an image, a placed file, type with an inline graphic or a raster effect, is still placed and evaluated again in every frame. At 1000 × 1000 pixels, a page of 2,000 instances of a symbol that holds an envelope takes 28 ms a frame instead of 126 ms, with the same pixels.
|
||||
|
||||
- **Live objects in documents with many symbols:** a live object, or an object with effects, that shows symbols or patterns is not walked again in a later frame to find them while the document's symbols and patterns stay the same. One that shows a placed file is walked in every frame. At 1000 × 1000 pixels, a page of 2,000 envelopes around instances of the last 2,000 of 10,000 symbols takes 30 ms a frame, and 83 ms when every frame walks them again, with the same pixels.
|
||||
@@ -2072,6 +2092,9 @@ Corners section in the Anchor Inspector sets the radius and kind, counts the sel
|
||||
Set Corners… (in the submenu and the Corners section) sets the radius and kind with Preview, on all the chosen anchors
|
||||
or only the odd- or even-numbered ones (`every`, #5546), and only the corners whose angle is in a range
|
||||
(`minAngle`/`maxAngle`, #5545).
|
||||
`cornerSet` and `cornerRemove` refuse an `items` member key other than `id` and `anchors`, and `items` given with `ids`;
|
||||
saved steps still play (`corner_commands_refuse_an_unknown_item_key`, `corner_commands_refuse_items_with_ids`,
|
||||
`saved_corner_steps_with_older_item_keys_still_play`).
|
||||
Slide Anchor Along Path drags an anchor along its curve, the two segments beside it refitted by the keep-shape kernel
|
||||
(Shift: where the tangent is a multiple of 45°). Commands `addon.pathtools.cornerSet`, `cornerRemove` and `slideAnchor`,
|
||||
each one undo step; `vectorcraft_pathops::addons::pathtools::slide_anchor`. Tests: `addons::pathtools` in
|
||||
|
||||
Reference in New Issue
Block a user