The answer whether Fit to Artwork Bounds has art to fit moves from a
function-local thread_local to DocState, beside any_empty_artboards, and
drops with the document. It is kept for that version of the document
(held weakly, as any_empty_artboards holds its own) and the artboards
asked about, and measured again when the installed plug-ins, whose
effects draw art, or the installed fonts, which set type drawn by its
effects' art, change: their generations are an explicit input of the
measure. A change of the selection or the view keeps it.
The test counts the measures, as the Delete Empty Artboards check's
does: a later frame, select.set and a view change keep the answer; an
edit, other artboards, and each generation measure again. Taking any
part out of the key fails it.
Found while testing crates/engine/src/cmd/graph/data.rs:45-47 (parse_csv)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Direct Selection of a path, compound path or type inside a dynamic instance now applies transparency and gradient or pattern fills through the usual paint commands, and the G5 docs catch up on Overlap and Pattern auto corners.
- A custom dictionary file that is there but can't be read whole (not a
file, unreadable, or larger than the 1,000,000 bytes craft-proof reads)
is not loaded and never written over: attaching it logs why, and every
add, delete or change is refused with that reason. A missing file is
still created by the first save.
- When a save fails, the command takes back only its own change, so memory
and file agree; words the save took in from the file stay.
text.spelling.addWord, removeWord and changeWord are Check Spelling's Add
and Edit Custom Dictionary's Add, Delete and Change; text.spelling.dictionary
lists the words. They live in craft-proof, which every language's check
reads. The desktop app and vectorcraft-cli keep them in
`Custom Dictionary.txt` next to the preferences (none without preferences);
elsewhere they last until the app closes.
text.spelling.ignoreAll is Ignore All: the active document's checks skip the
word while it is open; not saved, not undoable, and not a change to the
document's revision.
Behaviour: https://helpx.adobe.com/illustrator/desktop/design-with-text/edit-format-text/check-and-correct-spelling.html
Adds composefont, the CIDInit and FontSetInit procedure sets and the CMap
operators, so EPS with CID-keyed fonts (as pdftops -level3 writes) opens.
Type 0 fonts with FMapType 9 decode their codes through the CMap's codespace
ranges and CID mappings, and the Identity CMaps are predefined.
An embedded Type 1 font's eexec part is decrypted and its charstrings read,
so its glyphs and widths are used instead of the installed or fallback
font's. Codes are decoded through the font's Encoding, so fonts that place
glyphs at low codes no longer lose their type.
Found while testing crates/engine/src/cmd/graph/data.rs:166-172 (fmt_value)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A grayscale image colorized with a fill color keeps that color outside its
appearance, so the check for art without paint treated it like an uncolorized
image and new art kept its old fill while the Fill proxy showed the color.
Count a colorize paint as paint: the image then loads like any object with a
fill and no stroke.
Language per character rows in docs/type-parity.md: spelling is no longer listed as not yet done, and the hyphenation note names the languages that still lack it.
When an edit changes an object, the canvas draws again only the area
the object painted before and after it, measured by its cull bounds.
Type and groups with Extrude & Bevel, Inflate or Rotate were measured by
their letters or members, not by the solid the effect draws, which
reaches well past them. Making the solid shallower or turning it left
pieces of the old solid on the canvas outside that area until the view
was drawn again.
An object with a 3D effect is now measured by the effect's art, as the
renderer draws it: with its geometry effects, each object in it with
the raster effects of its own fills and strokes and the art its brushed
strokes draw, grown by the reach of the object's own raster effects.
One function measures that art for every bounds the renderer and
exports take, where three copies of it disagreed.
- The renderer measures the art it draws. What it makes to measure an
object it holds until the frame ends, with what the art read from
outside the object (fonts, symbols, color settings), and keeps it
with the art it draws if it draws the object while that is
unchanged. Art measured but not drawn (culled, off the view) isn't
kept. It holds at most as much as it keeps for the art it draws
(64 MB); past that, an object is made again to draw it. An object
whose 3D effect builds nothing (Revolve on a group, a solid too
complex) is measured as it is drawn otherwise, as without a renderer.
FrameStats::three_d_built counts the 3D art the renderer makes.
- The canvas measures what an edit changed through the renderer that
drew the frame shown (Renderer::changed). When it draws the part on
its own thread, it draws it with the art it made to measure it; when
the render worker draws the frame, or nothing in view changed, that
art is let go. Under Overprint Preview or Separations Preview, which
draw copies of the objects, the edit is measured afresh. An object
the frame doesn't draw (hidden, in a hidden group or layer, or
hidden by the view) is measured as nothing, before and after, so an
edit to it builds no solid: changed() without a renderer counts it as
nothing too, where it measured it. The canvas measures the edit
before it knows where the frame is drawn: when the worker draws it,
the solids it built to measure it are built again there.
- Fit to Artwork Bounds, the Artboards panel's check for it and
per-artboard SVG export measure every artboard through one renderer
(Renderer::art_bounds_on, Renderer::effect_bounds), which keeps each
object's bounds for the pass, a group holding 3D art or a hidden
member included, so each solid is built once: 30 extruded type
objects over 30 artboards take about 2 ms, where measuring their
letters took under 1 ms and building each solid for each artboard
would take 70 ms. Objects with brushed strokes, which culling leaves
room for and exports don't, are measured on each artboard. The
Artboard tool's canvas menu keeps whether Fit to Artwork Bounds has
art to fit for the document's revision, where it measured it on
every frame it was open.
- Other exports, Object › Rasterize and changed() without a renderer
build the art on each call, as 3D paths and groups already did.
Exports and Rasterize now take the solid of 3D type, where they
cropped it to the letters, and the art its brushed strokes draw, not
the room culling leaves for it. Rasterize on drawn 3D art measures it
once while the art is kept.
- A shadow after a 3D effect, on the object or on a fill after the
fill's own 3D effect, reaches past the solid once; it was counted
twice.
- With Crop Marks or Vector Halftone, which draw other art, the object
is measured by that art, as before.
- Culling leaves room for a 3D object's brushed strokes as for any
object's, and the renderer measures a 3D object again when the brush
library changes: a brush widened past that room would leave the
object culled.
A document's first frame builds the solid of every 3D object, those off
the view too, to know whether it reaches into the view: 200 extruded
words with 150 off the view take about 12 ms, where measuring their
letters took 6 ms.
Type whose object effects leave it as it is (Revolve builds no art from
type) is measured by its own box grown to hold its glyphs, as plain
type is; it was measured by its box alone, which needn't hold them.
plugin.install and plugin.remove count an entry of grants.json that this
version can't use when it can't be removed. plugin.install stops counting
a grant it can't remove when the old module can't be written back to the
Plug-ins folder.
A refused install keeps the grant, a failed write of the module to the
plug-in store leaves the grant in the store, and a stored module that is
disabled or not read in Safe Mode keeps the grant for its id. This
matches docs/plugins.md.
A grant accepted under --allow-plugin-grants is written to grants.json like a
person's approval and counts as approved in later sessions and in the desktop
app. The CLI usage text, the plugin.install params text and docs/plugins.md and
docs/mcp.md said only a person's approval in the desktop app records one.