In Safe Mode and for a disabled stored module, load_stored_plugins does
not read the module, so grants.json keeps the grant for its id. The next
load that reads the module forgets the grant.
SVG export wrote an SVG filter as a live <filter> when its SVG 1.1 form
was at most 64 KB, without counting the region and id it writes into
it. A filter close to the limit came back over it, SVG import dropped
it, and the reopened object had no filter.
Export now leaves room for the id and the measured region, checks the
SVG 1.1 form the way import does, and counts each character past U+00FF
as the character reference Latin-1 output writes. A filter that does not
fit is exported as the other pixel effects are. The SVG 1.1 form and its
check are kept for the filters seen last, as checked filters already
are, so export does not check one filter again for each object.
The test for a changed module under a granted id now checks that the next
start, a folder load and a refused install leave the id's settings and
cache unattached.
`plugin.clearCache` without an id empties the cache of every plug-in
installed in the process. In the engine's library tests it could empty
the cache of another storage test running at the same time, and its
`bytesFreed` could count that test's cache. It now runs in
`crates/engine/tests/plugin_clear_cache.rs`, and the library test checks
that clearing one plug-in's cache leaves the other plug-in's cache.
The storage fuzz test starts each case with an empty plug-in store,
deletes the store when the case ends, and installs `fuzz.storage` with
`replace: true`, so the cases that shrink a failure install their
module.
docs/mcp.md says that files `plugin.remove` can't delete stay in the
folder renamed with `.removed` until the plug-in is removed again.
Align to Path moved the whole line by the largest ascent and descent
among its characters. Each character now moves by its own font, size
and vertical scale. Ascender runs the top of the font's em box along
the path: the ideographic em box that the font's BASE table gives, or
in a Chinese, Japanese or Korean font the one that its typographic or
hhea box, a one-em box-drawing cross or its ideographs give; else an
em box centered on the cap height. Descender runs the bottom of the font's
bounding box along the path, and Center runs a line at half the height
of the top of the font's H along it. In vertical type, Ascender and
Descender move the characters half an em, and Center leaves them on
the path.
Existing documents with Align to Path set to Ascender, Descender or
Center lay their type out at a new distance from the path.
Generic CMYK's tone curves now pass through the CGATS TR 001 tone value
increase of each ink at 40% and 50% (C 20.0, M 17.6, Y 16.8, K 21.6 at
50%), and its 16 Neugebauer primaries mix linearly, so a single ink's
tints gain as TR 001 gives. The 300% ink limit stays. The primaries, the
black-generation curve and the black point are VectorCraft's own values.
- The black point is 90% black under neutral CMY that fills the ink
limit: sRGB black separates to C75 M68 Y67 K90 instead of C67 M67 Y67
K100.
- Black follows a curve over the gray component of the black-free
solve, raised by how far that solve stays lighter than the target.
Grays from sRGB 177 up carry no black, and sRGB 128 gray separates to
C50.5 M42.2 Y42.0 K7.5 instead of C38.8 M26.3 Y29.9 K24.4.
- Display of CMYK fills, swatches and imported CMYK values and the
separation of RGB and Lab colors use the same model.
Paper white still separates to C0 M0 Y0 K0, but other separations
change, and so does the display of CMYK colors with ink. Tests that held
numbers of the old model are updated.
The 2,000,000-triangle limit on a 3D object's meshes is now checked as
each mesh is built, so an object past it is refused before the rest of
its meshes are built:
- Revolve counts each fill's and stroke's mesh as it builds it, instead
of building every one first.
- Inflate still solves every shape's membrane at once (the eye depends
on the highest puff), but builds each solid only when its mesh is
reached (inflate_meshes), so a refused object leaves the later
solids unbuilt.
- All the objects of one 3D asset share one budget
(three_d_meshes_of), so assets.export3D refuses an asset whose
objects pass the limit together.