mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-10 23:01:02 +00:00
Merge main into feat/native-save-precision
This commit is contained in:
@@ -156,6 +156,11 @@ dialog open); without `name` it names a new style made from the selection (`grap
|
||||
`ui.mergeGraphicStyles {names}` opens the same dialog to name the style `ui.dialog.confirm` merges from them
|
||||
(`graphicStyle.merge`). Deleting styles from the panel asks first with a `confirm` dialog (`graphicStyle.delete`).
|
||||
|
||||
Text styles: `ui.newCharStyle` and `ui.newParaStyle`, what Alt-click on New in the Character Styles and Paragraph
|
||||
Styles panels runs, open the `newTextStyle` dialog (field `name`) for a style made from the text selected when it
|
||||
opened; `ui.dialog.confirm` makes it with `charStyle.new` / `paraStyle.new` (a name another style has returns an error
|
||||
and keeps the dialog open).
|
||||
|
||||
Symbols: `ui.symbolOptions` opens the `symbolOptions` dialog (field `name`) that the Symbols panel's New Symbol asks
|
||||
first; `ui.dialog.confirm` makes the symbol from the selection with that name (`symbol.new`). F8 runs
|
||||
`ui.symbolOptions` without params.
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ How the web shell (`apps/vectorcraft-web/src/web.rs`) differs from desktop:
|
||||
The canvas is rasterized on the CPU (`vectorcraft-render`, vello_cpu); the GPU (wgpu, through eframe) only composites the canvas texture and draws the UI, so any GPU that can show the window will do. The desktop app picks the window's adapter itself (`apps/vectorcraft/src/gpu.rs`, eframe's `native_adapter_selector`) and logs every adapter it found and the one it uses.
|
||||
|
||||
- **Order:** adapters that report they can't present to the window are never tried; then the one `WGPU_ADAPTER_NAME` names; hardware before software (llvmpipe, WARP); the native backends (Vulkan, Metal, DX12) before OpenGL; with Automatic, the GPU the Wayland compositor draws with, then the GPU that drives a display, and among those the one that drives the primary display; then the power preference; then a GPU's DX12 adapter before its Vulkan one (Intel's Vulkan driver made the whole window flicker black, #545), keeping the system's order among equals.
|
||||
- **Windows backends:** Direct3D 12. OpenGL is listed beside it only when a start leaves an adapter out (a crash or a failed restart) or Direct3D 12 lists no adapter (Windows 7): wgpu's OpenGL backend keeps a hidden window whose thread pumps no messages, and the app hung on a switch to another input language (#4150, gfx-rs/wgpu#10504). Vulkan isn't started at all unless `WGPU_BACKEND` asks for it (`WGPU_BACKEND=vulkan`): creating a Vulkan instance loads every installed Vulkan driver into the process, and a faulty one (Intel's `igvk64.dll`, #806) crashed the app before its window appeared. After a start that crashed while it listed the Direct3D 12 adapters, later starts list OpenGL's alone (see the crash bullet below).
|
||||
- **Windows backends:** Direct3D 12. OpenGL is listed beside it only when a start leaves an adapter out (a crash or a failed restart), when `WGPU_ADAPTER_NAME` names an adapter, or when Direct3D 12 lists no hardware adapter (Windows 7, or a GPU without a Direct3D 12 driver, which then draws through OpenGL rather than on the CPU with WARP): wgpu's OpenGL backend keeps a hidden window whose thread pumps no messages, and the app hung on a switch to another input language (#4150, gfx-rs/wgpu#10504). Vulkan isn't started at all unless `WGPU_BACKEND` asks for it (`WGPU_BACKEND=vulkan`): creating a Vulkan instance loads every installed Vulkan driver into the process, and a faulty one (Intel's `igvk64.dll`, #806) crashed the app before its window appeared. After a start that crashed while it listed the Direct3D 12 adapters, later starts list OpenGL's alone (see the crash bullet below).
|
||||
- **The GPU that drives the display.** A GPU without a monitor is the wrong one even when it says it can show the window: on a desktop with a Ryzen's integrated GPU (no monitor) and an NVIDIA card driving both monitors, power saving picked the integrated GPU, Windows had to present every frame across adapters, and the integrated GPU's driver reset under that: the graphics device was lost, or the desktop's compositor went down and every monitor stayed black for minutes (pdfcraft#378). So Automatic asks the system which GPU drives which display and puts that GPU first; the power preference only orders the rest, and decides alone where the system can't say.
|
||||
- **Windows:** `EnumDisplayDevices` (the display devices attached to the desktop, and the primary one), through the `winsafe` crate; the PCI ids in each device id are matched against wgpu's adapters. The registry doesn't tell a user which adapter drives a display, and WMI reports a resolution for a GPU without a monitor, so neither is used.
|
||||
- **Linux:** the connected connectors in `/sys/class/drm` and their cards' PCI ids; a built-in panel (`eDP`, `LVDS`, `DSI`) counts as the primary display.
|
||||
|
||||
File diff suppressed because one or more lines are too long
+3
-1
File diff suppressed because one or more lines are too long
@@ -81,6 +81,15 @@ 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
|
||||
about 90 bytes an anchor; a 4000 × 3000 photo at High Fidelity Photo makes about 1.9 million.
|
||||
**Tracing in the background.** On the desktop a trace runs on a thread of its own, so the window
|
||||
keeps answering while a photo or a large image is traced (#3098). Make, Make and Expand, the task
|
||||
bar's Image Trace and the panel's Trace and presets start it. The status bar says "Tracing the
|
||||
image…", and after 0.4 s a progress window shows how many of its colours are traced, with Cancel
|
||||
(also Esc, `imageTrace.cancelRuns`) and Continue in Background (`imageTrace.hideRuns`). The result is
|
||||
one undo step, as before. A new trace of the same object replaces one still running. A trace whose
|
||||
image or settings changed meanwhile changes nothing, and the status bar says to trace it again.
|
||||
`imageTrace.make` and `imageTrace.makeAndExpand` from MCP, scripts and the control channel trace at
|
||||
once and return their result, as every trace on the web does.
|
||||
These controls use VectorCraft's existing tracing algorithm. Parameter effects follow its
|
||||
implementation; they do not claim pixel-identical results with another application.
|
||||
The terminology and general control behavior are described in the
|
||||
@@ -88,4 +97,5 @@ The terminology and general control behavior are described in the
|
||||
|
||||
Regression coverage: `crates/ui-egui/src/panels/image_trace.rs` tests opening the panel,
|
||||
a quick trace leaving it as it was, repeated opening, floating ownership, slider commits, visible threshold
|
||||
changes, undo, and the Properties entry point. Tracer tests live in `crates/trace/src/tests.rs`.
|
||||
changes, undo, and the Properties entry point. Tracing in the background:
|
||||
`crates/ui-egui/src/tests/trace_runs.rs`. Tracer tests live in `crates/trace/src/tests.rs`.
|
||||
|
||||
+64
-7
@@ -396,6 +396,9 @@ when given; `paint` lists the stroke options applied.
|
||||
A gradient given to several objects fits each one's own bounds; `paint.setFill` / `paint.setStroke` with
|
||||
`span: "selection"` place a linear or radial gradient once on the union of the targets' bounds instead, so one
|
||||
ramp runs across them.
|
||||
`paint.setFill` without `item` on a grayscale or 1-bit image sets the color the image is drawn in: each pixel takes
|
||||
the color as far as the pixel is dark, and white pixels are transparent. `none` removes the color. An image with an
|
||||
alpha channel takes only a spot color, black or white; a process color is refused.
|
||||
For `draw_shape` and `draw_path`, omitted paint fields inherit the current [new-art appearance](#new-art).
|
||||
For a filled shape or path without an outline, pass an explicit `fill` and `stroke: "none"`.
|
||||
Lines start with no fill and a visible stroke.
|
||||
@@ -422,9 +425,8 @@ objects' fills or strokes differ (`fillMixed` / `strokeMixed`, drawn as a "?" pr
|
||||
| `invoke_menu` | `{command, params?}` | Invokes a menu item by command id. Includes UI commands such as `view.*` and `window.*` in remote mode. |
|
||||
| `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}` | Opens any readable file as a new active document: `.vectorcraft`/`.drawcraft`, `.vctemplate`, `.svg`/`.svgz`, `.pdf`/`.ai`, `.ait`, `.eps`/`.epsf`, `.ps`, `.dxf`, `.emf`, `.wmf`, PNG, JPEG, GIF, WebP, TIFF, BMP, Targa (`.tga`/`.vda`/`.icb`/`.vst`), PSD/PSB (an image opens as a document of its pixel size; a Photoshop file as its merged image). 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). `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). 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. 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`). `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 warning for a top-level `compress`, `version`, `preview` or `precision`. 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. |
|
||||
| `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`, `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 and WMF 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. |
|
||||
| `open_file` | `{path}` | Opens any readable file as a new active document: `.vectorcraft`/`.drawcraft`, `.vctemplate`, `.svg`/`.svgz`, `.pdf`/`.ai`, `.ait`, `.eps`/`.epsf`, `.ps`, `.dxf`, `.emf`, `.wmf`, PNG, JPEG, GIF, WebP, TIFF, BMP, Targa (`.tga`/`.vda`/`.icb`/`.vst`), PCX, PSD/PSB (an image opens as a document of its pixel size; a Photoshop file as its merged image). 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). `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). 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. 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`). `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 warning for a top-level `compress`, `version`, `preview` or `precision`. 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. || `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`, `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 and WMF 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`); `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. |
|
||||
| `apply_effect` | `{effect?, params?, ids?}` | Appends a live effect. Without `effect`, returns the effect catalogue with parameters and defaults. |
|
||||
| `pathfinder` | `{operation, ids?}` | `unite`, `minusFront`, `intersect`, `exclude`, `divide`, `trim`, `merge`, `crop`, `outline`, `minusBack`. For a live version, apply the `pathfinder.*` effect to a group (`effect.apply` groups several loose selected objects first). |
|
||||
@@ -538,7 +540,9 @@ Colors blends, inversions and Recolor Artwork keep each colour's model (a blend
|
||||
Guide panel shows: the harmony rule's colours, base first, and per colour its row of `2·steps+1` variations
|
||||
(shades, cool or muted on the left, tints, warm or vivid on the right). With `limitTo` (a swatch library id or name,
|
||||
or `"document"` for the document's swatches) every colour snaps to the library's nearest colour (ΔE 2000), as the
|
||||
panel's Limit to Library does (`ui.colorGuideLimit`); Recolor Artwork's `limitTo` takes the same values.
|
||||
panel's Limit to Library does (`ui.colorGuideLimit`); Recolor Artwork's `limitTo` takes the same values. A `limitTo`
|
||||
that is not a string, such as `5`, names no library and gets the same error as an unknown name; `null` or `""` sets no
|
||||
limit.
|
||||
|
||||
Color Themes (local only: no online service) keeps five-colour themes in the preferences. `colorTheme.save
|
||||
{colors: [...]}` saves up to five colours as they are, `colorTheme.save {color, rule}` saves the five-colour theme a
|
||||
@@ -1839,6 +1843,13 @@ is linked to a swatch rewritten with another color keeps its row's new color, ev
|
||||
linked to the swatch, as does art whose color the row converts into the art's own color model. Without `group`,
|
||||
the swatch keeps its color and the recolored art is no longer linked to it.
|
||||
|
||||
The `recolor.*` commands refuse parameters of the wrong form. A `limitTo` or `method` that is not a string gets the
|
||||
error for an unknown library or method. Other wrong-form parameters get an error that names them.
|
||||
`includeImages`, `includePatterns`, a row's `exclude`, `order`, `saturationBrightness` and the `white`, `black` and
|
||||
`grays` switches of `preserve` must be true or false; `colors` and `seed` must be whole numbers; `group` and `rename`
|
||||
must be strings, `groupColors` must be an array and `preserve` must be an object. Each refusal leaves the document unchanged and records no undo step. A `null`
|
||||
counts as a value left out except for `recolor.apply`'s `model`, which must be a string when given.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"recolor.reduce","params":{"colors":2,"preserve":{"grays":true}}}}
|
||||
{"name":"run_command","arguments":{"command":"recolor.apply","params":{"map":[{"from":["cmyk 0 100 100 0","cmyk 0 40 40 0"],"to":"cmyk 100 50 0 0"}],"method":"scaleTints"}}}
|
||||
@@ -1912,6 +1923,11 @@ app (a library file as it is; a document's swatches or a library loaded from `da
|
||||
as `.vcswatches`) under a name no file there has, and lists it as User Defined from then on; until the app
|
||||
quits, commands given its loaded id use the copy → `{library, name, count, path, copied}` (`copied: false`
|
||||
when the folder already held the same file). Without a user library folder the command is disabled.
|
||||
These commands refuse a parameter of the wrong form with an error that names it: `library`, `apply`, `path`, `data`,
|
||||
`dataBase64`, `format` and `name` must be strings, `names` must be a list of names, and `focus`, `replace` and `user`
|
||||
must be true or false. `graphicStyle.saveLibrary` checks `path`, `name`, `names` and `user` the same way,
|
||||
`graphicStyle.addFromLibrary` checks `name`, `names`, `apply`, `add` and `ids` before it adds a style, and `graphicStyle.loadLibrary` checks `path`, `data`, `dataBase64` and `name`. A `null` for one of these parameters counts
|
||||
as a value left out.
|
||||
|
||||
## Graphic style libraries
|
||||
|
||||
@@ -2186,6 +2202,23 @@ whatever the options are then.
|
||||
{"name":"run_command","arguments":{"command":"object.pathfinder.options","params":{"precision":0.1,"removeUnpainted":true}}}
|
||||
```
|
||||
|
||||
Compound shapes (the Pathfinder panel menu, and Alt-clicking a Shape Mode button): `object.compoundShape.make
|
||||
{mode?, ids?}` makes the two or more selected objects (paths, compound paths, groups, compound shapes, type) the
|
||||
members of one live compound shape, each in shape mode `mode` (`"add"`, the default, `"subtract"`, `"intersect"` or
|
||||
`"exclude"`). It draws, prints and exports as the area its members make from the backmost up, painted with its own
|
||||
appearance, which it takes from the topmost member not in Subtract (with every member subtracting, the backmost); a
|
||||
fill or stroke given to it or to a member paints the compound shape. The members stay editable (Direct Selection,
|
||||
the Layers panel, isolation mode). `object.compoundShape.setMode {mode, ids?}` sets the mode of the members the
|
||||
selection is or is in, `object.compoundShape.release` gives the members back as they were, and
|
||||
`object.compoundShape.expand` turns each compound shape into the path, or compound path, of its area. A saved file
|
||||
keeps the compound shape (`compound_shape` on the group, `shape_mode` on each member); a mode the file doesn't name
|
||||
reads as Add.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"object.compoundShape.make","params":{"mode":"subtract"}}}
|
||||
{"name":"run_command","arguments":{"command":"object.compoundShape.expand","params":{}}}
|
||||
```
|
||||
|
||||
The Eyedropper: `appearance.copyFrom {source}` copies what the Eyedropper Options pick up and apply from `source` to the
|
||||
selection (`ids`); `reverse: true` copies the selection's attributes onto `source` (Alt-click), or with nothing selected
|
||||
what the last copy without `reverse` picked up (a copy made then, kept for the session), and `append: true` adds
|
||||
@@ -3104,6 +3137,10 @@ Pen's second anchor at (150, 431), in line with the square's centre.
|
||||
give its Kerning or Tracking field the keyboard focus with the value selected, or open its font family menu with the
|
||||
search field focused; each replies `{field: "kerning" | "tracking" | "fontName"}`. Without selected type or text the
|
||||
Type tool edits, the panel shows and the command fails.
|
||||
shows it, in the same text; at a caret it leaves the text as it is. The UI command `type.underline` (Cmd+Shift+U,
|
||||
in remote mode `press_key {key: "U", mods: {cmd: true, shift: true}}` or `invoke_menu`) does what the Character
|
||||
panel's Underline button does: it underlines the Type tool's selected text or the selected type objects, or removes
|
||||
the underline when the text the panel shows is underlined, and returns whether the text is now underlined.
|
||||
- `missingGlyphProtection` (on by default): `text.setStyle` and `text.setRangeStyle` changing the font leave the
|
||||
characters the new font has no glyph for in the font that had one.
|
||||
- `typeSelectionByPathOnly` (off by default): on, the Selection tools (`pointer_gesture` with `selection`, and the
|
||||
@@ -3274,6 +3311,11 @@ each range, and a size of 0 or less is read as 1 pt.
|
||||
The desktop app's `file.newDialog` (Cmd/Ctrl+N) opens the New Document dialog on the first Recent entry, or on the
|
||||
Print category's Letter while Recent is empty. `file.newWithoutDialog` (Cmd/Ctrl+Alt+N) runs `file.new` with those
|
||||
settings and the next untitled name, without opening the dialog, and returns what `file.new` returns.
|
||||
`window.nextDocument` (Cmd/Ctrl+F6) and `window.previousDocument` (Cmd/Ctrl+Shift+F6) make the next and the previous
|
||||
open document in tab order the current one, as a click on its tab does, and return `{index}`. After the last document
|
||||
comes the first, and before the first document comes the last. From the Home screen they go to the first and the last
|
||||
document. With no document open they fail with "no document open". `document.activate {index}` makes a given document
|
||||
the current one.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"file.new","params":{"preset":"A4","orientation":"landscape","artboards":4,"artboardLayout":{"columns":2},"bleed":9}}}
|
||||
@@ -3554,7 +3596,7 @@ image `object.rasterize` makes with the same options.
|
||||
## Glass textures
|
||||
|
||||
Glass (`distort.glass`) takes an image file as its surface in `params.textureImage`, as `{path}` or
|
||||
`{name?, dataBase64}`: a PNG, JPEG, GIF, WebP, TIFF, BMP, Targa, PSD or PSB file, decoded within the pixel allowance the
|
||||
`{name?, dataBase64}`: a PNG, JPEG, GIF, WebP, TIFF, BMP, Targa, PSD, PSB or PCX file, decoded within the pixel allowance the
|
||||
renderer draws images in, counted as RGBA. `effect.apply` and `effect.setParams` store the image's gray levels in the effect as a grayscale PNG
|
||||
in base64 and set `texture: "loaded"` unless the params give a `texture`. `effect.list` reports the stored string,
|
||||
and a command given that string stores it unchanged. Any other string, a file that is not an image, or an image past
|
||||
@@ -4383,7 +4425,9 @@ As in the reference app, dragging a bounding-box handle of area type resizes its
|
||||
type: the Selection tool sends `object.transform {matrix, typeAreas: true}`, which reshapes the frame of each area
|
||||
type object it transforms (other objects, type inside groups and point type transform as usual) and reflows the
|
||||
text at its size, through its thread too. `text.reshapeArea {id, anchors: [[subpath, anchor]…], dx, dy}` moves
|
||||
frame anchors with their handles (Direct Selection dragging a corner, or an edge's two ends), and
|
||||
frame anchors with their handles (Direct Selection dragging a corner, an edge's two ends or the frame anchors its
|
||||
marquee selected, and the arrow keys nudging those); `{items: [{id, anchors}…], dx, dy}` moves the anchors of several
|
||||
frames in one step, and
|
||||
`text.areaOptions {width?, height?}` sizes the area from its top-left corner (the query returns both). Each is one
|
||||
undo step. Object › Transform › Scale, the Scale tool and the Transform panel still scale the type.
|
||||
`text.reshapePath {id, anchors: [[subpath, anchor]…], dx, dy}` does the same for the path of type on a path
|
||||
@@ -4541,7 +4585,10 @@ The letter and line counts are rounded, and every value is clamped to its range.
|
||||
listed word. The options are saved with the paragraph (`hyphenation` in `para`) only when they differ from the
|
||||
defaults, and paragraph styles carry them (`paraStyle.new {attrs: {hyphenation: {words_longer_than: 8}}}`). One undo
|
||||
step. `ui.hyphenation` opens the Hyphenation dialog on the values the Paragraph panel shows; OK sends the values that
|
||||
changed.
|
||||
changed. The UI command `type.hyphenate` (Cmd+Alt+Shift+H, in remote mode `press_key {key: "H", mods: {cmd: true,
|
||||
alt: true, shift: true}}` or `invoke_menu`) does what the Hyphenate checkbox does: it turns `hyphenate` off when
|
||||
every paragraph of the selected type (or every paragraph the Type tool's selection touches) hyphenates, else on, and
|
||||
returns the new value.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"text.setFormat","params":{"hyphenate":true,"wordsLongerThan":8,"hyphenLimit":2}}}
|
||||
@@ -4947,6 +4994,13 @@ inserting `\n`) continues the style of the paragraph it splits; deleting a break
|
||||
`text.setText` gives every paragraph the first one's attributes. Threaded text keeps each paragraph's attributes as
|
||||
the story re-flows (a paragraph split between frames has them in both).
|
||||
|
||||
`ui.newCharStyle` and `ui.newParaStyle` (Alt-click on New in the Character Styles or Paragraph Styles panel) open
|
||||
New Character Style or New Paragraph Style (dialog `newTextStyle`, field `name`) with the name `charStyle.new {}` or
|
||||
`paraStyle.new {}` would give the style, and add no style yet. OK runs `charStyle.new` or `paraStyle.new` with the
|
||||
name and the Type tool's selection as it was when the dialog opened (else the selected type); a name another style
|
||||
has, or an empty one, keeps the dialog open, and Cancel adds no style. A plain click on New still makes the style at
|
||||
once.
|
||||
|
||||
In the native file a text object's `para` holds the first paragraph's attributes and `paras` (left out when every
|
||||
paragraph is alike) one entry per paragraph, so older readers keep the first paragraph's. SVG export anchors each
|
||||
centred or right-aligned line on its own (`<tspan text-anchor>`), and SVG import gives each line's paragraph its
|
||||
@@ -5492,6 +5546,9 @@ Single-line fills each line as far as it goes. Point type and type on a path hav
|
||||
give the same result there. A paragraph whose characters differ in line metrics (type size, font, leading or vertical
|
||||
scale, or an inline graphic taller than the text) is composed with Every-line in rectangular area type, rows and
|
||||
columns included; in area type of another shape, or with text wrap, it falls back to Single-line.
|
||||
The UI command `type.lineComposer` (Cmd+Alt+Shift+C, in remote mode `press_key {key: "C", mods: {cmd: true, alt: true,
|
||||
shift: true}}` or `invoke_menu`) sets `singleLine` when every paragraph of the selected type (or every paragraph the
|
||||
Type tool's selection touches) uses Every-line, else `everyLine`, and returns the composer it set.
|
||||
|
||||
```json
|
||||
{"name":"run_command","arguments":{"command":"text.setFormat","params":{"ids":[7],"composer":"singleLine"}}}
|
||||
|
||||
+1
-1
@@ -164,7 +164,7 @@ to the target triple, so host build scripts aren't affected.
|
||||
AppStream metainfo, the MIME type for VectorCraft documents, the icons and the licence files.
|
||||
|
||||
**Document types.** The desktop entry's `MimeType` lists every format File › Open reads but PSD,
|
||||
PSB, `.ps` PostScript and Targa, so file managers list VectorCraft under Open With for them.
|
||||
PSB, `.ps` PostScript, Targa and PCX, so file managers list VectorCraft under Open With for them.
|
||||
`ai.storyteller.vectorcraft.mime.xml` declares the types that shared-mime-info lacks: VectorCraft
|
||||
documents and templates, `.ait` templates and Affinity files (`application/x-affinity`). An `.af`
|
||||
file gets the Affinity type by its content, and `.afdesign` and `.afpub` files by their extension.
|
||||
|
||||
+3
-2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+3
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user