Revolve, Extrude & Bevel, Inflate and Rotate on a group or layer draw only as the group's own effect. On the group's fill or stroke they drew nothing, yet effect.apply and effect.setParams accepted them. Both now refuse that placement.
Each fill or stroke with its own Revolve counted the copies of its paint from zero, so an object with several of them could draw past the 256 MiB budget. They now share one count, and past it the source path draws, as for the members of a group.
effect.apply and effect.setParams on a fill or stroke now check the Revolve in that item's paint, after the item's geometry effects before it, together with the object's other items that carry a Revolve. Before, they checked the object's top fill.
docs/revolve.md marks the axis position, type handling and member paint as VectorCraft's own rules, and docs/mcp.md says how the budget is counted.
Edit Colors > Convert to Grayscale wrote the new image as an RGBA PNG, so
a PDF wrote it as DeviceRGB, in a CMYK document too. The image is now
stored as a gray PNG, with alpha only when some pixel is not opaque. Adjust
Colors with mode gray and convert does the same.
An RGB image whose pixels are already neutral now converts, and an image
already stored as gray with no visible change is left as it is.
Type sweeps as its glyph outlines and stays editable. On a group or layer every visible member sweeps about one axis on the edge of the members' bounds together, each in its own paint.
A surface now takes up to 16,384 profile points and 163,840 faces. Curves take fewer samples, down to 4, when a surface passes those limits, and the command reports the failure below that, after the geometry effects before the Revolve and with the cumulative size of its paint copies counted. Mesh export turns the walls of holes toward them. Expand Appearance works on type with Extrude as well as Revolve.
Fixes#3617
The engine reads null params as {}, but engine.commands listed every
schema with the root type "object", so a client that validated a call
against the schema refused one the engine accepts. A schema with no
required parameter now has the root type ["object", "null"]. A schema
with a required parameter keeps "object", because the engine refuses
null params for it as a missing parameter. Nested objects are unchanged.
Check a new call's params against the schema in execute_spec, after the
key check and before the parser, and check every command.batch step
before the first one runs. menucmds::run_raw and the two other direct
runs go through the same check. Saved steps keep keys the schema does
not name and have the values it names checked.
Limit nesting to 16 levels, cut error text and paths to a fixed length,
and copy nothing before it has passed. Treat a whole number written
with a fraction as an integer. Check declared defaults and duplicate
names once at first use.
Give the five schema errors rows in the 22 complete-message catalogs.
Flatten Transparency composited each region over white, so a blend mode
on the bare page read that white. Raster renders now draw their
background under the finished art, and the flattened color no longer
matched them: a Color Burn object on the bare page flattened to white
and rendered in its own color. The region now composites the art alone
and puts the white under it.
- Tests that relied on the white under the art now draw art under the
style (`every_builtin_style_paints_visibly_on_a_rectangle`) or compare
only whole-pixel pans with a fresh render
(`a_coarser_glow_kept_whole_draws_after_a_pan_as_made_again`).
- New tests cover every blend mode on white and blue backgrounds, a
thumbnail and the ink planes with a Screen glow, and
`over_background` at background and pixel alpha 0, 128 and 255.
With Scroll Sideways with Cmd/Ctrl + Wheel on, wheel() turned all
Cmd/Ctrl wheel motion into a sideways scroll unless it arrived as a
pinch event. A wheel turn now zooms about the pointer once it holds an
event from a trackpad source, point deltas from an unnamed source in the
desktop app, or line deltas that are not whole notches. Whole notches
keep scrolling sideways, and the option's default is unchanged. The same
rule applies with Zoom with Mouse Wheel on. egui-winit reports a wheel
source only on macOS, so the delta decides elsewhere.
Docs: docs/mcp.md, docs/target-app-parity.md.
A raster export filled its background into the page before the art, so
blend modes read it as art underneath: an Outer Glow in Screen mode, the
default, turned white on a white background and was missing from PNG and
JPEG files while the canvas showed it. Blending against nothing also
differed from the canvas for Difference and the other modes.
The background now goes under the finished art, in frames and in object
thumbnails. A blend mode reads only the art below it. A white object
under a Difference object still inverts.
Page Isolated Blending no longer changes a raster export on a bare page.
Docs: docs/mcp.md, docs/target-app-parity.md.
copyFrom only writes paints enabled for pickup and apply, and paint, Transparency and the Eyedropper record an undo step only when the override changes.
copyFrom still edits the part when reverse, append and defaultsOnly are false, and reverse copies onto source. transparency.set records an undo step only when the override changes.
A picked part takes transparency and the Eyedropper only when those calls omit their other targets. Art, Pattern and Bristle brushes, native Wayland and the web still do not take tilt, bearing or rotation.
docs/mcp.md: vectorcraft-cli's mcp and run sessions keep the words in the file too; only without preferences do they last until the app closes. docs/type-parity.md: the custom dictionary commands are done and only the dialogs and Auto Spell Check remain, with the evidence at the end of the row.
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.
Each CID-keyed font in a FontSet's CFF data is defined as a CIDFont named by
the CFF Name INDEX, with its glyphs found by CID through the charset and
FDSelect, so a composefont over it draws its type.
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.
A plain Type 42 font now maps each code to its character through its glyph
names, or through the glyph its CharStrings give it in the font's own
character map or post names, instead of reading the code as Latin-1. The
font's own widths move the current point, charpath outlines its glyphs, and
the show operators' spacing and the embedded widths are kept on live type as
tracking. Type shown under nulldevice no longer appears.
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.
A server confined with --automation-read-root or
--automation-write-root has no plug-in store, so a grant accepted under
the flag could not be written to grants.json and recorded grants were
not read. mcp now refuses the combination at start-up.
The help text, docs/plugins.md and docs/mcp.md state that a confined
server does not install a module that lists permissions or asks for a
heavy budget, and that with VECTORCRAFT_NO_PREFS set a grant accepted
under the flag lasts for that session only.
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.