Commit Graph
442 Commits
Author SHA1 Message Date
BFlat 3b92bef27c Merge pull request #2606 from dotCooCoo/feat/jxl-import
File formats: JPEG XL (.jxl) images open and place
2026-11-09 10:50:56 +08:00
BFlat c5c1913f48 Merge pull request #6265 from dotCooCoo/feat/plugin-effect-paint
Plug-ins: live effects at API level 2 can paint the pieces they return
2026-11-09 10:50:46 +08:00
BFlat 04aedc87e5 Merge pull request #6268 from dotCooCoo/fix/freeform-mixes-in-point-model
Gradients: freeform points that share a color model mix in that model
2026-11-09 10:08:22 +08:00
dotCooCoo e064698086 Merge main into feat/jxl-import 2026-11-08 18:04:45 -08:00
dotCooCoo bd5ea2a1bf Merge main into feat/plugin-effect-paint 2026-11-08 17:59:33 -08:00
dotCooCoo d6a91b6142 Merge main into feat/plugin-effect-paint 2026-11-08 17:26:35 -08:00
BFlat b652599548 Merge pull request #6264 from dotCooCoo/feat/plugin-importers
Plug-ins: importer plug-ins open file types VectorCraft does not read
2026-11-09 09:24:07 +08:00
dotCooCoo ac0bb3c4ce Gradients: freeform points that share a color model mix in that model
The canvas, the gradient chips and the SVG, PDF, EPS and EMF writers mixed
freeform points in display RGB, while Object > Expand and Create Gradient
Mesh mixed them in the model the points share. Points that are all CMYK,
Gray, Lab or RGB now mix in that model in those places too. Points in
different models mix as before: in display RGB, and on ink planes as the
inks of each point.

This changes how existing art looks:

- CMYK and Lab points. With the default Generic CMYK working space and no
  ink planes, halfway between C100 and K100 the canvas drew (17, 106, 139)
  and now draws (54, 118, 143).
- RGB points in a working RGB space other than sRGB mix in that space.
- On ink planes (a CMYK document that shows transparency), RGB and Lab
  points mix first and then separate.

Gray mixes keep their values, and CMYK and Gray points on ink planes draw
as before. RGB points in an sRGB working space draw as before except on
ink planes.

- PDF and EPS write a gradient whose points are all CMYK, or all Gray in a
  CMYK file, as a CMYK image. PDF's Output settings convert it as they
  convert any CMYK image.
- Darkening applies to the points before they mix.
- With Appearance of Black set to Rich, the canvas mixes a gradient with a
  pure CMYK black point in display RGB, and the point fades from RGB black.
2026-11-08 17:18:43 -08:00
dotCooCoo aa74ee433c Merge main into feat/jxl-import 2026-11-08 16:52:56 -08:00
dotCooCoo 918ef940cb Merge main into feat/plugin-importers 2026-11-08 16:45:20 -08:00
dotCooCoo 988da4538a Merge main into fix/plugin-grant-module-hash 2026-11-08 15:55:53 -08:00
BFlat 22f5ede66f Merge pull request #6161 from dotCooCoo/feat/ai-editing-data-s6b2
.ai save: the editing copy keeps graphic styles and links to them
2026-11-09 07:52:12 +08:00
BFlat 3e836ad856 Merge pull request #6193 from dotCooCoo/feat/plugin-menu-commands
Plug-ins: a plug-in adds menu commands of its own under Object › Plug-ins
2026-11-09 07:47:49 +08:00
BFlat 7adc2f66a3 Merge pull request #6109 from dotCooCoo/feat/ai-symbol-libraries
.ai import: symbol libraries open with their symbols
2026-11-09 07:47:36 +08:00
BFlat 1bacc7f1f0 Merge pull request #6061 from dotCooCoo/fix/export-unknown-options
Export: the export commands refuse an unknown option key
2026-11-09 07:47:15 +08:00
dotCooCoo 438f1cd8f2 Plug-ins: importer tests use American spelling 2026-11-08 15:35:45 -08:00
dotCooCoo 421189893f Plug-ins: composite fonts stay out of importer filters; base64 size is checked first
File › Open imports .vccomposite files as composite fonts, so an importer
listing that extension no longer shows it under its own filter or in
document.formats. File › Open gets a Composite fonts filter.

