Merge main into fix/3d-face-budget-per-object

This commit is contained in:
dotCooCoo
2026-11-12 22:53:49 -08:00
105 changed files with 4986 additions and 442 deletions
+3
View File
@@ -140,6 +140,9 @@ of another kind, it moves.
Confirmations: deleting swatches from the Swatches panel opens a `confirm` dialog (fields `message`, `detail`);
`ui.dialog.confirm` runs the command it asks about (here `swatch.delete`) and `ui.dialog.cancel` drops it.
Deleting Layers panel rows that include a layer or sublayer with art (`engine.execute` of `ui.layerDelete`, which the
panel's trash, its menu's Delete Selection and Delete or Backspace run) opens a `confirm` dialog too; its OK deletes
those rows with `layer.delete` in the document the question was asked in. `layer.delete` itself deletes at once.
New swatches and colour groups: `ui.newSwatch {spot?, global?, group?}` opens the `newSwatch` dialog prefilled from the active
fill or stroke (fields as in `swatchOptions` plus `group`; a gradient or pattern only takes `name`) and
+2 -2
View File
@@ -21,7 +21,7 @@ Ordinary File > Save offers Save As when its own location refuses writes with a
| | Illustrator | VectorCraft | Notes |
|---|---:|---:|---|
| Formats opened or placed | ~30 | 30 | missing: FreeHand, CorelDRAW, DWG, PICT, PS |
| Formats opened or placed | ~30 | 31 | missing: FreeHand, CorelDRAW, DWG, PS |
| Formats saved (Save As) | 6 (AI, AIT, PDF, EPS, SVG, SVGZ) | 6 + native | `.ai` written PDF-compatible (with an editing copy of the art: layers, groups, paths, colors, gradients, patterns, images, type, symbols, artboards, transparency, opacity masks, clipping) or as legacy version 7 (layers and groups, one artboard per file) |
| Formats exported | ~16 | 18 | missing: DWG; extra: GIF/PNG-8 palette export, DXF up to 2018, layered PSD |
| **Overall (weighted by use)** | | **~75%** | `.ai` and PDF dominate the weighting |
@@ -285,7 +285,7 @@ Names in the editing data that aren't UTF-8 (layers, objects, artboards, colors,
| HEIC / HEIF | open, place | yes (HEVC-coded still images: single pictures and grids of tiles, 8 to 10 bits, with an alpha image; image sequences, other codings and grids of cropped tiles are refused) | no | `.heic`, `.heif`; decoded by heic-rs in the engine's default `heif` feature (a build without it refuses the files with a message); the container's rotation, mirror and crop are applied; without an `nclx` box the HEVC stream's video signal type gives the matrix and range; an RGB ICC profile, or Display P3 with the sRGB curve named by an `nclx` box or, without a color box, by the stream, is converted to sRGB; EXIF resolution tags size the image, or 72 ppi; bounded decoding; `tests_heifread.rs` |
| PCX | open, place | yes (1 bit in the header palette's first two colors, black and white without them; 1 bit in two to four planes and 4 bits with up to 16 colors; 2 bits in the CGA colors the header's CGA palette settings pick; 8 bits with the 256-color palette, gray without one; 24-bit color in three planes) | no | the header's HDpi and VDpi size the image; a file of another depth or plane count, cut short or past the pixel allowance is refused with a message; tests in `crates/engine/src/cmd/fileio/tests_pcxread.rs` and `crates/engine/tests/import_fuzz.rs` |
| JPEG 2000 | open, place | yes (JP2 and raw codestream images; multiple codestreams and JPX composition or layers are refused) | no | `.jpf`, `.jpx`, `.jp2`, `.j2k`, `.j2c`, `.jpc`; resolution uses the valid `resd` (display) value on each axis, or else the valid `resc` (capture) value, or 72 ppi; bounded decoding; `tests_jp2read.rs` |
| PICT | open, place (legacy) | no | no | rarely used |
| PICT | open, place (legacy) | yes (versions 1 and 2: shapes, lines, regions, text, bitmaps, pixel maps and QuickTime JPEG images; placed as one group clipped to the picture's frame) | no | `.pct`, `.pic` and `.pict`; a version 2 picture also opens by its content; a two-color pattern fills with its average color; inverted shapes, transfer modes other than a copy and QuickTime images in other formats come back as warnings; a picture cut short keeps what came before it; tests in `crates/metafile/src/tests/pict.rs`, `crates/engine/src/cmd/fileio/tests_pict.rs` and `crates/engine/tests/import_fuzz.rs` |
| Pixar PXR | open, place (legacy) | yes (any set of the R, G, B and A channels in 8 or 12 bits, dumped or run-length encoded, in tiles; R alone is gray; alpha matted to black or unassociated) | no | recognized by its magic number; 12-bit samples are clamped to 0.0 to 1.0; null tiles are transparent with A and black without; the offsets aren't read, and the image takes the default resolution; a file cut short, with header values or packets the format doesn't define, or past the pixel allowance is refused with a message; tested on synthetic files only; tests in `crates/engine/src/cmd/fileio/tests_pxrread.rs` and `crates/engine/tests/import_fuzz.rs` |
| FreeHand `.fh*` | open (legacy) | no | no | |
| CorelDRAW `.cdr` | open | no | no | |
+2 -2
View File
@@ -404,7 +404,7 @@ macOS cursor delivery (#2292) is narrowed to a native host adapter using the exi
- **Done:** a paragraph's Auto Leading also sets the Leading the Character panel shows for Auto type, the leading the
Alt+↑/↓ nudge steps from and the lines Fill with Placeholder Text counts; estimate unchanged.
- **Missing:** CJK vertical
composition (ruby, mojikumi sets and dialog, kinsoku settings #633, manual tate-chu-yoko), Middle Eastern
composition (ruby, custom mojikumi sets and the Mojikumi Settings dialog, kinsoku settings #633, manual tate-chu-yoko), Middle Eastern
- **Done:** Ruby (ふりがな) for live text (`type.ruby`): a reading over a byte range, above or below (right of the
column in vertical type), aligned, sized, overhanging or squeezed; saved natively, laid out with line growth, drawn
on the canvas and in SVG/PDF (outlines where ruby is present), EPS, EMF/WMF and legacy `.ai` (outlines where ruby is
@@ -442,7 +442,7 @@ macOS cursor delivery (#2292) is narrowed to a native host adapter using the exi
export, where the type's outlines used to leave them out; bitmap glyphs (emoji) too, as images that hold their
own pixels until a document takes them in; estimate unchanged.
- **Missing:** CJK vertical
composition (mojikumi sets and dialog, kinsoku settings #633, manual tate-chu-yoko), Middle Eastern
composition (custom mojikumi sets and the Mojikumi Settings dialog, kinsoku settings #633, manual tate-chu-yoko), Middle Eastern
features beyond bidi, digit types, Character Direction and Kashidas (Middle Eastern composers, a split caret), spell check (its engine is done, #4936: `text.spelling.check` and
`text.spelling.suggest` on craft-proof; the custom dictionary and Ignore All commands; Auto Spell Check, `edit.autoSpellCheck`, with a right-click on an underlined word offering its suggestions, Ignore All and Add to Dictionary, and Spelling › Auto Spell Check in the context menu of type; the Edit Custom Dictionary dialog; the Check Spelling dialog remains),
Touch Type, Retype, Snap to Glyph; optional preservation of font sizes during group scaling (#1034 enhancement).
+129 -8
View File
@@ -631,7 +631,7 @@ sampler.
| `invoke_menu` | `{command, params?}` | Invokes a menu item by command id. UI commands such as `view.*` and `window.*` are in `command_list` with `ui: true`; running them needs the desktop app (`--connect`). |
| `open_panel` | `{panel}` | Remote only. `panel` is a panel id (`layers`, `swatches`, `colorGuide`, …, as `window.panel` takes) or its display label (`"Color Guide"`), in any case. |
| `screenshot` | `{path?, scale?, artboard?, window?, max_side?, traceViews?}` | Returns MCP image content (`image/png`, base64) plus a text block. Renders the artboard with the pixels of a PNG `export` with `background: "white"` at the same scale; `traceViews:true` draws Image Trace objects in the view set with `imageTrace.setView`, as in the app's window; `window:true` captures the app window (remote only), as `ui_screenshot` does, and `max_side` (1–4096, window captures only) scales the returned image down as described for `ui_screenshot`. With `path` the backend (the headless session or the app) writes the PNG there too; a window capture written there keeps its full size with `max_side`. |
| `open_file` | `{path, importer?, params?}` | Opens any readable file as a new active document: `.vectorcraft`/`.drawcraft`, `.vctemplate`, `.svg`/`.svgz`, `.pdf`/`.ai`, `.ait`, `.eps`/`.epsf`, `.ps`, `.dxf`, `.emf`, `.wmf`, HP-GL (`.plt`/`.hpgl`/`.hgl`/`.hpg`, and a file of an extension no other format reads that starts with plotter instructions), PNG (`.png`/`.pns`), JPEG, GIF, WebP, TIFF, BMP (`.bmp`/`.dib`/`.rle`), Targa (`.tga`/`.vda`/`.icb`/`.vst`), PCX, Pixar (`.pxr`), JPEG 2000 (`.jpf`/`.jpx`/`.jp2`/`.j2k`/`.j2c`/`.jpc`), HEIC/HEIF (`.heic`/`.heif`), JPEG XL (`.jxl`), PSD (`.psd`/`.pdd`)/PSB (an image opens as a document of its pixel size; a PSD or PSB file with its layers as layers, or as its merged image through `run_command document.open` with `layers: false`; a JPEG XL file as its first frame). Templates (`.vctemplate`, `.ait`) open as a new untitled document. PDF, `.ai` and SVG files saved with Preserve Editing reopen as the document they carry. The reply is `document.open`'s: its `warnings` say what didn't come in as it was (an EPS whose PostScript can't be read opens as its preview, and the warning names the PostScript error, the operator and the procedure). A file of an extension only an installed importer plug-in lists opens with that importer ([Plug-ins](#plug-ins)); `importer: "plugin.<id>"` opens the file with the importer it names, which must list the file's extension, also one a built-in format reads (in the app, as File › Open With does), and `params` gives that importer's parameters (their defaults when omitted). `run_command document.formats` lists the formats. |
| `open_file` | `{path, importer?, params?}` | Opens any readable file as a new active document: `.vectorcraft`/`.drawcraft`, `.vctemplate`, `.svg`/`.svgz`, `.pdf`/`.ai`, `.ait`, `.eps`/`.epsf`, `.ps`, `.dxf`, `.emf`, `.wmf`, PICT (`.pct`/`.pic`/`.pict`, and a version 2 picture of any extension), HP-GL (`.plt`/`.hpgl`/`.hgl`/`.hpg`, and a file of an extension no other format reads that starts with plotter instructions), PNG (`.png`/`.pns`), JPEG, GIF, WebP, TIFF, BMP (`.bmp`/`.dib`/`.rle`), Targa (`.tga`/`.vda`/`.icb`/`.vst`), PCX, Pixar (`.pxr`), JPEG 2000 (`.jpf`/`.jpx`/`.jp2`/`.j2k`/`.j2c`/`.jpc`), HEIC/HEIF (`.heic`/`.heif`), JPEG XL (`.jxl`), PSD (`.psd`/`.pdd`)/PSB (an image opens as a document of its pixel size; a PSD or PSB file with its layers as layers, or as its merged image through `run_command document.open` with `layers: false`; a JPEG XL file as its first frame). Templates (`.vctemplate`, `.ait`) open as a new untitled document. PDF, `.ai` and SVG files saved with Preserve Editing reopen as the document they carry. The reply is `document.open`'s: its `warnings` say what didn't come in as it was (an EPS whose PostScript can't be read opens as its preview, and the warning names the PostScript error, the operator and the procedure). A file of an extension only an installed importer plug-in lists opens with that importer ([Plug-ins](#plug-ins)); `importer: "plugin.<id>"` opens the file with the importer it names, which must list the file's extension, also one a built-in format reads (in the app, as File › Open With does), and `params` gives that importer's parameters (their defaults when omitted). `run_command document.formats` lists the formats. |
| `save_file` | `{path?, compress?, version?, preview?, precision?, options?}` | Runs `document.save`: the document's own file in its own format (native `.vectorcraft` unless it was opened from or saved as SVG, PDF or a restorable `.ai`; then `warnings` say what that format loses). A path's extension picks the format (`.vectorcraft`, `.vctemplate`, `.pdf`, `.svg`, `.svgz`, `.ai`: a PDF carrying the native document, which reopens editable; `.eps`: by default one file whose bounding box fits the visible art, the first artboard when no art shows; `options.useArtboards: true` makes the chosen artboard the page and, with two or more chosen, the file at the path is the central file of the visible art and each artboard is also written to `<name>_<artboard>.eps` beside it, listed in the reply's `files`). For a native file, `compress: true` gzips it (default: the `useCompression` preference, Preferences › File Handling › Use Compression), `version` (1 to 4) writes it for an older VectorCraft (1 and 2 are never compressed, and `version: 2` with `compress: true` is an error), `preview: true` embeds a PNG of the first artboard, and `precision` (0 to 9) rounds path anchors and handles to that many decimal places for that save only (colors, transforms and type stay exact). `options` passes the format's save options as `run_command document.formats` lists them. When `compress`, `version`, `preview` or `precision` is given both at the top level and in `options` with different values, the call is an error (`` `compress: true` and `options.compress: false` disagree: give the option once ``) and nothing is written. A key in `options` that no save format takes is an error, and nothing is written (see Parameter keys). The save drops each option the written format doesn't read. The reply's `warnings` then name each such option given (for example `` `compress` was not used: SVG files don't read it `` for an `.svg` path, and `` `options.preview` was not used: … `` for a key in `options`; a `.ai` file reads `compress` but not `version`, `preview` or `precision`). For a `.ai` file, these warnings name the kind of `.ai` written: a legacy .ai (version 7) for `aiVersion: "7"`, a non-PDF-compatible .ai for `pdfCompatible: false`, and a PDF-compatible .ai otherwise, including a save that reuses the options the document was last saved with. `run_command document.save` and the other save commands refuse any option given beside the path and in `options` with different values, and give the same warnings for a top-level `compress`, `version`, `preview` or `precision` and for each key in `options` that the format doesn't read. The headless session and the app receive the same `app.save` params, and the app is also sent `wait: true`: the call returns once the file is written, or with the error (such as a path outside the write root), even with Background Save on. When the save asks first (the question before replacing a file that opened with losses, or on macOS and Linux the file dialog for an untitled document without `path`), the reply is `{pending}` or `"cancelled"` as before, and the save that runs after the answer uses the Background Save preference. Location refusals return `READ_ONLY_LOCATION: <reason>` without a fallback panel for automation; see [Save location errors](#save-location-errors). |
| `export` | `{path?, format?, scale?, artboard?, range?, selection?, outlineText?, options?}` | `svg`, `svgz`, `pdf`, `ai` (the PDF-compatible `.ai` that Save writes, which carries the document when every artboard is written in order), `eps`, `dxf`, `emf`, `wmf`, `hpgl` (a `.plt` plot file for plotters and cutters), `png`, `jpg`, `webp`, `gif`, `png8` (an indexed `.png`), `tiff`, `bmp`, `tga`, `psd` (layered), `txt` (the document's text), `vectorcraft` or `template` (a native template). The tool's `format` enum and `document.formats` list them, generated from the engine's format table. When `format` is omitted, it comes from the path's extension. PDF and `.ai` write one page per artboard: all of them, or `artboard` (0-based) / `range` (`"1-3, 5"`, 1-based). SVG and SVGZ write one file per chosen artboard. EPS writes one file of the visible art; with `artboard`, `range`, `options.artboards` or `options: {"useArtboards": true}` it writes one file per chosen artboard, after a central file of the visible art when there are two or more, and `useArtboards: false` keeps the one file. Rasters, DXF, EMF, WMF and HP-GL write one artboard, or one file per chosen artboard with `options: {"useArtboards": true}`. Rasters also take `options: {"rect": [x, y, width, height]}` (page points, y down): that area of the page at the given `ppi`/`scale`, without an artboard and without changing the document; it is refused with `artboard`, `artboards`, `range` or `useArtboards`, with a non-positive or non-finite size, and for non-raster formats. `options` carries more format options (e.g. `{"quality": 80}` for JPEG). `selection: true` exports the selected objects cropped to their bounds (the reply adds their `bounds`, and reports `format` and the encoder's `warnings` as a whole-document export does); `outlineText: true` writes SVG text as paths. Template layers are left out, live effects are kept, and exporting `vectorcraft` never changes the document's path. Without `path` the bytes come back as `dataBase64`. Both backends run the same `document.export` call. |
| `add_text` | `{text, x?, y?, width?, height?, fit?, fitMinPercent?, path?, mode?, pathEffect?, size?, font?, color?, justify?, vertical?}` | Point type at (x, y) (`justify`: `left`, `center` or `right` starts, centres or ends each line on x); area type with `width`/`height` (`fit`: `none`, `autoHeight`, `shrinkText`, as `text.areaOptions`); or `path` + `mode` (`area`/`onPath`) to flow text in or along a path, with `pathEffect` (`rainbow`, `skew`, `3dRibbon`, `stairStep`, `gravity`; SVG export writes type on a path with any effect other than `rainbow` as outlines, with a warning); `justify` (also `auto`, `justifyAll`) aligns the paragraphs of every kind, as `text.setStyle` does later. `vertical: true` uses the existing vertical writing mode for every kind (default `false`, horizontal). Returns `{id}`, with `overflow: true` when the text doesn't fit its frame or path. |
@@ -1488,14 +1488,33 @@ refused before the command runs:
Only the top level is checked, except for the export and save commands below: the keys of an object inside a value
(`artboardLayout: {…}`) are the command's to read. Another exception is an effect's `params`: `effect.apply` (and `appearance.addEffect`) and `effect.setParams`
check them against the effect's own entry in `effect.list`, its `defaults` and the keys its `params` text names. A key
the effect doesn't take, or a value of another type than its default (a string for a number, a number for a switch),
is refused the same way:
the effect doesn't take, or a value of another type than the effect reads (a string for a number, a number for a
switch), is refused the same way:
```json
{"id": "effect.apply", "params": {"effect": "blur.gaussian", "params": {"blurr": 3}}}
→ invalid parameters for `effect.apply`: unknown parameter `blurr`; the command takes: radius
→ invalid parameters for `effect.apply`: unknown parameter `blurr`; the command takes: radius, linear
```
A key the effect has a default for takes a value of its default's type. A key only the `params` text names takes the
type the effect reads: the earlier 3D `perspective`, `lightAzimuth` and `lightElevation` and Scribble's `variation` are
numbers, an Outline Stroke's `width` is a number and a Gaussian Blur's `linear` is true or false. A number written as
text (`"10 pt"`), `true` for a number, `1` for a switch and `null` for either are refused; a key left out keeps its
default. The `style` of Crop Marks must be `roman` or `japanese`. An installed plug-in effect's parameters take the
types its manifest gives them. A step of `command.batch` gets the same error, and the document and its undo history
stay as they were:
```json
{"id": "effect.apply", "params": {"effect": "path.outlineStroke", "params": {"width": "10 pt"}}}
→ invalid parameters for `effect.apply`: `width` must be a number
```
A replayed journal or action still plays such a value, as it plays a key the effect no longer takes.
`effect.setParams` with `warpStyle` checks `params` against the new Warp style, and with `threeDType` against the new
3D effect. Its own `visible` must be true or false (`null` leaves the visibility as it is); any other value is refused,
in a replayed journal or action too, and nothing changes.
The `color` of Drop Shadow, Inner Glow, Outer Glow and Shift to Color must be one the effect can read: a hex color
(`#rrggbb`, `#rgb` or `#rrggbbaa`, with or without the `#`), `black`, `white`, `red`, `green` or `blue`, `[r, g, b]`
(three numbers, each read on a 0 to 1 scale), or a color object (`{"model": "rgb", "r": 1, "g": 0, "b": 0}`).
@@ -4159,6 +4178,17 @@ the old name. A rename gives the new name to the pattern's swatches that had the
old name keeps it. A blank name gives "New Pattern N" in `object.pattern.make` and "`<pattern>` copy" in
`object.pattern.saveCopy`, and `pattern.options` keeps the name.
`object.pattern.cancel {}` leaves pattern editing mode and discards the changes. For a pattern that `object.pattern.make`
made for the edit, it removes the pattern and every swatch of it, a color group's included. Every other paint of the
pattern becomes no paint: on art outside the editing layer, in opacity mask art, type runs, symbol definitions, graph
designs, the series and label paints a graph keeps for its next redraw, other patterns' tiles, graphic and character
styles and brush art, and in the fill, stroke and appearance new art takes. A pattern that `object.pattern.saveCopy` saved during the edit stays, with those paints cleared in its tile.
For an existing pattern, Cancel puts the definition back as it was when editing started; when `pattern.options` renamed
it during the edit, the old name comes back with its swatches and paints, unless another pattern, swatch or color group
has taken that name. `pattern.delete {name}` clears the paints of the pattern in the same places and returns
`{unpainted}`, the number of document paints it cleared. A `pattern.options` rename renames the paints in the same
places. Undo and Redo restore the fill, stroke and appearance new art takes with the document.
The pattern commands (`object.pattern.make`, `object.pattern.edit`, `object.pattern.saveCopy`, `pattern.options`,
`pattern.delete`) and the Repeat commands (`object.repeat.radial`, `object.repeat.grid`, `object.repeat.mirror`,
`object.repeat.options`) reject a param of the wrong type, such as `"instances": "8"`, `"edit": "false"` or
@@ -4273,7 +4303,12 @@ and `layerRows`, the rows highlighted in the panel.
`layer.newSublayer {parent?, bottom?, name?, …options}` (on top of the parent's contents; `bottom`, under them but
above a clipping layer's clipping path, with Ctrl/Cmd+Alt; both refused while an opacity mask is edited),
`layer.delete {ids?}` (rows with what they hold; the
last layer stays), `layer.locate {id?}` (highlights the selected object's row; the panel opens the rows around it)
last layer stays; it does not ask), `ui.layerDelete {ids?|id?}` (the panel's trash, rows dropped on it, Delete
Selection, and Delete or Backspace on highlighted rows: when a layer or sublayer among the rows holds art, hidden,
locked or nested art included, dialog `confirm` asks "Delete this layer and its artwork?" for one layer, else "Delete
the selected items and their artwork?"; OK deletes the rows it asked about in that document, one undo step, and
Cancel keeps them; an empty layer, a layer with only guides, and groups or objects alone are deleted at once),
`layer.locate {id?}` (highlights the selected object's row; the panel opens the rows around it)
and `layer.clippingMask.toggle`.
- **Panel menu**: `layer.duplicate {ids?}`, `layer.merge {ids?}` (into the layer highlighted last, keeping the
stacking order), `layer.flatten {id?}` (every other visible layer's art into one layer; hidden layers are deleted,
@@ -4978,6 +5013,18 @@ used, as a transform's does.
{"name":"run_command","arguments":{"command":"object.transformEach","params":{"scaleH":50,"scaleV":50,"strokes":false}}}
```
## Free Distort on a turned bounding box
`object.distort` maps the corners of `from` (TL, TR, BR, BL) onto `corners`, which are page coordinates. With
`angle` (counter-clockwise degrees), `from` is a box in the frame turned by that angle, as a rotated object's bounding
box is; without `from`, that box is the selection's bounds measured in the turned frame. An `angle` that is not a
number is an error. Without `angle`, `from` is a box on the page, as before. The Free Transform tool's Perspective Distort and Free Distort send the selection's turned box
this way, so after a rotation they start from the corners the canvas shows.
```json
{"name":"run_command","arguments":{"command":"object.distort","params":{"from":[-100,0,0,100],"angle":90,"corners":[[0,100],[0,0],[120,-20],[100,100]]}}}
```
## Transform Each: Relative and Absolute
`object.transformEach` scales by percentages of each object's size (the dialog's Relative, the default), or with
@@ -5427,7 +5474,8 @@ The Selection & Anchor Display and General preferences apply to `pointer_gesture
scales it too; off (the default) it stays where it is. `artboard.duplicate`, `artboard.copy` and `artboard.cut` copy or
cut locked and hidden art only with it on. A `lockedAndHidden` param on any of these commands takes its place.
- `penRubberBand`, `curvatureRubberBand` (on by default): off, the Pen and Curvature tools draw no preview segment to
the pointer.
the pointer. With either off, the Pen, the Smart Pen (`penRubberBand`) and the Curvature tool (`curvatureRubberBand`)
still show the D / Angle / dX / dY readout at the pointer while `measurementLabels` is on.
- `showHandlesMultipleAnchors` (on by default): off, Direct Selection (and the Anchor Point tool, and the Pen with Alt)
shows and drags direction handles only while a single anchor is selected. On, the handles of the direct-selected
anchors, or of every anchor of a path selected as a whole, show and drag. `handleStyle` (`solid`, `hollow`, `large`) draws their ends (desktop app).
@@ -5644,6 +5692,13 @@ Pen's second anchor at (150, 431), in line with the square's centre.
Type → Font menus label a family by its native-language name when the font has one. `text.fontList` and
`text.setStyle {font}` always use the English (canonical) family name; a document may still name a font by any of
its aliases (`ヒラギノ角ゴシック` resolves to Hiragino Sans).
- `fontSamplesOnWhite` (off by default): Preferences › Type › Show samples on white. On, every font menu (the
Character panel, Control bar, Properties panel, Glyphs panel, the Composite Fonts and Dimension Tool Options dialogs, and Type → Font
in the in-window menu bar) draws each family's sample in dark type on a white area in every interface brightness. In
a menu row the white area leaves 2 pt above and below it, where a highlighted row's color shows; the names and the
rest of the menu keep the interface's colors. It has an effect only while `fontPreview` is on, and Preferences dims
its checkbox while previews are off. It is VectorCraft's own option. `prefs.set` refuses a value that is not a
boolean.
- `hyphenationExceptions` (empty by default): Preferences › Hyphenation › Exceptions. A comma-separated list of words,
matched without regard to case: a word with no hyphens is never hyphenated (`typography`), and a word with hyphens
breaks only where they are (`hap-pen`). `prefs.set` pushes the list into the hyphenator and reflows open documents.
@@ -6691,8 +6746,8 @@ no linked file, and `warnings` carries "an image couldn't be decoded and is miss
images.
DWG can't be written (no openly licensed writer exists): `document.formats` lists it under `unsupported` with that
hint, and exporting to it answers with the hint to export DXF. PICT files are not supported either and say so when
opened.
hint, and exporting to it answers with the hint to export DXF. PICT files open and place (see PICT import) but can't
be written.
```json
{"name":"run_command","arguments":{"command":"document.exportDxf","params":{"path":"/tmp/plan.dxf","version":"2013","unit":"mm","scale":10,"preserve":"editability"}}}
@@ -7106,6 +7161,36 @@ clipboard service offers it (the Windows desktop service doesn't read metafiles
{"name":"run_command","arguments":{"command":"file.place","params":{"path":"/tmp/chart.emf","at":[300,200]}}}
```
## PICT import
`document.open` and `file.place` read QuickDraw pictures, versions 1 and 2 (`.pct`, `.pic`, and `.pict`, which is
VectorCraft's own name for them), into one artboard, the picture's frame in points, and one layer. A file holds 512 bytes
of application data before the picture; a picture without them reads too. A version 2 picture also opens by its content
under any name. Opcodes and their data lengths follow Apple's
[Opcodes in Pictures](https://dev.os9.ca/techpubs/mac/QuickDraw/QuickDraw-461.html) and
[Version and Header Opcodes](https://dev.os9.ca/techpubs/mac/QuickDraw/QuickDraw-459.html):
- Lines, rectangles, rounded rectangles, ovals, arcs and wedges, polygons and regions become paths, in the order the
picture draws them. A framed shape is stroked inside its outline at the pen's size; a line is stroked below and to
the right of its points. Painted, filled and erased shapes are filled with the pen, fill or background pattern, and a
two-color pattern with the average of its colors.
- Text becomes point type in the font the picture names, at its size and style, read as Mac Roman.
- Bitmaps and pixel maps (1 to 8 bits with their color table, 16 and 32 bits, packed or not) become images, clipped to
their mask region. In the OR transfer mode, a bitmap's clear bits are left transparent. A QuickTime JPEG image
(opcode `0x8200`) becomes an image placed by its matrix.
- The clip region clips what follows it.
`file.place` places the picture as one group clipped to its frame. What isn't read comes back in `warnings`, once each:
inverted shapes, transfer modes other than a copy (drawn as a copy), QuickTime images in formats other than JPEG, and
regions or images past the reader's limits. A picture cut short keeps what came before it with a warning, and one that
draws nothing VectorCraft reads opens empty with a warning. A file that holds no picture is refused with
"not a PICT file". PICT can't be written: `document.export` to it is refused with "PICT files can be opened but not
written".
```json
{"name":"run_command","arguments":{"command":"file.place","params":{"path":"/tmp/logo.pct","at":[300,200]}}}
```
## HP-GL import
`document.open` and `file.place` read HP-GL/2 plot files (`.plt`, `.hpgl`, `.hgl`, `.hpg`) into one layer, with the
@@ -7964,6 +8049,42 @@ styles carry it, and Reset Panel sets it back to none. The change is one undo st
```json
{"name":"run_command","arguments":{"command":"text.setFormat","params":{"kashida":"medium"}}}
```
## Mojikumi Set
`text.setFormat {mojikumi: "none"|"yakumonoHankaku"|"gyomatsuYakumonoHankaku"|"gyomatsuYakumonoZenkaku"|"yakumonoZenkaku"|"lineEndHalf"}`
sets the Paragraph panel's Mojikumi Set (shown with the East Asian options) of the paragraphs of the selected type (or
`ids`, or the paragraphs a `start` / `end` range touches): how full-width Japanese punctuation is spaced. The menu lists
the five predefined sets the help page names, then Line-end Punctuation Half Width
(https://helpx.adobe.com/illustrator/desktop/design-with-text/edit-format-text/use-mojikumi-for-japanese-text-composition.html).
The spacing of each set below is VectorCraft's own rule. An opening bracket's empty half em is before it; a closing
bracket's, a comma's and a full stop's is after it; a middle dot (・) has a quarter em on each side.
- **None** sets every character at its full advance.
- **YakumonoHankaku** sets every opening and closing bracket, comma and full stop half width, takes a quarter em off
each side of a middle dot, and puts a quarter em between Japanese and Latin letters or digits.
- **GyomatsuYakumonoHankaku** keeps punctuation full width inside the line. An opening bracket starting a line is set
flush with the line's start, a closing bracket, comma or full stop ending a line is set half width, and a middle dot
ending a line loses the quarter em after it. A quarter em separates Japanese and Latin letters or digits.
- **GyomatsuYakumonoZenkaku** keeps punctuation full width everywhere, at a line's end too, with a quarter em between
Japanese and Latin letters or digits.
- **YakumonoZenkaku** keeps punctuation full width everywhere, with no added space between Japanese and Latin text; it
sets characters as None does.
- **Line-end Punctuation Half Width** (new type made with the Type tools and `text.create`) lets consecutive
punctuation share one half-em space, sets an opening bracket starting a line flush with its start and a closing
bracket, comma or full stop ending a line half width, and puts a quarter em between Japanese and Latin letters or
digits.
The space a set adds between Japanese and Latin text is not kept at a line's end. Both composers measure each line as it
is set, and vertical type follows the same rules down the column. Punctuation that Proportional Metrics re-spaced, and
tate-chu-yoko, keep their width. Documents from before the setting and imported text keep `none`, which isn't saved;
paragraph styles carry the set, and Reset Panel sets Line-end Punctuation Half Width. Any other value is refused and
the type is left as it was. One undo step. `.ai` editing data does not hold the set: a save reports a paragraph with
any set other than None or Line-end Punctuation Half Width as left out, and the paragraph reads back without it.
```json
{"name":"run_command","arguments":{"command":"text.setFormat","params":{"mojikumi":"yakumonoHankaku"}}}
```
## Kinsoku Set
`text.setFormat {kinsoku: "hard"|"soft"|"none"}` sets the Paragraph panel's Kinsoku Set of the selected type (or `ids`):
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -63,7 +63,7 @@ against Illustrator's public documentation; **estimated** unless noted.
| Middle Eastern: Kashidas | done | Paragraph Insert Kashidas sets the length for justified Arabic area type; Character-menu Kashidas allows or excludes selected characters, on by default. A kashida is inserted only between two allowed joined characters. The character switch is retained in character styles and the native file; the length is retained in paragraph styles and the native file. Paint-only harakat (coloured or hidden marks) stay in one shaping cluster so letters keep joining; when the character-level pass matches, a glyph may take a later in-cluster character's run only if GDEF names it a mark (class 3) and that character is a harakat—otherwise the cluster start (a mark may miss its colour; a base never takes a mark's). Inserted tatweels take the base letter's paint—not a trailing mark's. Fonts without GDEF and some AAT/`morx` ligatures (e.g. Geeza Pro Allah) can leave a mark painted as its letter. No Character-panel harakat colour command yet. Evidence: `tests::harakat`. [Public help](https://helpx.adobe.com/illustrator/desktop/design-with-text/fonts-and-scripts/justify-text-using-kashida-and-hyphenation.html). |
| Middle Eastern: Middle Eastern composers, split caret | missing | Character Direction is done; editable bidirectional SVG text remains incomplete. |
| CJK: input methods (marked text, candidate window) | done | |
| CJK: kinsoku (Hard, Soft, None), Line-end Punctuation Half Width, tate-chu-yoko (auto) | done / partial | custom kinsoku sets, the Mojikumi Settings dialog and the other mojikumi sets missing |
| CJK: kinsoku (Hard, Soft, None), the predefined mojikumi sets (None, YakumonoHankaku, GyomatsuYakumonoHankaku, GyomatsuYakumonoZenkaku, YakumonoZenkaku, with VectorCraft's own spacing for each) and Line-end Punctuation Half Width, tate-chu-yoko (auto) | done / partial | custom kinsoku sets, custom mojikumi sets and the Mojikumi Settings dialog missing |
| CJK: Kinsoku Shori Type (Push In First, Push Out First, Push Out Only) | done | Paragraph panel menu › Kinsoku Shori Type (`text.setFormat {kinsokuType}`), with the East Asian options ([Formatting Asian characters](https://helpx.adobe.com/illustrator/using/formatting-asian-characters.html)); Push Out Only is the default, and a push-in closes the line's gaps next to CJK characters by at most a tenth of an em each (VectorCraft's own limit). Evidence: `layout::wrapping_tests::kinsoku_shori_type_pushes_a_closing_bracket_in_or_out`, `tests::vertical::kinsoku_shori_type_pushes_a_closing_bracket_in_or_out`, `typecmd::area_tests::kinsoku_shori_type_is_set_per_paragraph_and_saved_only_when_not_push_out_only` |
| CJK: Proportional Metrics (`palt` in horizontal type, `vpal` in vertical type) | done | #966 |
| CJK: East Asian Type units (Q, Ha) | done | Preferences › Units › East Asian Type (`unitsAsianType`, Points by default) offers every unit and Q and Ha, a quarter of a millimetre each ([Scripting Guide](https://ai-scripting.docsforadobe.dev/scripting/measurementUnits/): 0.709 pt per Q; [InDesign's unit notation](https://helpx.adobe.com/in/indesign/desktop/layout-and-grid-tools/rulers-and-measure-tools/change-ruler-measurement-units.html): `q`, `h`). The public pages do not say which fields follow it, so no field uses it yet and that waits for a source. Evidence: `q_and_ha_are_a_quarter_millimetre`, `east_asian_type_unit_*` |
+1 -1
View File
@@ -235,7 +235,7 @@ tools, never checked side by side) isn't captured row by row.
| "intersect" label and snapping to path intersections | partial | #1658 (part of #1602): a point drawn with the Pen, the shape tools or the other drawing tools and an anchor dragged with Direct Selection snap to where paths and ruler guides cross; a moved selection's own anchors and the Width tool don't |
| Construction guides at preference angles while drawing | done | #506 |
| Line extension: the dragged end of a straight segment snaps to the segment's own direction at any angle, past its other end or short of it, with the guide along it | done | #2120; Direct Selection and Curvature, one anchor dragged (with several, the move has no single direction); nearer the horizontal or vertical through the other end, the point lines up with it ("align"), so a nearly level segment can still be straightened |
| Measurement labels while drawing, moving and resizing | done | sizes and offsets; the segment being drawn is labeled with its distance, angle and offsets by the Line Segment tool, and by the Pen, Curvature and Smart Pen tools with Enable Rubber Band on (#2983) |
| Measurement labels while drawing, moving and resizing | done | sizes and offsets; the segment being drawn is labeled with its distance, angle and offsets by the Line Segment tool, and by the Pen, Curvature and Smart Pen tools with Enable Rubber Band on or off (#2983) |
| Spacing guides (equal distances) | partial | for moves and bounding-box resizes (#394); not while drawing |
| Distance Guides: Alt/Option over another object, or an empty part of an artboard, shows the selection's distances to it (Smart Guides › Invoke Distance Guides) | done | Selection tool hover with Smart Guides on: the gap between facing edges, else the offsets of matching edges, to another object; the left, right, top and bottom distances to the artboard; labelled in the General unit. The selection is measured as a whole. Nothing while moving or nudging, which the public pages don't describe. [Use Distance Guides](https://helpx.adobe.com/illustrator/desktop/measure-and-align/grids-and-guides/use-distance-guides-for-accurate-placement.html), [Smart Guides options](https://helpx.adobe.com/illustrator/desktop/measure-and-align/grids-and-guides/smart-guides-options.html) |
| Snapping tolerance preference | done | |