With Double Click To Isolate on, the Selection tool isolated groups only. A
double-click on a single path, compound path, image, mesh or placed file now
isolates it too, as the public documentation describes. Type still switches to
the Type tool; blends, envelopes, repeats and symbol instances keep their own
editing modes.
While a single object is isolated only it is hit, marqueed and taken by Select
All, new art goes beside it in its group or layer, and a double-click on the
empty canvas leaves with it selected. object.isolate accepts any object except
type.
Each pointer move of a drag applies the move to the interaction's
snapshot, so the dragged object is a new node in every frame. The
renderer kept the rasters of an object's drop shadows, outer glows and
filtered content (Gaussian Blur, Feather and the Photoshop-style
filters) only for the same node, so every frame of a drag ran those
effects again. On main, a moved frame of texture_drag_perf (a CMYK
rounded rectangle at 190.07% and DPI 1.5 in an 1800 x 1500 view) took
112 to 197 ms in a release build.
The canvas now renders with RenderOptions::interacting while a drag or
a dialog's preview is in progress. When an object misses its cached
raster in such a frame, the renderer takes the raster an earlier frame
made for an object with the same id, slot and ink at the same zoom and
rotation, made by the same effects from content of the same size (to
within 0.000001 pt). It draws the object's content into a raster
placed as that one was and compares the pixels byte for byte (only the
alpha under a shadow or glow). For Feather it also compares the points
of the clip outline, to within 0.000001 pt. When they match, the old
raster is drawn at the new place, rounded to a whole pixel, as a pan
draws a cached raster. Content under De-Interlace never takes a moved
raster, and a raster made over moved rasters counts as moved itself.
A frame rendered without interacting never draws such a raster, or a
raster made over one: the frame after the drag runs the effects again
and draws what a fresh renderer draws. The canvas's cache key includes
whether an interaction is in progress. On the desktop, the canvas
sends the frame after an interaction to the render worker when the
frame shown drew moved rasters. Each cached raster keeps the content it
was made from, within the existing 512 MiB budget. The pixels kept
with a filtered raster take as many bytes as the raster, and the alpha
kept with a shadow or glow takes a quarter as many as the shadow.
texture_drag_perf now renders a drag's frames as the canvas does, then
the frame after the drag, and that frame once more with every raster
cached. A moved frame now takes 20 to 26 ms, close to the 18 to 25 ms
of the cached frame; the frame after the drag takes 110 to 189 ms.
Docs: docs/target-app-parity.md.
--control took the next argument as its port and dropped it when it wasn't a number, so the app
started without a control server and `--control --automation-read-root DIR` opened DIR as a
document. automation_args::ControlArg now reads --control <port> or --control=<port> once and
requires a port from 1 to 65535; VECTORCRAFT_CONTROL_PORT must be one too, checked only when
--control isn't given so --control and --version win over a bad value. Errors go through the
same exit as the root flags (#1157).
Tests: unit tests in automation_args.rs; tests/automation_args.rs runs the binary for each bad
form and checks the exact message and a prompt failing exit.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A .ai file with placed files opened from its PDF part (no guides, no sublayers,
no hidden objects), because the editing-data reader stopped at them.
- Lexer: a placed file's preview section is one token (it was skipped).
- Reader: %AI5_BeginPlace ... ~ becomes a linked image with the file's path,
showing the preview the data keeps of it (premultiplied ARGB, capped at
MAX_PIXELS, its rows checked against the bytes there), in its place: the
matrix takes the file's pixels from the canvas, where they start at the point
of art space's origin. A placed file without a preview, a path or a matrix
still makes the file open from its PDF part.
- The open result lists one warning saying linked pictures show the
low-resolution preview until their files are found (rows in the catalogs).
- Engine: a link nothing is known of whose image shows a preview is read where
it is found as the document opens, into the image's bounds, and isn't
reported as modified.
- Tests: lexer, reader (hand-written data), engine open with the link missing
and found, fuzz tokens.
- Docs: file-format-parity, target-app-parity, gaps, ROADMAP.
A PDF-compatible .ai opens on its trim boxes, its editor's artboards,
with the bleed boxes round them as the document's bleed (#1349). A PDF
saved with its editing data (#1345) keeps that data under
AIPDFPrivateData keys, which has_illustrator_data didn't look for, so
such a PDF with a bleed still opened on its crop box: the artboard took
the bleed in and the editing data was refused as being for a different
page. has_illustrator_data now finds either key. has_private_data, which
also decides how a page is clipped, is unchanged.
Test: a_file_with_a_bleed_opens_on_its_artboard_with_the_bleed_round_it
(the .ai case, and the same hand-written file with AIPDFPrivateData).
Object › Align ran object.align without to, so it aligned to the key
object while there was one and otherwise to the selection. With Align
to Artboard chosen it aligned two objects to the selection's bounds,
and it left a single selected object where it was, while the align
buttons of the Align panel, the Control bar and the Properties panel
move that object to the active artboard. The Align To choice was kept
in egui's temporary memory, so it went back to Align to Selection at
each launch, and ui.inspect did not report it.
The choice is now the UiState field align_to, which the desktop app
saves with its preferences and ui.inspect reports. A saved value other
than "artboard" reads as Selection, and the other preferences still
load. Object › Align now sends the to that the align buttons send: the
artboard when one object is selected, else the key object while there
is one, else the Align To choice. With anchor points selected it sends
its parameters as before, and the points align to their own bounds.
While one object is selected, the Align To row shows Artboard. Agents'
object.align calls without to keep the engine's default.
Docs: docs/control-protocol.md, docs/target-app-parity.md.
Preferences › Appearance of Black › On Screen was stored and never read.
Display All Blacks Accurately (the default) shows pure CMYK black, black
ink alone at 100%, through the working CMYK profile, a dark grey, as the
canvas always did. Display All Blacks as Rich Black now shows it on the
canvas as RGB black: fills, strokes, type, gradient stops, effect colours
and pattern tiles, and in CMYK documents drawn by ink planes a pixel
whose inks come out as black ink alone. Rich blacks, black tints and
placed images show the same either way; exports and printing are
unchanged (Printing / Exporting is a separate option).
The renderer gets RenderOptions::rich_black, painted with a new
Ink::RichBlack (screen colours with pure black as RGB black) and applied
by ink::compose. The canvas sets it from blackOnScreen and keeps it in
its cache key, so changing the preference redraws.
A headless frame test reads the canvas raster: K100 shows its profile
grey by default, RGB black with rich, a rich black unchanged, and grey
again with accurate. A render test covers the opaque and ink-plane paths
and checks that rich blacks, tints and images don't change.
Docs: docs/mcp.md (blackOnScreen), docs/target-app-parity.md,
docs/gaps.md, docs/ui-parity.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With anchors of one path direct-selected and another object selected
whole, the arrow keys (object.nudge), path.moveAnchors and a Direct
Selection drag of the selected anchors moved that object without its
pattern tiles, whatever General › Transform Pattern Tiles was set to.
When the same object was selected on its own, the arrow keys and a
Direct Selection drag followed the preference. path.moveAnchors left
the tiles in place in that case too.
path.moveAnchors now follows the preference for the objects it moves
whole, as the transforms, Align and Distribute do. path.moveAnchors
and object.nudge also take a `patterns` param for one call. When those
objects use a pattern, the journal records the choice, and a recorded
action plays back with it. Partly selected paths still move only their
selected anchors.
Docs: docs/mcp.md (transformPatternTiles), docs/target-app-parity.md.
These commands moved selected objects into a hidden or locked layer,
or hid them, and left them selected, with the key object still set
when it was one of them:
- a row dragged into a hidden layer or group (layer.move);
- node.move into a hidden or locked layer or group;
- Merge Selected into a hidden or locked layer;
- Flatten Artwork into a locked layer;
- Collect in New Layer, when the topmost row it collects is in a
hidden or locked layer;
- applying a data set that hides bound objects (dataset.select,
dataset.next, dataset.prev).
They now call Selection::deselect_uneditable after the change, as
layer.setProps, layer.hideOthers and layer.lockOthers do. Every
selected object left hidden or locked is deselected, and the key
object is cleared when it is one of them. Undo restores the objects
and selects them again with the key object. A row drag into a hidden
layer and node.move into a hidden or locked layer still succeed. The
params text of layer.move, node.move, layer.merge, layer.flatten,
layer.collectInNew and dataset.select describes the deselection.
The Layers panel section of docs/mcp.md said that node.move has the
same rules as layer.move; it now says that node.move also moves a row
into a locked layer or group, which layer.move refuses.
Docs: docs/mcp.md, docs/target-app-parity.md.
A PDF saved with the reference app's editing data keeps that data in
streams named AIPDFPrivateData1, AIPDFPrivateData2, ..., where a .ai
file uses AIPrivateData1, AIPrivateData2, .... illustrator_data read
only the .ai names, so such a PDF opened like any other PDF: plain
groups opened ungrouped, and hidden objects and guides were missing. The
import gave no warning that the PDF's editing data went unread.
illustrator_data now reads the AIPDFPrivateData streams when the file
has no AIPrivateData1, and the PDF opens from its editing data as a .ai
file does. editingData: false still opens it like any other PDF.
has_private_data still looks for AIPrivateData keys only.
layered_ai also returns whether it read the layers. When it did, art
reaching past a PDF's page opens whole, and through_editing_data drops
the PDF importer's note that such art was clipped (PAST_PAGE_NOTE, now
public) as it drops the off-artboard note. When it didn't, both notes
stay. On main, a .ai whose editing data can't be decoded or has no
layers opened from its PDF part without the off-artboard note.
testkit::ai::pdf writes the .ai file of testkit::ai::ai with the PDF
key names. The editing-data tests open it as a PDF, and the import fuzz
test opens the damaged sample as a PDF too.
Docs: the document.open params, docs/mcp.md,
docs/file-format-parity.md, docs/gaps.md (G9: the export direction of
#868 remains), one evidence line in docs/target-app-parity.md, and #868
moved from layer structure to editing data in the File formats row of
docs/target-app-parity.md and in docs/roadmap.md.
A PDF-compatible .ai with a bleed writes its PDF part's page as the
artboard grown by the bleed: the crop box takes the bleed in, the trim
box is the artboard and the bleed box the bleed. The importer made the
crop box the artboard, so the bleed opened as more white page with no
bleed guide; and since the editing data's artboard no longer matched
that page, its layers weren't read either ("its editing data is for a
different page").
Opening a PDF-compatible .ai with the crop box (the default) now takes
its trim boxes as the artboards. Any import on the trim boxes (Crop To
› Trim, for a PDF too) sets the document's bleed to how far the bleed
boxes reach past them on each side (ISO 32000-1, 14.11.2), kept to
0–72 pt, and the document read from the editing data keeps it. Art in
the bleed shows outside the artboard, within the bleed guide. Plain
PDFs still open on their crop box by default, and Place is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a Korean catalog (crates/ui-egui/src/i18n/ko.tsv, 4,151 rows) covering
every menu string, every tl! literal and the status and error messages, and
register `ko` in i18n::LANGUAGES (plural_none; every ko-* locale resolves).
- tests: korean_reads_as_korean, ko locale tags, ko in KEEPS_MENU_NAMES and
COMPLETE_MESSAGES; is_cjk covers Hangul so the bundled-font glyph check
leaves Hangul to installed fonts, as it does CJK without craft-fonts.
- Hangul is drawn with an installed system font on the desktop; the web
build still needs a Korean UI face in craft-fonts.
- docs: localization-parity (Korean row, 12-language score 54% -> 63%,
60-100 h), ROADMAP, README, development.md, gaps.md G16,
target-app-parity.
Clean-room: written from the meaning of the English strings in ordinary
Korean vocabulary; no other product's Korean localisation was used.
AI-drafted; native-speaker review welcome.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Simplify and Add Anchor Points edited the document whenever the
selection held a path, so a call that changed no path still recorded
an undo step, emptied Redo, marked the document modified and turned
the selected live shapes into plain paths. OK in the Simplify dialog
did the same. Simplify at its default options leaves a rectangle, a
star, a line and a path with one anchor as they are, and Add Anchor
Points leaves a path with one anchor as it is.
Both commands go through edit_paths, which now computes the new paths
before it edits the document. When no path changes, the command
returns without editing the document, and the reply
({ids, before, after}) has the same form and counts as before. When
some paths change, the command replaces only those paths and records
one undo step, so a path that Simplify leaves as it is keeps its live
shape.
One line in the evidence list of docs/target-app-parity.md names the
commands.
Disable, Enable, Unlink and Link Opacity Mask and Opacity Mask Options
(transparency.setOpacityMask) edited the document whenever a target
had an opacity mask, even when every mask already had the flags the
call set. Such a call recorded an undo step, emptied Redo and marked
the document modified.
When every mask a call acts on has those flags already, the call now
returns without editing the document, whether it acts on the
selection, on id or ids, or on the object whose mask is being edited.
The reply is still null, and the journal still records the call. A
call that changes a flag on any of the masks is still one undo step.
One line in the evidence list of docs/target-app-parity.md names the
commands.
These commands edited the document even when nothing changed, so the
call recorded an undo step, emptied Redo and marked the document
modified:
- Fill, Stroke, None, Apply Last Color and Apply Last Gradient with the
paint the objects have already, also on characters selected with the
Type tool.
- stroke.set and stroke.setAdvanced with the options the strokes have
already.
- paint.editGradient, paint.setGradientGeom and the freeform point
commands when the gradient comes out as it was.
- Invert and Complement on the Appearance panel's selected row when no
color changes.
- Swap Fill and Stroke and Default Fill and Stroke when every object
comes out as it was.
- appearance.setItem with the values the item has or an index no
object has, and transparency.set with an item and the values that
item has; appearance.removeItem with indices past every stack;
appearance.moveItem, Reduce to Basic Appearance, Clear Appearance,
the Eyedropper (appearance.copyFrom) and appearance.transfer when
every object comes out as it was.
These commands now return without editing the document. The replies
have the same form as before. On a graph's series or labels, a fill or
stroke that the art has already still records one undo step when the
graph does not keep that paint for them (for example after the
Eyedropper painted the art), and the graph then keeps it.
The Eyedropper test whose second copy changed nothing gives its target
a green fill first, which the copy turns red again.
One line in the evidence list of docs/target-app-parity.md names these
commands, apart from Invert and Complement.
Select All, All on Active Artboard and Inverse select from selectable:
the visible, unlocked objects on visible, unlocked, non-template
layers and sublayers, or in isolation mode the visible, unlocked
objects in the isolated group or layer and in its visible, unlocked,
non-template sublayers. Other Select menu commands did not use it:
- Clipping Masks, All Text Objects, Stray Points and Open Paths
selected hidden and locked objects and the objects in hidden or
locked groups and sublayers.
- Point Text Objects, Area Text Objects, Brush Strokes, Bristle Brush
Strokes and the Same commands for symbols, fonts and text colors
checked an object's own flags and its layer's, but not those of the
groups and sublayers between them.
- Next Object Above and Below selected the object beside the selected
one even when it was hidden, locked or a sublayer.
- A saved selection picked from the Select menu selected again the
objects hidden or locked since it was saved.
- Direction Handles direct-selected the hidden and locked paths in a
selected group.
- In isolation mode, the commands in the first two bullets, the other
Same commands, All on Same Layers and a recalled saved selection
selected art outside the isolated group or layer. Next Object Above
and Below and Direction Handles did so only when the selection
already held something that was not inside the isolated group or
layer.
In isolation mode selectable checked the flags of the isolated group's
or layer's objects and sublayers, but not those of the group or layer
itself or of the groups and layers it is in. Select All, All on Active
Artboard and Inverse still selected the isolated group's or layer's
objects after it, or a group or layer it is in, was hidden or locked.
In isolation mode selectable now returns nothing while the isolated
group or layer, or a group or layer it is in, is hidden, locked or a
template layer. walk_selectable visits the objects selectable returns
and the objects inside them, leaving out hidden and locked objects
with what they hold. It visits nothing in a hidden, locked or template
layer, sublayer or group. The commands in the bullets above now select
from it. All on Same Layers takes the objects on the selected objects'
layers that selectable returns. Next Object Above and Below pass over
the objects walk_selectable leaves out, and leave the selection as it
is when none is left in that direction.
The params texts of Direction Handles and Recall Selection,
docs/mcp.md (Object selection, Saved selections) and one line in the
evidence list of docs/target-app-parity.md describe the change.
Overnight doc conflicts were resolved by keeping both sides, which left two or three copies of
some milestone and parity rows (M1–M3, M5–M7, M14; six area rows; one type row). Each is now one
row with every note. The 2026-10-12 progress row takes the 30 PRs landed since and the Film
Grain row that #1282 added separately.
These commands edited the document even when nothing changed, so the
call recorded an undo step, emptied Redo and marked the document
modified:
- Change Case to the case the text has, Smart Punctuation on type with
nothing left to change or on a selection with no type in it, and
Find and Replace when every match is replaced with the text it is.
All three rewrite the text runs through edit_runs, which now edits
only when a run changes.
- Convert To Area Type with no point type among the objects, and
Convert To Point Type with no area type among them.
- Type on a Path Options given the values the type has, without Flip:
OK in the dialog with nothing changed, or a Type on a Path effect
the type has.
- Fill with Placeholder Text on type that holds its placeholder text
already.
- type.insert with an empty text on type that ends with a run of
text.
These commands now return without editing the document. The replies
have the same form as before. A call that changes something still
records one undo step.
One line in the evidence list of docs/target-app-parity.md names every
command above except type.insert.
An image larger than the tracer's 64 megapixels was refused. It is now
decoded and box-filtered down to the largest size of its aspect within
64 megapixels, and the traced paths are mapped back to the image's own
size. Images over 192 megapixels are still refused from their header,
before decoding.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XbTizgRsDpFPjtBgZAvfrZ
Each tool switch builds a new tool, and a new Artboard tool started on
Artboard 1 whatever artboard was active. With Artboard 2 active, after
the tool was chosen with Shift+O, its toolbar button, Edit Artboards in
Properties or Document Setup, or the Artboards panel menu's Artboard
Options…, the canvas outlined Artboard 1, and Delete, Cut, Copy, the
Transform panel and Artboard Options acted on Artboard 1. The first
pointer event over the canvas, a hover included, then made Artboard 1
the active artboard for Align to Artboard and Paste in Place too.
VectorcraftApp::select_tool now starts a newly chosen Artboard tool on
the active artboard, as the Artboards panel row's Options button does.
Choosing the tool again while it is in use leaves it as it was, and the
artboards Shift-clicked into its selection stay selected.
The test makes Artboard 2 active, chooses the tool with tool.select,
and checks the tool's active option, Artboard Options, a hover over
Artboard 1 and Delete. It then presses Shift+O with two artboards
selected and checks that both stay selected.
Docs: docs/mcp.md (tool.select), docs/target-app-parity.md.
Add the Hungarian catalog (4,524 rows): every menu string, every `tl!`
literal, the contextual and `@id` rows, the plurals and the status and
error messages, written from the meaning of the English labels in
general Hungarian vector-illustration vocabulary. Conventions are in the
header of `hu.tsv`.
- Register `hu` ("Magyar") in `i18n::LANGUAGES` as a complete language
with `plural_none` (a count takes the singular); every `hu-*` locale
resolves to it.
- Tests: Hungarian joins the menu-label, menu-string, `tl!`-literal and
message coverage checks; `hungarian_reads_as_hungarian` pins the core
vocabulary, the plural, the `file.close` override and a nested
message; ő ű Ő Ű are checked in the bundled UI fonts.
- README, ROADMAP, docs/development.md and docs/localization-parity.md
list Hungarian.
Localize native/web file filters, diagnostic labels, numbered presets
and contributor tooltips with English fallback and Czech plural forms.
Fix gradient adjective agreement and disambiguate Japanese printer marks
in PDF/Print choices and summaries. Keep file extensions and names intact.
Add Czech catalog rows and regression coverage; update localization evidence.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Find in Folder… in Linked File Not Found and in the Links panel menu
looks in a folder the user picks, and in its subfolders, for the files
with the names of missing linked files, in any letter case. In the
Links panel menu it looks for the selected linked files when there are
any. It uses the folder search of the Missing Fonts dialog. Find
Linked Files lists each file it looks for with the files found for it.
A file with the size and contents saved with the link comes first. A
file of the saved size comes next when the link saved no hash or the
file is larger than 1 GB, and any other file of the name comes last.
Within each group, a file named in the same letter case comes first.
Then each file's folder names are compared with the saved path's, from
the innermost outward, up to the first one that differs, and a file
with more matching names comes before one with fewer. A file is chosen
when it is the only file found, or the only one with the saved
contents, and the user can choose another file or Don't Relink.
Relink relinks each file chosen, and each relink is one undo step.
With Copy into the document's folder, which shows for a saved
document, each image's file is copied next to the document first. The
file's name, then Name 2.png, Name 3.png and so on, are tried in turn
until one is free, which gets the copy, or is a file with the same
contents, which is used. A placed document is relinked where its file
is. The status line names the first file that fails to relink, and the
other files still relink. When Find Linked Files opens from Linked
File Not Found, the missing files left without a choice, and any that
fail to relink, go back to that dialog. On the web, Find in Folder… is
disabled in the Links panel menu, and links.findFiles can't start a
search.
- links.findFiles searches on separate threads and returns at once;
links.findFiles {} reports the search, and {stop: true} stops it. It
looks for at most 1,000 linked files at once: the active document's
missing ones, or those of the objects it is given. It hashes a file
only when a link of its name saved the file's size and a hash, and
only when the file is 1 GB or smaller. It ends once every linked
file has its same file, and it searches only the folders
text.findFontFiles may search, with the same maxSeconds, depth and
count limits.
- links.relink {copy} copies the file it is given into the saved
document's folder and links images to the copy; a call that includes
a placed document fails. Each name it writes is checked against the
automation write root. text.addFontFiles and links.relink {copy}
make their copies with fileio::copy_new, which never replaces a
file. The text.addFontFiles params text and docs/mcp.md say which
names are tried for a copy.
- vectorcraft-doc adds links::hash_reader, which hashes what a reader
reads as hash_bytes hashes bytes.
- ui.findLinksInFolder is the Links panel's Find in Folder… for agents;
docs/control-protocol.md lists the dialog's fields.
Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md.
A click on a Layers row runs layer.setCurrent, which makes the row's
layer current whether it is hidden or locked and keeps the selection.
Object › Arrange › Send to Current Layer then moved the selected
objects into that layer, or into a sublayer of a hidden or locked
layer, and left them selected. In that case drawing, typing and
pasting put new art on the topmost layer that is shown and unlocked,
and since #1039 they fail with "the target layer is locked or hidden"
when no layer is shown and unlocked.
Send to Current Layer now fails with that error when the current layer
is hidden or locked, or is inside a hidden or locked layer. It makes
the check that DocState::target_parent makes for new art
(Document::is_editable) before it moves anything or records an undo
step. The objects stay where they are and stay selected. The message
already has a row in the cs, de, es, fr, it, ja, pt-br, ru and uk
catalogs.
Docs: docs/target-app-parity.md.
Transform Again kept only the last transform's matrix and its Copy
flag. After a Selection tool handle drag resized area type, Transform
Again scaled the type instead of resizing the type area again. After
Move, Rotate, Scale, Reflect or Shear with Transform Patterns set
differently from General › Transform Pattern Tiles, Transform Again
followed the preference, and after a scale whose strokes or corners
param differed from Scale Strokes & Effects or Scale Corners, it
followed those preferences. A recorded Transform Again played back
with the preferences in effect at playback, although its step records
the strokes, corners and patterns values it used.
last_transform now keeps the options with the matrix, as
last_perspective keeps the perspective.transform params.
apply_transform stores the copy, typeAreas and patterns values a
transform command used, and strokes and corners when it scales.
commit_interaction stores the params of a drag's last object.transform
preview with the values that preview noted. object.transformAgain
passes the options to the transform it repeats, and a true or false
value given in its own params under one of those names takes
precedence. A recorded step plays back with the values it records.
Three engine tests fail without the change: Transform Again after a
handle drag on area type, Transform Again after a Move with patterns:
false while Transform Pattern Tiles is on and after a Scale with
strokes: true while Scale Strokes & Effects is off, and a recorded
Transform Again played back with Transform Pattern Tiles on.
Docs: docs/mcp.md, docs/ui-parity.md, docs/target-app-parity.md.
Preferences › Guides & Grid › Gridline every and Subdivisions set the
grid of the documents that were open when either value changed, and of
no other document. A document made with File › New, or opened from a
file VectorCraft reads no grid from (SVG, PDF, EPS, .ai and the other
imported formats), got a 72 pt grid with 8 subdivisions, whatever the
preferences were set to. After a restart the saved values applied to no
document, because the desktop app restores the preferences at launch,
before any document is open.
file.new now gives a new document the preferences' grid, and
document.open, file.newFromTemplate and file.revert give it to a
document read from such a file. A native file, and the native document
that an SVG, PDF, .ai or EPS file carries, keep the grid they were
saved with. Changing either preference still sets the grid of every
open document.
Docs: docs/mcp.md (gridlineEvery, gridSubdivisions),
docs/target-app-parity.md.