Merge main into fix/graph-series-group-opacity

This commit is contained in:
dotCooCoo
2026-11-14 07:11:27 -08:00
188 changed files with 10850 additions and 1075 deletions
+2 -2
View File
@@ -125,7 +125,7 @@ On GNOME/Wayland, enable **Preferences › User Interface › 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:
- **Clipboard:** under Wayland arboard talks to the compositor through the data-control protocol (wlroots compositors such as Sway and Hyprland, KDE Plasma), so bitmaps (`image/png`), SVG markup and text copied in any app paste (#398). Where the compositor lacks the protocol (GNOME's Mutter, [arboard#223](https://github.com/1Password/arboard/issues/223)), arboard falls back to the X11 clipboard through XWayland, which only holds what X11 apps copied. Where there is no X11 either (the Flatpak on a Wayland session: `--socket=fallback-x11` gives it none), Copy and Paste use the compositor's core data-device protocol (`wl_data_device`) on the window's own connection, and only while the window has focus. One Copy offers the PNG as `image/png`, the SVG as `image/svg+xml` (with Include SVG Code on) and the text as `text/plain;charset=utf-8`, `UTF8_STRING` and `text/plain`; a format with no data is not offered. Paste reads `image/svg+xml`, then text, then `image/png`, and blank text or text that only names a picture gives way to the PNG; the Paste menu item is enabled by the types offered, without reading any data. Whether the clipboard still holds VectorCraft's Copy is told by its data source, which the compositor cancels when another app copies. A read takes 64 MiB at most and fails beyond that. Reads run on a worker thread: text waits 2 s at most on the UI thread, SVG and PNG 10 s on the paste's background thread. An owner that never sends its data costs one read its wait, and later reads return at once until it answers. When a text read gets no answer in its 2 s, the paste waits on its background thread for that read's answer, up to 10 s after the read was sent, then reads the clipboard again unless it holds VectorCraft's Copy. Another app's paste of a Copy is sent on a thread of its own, 8 at once at most; a paste beyond them gets nothing. A clipboard neither backend opens is tried again after 1 s, doubling to a minute (a Copy or Paste of the user's at most once a second), and logged once when it goes and once when it comes back: before, the background Paste check reconnected and logged a warning every 250 ms. egui's own text paste into fields goes through smithay-clipboard and works either way.
- **Clipboard:** under Wayland arboard talks to the compositor through the data-control protocol (wlroots compositors such as Sway and Hyprland, KDE Plasma), so bitmaps (`image/png`), SVG markup and text copied in any app paste (#398). Where the compositor lacks the protocol (GNOME's Mutter, [arboard#223](https://github.com/1Password/arboard/issues/223)), arboard falls back to the X11 clipboard through XWayland, which only holds what X11 apps copied. Where there is no X11 either (the Flatpak on a Wayland session: `--socket=fallback-x11` gives it none), Copy and Paste use the compositor's core data-device protocol (`wl_data_device`) on the window's own connection, and only while the window has focus. One Copy offers the PNG as `image/png`, the SVG as `image/svg+xml` (with Include SVG Code on) and the text as `text/plain;charset=utf-8`, `UTF8_STRING` and `text/plain`; a format with no data is not offered. Paste reads the files a file manager copied (`text/uri-list`, else `x-special/gnome-copied-files`; local `file:` URIs only, 1,024 at most), then `image/svg+xml`, then text, then `image/png`, and blank text or text that only names a picture gives way to the PNG; the Paste menu item is enabled by the types offered, without reading any data. Whether the clipboard still holds VectorCraft's Copy is told by its data source, which the compositor cancels when another app copies. A read takes 64 MiB at most and fails beyond that. Reads run on a worker thread: text waits 2 s at most on the UI thread, file lists, SVG and PNG 10 s on the paste's background thread. An owner that never sends its data costs one read its wait, and later reads return at once until it answers. When a text read gets no answer in its 2 s, the paste waits on its background thread for that read's answer, up to 10 s after the read was sent, then reads the clipboard again unless it holds VectorCraft's Copy. Another app's paste of a Copy is sent on a thread of its own, 8 at once at most; a paste beyond them gets nothing. A clipboard neither backend opens is tried again after 1 s, doubling to a minute (a Copy or Paste of the user's at most once a second), and logged once when it goes and once when it comes back: before, the background Paste check reconnected and logged a warning every 250 ms. egui's own text paste into fields goes through smithay-clipboard and works either way.
- **Clipboard owners that never answer (#510):** reading the clipboard waits on the app that owns it: arboard gives up on an X11 owner after 4 s for each format it tries, and a Wayland read waits for the owner to send its data. So on Linux the check that enables the Paste menu items runs on a background thread with a second clipboard handle (`crates/ui-egui/src/clipboard_probe.rs`, installed as `Services::clipboard_probe`), only while nothing is copied in the app and a document is open, and the window keeps drawing. Every arboard read on Linux and the BSDs, including the UI thread's (a paste, and a Copy or Cut checking what the clipboard held), runs on a worker thread with a handle of its own and waits 2 s at most: an owner that never sends its data costs one read that wait, and later reads fail at once until it answers. A paste's bitmap read waits up to 10 s on the paste's background thread, so the UI thread does not wait for it. When one of a paste's reads gets no answer in its 2 s, or a paste follows a read that has not been answered yet, such as the paste's own check whether the clipboard still holds what VectorCraft copied, the paste waits on that thread for that read's answer, up to 10 s after the read was sent, and pastes what it holds. When the answer is what VectorCraft copied, holds nothing to paste, or does not come, the paste takes the internal clipboard. On X11, quitting within 25 s of a read that got no answer waits for that read to end, so the app's own handle is the last one and hands what it copied to the clipboard manager when one runs. That includes a read of the Paste menu check's handle: quitting waits up to 27 s for the background thread to drop it before the app drops its own, and quits after that wait even when the handle has not been dropped. The app takes its windows off screen before these waits (`apps/vectorcraft/src/quit_windows.rs`). An X11 main window, an XWayland one included, is hidden. winit cannot hide a native Wayland window, so on Linux the app attaches no buffer to the main window's surface, which unmaps it while the window and its connection stay open for the Wayland clipboard. On Linux the X11 windows of floating panels and documents are unmapped through a second X11 connection. On native Wayland, floating panels and documents are normally drawn inside the main window; on the BSDs a native Wayland main window stays on screen until the waits end. Windows and macOS keep the check on the UI thread: Windows only asks which formats the clipboard holds, macOS asks the pasteboard server.
- **Copied files:** files copied in a file manager (`text/uri-list`; `CF_HDROP` on Windows, file URLs on macOS) paste as the first one that is art (SVG, PDF, EPS, EMF/WMF or a bitmap; a `.ai` or `.ait` file from the editing data it holds, else as the PDF or PostScript it holds), before the clipboard's other formats (which include the files' paths as text).
- **Dropping files on the window does not work under Wayland:** winit 0.30, which eframe 0.37 runs on, has no Wayland drag and drop ([winit#1881](https://github.com/rust-windowing/winit/issues/1881), added in winit 0.31; [egui#1563](https://github.com/emilk/egui/issues/1563)), so no `dropped_files` arrive. Until eframe moves to winit 0.31: copy the files in the file manager and paste them, use File › Place or Open, or open the window through XWayland, where drops work: set **Preferences › Performance › Linux Display Server** to **X11 (XWayland)** and restart (#1151), or start the app with `WAYLAND_DISPLAY= vectorcraft`. The preference (`linuxDisplayServer`, read at startup in `apps/vectorcraft/src/main.rs`, shown on Linux only) has winit open the window on X11 (`EventLoopBuilderExtX11::with_x11`) when the session is Wayland, `DISPLAY` is set and the X11 libraries winit loads are installed (`apps/vectorcraft/src/xwayland.rs` reads `ldconfig -p` and the usual library directories); otherwise the window opens on Wayland and the log says why. Unlike clearing `WAYLAND_DISPLAY`, it leaves the clipboard on the compositor's own.
@@ -297,7 +297,7 @@ other `sv-*` locale resolve to it), Georgian (`ka`, complete; `ka-GE` and `ka_GE
placeholders are translated in turn (the reason after `: {e}` is often a message too). A literal brace in a
row is written `{{` or `}}`, in the English and in the translation: a message made with `format!` keeps the
doubled braces of its format string, and a plain string literal has each of its braces doubled, so the row for
`"expected {\"objects\": [...]}"` is `expected {{"objects": [...]}}`. Czech, German, Greek, Spanish, French, Georgian, Hungarian, Italian, Japanese, Korean, Polish, Brazilian Portuguese, Russian, Simplified Chinese, Traditional Chinese, Swedish, Ukrainian, Vietnamese, Finnish, Turkish, Catalan and Dutch
`"expected {\"objects\": [...]}"` is `expected {{"objects": [...]}}`. Czech, German, Greek, Spanish, French, Georgian, Hindi, Hungarian, Italian, Japanese, Korean, Polish, Brazilian Portuguese, Russian, Simplified Chinese, Traditional Chinese, Swedish, Ukrainian, Vietnamese, Finnish, Turkish, Catalan and Dutch
translate status and error messages (`COMPLETE_MESSAGES` in `i18n::tests`); the untranslated report lists the
message literals the scan finds, and the phrases a parameter schema's error builds at run time
(`SCHEMA_PHRASES`), that one of them has no row for. The scan covers the crates in `MESSAGE_CRATES`, the
+2 -1
View File
@@ -66,7 +66,8 @@ Measurements follow the art they measure through moves, scaling and anchor and h
undo and redo included. When the art is reflected, the line of a linked linear dimension goes to
the reflected side, as far past the outermost point as before. This does not happen for art whose
anchors and handles all lie on one line, such as a straight line, which a half turn puts in the
same place as a reflection. Deleting the art, changing its number of anchors or whether it is
same place as a reflection. An unlinked aligned dimension that is reflected, or scaled by a
negative factor, has its line on the reflected side of its points. Deleting the art, changing its number of anchors or whether it is
closed, turning an angle's arm into a curve, or making a measured circle or arc no longer circular
leaves its dimensions where they were, no longer linked, in the same undo step, rather than
attaching them to a different edge. Undo links them again. A linked dimension moved on its own
+1 -1
View File
@@ -285,7 +285,7 @@ Names in the editing data that aren't UTF-8 (layers, objects, artboards, colors,
| EPS | open, place, save | yes (own PostScript L3 interpreter, Illustrator EPS editing data structure) | yes (L2/L3, TIFF previews) | CIDFonts the file doesn't carry not drawn, but for those over a predefined CMap (`UniJIS-UCS2-H`, `90ms-RKSJ-H`, `GBK-EUC-H`, `KSCms-UHC-H`, `ETen-B5-H`), set as type in the font of the CIDFont's name, vertical over a `-V` CMap; a name that ends in the row-and-cell CMap `H` or `V` splits off the CMap only when the file defines the CIDFont of that name, or the name has a hyphen and an installed face that covers Japanese has it; name-keyed fonts in a FontSet set as type by name; #505; images encoded with `CCITTFaxDecode` (ITU-T T.4 Group 3 and T.6 Group 4, with `K`, `Columns`, `Rows`, `EndOfBlock`, `EndOfLine`, `EncodedByteAlign` and `BlackIs1`) draw, and damaged data keeps the rows decoded before its first damaged row; Type 42 (TrueType) fonts set type at its size (#1553); an embedded Type 1 font's encrypted part is read for its glyphs, which space its type, outline it and draw glyphs without a character, in plain and composite fonts; a Type 42 font that carries its TrueType font gives each code its character by its glyph name or, for names that say nothing (`/g12`), by the glyph's entry in the font's own character map, spaces its type by its own widths and draws glyphs that stand for no character from its outlines; the show operators' spacing along the baseline (`ashow`, `widthshow`, `xshow`, `yshow`, `xyshow`, and the moves of `kshow`'s procedure, run between each two characters) is kept on live type as tracking, so type in a font that isn't installed keeps the file's line lengths (spacing that moves characters off the baseline, as `yshow`, `xyshow` or a `kshow` procedure can, places each character as its own text object); composite (Type 0) fonts with the 8/8 mapping, as PDF-to-PostScript converters write two-byte fonts, draw a Type 42 descendant's glyphs from the TrueType outlines it carries and an embedded Type 1 descendant's from its charstrings, and set other descendants' characters as type at the composite font's size (other mappings are still set as type in the font of their name); CID-keyed fonts (`composefont`, `FMapType` 9 over a CMap built with the CIDInit operators or `Identity-H`/`Identity-V`; `bfchar` and `bfrange` mappings give a base-font descendant its codes or glyph names) draw the glyphs of the Type 0 CIDFonts (Type 1 charstrings in their `StartData` binary data or `GlyphDirectory`) and Type 2 CIDFonts (TrueType glyphs through `CIDMap`) they carry, and the CID-keyed fonts of a FontSet's Compact Font Format data (Type 2 charstrings); a clip only counts as covering the page when its shape does (#1542); an EPS another app copied pastes as editable vector art (`clipboard.importEps`, #1499); a stitched shading keeps its hard colour changes on import (#1654); sampled functions (type 0) interpolate between their samples, multilinearly or by cubics with `Order 3`, and a sampled axial or radial gradient has a stop at each sample; a gradient the page paints as a row of abutting one-colour strips (as Level 2 writers draw smooth shades) imports as one linear gradient, without the seams the strips leave when each is drawn alone; CMYK images, CMYK JPEGs included, keep their ink amounts on import, as from PDF, and the pixels a `MaskColor` or `ImageType 3` mask hides become a grayscale opacity mask; ruzstd 0.9.1 for compressed editing data (#1807, RUSTSEC-2026-0344) |
| PostScript `.ps` | open, place | yes (the EPS reader reads its first page; `.epsf` files open and place as EPS) | via Print to PostScript | `tests_epsimport.rs` |
| DCS 1.0 / 2.0 | place linked | place linked only (one image of the plates; spot plates as spot swatches; the composite's clipping path; each plate on its own ink in Separations Preview and print separations) | no | `crates/eps/src/dcs/tests.rs`, `crates/engine/src/tests/dcs.rs` |
| SVG / SVGZ | open, place, save | yes | yes (SVG Options, Preserve Editing, symbols, filters, rich text) | strongest format; tests in `crates/svg/tests`; text on a path follows basic shapes as their SVG 2 equivalent paths (#1527); CSS transforms and the `font` shorthand (#1565), percentage lengths in symbols (#1596), Inkscape flowed text as area type (#1568) and Inkscape pages as artboards (#1601) import; an unsupported filter is named in its warning (#1598); an artboard exported on its own (Export As with Use Artboards, Export for Screens, Asset Export) has the artboard's name as `<title>`, Save the document's (#3544); attributes in other applications' XML namespaces (`plotter:pen="2"`) kept on their objects from import to export, as `data-*` attributes are (`crates/svg/tests/it/foreign_attributes.rs`); simple shapes export as `<rect>`, `<circle>`, `<ellipse>`, `<line>`, `<polygon>` and `<polyline>` where they draw the same as the path (#4652, `crates/svg/tests/it/basic_shapes.rs`); the regions of exported masks and filters (opacity masks, inverted masks, knockout groups) cover the art they apply to, and over type keep a region that covers any artwork (#6401, `crates/svg/tests/it/blend_export.rs`); SVG Options › Include Variable Data writes the text variables, data sets and bound type objects, and opening the SVG reads them back (`tests::variables::an_svg_with_variable_data_opens_with_its_variables_data_sets_and_bindings`) |
| SVG / SVGZ | open, place, save | yes | yes (SVG Options, Preserve Editing, symbols, filters, rich text) | strongest format; tests in `crates/svg/tests`; text on a path follows basic shapes as their SVG 2 equivalent paths (#1527); CSS transforms and the `font` shorthand (#1565), percentage lengths in symbols (#1596), Inkscape flowed text as area type (#1568) and Inkscape pages as artboards (#1601) import; an unsupported filter is named in its warning (#1598); an artboard exported on its own (Export As with Use Artboards, Export for Screens, Asset Export) has the artboard's name as `<title>`, Save the document's (#3544); attributes in other applications' XML namespaces (`plotter:pen="2"`) kept on their objects from import to export, as `data-*` attributes are (`crates/svg/tests/it/foreign_attributes.rs`); simple shapes export as `<rect>`, `<circle>`, `<ellipse>`, `<line>`, `<polygon>` and `<polyline>` where they draw the same as the path (#4652, `crates/svg/tests/it/basic_shapes.rs`); the regions of exported masks and filters (opacity masks, inverted masks, knockout groups) cover the art they apply to, and over type keep a region that covers any artwork (#6401, `crates/svg/tests/it/blend_export.rs`); a masked group, or a knockout group's masked group, whose content has a shadow, glow, blur or feather starts with a hidden, unpainted rectangle over the mask's region, so readers that draw a masked group only inside the box of its shapes draw those effects too (`crates/svg/tests/it/blend_export.rs`); SVG Options › Include Variable Data writes the text variables, data sets and bound type objects, and opening the SVG reads them back (`tests::variables::an_svg_with_variable_data_opens_with_its_variables_data_sets_and_bindings`) |
| DXF | open, export | yes | yes (R12–2018) | R13–2018 closed SPLINE flags and control-point closure on import verified (#1299); circular cubic paths export as native CIRCLE/ARC where stroke semantics permit; R12 weighted strokes remain POLYLINE while non-circular curves keep the existing fallback (`crates/cad/src/tests.rs`); [Autodesk group 70](https://help.autodesk.com/cloudhelp/2024/ENU/AutoCAD-DXF/files/GUID-E1F884F8-AA90-4864-A215-3182D47A9C74.htm). DXF 2000–2018 LAYOUT objects write the paper image origin as 148/149 (was a stray 158), the shade plot codes (2004+) and the model type flag, and the plot style placeholder carries no subclass marker (#3085; structure test `r2000_and_later_files_have_the_structure_cad_apps_require`, checked with ezdxf's audit; not yet confirmed in Autodesk Fusion). DXF Options' Preset menu and `document.exportDxf`'s `dxfPreset: "cnc"` set the CNC / CAM options (#5500); VCarve QA remains open |
| HP-GL/2 `.plt`, `.hpgl`, `.hgl`, `.hpg` | — | yes (pen moves, pens and widths, line types and attributes, circles, arcs, wedges and Bézier curves, filled and edged rectangles, wedges and polygons, encoded polylines, scaling and rotation; labels, symbol mode, raster images and hatching aren't drawn) | yes (`.plt`: each visible path once along its line, a pen per color or a pen table, type as outlines, clipping applied, HP-GL or HP-GL/2 with pen colors and encoded polylines) | recognized by its first instructions after any printer escapes, under its own extensions or one no other format reads; `crates/cad/src/hpgl/tests.rs`, `crates/cad/src/hpgl/write/tests.rs` (plots read back by the reader), `tests_hpgl.rs`, `import_fuzz.rs` |
| DWG | open, export | no | no | no open spec; DXF instead |
+21 -2
View File
@@ -109,6 +109,24 @@ The trace then uses only the named colors, and white while white is a color of i
color that was not named is traced too: each of its pixels goes to the named color, white or
transparent that has the largest share in the blend of them that comes closest to the pixel.
**Flat Logo with a color between two others.** When a traced color lies between two others, as a gray
lies between black and white, an anti-aliased edge pixel between the outer two is also a blend of the
middle color and one of them. Flat Logo then reads the pixel as the blend of the colors that lie nearest
it in the flat areas within 6 pixels, when the pixel has a neighbor darker and a neighbor lighter than the
middle color, along the line between the other two. A black disc beside a gray square on white traces
with one gray shape, the square, and no gray slivers around the disc, when its edges are sharp or blurred
by up to about half a pixel. An edge blurred by a pixel or more can still leave gray slivers along the
disc, and so can an image with noise of a level or more in its pixels. A gray stroke two or three pixels
wide beside black has no darker pixel next to it and stays gray. A soft-edged gray stroke about two
pixels wide that touches black traces as black and white, and one about three pixels wide that touches
black can lose most or all of its gray when it is short (12 pixels long or less). A line of gray one
pixel wide between black and white stays gray when at least 13 of its pixels touch: such a line and a
straight black-to-white edge whose pixels are as light as the gray give the same pixels, and both
trace as gray. A one-pixel gray line between black and white that is shorter than 13 pixels, falls
between pixels or is blurred traces as black and white. A flat area whose color lies between two named colors, as when the colors are named
some levels off, counts as holding the named colors it is a blend of, and so do the pixels of exactly
its color that touch it.
**Large images.** An image of more than 1500 pixels on a side is traced as any other, only more
slowly, and the trace says so: `imageTrace.make` returns the note in `warnings` and the status bar
shows it (the [results optimization](https://helpx.adobe.com/illustrator/using/image-trace-results-optimization.html)
@@ -118,8 +136,9 @@ most 1024 pixels on a side: a larger decoded raster is averaged down in whole-nu
image is traced at 513, and a 16,000 × 12,000 image, decoded at 9,459 × 7,094, is traced at 946 × 710), and the trace names both sizes in `warnings`. Flat Logo gives that note in place
of the slower-trace note for an image over 1500 pixels and in place of the 64-megapixel note. An image at most
1024 pixels on a side is traced at its own size, also when the named `logoColors` differ slightly from the
image's colors. Only an image with more than 150,000 different pixel values that are not exactly one traced
color is averaged down further: the factor doubles until at most 150,000 remain or the working copy has at
image's colors. Only an image with more than 150,000 different pixel values to unmix (values that are
not exactly one traced color, and values that are, at pixels outside a flat area) is averaged down
further: the factor doubles until at most 150,000 remain or the working copy has at
most 16,384 pixels (at most six times). A trace that would
make more than 8,000,000 anchor points (2,000,000 on the web) is refused to protect memory, with advice:
raise Noise, lower Paths or Colors, or pick a lower-fidelity preset. A trace keeps
+4 -4
View File
@@ -15,7 +15,7 @@ translation never fails a test or a build: the interface shows the English text
`cargo xtask ci` prints the untranslated report (`cargo xtask i18n-report` alone), which lists per language the
strings missing from each catalog with the `complete_menus` flag and the messages missing from each language in
the `COMPLETE_MESSAGES` list. Every non-English language marked "full" has the flag, and all of them except
Bulgarian, Danish and Indonesian are in the list. No language has help content: there is no translated (or
Bosnian, Bulgarian, Danish and Indonesian are in the list. No language has help content: there is no translated (or
English) in-app help, and the docs are English.
**Native review:** every catalog was written clean-room from the English meaning, most of it by agents
@@ -35,7 +35,7 @@ Chinese by `imachus`). Georgian and the original Gujarati catalog are recorded a
| Gujarati | `gu` | 4,673 rows (2026-11-14): original 4,286 unchanged; all 387 additions contributor-reviewed and approved | menus and dialogs; status/error messages partial | installed Gujarati fonts on desktop; optional `Gujr` craft-fonts fallback; no Gujarati face in the pinned CI/release fonts or web startup list | original catalog reviewed by a native speaker; all 387 later additions approved by the contributor, with 11 wording corrections | contributor-reviewed catalog | remaining messages and a bundled Gujarati 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` | 9,166 rows, 3,436 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 178 missing messages for it | all | Latin | no | full | — (review) |
| Portuguese | `pt-br` | 9,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) |
| Portuguese | `pt-br` | 9,378 rows, 3,563 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 55 missing messages for it, which open #7116, #7211, #7330, #7378 and #7405 translate; one/other plurals | all | Latin | contributor is a Brazilian Portuguese speaker; further native review welcome | full | — (review) |
| Indonesian | `id` | 5,279 rows, 750 of them `@msg` (counted 2026-10-21): menus and `tl!` literals complete when counted; its messages are partial; one plural form | dialogs and tooltips all; 750 message rows (French has 796) | Latin | no | full | — (review) |
| Japanese | `ja` | 4,004 / 4,020 (99.6%) | all | CJK UI font as above; Japanese IME; vertical type partial; Japanese crop marks and composition settings | no | full | — (review) |
| German | `de` | 3,952 / 4,020 (98%; menus, literals and messages complete when counted) | all (3,563 `@msg` and 48 `@msgplural` rows, counted 2026-11-13: the untranslated report lists 52 missing messages for it, which open #7116, #7211 and #7378 translate) | Latin | contributor-written, not reviewed | full | — (review) |
@@ -61,9 +61,9 @@ plus review. Native-speaker review is human work and isn't in the hours.
| Hungarian | `hu` | 5,253 rows (counted 2026-10-21): menus, `tl!` literals and messages complete when counted; one plural form | full |
| Polish | `pl` | 9,044 rows, 3,439 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 46 missing messages for it, and 47 menu strings, 26 `tl!` literals, 11 undo labels and 45 swatch names; one/few/many plurals | full; native review pending |
| Finnish | `fi` | 5,318 rows (counted 2026-10-21): menus, `tl!` literals and messages complete when counted; one/other plurals, 797 `@msg` rows | full; AI-assisted, native proofreading pending |
| Czech | `cs` | 9,155 rows, 3,445 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 40 missing messages for it | catalog complete; render-site gaps reduced; native review pending |
| Czech | `cs` | 9,273 rows, 3,560 of them `@msg` and 48 `@msgplural` (counted 2026-11-13): the untranslated report lists 2 missing Czech messages, and 54 messages that no language has a row for | catalog complete; render-site gaps reduced; native review pending |
| Bosnian | `bs` | 5,841 rows (counted 2026-10-30): menus, `tl!` literals and messages complete when counted; one/few/other plurals | full; AI-assisted, native review pending |
| Swedish | `sv` | 5,251 rows, 795 of them `@msg` (counted 2026-10-21): menus, `tl!` literals and messages complete when counted; one/other plurals | full; native review welcome |
| Swedish | `sv` | 8,991 rows, 3,106 of them `@msg` and 48 `@msgplural` (counted 2026-11-14): the untranslated report lists 518 missing messages for it, and 12 menu strings, 1 `tl!` literal and 3 undo labels; one/other plurals | full; native review welcome |
| Bulgarian | `bg` | 5,245 rows, 763 of them `@msg` (counted 2026-10-21): menus and `tl!` literals complete when counted; its messages are partial | full; AI-drafted, native review pending |
| Greek | `el` | 5,251 rows, 795 of them `@msg` (counted 2026-10-21): menus, `tl!` literals and messages complete when counted | full; native review welcome |
| Georgian | `ka` | 5,200 rows (counted 2026-10-21): menus, panels, dialogs, plurals (one count-neutral form) and messages, tested complete; reviewed by a native speaker | full |
+123 -39
View File
@@ -289,7 +289,13 @@ the suite) keep the agent to the folders you give it:
- The preferences that move folders the app reads or writes on its own (`fontsFolder`,
`pluginsFolder`, `recoveryFolder`, `templatesFolder`) can only be set inside the roots. The app's own folders
(preferences, Data Recovery, the User Defined library folders, VectorCraft's Fonts folder) are not
confined: no agent names a path there.
confined. These commands that act on a file there are confined: `stroke.arrowheads.edit` and
`stroke.arrowheads.reload` refuse an arrowheads file outside the read roots, and `stroke.arrowheads.list` gives its
`file` as `null` there (see [Arrowheads](#arrowheads)); `file.newProfiles.edit` needs read and write access to the
New Document profile's file, `file.newProfiles.reset` needs write access, and `file.new` starts with the defaults
when the read roots leave out the profiles folder (see [New Document profiles](#new-document-profiles));
`script.listInstalled` lists the Scripts folder and `ui.runInstalledScript` runs a script only inside a read root
(see [Script engines](#script-engines)).
- The roots must be existing folders; a missing one stops the server with an error. Each flag takes one
folder per use (`--flag <dir>` or `--flag=<dir>`) and may be used again for more.
@@ -678,7 +684,8 @@ CJK composition.
(the selection, or `ids`) and reply `{vertical, ids}`. The writing direction is a setting of the whole thread: the
commands set every frame of a selected frame's thread, and `ids` lists them all. Threading frames gives the thread its
first frame's direction, frames taken out of a thread keep theirs, and a file whose frames of one thread differ opens
with the first frame's direction in all of them.
with the first frame's direction in all of them. When every frame already has the direction, the command records no
undo step.
For SVG/SVGZ, `export`'s top-level `outlineText: true` writes text as paths; DXF takes it too (its type is outlined anyway unless `preserve: editability`).
PDF instead uses `options: {"advanced": {"outlineText": true}}`; its default is false (live text).
@@ -894,13 +901,15 @@ Errors (unknown tool, bad arguments, a disabled or failing command) come back as
`isError: true` and a message. The model can read the message and retry.
Swatches go through `run_command`: `swatch.list` lists every swatch with its colour group, kind and colour;
`swatch.edit {name, newName?, color?, mode?, global?, spot?}` edits one (fills, strokes and text linked to a
`swatch.edit {name, newName?, color?, mode?, global?, spot?, paint?}` edits one (fills, strokes and text linked to a
global or spot swatch follow its colour and name, as one undo step, in the art, opacity masks, symbols, graph
designs, pattern tiles, graphic styles and the art of brushes); `swatch.delete {names, unlink?}` deletes
designs, pattern tiles, graphic styles and the art of brushes). A replacement colour, gradient or pattern given as
`paint` (`{color}`, `{gradient}`, `{swatch}` or `{pattern: name}`) is stored as `swatch.new` stores it;
`swatch.delete {names, unlink?}` deletes
swatches and colour groups in one undo step (art using a deleted global swatch keeps its colour, unlinked).
`swatch.new {color?, mode?, spot?, global?, group?}` saves a colour (into a colour group with `group`), gradient
or pattern (a gradient swatch holds no link to the swatch its gradient came from, and a pattern swatch holds the
pattern untransformed); `swatch.newGroup {fromArtwork: true, toGlobal?, includeTints?}` makes a colour group of the selected
or pattern (a gradient swatch keeps the gradient's aspect, with or without `start` and `end`, and holds no link to
the swatch its gradient came from, and a pattern swatch holds the pattern untransformed); `swatch.newGroup {fromArtwork: true, toGlobal?, includeTints?}` makes a colour group of the selected
art's colours (by default as global swatches the art links to).
`swatch.move {names, to?, group?}` reorders swatches or moves them into or out of a colour group (as dragging
them in the Swatches panel does); give colour group names instead to reorder the groups. Dropping a swatch on art
@@ -2909,14 +2918,18 @@ own layout rules.
Window › Learn and the Explore tutorials button beside the search icon at the right end of the app bar show and hide
the Learn panel. Its For you tab holds a Get started section with a Quick skill guide card; choosing the card opens
the Skills tab. The Skills tab lists VectorCraft's own skills, each with its number of tutorials and an empty progress
ring. Choosing a skill lists its tutorials, choosing a tutorial shows its numbered steps, and Back goes up one level.
the Skills tab. The Skills tab lists VectorCraft's own skills, each with a progress ring and the count of its tutorials
finished of all its tutorials. Choosing a skill lists its tutorials, choosing a tutorial shows its numbered steps, and
Back goes up one level.
The tutorial text is English. `window.learn {show?}` shows the panel (`show: true`), hides it (`show: false`) or
toggles it (`show` omitted or null), and answers whether it shows; Window › Learn and Explore tutorials run it.
The panel counts as hidden while the dock is hidden or a full screen mode hides the panels. Showing it shows a hidden
dock; in a full screen mode it makes Learn the front panel, which shows when the mode ends, and answers false. Any
other value of `show` is an error and changes nothing. `learn.list {}` → `{skills: [{id, title, tutorials: [{id, title, steps}]}]}`, in the order the Skills tab
lists them, where `steps` is the number of steps. `learn.skills {}` shows the panel on its Skills tab with the list of
other value of `show` is an error and changes nothing. `learn.list {}` →
`{skills: [{id, title, done, total, tutorials: [{id, title, steps, finished, completedSteps}]}]}`, in the order the
Skills tab lists them, where `done` is the number of the skill's tutorials finished, `total` the number of its
tutorials, `steps` the number of a tutorial's steps, `finished` whether it is finished, and `completedSteps` the
zero-based indexes of its steps marked done (every step of a finished tutorial). `learn.skills {}` shows the panel on its Skills tab with the list of
skills, with no skill and no tutorial open, as the Quick skill guide card and Back to skills do, and answers what
`learn.list` answers. `learn.show {tutorial}` shows the panel on its Skills tab with that
tutorial's steps → `{skill, tutorial, title, steps: [text]}`. A missing, non-string or unknown `tutorial` is an error
@@ -2926,18 +2939,33 @@ Under a tutorial's steps, View more opens the tutorial's practice sample, a smal
art its steps work on, as a new untitled document that becomes the active one; Save asks where to save it. Once the
sample is open, Finish tutorial marks the tutorial finished. A finished tutorial shows Next Up with the title of the
next tutorial in the same skill, which Next Up shows without opening its sample. A skill's last tutorial, finished,
says so and shows Back to skills instead; Next Up never moves to another skill. Which tutorials are finished is kept
while the app runs, and the skill rings and counts do not show it yet. These are VectorCraft's own rules; the help
page also plays a short video, which VectorCraft does not have. `learn.openSample {tutorial}` runs View more →
says so and shows Back to skills instead; Next Up never moves to another skill. These are VectorCraft's own rules; the
help page also plays a short video, which VectorCraft does not have. `learn.openSample {tutorial}` runs View more →
`{tutorial, index, title}` of the new document, and moves the Learn view to that tutorial; each call opens another
copy and leaves the open documents as they are. `learn.finish {tutorial}` runs Finish tutorial →
`{tutorial, finished: true, next}`, where `next` is the next tutorial's id in the skill, or null after the skill's
last one; the tutorial's sample must have been opened, and finishing it again keeps one entry. `learn.next {tutorial}`
last one; the tutorial's sample must have been opened, and finishing it again keeps one entry, also after a restart
without opening the sample again. `learn.next {tutorial}`
runs Next Up on a finished tutorial and shows the panel on the next one → `{skill, tutorial, title}`; on a tutorial
not finished, or a skill's last tutorial, it is an error. For all three, a missing, non-string or unknown `tutorial`
is an error, and an error changes nothing. Behavior reference:
[Quick skill guide](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/learn-skills-quick-skill-guide.html).
Each step has a check box before its number that shows whether it is done, and a skill's ring fills as its tutorials
are finished, as the help page describes; a finished tutorial has a check mark in its skill's list. A step is marked
done by its check box, which can be changed once the tutorial's sample is open and until the tutorial is finished;
marking every step does not finish the tutorial. Finish tutorial marks all its steps done, and a finished tutorial's
steps stay marked. Reset progress under the list of skills, shown while there is progress, clears every tutorial
finished and every step marked. The desktop app keeps the progress in its preferences, so it lasts to the next start;
when two windows change it, the one that saves last keeps its progress. The web build keeps it while the page is open.
Marking steps by hand, keeping the progress and Reset progress are VectorCraft's own rules.
`learn.markStep {tutorial, step, complete?}` runs a step's check box → `{tutorial, step, complete}`: `step` is the
zero-based step number, and `complete` marks the step done (`true`, omitted or null) or not done (`false`). A missing
`step` or one the tutorial does not have, a `complete` that is not true or false, a tutorial whose sample was not
opened, and a finished tutorial are errors. `learn.resetProgress {}` runs Reset progress and answers what `learn.list`
answers; open documents, opened samples and the Learn view stay as they are. For both, a missing, non-string or
unknown `tutorial` is an error, and an error changes nothing.
The Home screen has a Learn section between Recent Files and the new-file presets, as
[the help page](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/homescreen-overview.html)
lists Learn, with in-app tutorials, among the Home screen's options. The section holds the Quick skill guide card,
@@ -2949,9 +2977,11 @@ rules.
```json
{"name":"invoke_menu","arguments":{"command":"learn.show","params":{"tutorial":"pen-paths"}}}
{"name":"invoke_menu","arguments":{"command":"learn.openSample","params":{"tutorial":"pen-paths"}}}
{"name":"invoke_menu","arguments":{"command":"learn.markStep","params":{"tutorial":"pen-paths","step":0}}}
{"name":"invoke_menu","arguments":{"command":"learn.finish","params":{"tutorial":"pen-paths"}}}
{"name":"invoke_menu","arguments":{"command":"learn.next","params":{"tutorial":"pen-paths"}}}
{"name":"invoke_menu","arguments":{"command":"learn.skills","params":{}}}
{"name":"invoke_menu","arguments":{"command":"learn.resetProgress","params":{}}}
```
A step that names a tool shows the tool's name as a blue link. A click on it, or Enter or Space while it has the
@@ -3151,7 +3181,12 @@ already walks Image Trace. Short agent entry points:
is unused, and offers Remove Strokes or Cancel when one of them is in use.
- Brushes: `brush.list`, `brush.get {name}`, `brush.apply {name, ids?}`, `brush.new {type, name?, params?, ids?}`,
`brush.setCurrent {name}`, `brush.options {name, params?, newName?}`, `brush.delete {name} | {names}`,
`brush.duplicate {name, newName?} | {names}`, `brush.freehand`, `object.expandBrush {ids?}`. A document or brush
`brush.duplicate {name, newName?} | {names}`, `brush.freehand {…path.freehand params, brush?}`,
`object.expandBrush {ids?}`. `brush.freehand` draws the plain path when `brush` is left out or null. It refuses a
`brush` that is not a string with "`brush` must be a string", a name that no brush in the document has (an empty
name included) with "no brush named `<name>`", and a `style` other than "pencil" or "brush"; the document does not
change and no undo step is recorded. The Paintbrush skips a tool brush or current brush that has been deleted and
paints with the other, or draws the plain path when neither is in the document. A document or brush
library file whose brushes repeat a name is read with the first brush of that name as stored and each later one
numbered with the first "`<name>` 2", "`<name>` 3"… the file does not have; strokes of the name keep the first
brush. `brush.new`,
@@ -4370,7 +4405,11 @@ with); without `path` it returns `{data}`, and `user: true` saves into the user
(category `user`, User Defined). `graphicStyle.loadLibrary {path? | data? | dataBase64?, name?}` loads a `.vcstyles`
file, or another document's graphic styles, as a library to add from (a `.ai` or EPS whose editing data holds graphic
styles and no layers gives the styles of its style list, in that order); a file in the user library folder, or a file
with the same extension and bytes as one there, loads as that User Defined library.
with the same extension and bytes as one there, loads as that User Defined library. A `.ai` or EPS style that paints a
fill or stroke with one of the file's gradients by name loads with that gradient at the style's angle. The style stores
only the gradient's name and angle, so the gradient is fitted to the bounds of each object the style is applied to; this
placement is VectorCraft's own rule. A style that names a gradient the file doesn't define, or paints with a pattern, is
left out.
## Symbol libraries
@@ -5462,7 +5501,9 @@ too and printer's marks are not. The destination is any profile `edit.colorSetti
for its colour mode). `profiles` (`all`, `destination`, or `taggedSource` for a document assigned profiles with
`edit.assignProfile`) writes colours in ICC-based spaces with their profiles embedded: CMYK with the destination's or
the document's CMYK profile, RGB as sRGB, grey with the sRGB tone curve (PDF/A, PDF/X-3 and PDF/X-4 files are
always tagged, whatever `profiles` says). `outputIntent` embeds a profile as the file's
always tagged, whatever `profiles` says). A CMYK image that keeps its numbers carries the CMYK profile it embeds
with `all` and `taggedSource`, and in PDF/A, PDF/X-3 and PDF/X-4 unless `profiles` is `destination`; PDF/X-1a
images are always untagged CMYK. `outputIntent` embeds a profile as the file's
`/GTS_PDFX` output intent with `outputCondition`, `outputConditionId` and `registry`, and `trapped` sets `/Trapped`
(PDF/A files keep their own output intent). Type is written as selectable, searchable text in embedded subset fonts
with a ToUnicode map (fonts whose licence forbids embedding stay outlines, with a warning); `advanced: {outlineText:
@@ -5723,6 +5764,15 @@ tool's active artboard in place, and the Distribute buttons then send the Distri
can then be negative. Align to Selection sends `to: "selection"`. The Distribute buttons need two or more selected
artboards with Align to Artboard, and three or more with Align to Selection.
Edit › Keyboard Shortcuts and `shortcuts.list` list an undoable command that is not an alias and has no menu path or
default shortcut, such as a panel menu's Break Link to Symbol (`symbol.breakLink`), when its params doc names no
required field and it is not one of the commands left out below. A field is optional when each of its names ends with
`?`, whatever type follows it (`on?: bool`, `ids?: [id…]`), when its name is followed directly by an `=` default
(`rows=10`), or when it starts with `…`. Such a command is listed in the group named by the first part of its id.
Commands listed this way include `type.fractionalWidths`, `type.systemLayout`, `object.setPixelAligned`,
`links.embed`, `links.update`, `object.slice.delete`, `artboard.switchOrientation`, `artboard.distributeSpacing`,
`appearance.targetContents` and `paint.invert`.
Edit › Keyboard Shortcuts and `shortcuts.list` leave out a command with no default shortcut when a key press cannot
run it: no item of the menu bar runs it, it opens no dialog when run without params, and it is one of these:
@@ -5732,7 +5782,22 @@ run it: no item of the menu bar runs it, it opens no dialog when run without par
- a command that sets nothing or fails without a param: `transparency.set`, `transparency.setOpacityMask`,
`stroke.set`, `layer.setProps`, `object.align`, `object.distribute`, `swatch.delete`, `swatch.move`,
`swatch.spotOptions`, `edit.colors.adjustBalance`, `swatch.library.load`, `graphicStyle.loadLibrary`,
`symbol.loadLibrary`, `brush.loadLibrary`, `dataset.import` and `variable.loadLibrary`.
`symbol.loadLibrary`, `brush.loadLibrary`, `dataset.import`, `variable.loadLibrary`, `charStyle.load`,
`paraStyle.load`, `textStyle.loadAll` and `svgFilter.import`;
- a command without a menu path that sets nothing, fails or only gives data back without a param:
`addon.pathtools.setAnchor`, `addon.shapes.configure`, `appearance.addEffect`, `artboard.align`,
`artboard.distribute`, `assets.export`, `assets.export3D`, `assets.settings.set`,
`attributes.set`, `brush.move`, `css.export`, `dimension.create`, `document.export`, `document.exportDxf`,
`document.exportEps`, `document.exportForWeb`, `document.exportPdf`, `document.save`, `document.setup`,
`edit.undoGroup.begin`, `edit.undoGroup.end`, `eyedropper.setOptions`, `file.package`, `library.createGroup`,
`links.placementOptions`, `links.unembed`, `livePaint.gapOptions`, `object.blend.createSpine`,
`object.blend.setEasing`, `object.intertwine.arrange`, `object.objectsOnPath.options`, `object.puppetWarp.pins`,
`object.setBounds`, `object.setLiveShape`, `object.setOverprint`, `object.setProps`, `object.slice.select`,
`paint.freeform.setPoint`, `paint.setFill`, `paint.setGradientGeom`, `paint.setStroke`, `perspective.grid.define`,
`perspective.grid.set`, `perspective.plane.move`, `print.setup`, `select.color`, `select.globalEditOptions`,
`stroke.setAdvanced`, `symbol.options`, `text.setFormat`, `text.setRangeStyle`, `text.setStyle` and `type.ruby`;
- `symbol.new`, which the Symbols panel's New Symbol button and its New Symbol… menu item run through the Symbol
Options dialog.
They list such a command while the user has changed its shortcut (`overridden: true` in `shortcuts.list`), and
`shortcuts.set` can change or clear it. When every menu bar item that runs a command gives it the same params, a
@@ -5849,7 +5914,12 @@ files or data sets, 8 folder levels, 256 steps. `action.batch` refuses `includeS
`` `stopOnError` must be true or false ``, and `source`, `folder`, `destination`, `destinationFolder`,
`datasetFileNaming` or `label` given as anything but a string with `` `label` must be a string ``, naming the key.
It checks them, and that `source` is `folder` or `datasets`, before it makes the destination folder or opens a file.
A null is read as a key left out. An action recorded in the Actions panel leaves the artboard out,
A null is read as a key left out. When a step fails on a file or data set, that row's `error` names the step by its
place in the `commands` sent, from 1, counting the Open steps the batch skips: with `commands` of an Open, an Unlock
All and an Align, a failed Align gives `` action step 3 (`object.align`) failed: `` and the reason. The batch's own
opening of a source file, choosing of a data set and destination save, export or close give their errors without a
step number. This numbering is VectorCraft's own rule. A `prefs.import` step is refused before any file is opened,
with `` commands[1]: `prefs.import` runs on its own, not as a batch step `` (counted from 0, as for an unknown command). An action recorded in the Actions panel leaves the artboard out,
and its steps of these commands get the artboard that is active when the action plays. A press with the Selection,
Direct Selection or Group Selection tool inside an artboard makes that artboard the active one; with the Selection
tool, a Shift-click on an empty spot inside an artboard makes it active and keeps the selection. Choosing the Artboard
@@ -7099,7 +7169,7 @@ comes back to the front, following the same preference. `links.check` reports ev
`missing`), `links.update {ids?}` reads modified files again and `links.relink {ids?, path | folder}` points images at
another file (or each at the file of its name in a folder); images keep their bounds, one undo step each.
`links.relink`'s `scope` picks which links take the new file (Relink's Replace choice): `selected` (the default) relinks `ids`; `all` also relinks every other stored object linked to the same file as
one of them, in the layers, opacity-mask art, symbols, graph designs and patterns; `missingInFolder` relinks `ids` to `path`, then every other missing link to the file of its name in
one of them, in the layers, opacity-mask art, symbols, graph designs, patterns and the art of the stored brushes; `missingInFolder` relinks `ids` to `path`, then every other missing link to the file of its name in
`path`'s folder, and lists the names not there in `notFound` (with `copy`, only missing images are looked for); `each` takes `paths: [{ids, path}]` in place of `ids`,
`path` and `folder` and relinks each link to its own file. An unknown scope, `paths` without `each`, `each` with `ids`,
`path` or `folder`, an entry without `path` or `ids`, an id in two entries and `missingInFolder` with `folder` are
@@ -7107,9 +7177,11 @@ errors, and nothing is relinked. Each call is one undo step. The Links panel's R
(`ui.relinkDialog`) with a Replace menu of these four choices. A PNG, JPEG,
another file (or each at the file of its name in a folder); images keep their bounds, one undo step each.
`links.update`, and `document.open` when it reads a modified file, also read the file again for the images and placed
documents inside symbols, graph designs, patterns and opacity masks that show the same content. Those objects have ids
documents inside symbols, graph designs, patterns, opacity masks and the art of the stored brushes (a scatter or art
brush's art, a pattern brush's tiles) that show the same content. Those objects have ids
of their own: `links.list`, `links.check`, `links.findFiles`, the `missingLinks`, `modifiedLinks` and `updatedLinks`
rows and the link watch list them, and every `links.*` command takes their ids. Opening a document gives an object
rows and the link watch list them, and every `links.*` command takes their ids. A `links.*` command that changes a
brush's art writes it back into the brush library with those ids. Opening a document gives an object
there whose id is 0 or already used by another object a new id, and the next save writes it. Saving a document also reads it
again for the placed documents of it inside that art in the other open documents. A PNG, JPEG,
GIF or WebP file whose pixels can't be read is not shown: `links.relink` fails with "the image's pixels can't be
@@ -7351,10 +7423,12 @@ listed in `warnings`. ASCII and binary DXF files are read; DWG files answer an e
`links.list {show?: all|missing|modified|embedded, sort?: name|kind|status}` lists every image in the layers, top
first, as the Links panel does, then every image and placed document in opacity-mask art and in the art of symbols,
graph designs and patterns, one row per stored object (never one per symbol instance or pattern tile): `{id, name,
linked, status: ok|modified|missing|embedded, format, pixelWidth, pixelHeight, path?, found?, page?, preview?, note?,
owner?}` (`owner`, for an object outside the layer tree: `{kind: layers|symbol|graphDesign|pattern, name?, maskOf?}`,
`maskOf` naming the object whose opacity mask holds it; `note`: the image takes more than the decode allowance, 2 GiB
graph designs, patterns and stored brushes, one row per stored object (never one per symbol instance, pattern tile or
brushed stroke): `{id, name, linked, status: ok|modified|missing|embedded, format, pixelWidth, pixelHeight, path?,
found?, page?, preview?, note?, owner?}` (`owner`, for an object outside the layer tree:
`{kind: layers|symbol|graphDesign|pattern|brush, name?, maskOf?, index?, tile?}`, `maskOf` naming the object whose
opacity mask holds it, `index` a brush's place in the library as `brush.list` lists it and `tile` the pattern brush tile
that holds it: `side`, `outerCorner`, `innerCorner`, `start` or `end`; `note`: the image takes more than the decode allowance, 2 GiB
or 512 MiB in the web app, as RGBA or as decoded, and it is drawn at the largest size within the allowance ("shown at
reduced size"; the document keeps the whole file) or, when it can't be read that way or has more pixels than the
allowance has bytes, drawn as a crossed gray box on the canvas and left out of exports ("too large to draw"); `document.open` and `file.place` say the same in their `warnings`). `links.info {id?}` is the Link Info: `image.info`'s fields plus
@@ -8933,6 +9007,7 @@ for the selected type objects (or `ids`); without `on` it sets the opposite of t
on. Optical Margin Alignment is a setting of the whole thread: the command sets every frame of a selected frame's
thread, and `ids` lists them all. Threading frames gives the thread its first frame's setting, frames taken out of
a thread keep it, and a file whose frames of one thread differ opens with the first frame's setting in all of them.
When every frame already has the setting, the command records no undo step.
In every paragraph of point and area type, these characters hang outside the margin when they
start or end a line: quotation marks, hyphens (a hyphenated line's hyphen too), full stops and commas hang wholly;
asterisks, tildes, ellipses, en and em dashes, colons and semicolons hang by half their width; and A, V, W, Y, v, w
@@ -9719,7 +9794,9 @@ and turn, shear and flip about it (`origin`).
WebAssembly plug-ins ([plugins.md](plugins.md)) are reached through commands; the desktop app and an unconfined
`vectorcraft-cli` keep the ones `plugin.install` installs in a `Plug-ins` folder next to the preferences and install
them again at startup (`plugin.remove` deletes them there):
them again at startup (`plugin.remove` deletes them there). A window or process locks `disabled.lock` in that folder
while it changes it, so installs, removals, grants and plug-in settings from two of them do not mix; when the file can't
be locked, `plugin.install` and `plugin.remove` fail and change nothing:
`plugin.install {path | dataBase64}` installs one, `plugin.list` / `plugin.info {id}` describe them (parameters,
schema, defaults). An object filter runs on the selected paths and compound paths with `plugin.run {id, params}` (one
undo step; it may change, delete or add objects, and the result is selected). A filter whose manifest lists `inputs`
@@ -10117,8 +10194,10 @@ Perspective grid presets: `perspective.presets.list` lists the built-in views (`
`[1P-High View]`, `[2P-Normal View]`, `[2P-Low View]`, `[2P-High View]`, `[3P-Normal View]`, `[3P-Low View]`;
`builtIn: true`, fitted to the first artboard, protected), then the saved ones, each with its Define Grid fields.
`perspective.grid.preset {name}` (or `{kind}`, that type's normal view) resets the grid to one, fitted to the first
artboard. `perspective.presets.save {name?, newName?, preset?, …fields}` saves a preset: just `{name}` saves the
document's grid (View → Perspective Grid → Save Grid as Preset). `perspective.presets.delete {name}`,
artboard. It adds no undo step when the document already holds that grid. When only whether the grid shows or its
active plane differs, it sets them without an undo step, as `perspective.grid.show` and `perspective.plane.set` do.
`perspective.presets.save {name?, newName?, preset?, …fields}` saves a preset: just `{name}` saves the document's grid
(View → Perspective Grid → Save Grid as Preset). `perspective.presets.delete {name}`,
`perspective.presets.export {names?, path?}` (a `.vcperspective` JSON file; without `path` it returns `data`) and
`perspective.presets.import {path? | data? | dataBase64?, replace?}` manage them. Saved presets are kept with the
preferences, and a grid whose fields are a preset's is named after it (`name`).
@@ -10778,8 +10857,12 @@ topmost piece.
### Text tools
The add-on's text tools act on the selected type (or `ids`), each as one undo step, and refuse with an error when there
is nothing for them to do. The pieces they make are point type that keeps its characters' styles, each placed so the
glyph of its first character lands where it was drawn.
is nothing for them to do. From the selection they take only type that can be edited; the type that `ids` names, or
that is inside a group or layer it names, is taken even when it, its group or its layer is locked or hidden (not type
on a locked artboard). The objects they make from locked or hidden type are not selected. Combine Point Text and Join
Point Text join a piece only with pieces that are as visible and as locked as it is, counting their groups and layers.
The pieces they make are point type that keeps its characters' styles, each placed so the glyph of its first character
lands where it was drawn.
- `addon.cleanup.breakText {by?, ids?}` turns each horizontal point or area type object into point type objects, one
per line (`by: "lines"`, the default), paragraph (`"paragraphs"`), word (`"words"`) or glyph (`"glyphs"`; a ligature
@@ -10791,14 +10874,15 @@ glyph of its first character lands where it was drawn.
staying where it was (within 0.01 pt). Pieces turned and sheared alike whose baselines lie within 0.4 em of each
other join left to right (a baseline a little off becomes baseline shift); a space goes between pieces at least half
a space apart, and tracking on the character before each piece keeps its place. A gap wider than 10 em, an overlap of
more than 1 em, another look (paint, opacity, effects) or a piece that can't keep its place once joined (a ligature
forming across the join) starts another object. Each object made takes the place and paint of its leftmost piece. The
main use is type from a PDF that arrives one glyph per object.
more than 1 em, another look (paint, opacity, effects), another visibility or lock state, or a piece that can't keep
its place once joined (a ligature forming across the join) starts another object. Each object made takes the place
and paint of its leftmost piece. The main use is type from a PDF that arrives one glyph per object.
- `addon.cleanup.joinText {ids?}` (Join Point Text) joins one-line horizontal point type into one point type object,
for text that arrives one line or fragment per object. Pieces turned and sheared like the top-left one are read as
lines (baselines within 0.4 em), top to bottom; a line's pieces join left to right with a space between them. Each
line becomes a left-aligned paragraph whose leading is the distance from the baseline above, so the lines stay where
they were. Character styles stay; the object takes the top-left piece's place and paint. Returns `{id, joined, lines}`.
for text that arrives one line or fragment per object. Pieces turned and sheared like the top-left one, and as visible
and as locked as it is, are read as lines (baselines within 0.4 em), top to bottom; a line's pieces join left to
right with a space between them. Each line becomes a left-aligned paragraph whose leading is the distance from the
baseline above, so the lines stay where they were. Character styles stay; the object takes the top-left piece's
place and paint. Returns `{id, joined, lines}`.
- `addon.cleanup.removeBreaks {kind, ids?}` removes the forced line breaks (`kind: "line"`) or paragraph returns
(`"paragraph"`) in the characters selected with a Type tool, else in all the text of the selected type. After
Select All in a frame of threaded text, it removes them from the text of every frame of the story, as one undo step.
@@ -11505,7 +11589,7 @@ as `object.setBounds` measures them (Use Preview Bounds), except Arrange in Grid
| `addon.arrange.replace` | `fit`: `keep`, `bounds` (the replaced object's width and height), `proportional` (fits inside them) (`keep`); `scaleStrokes`; `keep` (false) | Puts a copy of the topmost selected object centred on each of the other selected objects, in that object's place in the stacking order; the replaced objects are deleted unless `keep` (the copy then goes right above each). Needs two objects or more; the copies are selected. → `{ids}` |
| `addon.arrange.size` | `width`, `height` pt, 0.001…1000000 (at least one); `proportional` (false: a side not given stays; true: it follows the given one in proportion); `reference` 0…8 (4, the centre); `scaleStrokes` | Gives every selected object that width and height, keeping its reference point in place (the 9-point grid row by row from the top-left). |
| `addon.arrange.groupOverlapping` | none | Groups the selected objects (at most 20000) wherever their visual bounds overlap or touch, chains included: when A overlaps B and B overlaps C, all three go in one group. Only objects in the same layer or group are grouped together; objects that overlap nothing stay as they are. Each new group goes where its frontmost member was in the stacking order, and the groups and the objects left alone stay selected; with nothing overlapping it makes no step. Needs two objects or more. → `{groups: [id…], grouped}` (how many objects went into groups) |
| `addon.arrange.randomizeOpacity` | `min`, `max` % 0…100 (30, 100; `min` not more than `max`); `seed` whole number (0); `ids` (the selection) | Gives each selected object its own opacity (the object opacity the Transparency panel sets), picked at random and evenly from `min` to `max`; the same seed, objects and range give the same opacities. Groups take one opacity of their own; the objects inside keep theirs. → `{count}` |
| `addon.arrange.randomizeOpacity` | `min`, `max` % 0…100 (30, 100; `min` not more than `max`); `seed` whole number (0); `ids` (the selection) | Gives each selected object its own opacity (the object opacity the Transparency panel sets), picked at random and evenly from `min` to `max`; the same seed, objects and range give the same opacities. Groups take one opacity of their own; the objects inside keep theirs. A run that changes no opacity, such as `min` and `max` both at the opacity every object has, records no undo step. → `{count}` |
| `addon.arrange.sort` | `by`, `apply`: `width`, `height`, `area` (width × height), `x` (left edge), `y` (top edge), `opacity` (%), `stacking` (stacking order from the back) (`area`, `stacking`); `order`: `ascending` (small to large), `descending` (large to small), `random` (`ascending`); `distribute` (false); `seed` whole number (0, for `random`); `scaleStrokes`; `ids` (the selection) | Sorts the selected objects (at most 20000) by `by` and gives them the values of `apply` in that order: the first gets the smallest value. Without `distribute` the objects trade the values they have; with it the values step evenly from the smallest to the largest. A width, height or area changes about each object's centre (an area in proportion), a place moves the top-left corner. Stacking order always trades places, and only among objects in the same layer or group. Needs two objects or more. → `{count}` |
Zoom to Selection is the UI command `addon.arrange.zoomSelection {}` (remote mode only): it zooms and centres the
+7 -1
View File
@@ -269,7 +269,13 @@ capability model proposed for PhotoCraft plug-ins
while `plugin.install` checks a module, the install is refused, before anything is written to the `Plug-ins` folder,
if the other plug-in would need `replace: true` or the changed grant no longer approves the module. A
`plugin.remove` in another session waits until the install has written the `Plug-ins` folder, and then removes the
module and its grant. Loading the `Plug-ins` folder or a plug-ins folder in another session waits for it too. When
module and its grant. Loading the `Plug-ins` folder or a plug-ins folder in another session waits for it too.
Another process using the same `Plug-ins` folder, for example `vectorcraft-cli` beside the app, waits as well: each
window or process locks `disabled.lock` in the folder while it reads and changes the stored modules, `grants.json`,
`disabled.json` and the plug-ins' settings and caches. An install therefore keeps a module with its own grant, and a
grant or setting written in one process does not undo one written in another. When `disabled.lock` can't be
locked, `plugin.install` and `plugin.remove` fail and change nothing, `plugin.setEnabled` keeps its change in the
process until a later change can be saved, and loading the folder writes nothing to it. When
an install of a module that lists no permissions can't
write the module to the `Plug-ins` folder, or can't remove the grant from `grants.json`, the folder keeps the module
it held and `grants.json` keeps the grant. The new module runs until the session ends. When the grant can't be
File diff suppressed because one or more lines are too long
+4 -2
View File
@@ -85,8 +85,10 @@ object is where the art was.
| Bevel Inside | The bevel carved into the shape (the front face shrinks) instead of added around it (the walls stand outside the art). |
| Bevel both sides | The back is bevelled too. |
Holes stay holes, with walls of their own. Bevels move each corner along its bisector (mitres are limited to four
times the width), so a bevel wider than a narrow part of the shape folds over itself. Each facet has a seam ([Seams](#seams)).
Holes stay holes, with walls of their own. Bevels move each corner along its bisector. A corner the bevel opens (a
sharp point with the bevel outside, a narrow notch with it inside) whose miter would reach past four times the width is
cut square across instead; at the other corners the miter is limited to four times the width. A bevel wider than a
narrow part of the shape folds over itself. Each facet has a seam ([Seams](#seams)).
## Inflate
+1 -1
View File
@@ -39,7 +39,7 @@ against Illustrator's public documentation; **estimated** unless noted.
| Full font-name matching (OpenType name ID 4) | done | #1258: loaded/cataloged faces and Missing Fonts searches; localized names and variable default faces; Windows font-service QA pending |
| Variable fonts | done | named instances as styles; Character panel › Variable Font sets each axis (`fontAxes`); the font menu's Font Technology › Variable lists only variable font families, with the script, kind and ★ filters ([Find, apply, and adjust variable fonts](https://helpx.adobe.com/illustrator/desktop/design-with-text/fonts-and-scripts/find-apply-and-adjust-variable-fonts.html)); a family with a variable file beside static ones counts as variable. Evidence: `font_menu::tests::the_variable_filter_lists_only_variable_families`, `tests_axes::a_family_with_variation_axes_is_variable`, `tests_sysfonts::a_family_with_a_variable_file_beside_static_ones_is_variable` |
| Fallback glyphs keep the text's weight and slant | done | #2491: a character from a fallback face is set in that family's face nearest the run's weight and slant; Bold Italic of a missing family is drawn Bold (Source Sans 3 has no Bold Italic) rather than Italic; a letter and its combining marks (a grapheme cluster) are drawn in one face, the first that has all of them, so marks the text's font lacks attach to their letter instead of drawing as missing glyphs (#4491). Vietnamese letters with two marks (Ể, Ứ, Ự) sit on their letter whether typed precomposed, decomposed or as a vowel plus a tone mark, built from GPOS mark-to-mark in fonts without the precomposed letters. Evidence: `tests::vietnamese` |
| Colour fonts (bitmap, COLR, OpenType SVG) | partial | bitmap glyphs (`sbix`, `CBDT`) done: the largest strike's PNG, transformed with the type, fill and stroke ignored; PDF Type 3 glyphs or images, SVG images with outlined text (live text leaves emoji to the viewer, their fonts not embedded), EPS and legacy `.ai` images, Create Outlines images; not `sbix` duplicate, flipped, JPEG or TIFF glyphs, or `CBDT` BGRA or mask data, or ruby; in envelopes they warp as images do, and a Warp effect moves them without bending them. COLR (v0 and v1) done: a glyph's layers as vector art (solid colours, linear and radial gradients that pad, repeat or reflect (the [COLR specification](https://learn.microsoft.com/en-us/typography/opentype/spec/colr)'s extend modes), clip glyphs and boxes, blend modes, transforms, palette 0, the foreground colour from the run's fill, variable fonts at the face's instance), transformed with the type; drawn on the canvas, written as paths in SVG, EPS, legacy `.ai` and PDF with outlined text, as text in PDF (Type 3 glyphs), and Create Outlines makes groups of editable paths. Paints documents have no form for draw the glyph as an image (256 px per em): sweep gradients, Porter-Duff compositing, radial gradients from a circle that isn't the centre, radial gradients that repeat or reflect and start at a circle, gradients that repeat or reflect with a stop whose color isn't in the palette. Not ruby. COLR and SVG glyphs also go with type that geometry effects reshape (on the canvas and in exports), into Expand Appearance and EMF/WMF export, as their art, and bitmap glyphs as images. OpenType SVG done: a glyph's SVG document (its element `glyph<gid>`) is read by the SVG importer into vector art in font units, `currentColor` in the run's fill (and the legacy `context-fill` and `context-stroke` in its fill and stroke), a `viewBox` mapped onto the em square, and then drawn, exported and outlined as COLR glyphs are; in PDF real text such glyphs are text that draws nothing, with their art drawn where they sit. Images in glyph documents are in the art, holding their pixels until a document takes them in; text, scripts and embedded content are left out, as the table rules them out. Not CPAL palette variables. Evidence: `tests_svg_glyphs`, `svg/tests/it/svg_glyphs.rs`, `tests_colourfonts::svg_glyph_images_draw_and_outline`, `tests_colourfonts::create_outlines_turns_svg_glyphs_into_groups`, `tests_colourfonts::pdf_real_text_draws_svg_glyphs_as_art_and_keeps_their_characters`, `tests_colourfonts::expand_appearance_keeps_the_colour_glyphs_of_type_with_effects`, `render::tests_colrglyphs::colour_glyphs_go_with_type_that_a_geometry_effect_reshapes`, `tests_bitmaps`, `tests_colr`, `render::tests_bitmapglyphs`, `render::tests_colrglyphs`, `pdf::tests::colour_bitmap_glyphs_export_as_images`, `pdf::tests::colr_glyphs_export_as_vector_art`, `svg/tests/it/colour_glyphs.rs`, `eps` `colour_bitmap_glyphs_*` and `colr_glyphs_*`, `tests_pathops::create_outlines_turns_bitmap_glyphs_into_images`, `tests_pathops::create_outlines_turns_colr_glyphs_into_layer_groups` |
| Colour fonts (bitmap, COLR, OpenType SVG) | partial | bitmap glyphs (`sbix`, `CBDT`) done: the largest strike's PNG, transformed with the type, fill and stroke ignored; PDF Type 3 glyphs or images, SVG images with outlined text (live text leaves emoji to the viewer, their fonts not embedded), EPS and legacy `.ai` images, Create Outlines images; not `sbix` duplicate, flipped, JPEG or TIFF glyphs, or `CBDT` BGRA or mask data, or ruby; in envelopes they warp as images do, and a Warp effect moves them without bending them. COLR (v0 and v1) done: a glyph's layers as vector art (solid colours, linear and radial gradients that pad, repeat or reflect (the [COLR specification](https://learn.microsoft.com/en-us/typography/opentype/spec/colr)'s extend modes), clip glyphs and boxes, blend modes, transforms, palette 0, the foreground colour from the run's fill, variable fonts at the face's instance), transformed with the type; drawn on the canvas, written as paths in SVG, EPS, legacy `.ai` and PDF with outlined text, as text in PDF (Type 3 glyphs), and Create Outlines makes groups of editable paths. Paints documents have no form for draw the glyph as an image (256 px per em): sweep gradients, Porter-Duff compositing, radial gradients from a circle that isn't the centre, radial gradients that repeat or reflect and start at a circle, gradients that repeat or reflect with a stop whose color isn't in the palette. Not ruby. COLR and SVG glyphs also go with type that geometry effects reshape (on the canvas and in exports), into Expand Appearance and EMF/WMF export, as their art, and bitmap glyphs as images. OpenType SVG done: a glyph's SVG document (its element `glyph<gid>`) is read by the SVG importer into vector art in font units, `currentColor` in the run's fill (and the legacy `context-fill` and `context-stroke` in its fill and stroke), a `viewBox` mapped onto the em square, and then drawn, exported and outlined as COLR glyphs are; in PDF real text such glyphs are text that draws nothing, with their art drawn where they sit. Images in glyph documents are in the art, holding their pixels until a document takes them in; text, scripts and embedded content are left out, as the table rules them out. Not CPAL palette variables. Evidence: `tests_svg_glyphs`, `svg/tests/it/svg_glyphs.rs`, `tests_colourfonts::svg_glyph_images_draw_and_outline`, `tests_colourfonts::create_outlines_turns_svg_glyphs_into_groups`, `tests_colourfonts::pdf_real_text_draws_svg_glyphs_as_art_and_keeps_their_characters`, `tests_colourfonts::expand_appearance_keeps_the_colour_glyphs_of_type_with_effects`, `render::tests_colrglyphs::colour_glyphs_go_with_type_that_a_geometry_effect_reshapes`, `tests_bitmaps`, `tests_colr`, `render::tests_bitmapglyphs`, `render::tests_colrglyphs`, `pdf::tests::colour_bitmap_glyphs_export_as_images`, `pdf::tests::colr_glyphs_export_as_vector_art`, `svg/tests/it/colour_glyphs.rs`, `eps` `colour_bitmap_glyphs_*`, `colr_glyphs_*` and `type_taken_back_for_the_page_limit_takes_its_glyph_images_with_it`, `tests_pathops::create_outlines_turns_bitmap_glyphs_into_images`, `tests_pathops::create_outlines_turns_colr_glyphs_into_layer_groups` |
| Every-line and Single-line composers | done | tuned by eye, never compared side by side |
| Optical Margin Alignment | done | Type › Optical Margin Alignment, `type.opticalMarginAlignment`: per type object, with one setting for all the frames of a thread, in point and area type of left-to-right paragraphs, and at the brackets of type on a path whose first paragraph runs left to right; right-to-left paragraphs of point and area type, and type on a path whose first paragraph runs right to left, do not hang |
| System Layout | done | Character panel menu › System Layout, `type.systemLayout`: the whole document, off by default and for documents from before it, saved only when on. On, every text object advances by whole points (at least one when a character takes space). New point, area and path type, threaded frames, placed text, graph and dimension labels and pasted plain text inherit it. Evidence: `tests::system_layout_rounds_positive_advances_to_whole_points`, `typecmd::area_tests::system_layout_sets_the_document_and_every_text_object`, `panels::character::tests::system_layout_menu_item_toggles_the_document` |
+1 -1
View File
@@ -384,7 +384,7 @@ next unit in the order a right-click on a ruler lists them, from Feet back to Po
|---|---|---|
| Effect > Warp Options: style previews, orientation choices and percent controls | done | #1760; focused input, mixed-style and history checks passed; original captures reviewed. No geometry or optional Properties changes. |
| Command search: Up and Down move through the results, Enter runs the highlighted one | done | #1798 (#1757) |
| Learn panel: Window › Learn and Explore tutorials on the app bar open it; For you holds a Quick skill guide card, Skills lists VectorCraft's own skills with tutorial counts and empty progress rings, a tutorial shows its numbered steps, Back goes up a level; a tool's name in a step is a link that marks the tool where the toolbars show it (its button, its group's flyout, a torn-off strip, a toolbar made with New Toolbar or the All Tools drawer) without choosing it; View more opens the tutorial's practice sample as a new untitled document, Finish tutorial then marks it finished, and Next Up shows the next tutorial in the same skill (no video) | done | [the help page](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/learn-skills-quick-skill-guide.html); `learn.list`, `learn.skills`, `learn.show`, `learn.locateTool`, `learn.openSample`, `learn.finish`, `learn.next`; the mark's look and 3-second lifetime are VectorCraft's own rules; `panels::learn::tests`, `toolbar::tests` |
| Learn panel: Window › Learn and Explore tutorials on the app bar open it; For you holds a Quick skill guide card, Skills lists VectorCraft's own skills with progress rings that fill and counts of tutorials finished, a tutorial shows its numbered steps with a check box each that marks the step done once its sample is open, a finished tutorial has a check mark, Back goes up a level; a tool's name in a step is a link that marks the tool where the toolbars show it (its button, its group's flyout, a torn-off strip, a toolbar made with New Toolbar or the All Tools drawer) without choosing it; View more opens the tutorial's practice sample as a new untitled document, Finish tutorial then marks it finished with all its steps, and Next Up shows the next tutorial in the same skill; Reset progress clears the progress (no video) | done | [the help page](https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/learn-skills-quick-skill-guide.html); `learn.list`, `learn.skills`, `learn.show`, `learn.locateTool`, `learn.openSample`, `learn.markStep`, `learn.finish`, `learn.next`, `learn.resetProgress`; the mark's look and 3-second lifetime, marking steps by hand, keeping the progress in the preferences and Reset progress are VectorCraft's own rules; `panels::learn::tests`, `toolbar::tests` |
| Pathfinder panel: a group selected alone counts its nested shapes, so an expanded stroked object keeps the Shape Modes enabled | done | #1642 (#1635) |
| Selected Grid Repeat shows row, column and corner handles and spacing sliders; bounding-box handles take priority where they meet | done | #2691, `tools/src/repeat_grid.rs`; [public behavior reference](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/create-and-edit-patterns/set-grid-repeat-options.html); drags preview and commit `object.repeat.options` as one undo step, Escape cancels; Radial Repeat has no handles yet |
| Grid Repeat Options (Object › Repeat › Options…) has a Preview checkbox: the repeat on the canvas follows the fields while the dialog is open, Cancel puts the original back without a history step, OK keeps the previewed values as one undo step | done | #2651; [public behavior reference](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/create-and-edit-patterns/set-grid-repeat-options.html) lists the Preview option for the grid options only, so Radial and Mirror Repeat Options have none; `dialogs/command.rs` tests |