While the app draws a document on screen, the live-effect plug-in runs of
its first view share a 2,000 ms budget (VectorCraft's own value); each run
takes the lesser of its 5,000 ms limit and what is left. A stage left out
for time, or one that times out, fails, has no plug-in or meets Safe Mode,
draws its input art unchanged and is deferred, and the status bar says how
many. Later drawings leave a deferred stage as it is until its input or
parameters change.
- effect.deferredStatus lists the deferred stages with object, effect
index, fill or stroke, plug-in and reason, objects in symbol, pattern,
brush and opacity-mask art included.
- Effect › Refresh Deferred Effects (effect.refreshDeferred {ids?}) runs
them again with a fresh budget and returns {refreshed, stillDeferred,
failed}.
- Each document has its own budget and deferred stages; exports, Expand
Appearance and commands run every stage under the per-call limit.
- The web build has no clock for the budget: its first view runs no
plug-in effect, and a refresh runs them.
Docs: docs/mcp.md, docs/plugins.md, docs/target-app-parity.md.
Break Link to Symbol on a selected group selected the art of every
instance it expanded that was itself shown and unlocked, including art in
a hidden or locked group inside the selection. The art now goes into the
selection only when it and every group and layer holding it are shown and
unlocked, the check Select All uses (select::is_selectable).
The text fields and menus of the Basic Character Formats, Advanced
Character Formats, Character Color and OpenType Features sections, and
the Style Name field of Character Style Options, are now named by the
label beside them, so screen readers announce them. This covers both
Character Style Options and New Character Style, which share the
sections. The New Character Style UI test runs with the accessibility
check on again, and a new test opens every section of both dialogs and
checks that no input is unnamed.
A PDF, an EPS or .ai without ruler units, a raster image, a metafile, an
Affinity file or an importer plug-in's document opened (and reverted) in
points whatever the General unit was. They now open in the General unit,
as the reference app opens files that record no unit. Native, SVG and DXF
files and a .ai or EPS with %AI5_RulerUnits keep their own units. Only the
displayed units change, not the art.
A popup measures its list on the first frame, when the scroll area does
not yet show its bar. When the bar then appeared, its column took its
width from the items, and the widest label wrapped onto two lines:
Distort & Transform in the Add New Effect menu, and Black and White Logo
in the Image Trace presets, in short windows.
menu_scroll now lays the items out at least as wide as on the popup's
first frame, so the bar's column widens the popup instead. That width
is kept until the popup closes and is never wider than the window has
room for. The items are laid out in the same child Ui on every frame,
so their ids do not change when the width does.
A click with the Reshape tool on an anchor of a selected path makes it
the focal point, and a click on a segment adds an anchor there that
becomes the focal point. Shift-click adds an anchor or a point on a
segment to the focal points, or removes an anchor that is one already.
Each focal point shows a filled anchor square in a larger hollow one.
A drag from a focal point moves all of them; a drag from another point
moves that point alone, and Shift only keeps the drag's angle.
path.reshape takes the other focal points as focal: [[subpath,
anchor]...]. Anchors that are not direct-selected stay in place, and so
do the ends of an open path unless they are focal points. A selected
anchor between two focal points moves by the whole drag, and one
between a focal point and an anchor that stays takes u² (3 - 2u) of
the drag, as before. A closed subpath with every anchor selected moves
whole: a Reshape drag on a fully selected closed path, and path.reshape
without radius on a closed path selected whole or not selected, move
the whole path instead of a local area. With radius, only the grabbed
point's subpath changes, with the falloff as before.
- An anchor added on a segment of a partly selected path is selected,
and the selected anchors and segments after it keep their points.
- A focal pair that names no anchor is refused ("`focal` names [0, 7],
which is not an anchor of the path"), and so is focal with radius.
Docs: docs/mcp.md, docs/target-app-parity.md.
Found while testing crates/engine/src/cmd/graph/data.rs:51 (parse_csv); written by crates/doc/src/graph.rs:497 (GraphSpec::to_csv)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Break Link to Symbol on a selected group, and Delete Symbol with its
instances expanded, turned a hidden or locked instance into visible,
unlocked art. The art now keeps the instance's hidden and locked state,
as Object > Expand does, and Break Link leaves hidden or locked art out of
the selection.
Opening a native file read its JSON twice: once for the document and once
more for the saved pdfCompatible preference. The format crate now takes
the preference from craft-vectorcraft-format's
Contents::read_with_pdf_preference (craft-libs#562), so a file is read in
one pass.
That method refuses a pdfCompatible that is not a boolean, which main
opens by skipping the value and falling back to whether the file carries
a PDF. Such a file, or one with any other data error, is read again with
Contents::read and scanned for the preference as before, so the files
that open today still open with the same result.
The craft-vectorcraft-format pin moves to 1b34eba41e, the craft-libs
revision craft-update already uses.
Each artboard can carry a guide label: one of the layer colors or a
custom RGB. Guides that belong to an artboard draw in its label color,
and guides without an artboard, or on an artboard without a label, keep
the guide color from the preferences. Selected guides still draw in the
selection color.
- Artboard Options has a Guide Label row (None, the layer colors with
swatches, or Custom with a color swatch).
- artboard.new and artboard.setProps take guideLabel: null, a layer
color's name, or #rrggbb. Any other value is an error. The inspect
summary lists guideLabel when one is set.
- The native format saves the label and skips it when unset; a preset
index outside the layer colors reads as no label.
- artboard.setProps no longer adds an undo step when nothing changes.
Docs: docs/mcp.md, docs/target-app-parity.md.
A warp of type may now spend up to four checks (its warp and its saved
grid, each with and without strokes). A try after the first is only
made while more checks are left than there are envelopes of type and
warped text objects still to come, so one envelope's retries don't use
up the checks of the others.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summing only the end rows and columns let a grid symmetric about its
middle (a mesh bent halfway round) read by rounding, so it came out
turned or not depending on where it sat on the page. Every row and
column is now summed, a sum shorter than 1% of its parts (or than the
grid's reach) counts as no direction and falls back to the first row or
column, and the same comparison decides both cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With Distort Appearance, an envelope's contents map from the box the
file measured for them: their bounds with their strokes or without
them. For type, the size the file saves for that box is often out of
date, so it can't say which. Envelopes of type are now checked both
ways: as before, and mapping from their bounds with their strokes.
Whichever draws as the drawn art opens live.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An envelope's mesh is turned upright by which way its rows and columns
run. That was read from the first row alone, so a warp bent past halfway
(its end columns leaning more than 45 degrees) read as turned round and
mapped its contents across instead of along. Read it from the first and
last rows and columns added up instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A warp of type whose own warp doesn't draw as its drawn art is checked
again as a mesh envelope on the grid the editing data saves for it, its
points and handles as saved. Where that draws as the drawn art, it opens
live in its place: the type stays editable in that shape, and the warp's
style and bend are lost.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The panel's note and the doc comment on ui.copyScriptConsole now say the
count of dropped and cut lines appears only when there are any, and the
returned lines count leaves that line out.
A copy of every Script Console line starts with the count of dropped and
cut lines only when there are any, and the returned lines count leaves
that line out. The end-line text is described without a code span that
ends in a space.
A scrolling menu list took its height from its own top down to the
window's bottom bars. egui picks a popup's side from its size on the
previous frame and moves a popup that does not fit back into the
window, so the list's height changed with where the popup was drawn.
In a short window the Add New Effect menu and other long menus moved
between two places while open, and a menu that did not fit crept a
few points per frame.
The list now takes its height from the room below and above the
button, row or point it opens from: below while that side leaves the
120 pt minimum, otherwise on the side with more room. A submenu
measures down from its row's top or up from its row's bottom. The
change is in menu_scroll, so it applies to every menu built on it.
The text document reader set a type stroke's paint and weight but never
its cap, join or miter limit, so every stroked text object imported from
a .ai or EPS editing copy drew with a miter join at a limit of 10. Type
the file strokes with round joins, or with a miter limit of 4 or less,
drew long spikes at its sharp corners.
Keys 61, 62 and 64 of a run's character attributes (the run, its
character style, then the document defaults) are now read as the
stroke's cap (0 butt, 1 round, 2 projecting), join (0 miter, 1 round,
2 bevel) and miter limit, as PostScript numbers caps and joins. In the
users' files the page strokes type with exactly these settings. Other
values keep the defaults, a miter limit is capped at 500, and type
without a stroke keeps the defaults.
- ate.rs: Style reads the three keys and char_style passes them on,
with a unit test over defaults, character styles, run overrides,
hostile values and unstroked type.
- tests_native.rs: an imported story with round, bevel, default and
unstroked runs.
- docs/file-format-parity.md: revision row, status line, one line on
the mapping.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Part of #6435. An optional VectorCraft feature: the Preferences dialog's
Export Preferences... saves the applied preferences to a JSON file (the
web build downloads it), and Import Preferences... applies such a file and
shows the imported values. They run the new commands prefs.export {path?}
and prefs.import {path | data}.
The file holds every preference prefs.list lists and the eyedropper,
perspectiveWidget, pathfinder and glyphSnap groups, without the four
folder preferences and saved presets. prefs.import reads at most 1 MB and
checks every value first: another format, a newer version, an unknown
preference, a bad value or a folder preference is an error, and nothing
changes. It keeps the open document's units, records no undo step, and is
refused as a command.batch step. prefs.set now rejects a group value that
is not an object.
With sizeTileToArt on, pattern.options ignores width and height for sizing but
still rejects a value that is not a positive number, such as width 0, and
changes nothing.
With View > Pixel Preview on, the tools still snapped to Smart Guides
and showed their guides; only the Object Highlighting outline was
hidden. Work with Smart Guides says Smart Guides cannot be used while
Snap to Grid or Pixel Preview is on.
ViewInfo has a pixel_preview field, and Session::with_tool_cx turns
Smart Guides (and Snap to Glyph, which needs them) off in the tools'
context while it is set. VectorcraftApp::view_info passes View > Pixel
Preview. View > Smart Guides keeps its setting.
Docs: docs/target-app-parity.md.
A brick tileType or gridType with brickOffset omitted or null sets the
offset to 0.5. While sizeTileToArt is on, every pattern.options call
sizes the tile to the art plus hSpacing and vSpacing again and ignores
width and height, so a new hSpacing changes the tile's width.
Scripts write to a new Script Console with $.write(...values) and
$.writeln(...values), each value as String(value) gives it. vc.log
entries, a run's uncaught error as name:line:column: message, and a
start, end and report line for each run go there too. The report line
gives the run's time, host calls and slowest commands.
- The console keeps at most 2,048 lines and 1 MiB of text, dropping the
oldest and counting what it dropped. A line is cut at 4,096 bytes and
a script's name at 256 bytes, with a count of cut lines. Line feeds,
carriage returns and CRLF break lines; other control characters show
as Unicode Control Pictures.
- script.run's result and scriptReport gain runTimeMs, timingAvailable,
hostCallCounts, slowestCommands and the run's own console. A failed
run's report has them too.
- script.console and script.console.clear read and empty the console;
ui.copyScriptConsole {first?, last?} copies lines as the panel shows
them.
- The panel lays out only the rows in view, selects with click and
Shift-click, and has Clear, Copy Selected and Copy All. Output goes on
while it is closed, and Clear works during a run.
Docs: docs/mcp.md, docs/gaps.md, docs/roadmap.md,
docs/target-app-parity.md.