document.open refuses dataBase64 that decodes past the importer input
limit before decoding it. A file whose start shows a built-in format
still opens as that format, as it does by path.
2026-11-08 15:18:31 -08:00
dotCooCoo 230fbb96a3 Merge main into feat/ai-editing-data-s6b2 2026-11-08 15:00:10 -08:00
dotCooCoo b8ab981058 Merge main into feat/ai-symbol-libraries 2026-11-08 14:56:51 -08:00
dotCooCoo 64c7c2703e Merge main into feat/plugin-menu-commands 2026-11-08 14:41:13 -08:00
dotCooCoo 4fff063dcc Merge main into fix/export-unknown-options 2026-11-08 14:25:57 -08:00
dotCooCoo 4b665ad13c Plug-ins: clearing every cache is tested in a binary of its own
`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.
2026-11-08 13:03:31 -08:00
dotCooCoo 36bca85879 Plug-ins: app.open passes params to the importer File › Open picks
app.open with params and no importer ran file.open with the path alone, so the desktop app ran the importer on its defaults while headless app.open passed the params to document.open. file.open now carries params to the importer that opens the file.

The importer parameters test installs its module with replace from the second pass on, as plugin.install requires. The permission table in docs/plugins.md lists doc.read for filter, effect and exporter.
2026-11-08 12:59:17 -08:00
dotCooCoo 11703bd350 Merge main into feat/plugin-effect-paint 2026-11-08 12:56:42 -08:00
dotCooCoo a717e34f02 Merge main into fix/plugin-grant-module-hash 2026-11-08 12:55:59 -08:00
dotCooCoo 9518dc0e3a Merge main into feat/plugin-importers 2026-11-08 12:33:17 -08:00
dotCooCoo 26804fb0c4 Plug-ins: tests hold an importer to its budget and hostile extensions in the manifest fuzz
An import's instruction and time budgets are now host limits on Limits, as a heavy filter's are, so a test can give an importer a small budget. An importer past its instruction or time limit, and a file past the input limit, return their error and leave an open document and its undo history unchanged. The manifest fuzz varies extensions (missing, dotted, mixed-case, repeated, too long and too many).
2026-11-08 12:29:27 -08:00
dotCooCoo c539c04625 Merge main into feat/plugin-effect-paint 2026-11-08 12:23:39 -08:00
dotCooCoo 94dcb63c01 Merge main into feat/plugin-importers 2026-11-08 12:12:34 -08:00
bflatastic d4f2cf5394 Plug-ins: the fuzz tests install each case's module in place of the one before 2026-11-09 03:08:22 +07:00
dotCooCoo 9f23044b87 Merge main into fix/plugin-grant-module-hash 2026-11-08 12:04:11 -08:00
dotCooCoo a224331554 Plug-ins: a failed store write keeps the stored module and its grant together
plugin.install wrote the grant and the module as two separate writes,
and either could fail with only a log record. With a grant tied to the
module's hash, the stored pair then no longer matched and the plug-in
was skipped at the next start.

The module is now written first and its grant only once it is there.
When the grant can't be written, the store gets its old module back, or
loses the new one on a first install, and a disabled plug-in stays
disabled. A stored module that can't be read back is not replaced by
one that needs a grant.
2026-11-08 12:04:03 -08:00
dotCooCoo 218c711181 Plug-ins: a plug-in keeps settings and a cache of its own
Squashed from #6228 onto main.
2026-11-09 02:54:33 +07:00
dotCooCoo b5adb679e4 .ai import: images past 2^25 pixels in the editing data keep the layers
Squashed from #5143 onto main.
2026-11-09 02:43:13 +07:00
dotCooCoo 81c5b047bc Merge main into feat/plugin-effect-paint 2026-11-08 11:36:48 -08:00
dotCooCoo 19f7fb774b Merge main into feat/plugin-importers 2026-11-08 11:30:49 -08:00
Don Omondi 3bb43b2fe6 EPS import: composite fonts draw their Type 42 descendants' glyphs
A composite (Type 0) font with the 8/8 mapping picks a descendant font
and a code in it with each pair of bytes (PLRM 3rd ed., 5.10). The reader
set its strings as type in a font of the composite font's name, the
bytes read as Latin-1 and at a thousand times the size, so EPS from
pdftops of a PDF with embedded TrueType fonts showed nothing, or one
black shape, where its type was.

Characters now go to their descendants: a Type 42 font's glyphs are drawn
from the TrueType outlines its sfnts strings carry (Adobe Technical Note
5012), by the glyph index CharStrings gives their names, spaced by their
own widths or the show operator's numbers; charpath and stringwidth read
them too. A Type 3 descendant runs its procedures, and a descendant found
by name sets its character as type at the composite font's size.
2026-11-09 02:24:54 +07:00
ruchirguitar b1f52d1369 Select Text by Font: limit it to artboards or layers (#5529)
Squashed from #5578 onto main.
2026-11-09 02:03:01 +07:00
dotCooCoo 64817c2e8c Merge main into feat/plugin-effect-paint 2026-11-08 10:46:47 -08:00
dotCooCoo 79351d7063 Merge main into feat/plugin-importers 2026-11-08 10:25:28 -08:00
dotCooCoo 2ecd593e61 Plug-ins: a file past an importer's limit is refused from its size, without reading it
document.open by path reads the first 64 KiB of a file only an importer
reads to look for a built-in format. A larger file is read to the limit
only when its size is within the limit, so an over-limit file costs no
128 MiB read and a built-in file over the limit is not held in memory
twice.
2026-11-08 10:20:53 -08:00
dotCooCoo 1ce9e9e9eb Merge main into feat/plugin-importers 2026-11-08 09:41:06 -08:00
dotCooCoo fb848d28ac .ai import: objects in pattern and brush art take the file's art styles
A pattern's definition (in either form) and a brush's art were read
without the file's art styles, so an object there with a style came in
as the look it draws, with a "drawn look" note, while the same object on
a layer or in a symbol came in as itself with its effects live. The
three definition readers now take the art styles as the symbol reader
does, and an object in a pattern's art with a style in the file's style
list keeps that graphic style's id.

An art styles section inside a symbol's, a pattern's or a brush's art
is now skipped, so it no longer replaces the file's own art styles.
2026-11-09 00:36:09 +07:00
dotCooCoo a37ad90e6c .ai import: type keeps Standard Vertical Roman Alignment from its editing data
The modern type reader read key 35 of a character style only for
Tate-chu-yoko (3). A run whose key 35 is 1 (Standard), in the run, its
character style or the document's defaults, now opens with Standard
Vertical Roman Alignment on, so its half-width characters stand upright
in vertical type. Horizontal type keeps the mark with no change to its
layout. A value of 2 (rotated), 3, any other value and no key at all
leave it off, VectorCraft's default.

- ate.rs: Style reads the flag and passes it to CharStyle, with a unit
  test over defaults, character styles, run overrides and bad values.
- tests_native.rs: a vertical and a horizontal story with Standard,
  rotated and unset runs; the test of values the reader ignores also
  checks the flag.
- import_fuzz.rs: the vertical fixture also checks the flag.
- docs/file-format-parity.md: one line on the mapping.
2026-11-09 00:35:02 +07:00
dotCooCoo cca9a42c6c Effects: Effect › SVG Filters applies the document's SVG filters as live effects
Squashed from #6200 onto main.
2026-11-09 00:34:23 +07:00
dotCooCoo 332e115b68 Plug-ins: the bulk memory fuzz generators follow the paint generators
Moves the bulk memory case types, strategies and their test after arb_paint, so they no longer share the lines after output where other fuzz generators are added.
2026-11-09 00:31:14 +07:00
dotCooCoo 44432a4310 Plug-ins: the fuzz test generates bulk memory operations
plugin_fuzz now builds plug-ins whose run executes memory.fill,
memory.copy (overlapping ranges included), memory.init followed by
data.drop, and data.drop followed by memory.init. Lengths and offsets
are sampled at zero, small, page and mebibyte sizes, at an exact end,
one before and one past it, with copy sources and destinations and init
memory and segment offsets chosen separately. Fill and copy can repeat
up to about one fuel slice of copying.

Each case runs directly under the default budget, a small fixed budget
or one near its estimated cost. A run must trap exactly when a range
leaves memory or the data segment (empty once dropped), and must finish
when it is in bounds and has ample fuel; otherwise it may hit the
instruction budget. The same plug-in then runs through plugin.run: a
failed run leaves the document unchanged and the document still renders
and exports.

bulk_memory_cases_reach_their_instruction checks that each operation's
module contains its instruction and traps on a small out-of-bounds case.
2026-11-09 00:31:14 +07:00
dotCooCoo b5e6f6e80f Plug-ins: Safe Mode starts without plug-ins, offered after a launch stops while one loads
Squashed from #6185 onto main.
2026-11-09 00:30:24 +07:00
dotCooCoo 657a99b629 Actions: Load Actions… reads action sets saved as .aia files
Squashed from #6149 onto main.
2026-11-09 00:28:25 +07:00
dotCooCoo 58a9de88a9 Merge main into feat/plugin-effect-paint 2026-11-08 09:27:58 -08:00