Commit Graph
10785 Commits
Author SHA1 Message Date
dotCooCoo 76bb829e3a Graphs: a style that removes a mark's painted row resets the stored opacity
Applying or redefining a graphic style on a series mark whose fill or
stroke had paint, when the style leaves that row without paint, now
stores the row's opacity and blend mode on the graph. Before, the
opacity and blend mode another mark of the series left stayed, so a
Filled Lines band's outline kept a stroke opacity after a style without
a stroke went on a stroked marker. A row with no paint before and after
the edit still keeps what the graph stores.
2026-11-08 06:50:03 -08:00
dotCooCoo 517e0b7ae8 Effects: hiding a 3D effect still checks the values given with it
effect.setParams with visible: false skipped every 3D parameter check,
so a hidden edit could store a Classic depth of 2001, an unknown
surface or bevel, an empty light list or a Revolve edge other than left
or right. The values given are now checked by validate_three_d_params
(the checks of validate_three_d that do not build the art); after a
change of 3D type the values the effect keeps are checked too. The
object still does not need to fit while the effect is hidden.
2026-11-08 06:35:39 -08:00
dotCooCoo f384d27bee 3D (Classic): the solids test checks the classic faces' hue
every_solid_draws_shaded_faces_and_leaves_the_source_editable no longer
skips the color check for Extrude & Bevel (Classic). Its faces must be
the fill's red or the stroke's black, shaded, or lightened toward white
by the Plastic highlight, which keeps r - g to r - b at 6 to 7.
2026-11-08 06:35:38 -08:00
Ahmed Gomaa f12cf9a545 G13: merge main and strengthen snapping regression checks 2026-11-08 16:24:25 +02:00
ruchirguitar 3984874728 M2.1: avoid discarded path copies during deletion (#3380) 2026-11-08 19:35:48 +05:30
M Balazs PC a24ab06c6d Merge branch 'fix/ai-type-leading-forced-breaks' into fix/ai-right-aligned-tabs
# Conflicts:
#	crates/engine/tests/import_fuzz.rs
#	crates/eps/src/import/ate.rs
2026-11-08 14:58:13 +01:00
M Balazs PC f5c3f47612 Merge remote-tracking branch 'origin/main' into fix/ai-type-leading-forced-breaks
# Conflicts:
#	crates/eps/src/import/ate.rs
#	crates/text/src/layout.rs
2026-11-08 14:57:14 +01:00
dotCooCoo b6404f2f8b JavaScript: toLocaleString calls toString on the boxed value, and overwriting an element reserves no heap
Object.prototype.toLocaleString passed the primitive this value to
toString; section 15.2.4.3 calls it on ToObject(this), so a strict
toString now sees the object. The array methods' element write reserved
room for a new element even when it only replaced an own property, so a
heap at its limit stopped reverse or sort writes that add nothing.
2026-11-08 05:54:07 -08:00
dotCooCoo 923faeb35a JavaScript: the test262 interpreter runs fail when a harness file is missing or no test runs
run_tests read an unreadable harness, include or test file as an empty
string, so a broken suite checkout passed with every run counted as a
failure. It now stops with the file's path. The language run checks
that test/language exists, and the language and built-ins runs check
that at least one ES5 test ran.
2026-11-08 05:52:46 -08:00
dotCooCoo d8afed1562 Plug-ins: painted pieces keep their swatches in Pathfinder and baked art
Pathfinder effects, compound shapes, Expand Appearance and pattern
expansion now pass the document to the effects they evaluate, so a
painted piece that names a swatch or pattern takes part as drawn instead
of being refused. A path with a painted effect takes part in Pathfinder
and compound shapes as its pieces, each with its own paint, inside the
path's opacity and blend mode.

The renderer's kept effect art and live evaluations now count the
document's swatch and pattern names for objects with a plug-in effect,
so deleting or restoring a swatch a piece names redraws the object.
2026-11-08 05:52:39 -08:00
dotCooCoo 01c89d4bc5 JavaScript: a small heap limit no longer leaves a realm without built-ins
Installing the built-ins is not bounded by the heap limit: Math and JSON
no longer reserve heap while they install, so a realm made with a tiny
heap_bytes gets every built-in and runs once the limit is raised. If
installing fails, the realm keeps the reason and every run ends with an
internal error instead of running against missing built-ins.

The json2.js test skips only when the built-in check returns false, and
fails on any other result. The parser's progress line says the app does
not run scripts yet.
2026-11-08 05:35:27 -08:00
dotCooCoo d65207dc62 Plug-ins: only File › Open lists importers' files, and imported art at the canvas edge keeps an editable artboard
New from Template, Load Character/Paragraph/All Styles, Recolor's Other
Library… and the library panels' Other Library… read files with the
built-in readers, so their open dialogs now use builtin_open_filters(),
which leaves out the extensions only importer plug-ins read. File › Open
keeps open_filters() with the importers' files.

The artboard of a document an importer opens is now kept within
±4,000,000 pt. Art at the edge (a zero-width path at x = 4,000,000, or a
stroke past the edge) gave an artboard beyond it, and every later edit
of the document was rejected.
2026-11-08 05:35:23 -08:00
dotCooCoo 56f8e3208a i18n: French rows keep the no-break space before punctuation 2026-11-08 05:13:18 -08:00
dotCooCoo 58f5789e9a Plug-ins: Open With passes an importer its parameters and adds the file to Open Recent
File › Open With asks for the parameters of an importer that declares
any, at their defaults, once the file is picked (dialog `pluginImport`),
and opens the file with the values set. `file.openWith`, `app.open` and
MCP's `open_file` take `params` and pass them to the importer;
`app.open` without them runs the importer on their defaults, with no
dialog. A file opened with Open With is added to Open Recent, as File ›
Open adds the files it opens.
2026-11-08 05:07:08 -08:00
dotCooCoo 96bdb813a6 Plug-ins: read-only inputs count toward the input's memory share
A filter's input is now encoded within the half of the plug-in's memory
cap that the input and the parameters share. Every object counts toward
it in paint order, with its id, bounds, transform and name. Type runs
and image pixels that don't fit what is left come with truncated or
pixelsOmitted, and a type, image or symbol instance whose other fields
alone don't fit fails the run before the plug-in starts with
"memory budget (object N needs S bytes of input, L left)".
2026-11-08 04:42:17 -08:00
dotCooCoo 36eec28617 MCP: open_file takes an importer plug-in to open the file with
open_file passes `importer` (an importer plug-in's format id,
plugin.<id>) on to app.open. Headless, it becomes document.open's
`importer`; in the app, app.open with `importer` runs file.openWith, so
the file opens with that importer as File > Open With does, also when a
built-in format reads its extension.
2026-11-08 04:40:23 -08:00
dotCooCoo ca7c0462fb Merge main into fix/ai-writer-object-limit-2 2026-11-08 04:38:21 -08:00
dotCooCoo 9316c17967 .ai save: the editing copy stops at the reader's object limit
The reader stops a whole file past 4,000,000 objects (MAX_NODES), and
the writer had no limit of its own. The writer now counts the objects
it writes as the reader counts them, across layers, symbol and pattern
definitions, opacity masks and art styles, and leaves out art past the
limit with a warning. Art that does not fit is given back as a whole:
a mask, a pattern or a symbol definition is left out with all its art,
and a symbol's definition is written only with room for its instance.
The limit is the reader's own constant, re-exported as
MAX_EDITING_OBJECTS.
2026-11-08 04:38:15 -08:00
dotCooCoo 95678340b0 .ai import: a symbol's linked color named like a color group is renamed
A global or spot color that a symbol library's art links to and whose
name a color group of the document has now comes in under a free variant
of the name, which the art then names, as for a name another swatch has.
Swatches and color groups share one set of names.
2026-11-08 04:34:49 -08:00
Don Omondi 9d706a9a6d Parity doc: paths with an older Art brush keep their drawn look 2026-11-08 06:41:09 -05:00
Don Omondi d87844bba6 Merge remote-tracking branch 'upstream/main' into fix/eps01-editing-overlay
# Conflicts:
#	docs/gaps.md
2026-11-08 06:36:42 -05:00
ruchirguitar 655a16fa67 #5925: add collapse arrows to floating panels and rail flyouts 2026-11-08 17:02:29 +05:30
HassanKhan f71952730f Contributors: Hassan1305's name for the About window 2026-11-08 15:07:37 +05:00
dotCooCoo 7a38e2c990 Merge main into feat/plugin-menu-commands 2026-11-08 02:04:06 -08:00
HassanKhan 7a145576d4 Part of #4936: text.spelling.check lists unknown words, text.spelling.suggest suggests
The Edit > Spelling items have been placeholders with nothing behind them. This adds the
engine half of Check Spelling on craft-proof, the shared spelling engine in craft-libs (at the
revision the other craft-libs crates already pin), so no word list is copied here:

- text.spelling.check {ids?} lists the words the dictionaries don't know in every visible,
  unlocked type object (or ids), each run checked in its Character panel Language (English
  when it has none; nothing in a language without a dictionary), as {id, start, end, word,
  lang}. start/end are byte offsets in the object's text, the ones text.editRange takes, so a
  word is changed with text.editRange as one undo step. At most 10,000 words, with `more`.
- text.spelling.suggest {word, max?, lang?} gives the dictionary's suggestions, asked for one
  word at a time as craft-proof recommends.

English comes from the public-domain Moby word list built into craft-proof. Its dependencies
(log, miniz_oxide, toml, unicode-normalization) are already in the lockfile. The Check
Spelling dialog, Auto Spell Check and Edit Custom Dictionary follow in later PRs.
2026-11-08 14:59:52 +05:00
dotCooCoo 065170b735 Merge main into feat/js-builtins-text 2026-11-08 01:44:20 -08:00
Don Omondi e5674ba1c5 EPS/.ai editing data: test a stack of a solid fill and a stroke without a brush
A path whose style is a solid fill under a 50% Screen stroke comes in as
itself with both, each with its own transparency.
2026-11-08 04:40:55 -05:00
dotCooCoo c66f6b2068 Merge main into fix/export-unknown-options 2026-11-08 01:40:37 -08:00
dotCooCoo f17e700421 Merge main into fix/edit-copy-artboard-route 2026-11-08 01:11:05 -08:00
dotCooCoo 0801e4373f Merge main into feat/js-builtins-core 2026-11-08 01:04:44 -08:00
Don Omondi ba1abb73b0 .ai import: tests for Pattern brushes' number counts and an older Art brush's first number
A Pattern brush reads its scale from 3 or more numbers (the older form's
8 too) and isn't read with fewer; an 8-number Art brush is the older form
whatever its first number. The module notes say the count tells the form.
2026-11-08 03:51:30 -05:00
Don Omondi 6abe10583a Merge remote-tracking branch 'upstream/main' into fix/ai-import-brushes
# Conflicts:
#	docs/file-format-parity.md
2026-11-08 03:35:43 -05:00
dotCooCoo 9f629418e9 Merge main into perf/contours-cover-lists 2026-11-08 00:21:42 -08:00
dotCooCoo 66a01584ae Plug-ins: inputs need a granted doc.read and stay within totals
A filter manifest that lists `inputs` must now list `doc.read` in
`permissions`, so installing it asks the user to grant them and the
Additional Plug-ins Folder loads it only once granted. Left out, the
manifest does not install.

The pixels of all images in one filter input take at most 16 MiB of
base64, and the runs and paragraphs of all its type at most 16 MiB of
JSON. An image whose pixels do not fit what is left comes with
`pixelsOmitted`, checked before it is decoded, and type that does not
fit comes with `truncated`. The read-only objects are kept once and
written into the input from there.

A field a filter adds to a read-only object is named in the refusal
with control and bidirectional characters escaped, cut to 64
characters.
2026-11-08 00:15:36 -08:00
dotCooCoo 32abbfdb8f Merge main into fix/graph-series-object-opacity 2026-11-08 00:05:18 -08:00
dotCooCoo 4a64208b82 Merge main into feat/3d-classic-extrude-bevel 2026-11-08 00:02:52 -08:00
dotCooCoo a3c37ea1f4 Merge main into feat/plugin-importers 2026-11-07 23:49:11 -08:00
dotCooCoo c2f0a5667f Merge main into feat/plugin-effect-paint
# Conflicts:
#	crates/engine/src/cmd/plugin.rs
#	crates/engine/src/store.rs
#	crates/engine/src/tests/plugins.rs
#	crates/engine/tests/plugin_fuzz.rs
#	crates/plugins/src/lib.rs
#	crates/plugins/src/manifest.rs
#	crates/plugins/src/permissions.rs
#	crates/plugins/src/runtime.rs
#	crates/ui-egui/src/i18n/bg.tsv
#	crates/ui-egui/src/i18n/bs.tsv
#	crates/ui-egui/src/i18n/ca.tsv
#	crates/ui-egui/src/i18n/cs.tsv
#	crates/ui-egui/src/i18n/da.tsv
#	crates/ui-egui/src/i18n/de.tsv
#	crates/ui-egui/src/i18n/el.tsv
#	crates/ui-egui/src/i18n/es.tsv
#	crates/ui-egui/src/i18n/fi.tsv
#	crates/ui-egui/src/i18n/fr.tsv
#	crates/ui-egui/src/i18n/hi.tsv
#	crates/ui-egui/src/i18n/hu.tsv
#	crates/ui-egui/src/i18n/id.tsv
#	crates/ui-egui/src/i18n/it.tsv
#	crates/ui-egui/src/i18n/ja.tsv
#	crates/ui-egui/src/i18n/ka.tsv
#	crates/ui-egui/src/i18n/ko.tsv
#	crates/ui-egui/src/i18n/nl.tsv
#	crates/ui-egui/src/i18n/pl.tsv
#	crates/ui-egui/src/i18n/pt-br.tsv
#	crates/ui-egui/src/i18n/ru.tsv
#	crates/ui-egui/src/i18n/sv.tsv
#	crates/ui-egui/src/i18n/tr.tsv
#	crates/ui-egui/src/i18n/uk.tsv
#	crates/ui-egui/src/i18n/vi.tsv
#	crates/ui-egui/src/i18n/zh-hans.tsv
#	crates/ui-egui/src/i18n/zh-hant.tsv
#	crates/ui-egui/src/io/open.rs
#	crates/ui-egui/src/tests/plugins.rs
#	docs/mcp.md
#	docs/plugins.md
#	docs/target-app-parity.md
2026-11-07 23:43:15 -08:00
dotCooCoo 68609fb43b Plug-ins: filters at API level 2 read type, images and symbol instances
A filter manifest at `api` 2 may list `inputs` (`type`, `image`,
`symbolInstance`). Such a filter is also given the selected objects of
those kinds, read only: type with its runs and paragraph attributes,
images with their pixel size, color mode and, when embedded and small
enough, their RGBA pixels in base64 (never a linked file's pixels or
path), and symbol instances with their symbol and transform.

The output must return each read-only object as {"id": ...} alone or
exactly as given. A change, an omission or a duplicate is refused
before the edit, so the document and undo history stay as they were,
including for output handed in from a heavy run. A filter without
`inputs` gets the same input bytes as before.

A manifest that lists `inputs` below `api` 2, outside a filter, with an
unknown or repeated kind, or with a permission list that lacks
`doc.read` does not install.

Part of #4333
2026-11-07 23:34:20 -08:00
dotCooCoo cdd2cc234f fmt: wrap the .ai reader's document imports as rustfmt does 2026-11-07 23:29:09 -08:00
dotCooCoo 272a34bee5 Merge main into feat/ai-editing-data-s6b2 2026-11-07 23:24:31 -08:00
dotCooCoo c43e4a388e Tests: placed gradient tests check the whole gradient after Transform and Free Distort
The baked Transform and Free Distort tests now compare each placed
gradient's start, end, aspect and focal point with the expected values
within a tolerance, and the Transform test adds a turn with a scale.
2026-11-07 23:24:09 -08:00
dotCooCoo b109378ae6 Plug-ins: live-effect plug-ins at API level 2 can paint the pieces they return
A live effect whose manifest has "api": 2 and "paintOutput": true returns
{"objects": [...]} as pieces, each drawn by itself in order with fills and
strokes of its own in the forms a filter returns. A piece without fills or
strokes keeps the ones the effect was given, and an empty list paints none.
An effect on a fill returns only fills, one on a stroke only strokes.

The whole result is checked before any of it is drawn: the output limits,
finite numbers in range with nothing clamped, known keys only, and every
swatch and pattern it names in the document. One fault draws that step of
the stack unchanged, keeps the effect record and puts the plug-in's name
and the field in plugin.info's lastError. Each piece counts against the
geometry-effect budget, so the painted effects of one stack make at most
100,000 pieces.

The pieces are drawn, measured and exported to PDF and SVG from the
appearance stack without changing the document, and Expand Appearance
writes them as ordinary paths in one undo step. The plug-in API level
rises to 2; plugin.list and plugin.info give api and paintOutput. Effects
without the key behave as before.
2026-11-07 23:22:11 -08:00
dotCooCoo fd94ebe86c Plug-ins: importer plug-ins open file types VectorCraft does not read
An importer plug-in (kind "importer", permission import.read) lists 1 to 8
file extensions and turns a file's bytes into objects, which open as a new
document whose artboard is their bounds. File › Open lists its extensions,
File › Open With (file.openWith) opens a file with a chosen importer, and
document.open takes importer and params. A built-in format that reads the
file by its content or extension always opens it; among importers listing
the same extension, the one whose id sorts first opens it. An importer reads
at most 128 MiB, and Place still reads only the built-in formats.

Docs: docs/plugins.md, docs/mcp.md, docs/gaps.md, docs/target-app-parity.md.
2026-11-07 23:05:09 -08:00
BFlat 0a702cc0a5 Merge pull request #6190 from dotCooCoo/fix/plugin-bulk-memory-fuel
Plug-ins: a run keeps the fuel left in a slice at a bulk memory instruction
2026-11-08 14:42:28 +08:00
BFlat cc8770a57d Merge pull request #6188 from dotCooCoo/fix/ai-scatter-tints-brush-frame
.ai import: Scatter brushes in Tints open in Tints, and brush art drops its frame
2026-11-08 14:42:14 +08:00
BFlat 0a0ff46e9c Merge pull request #6187 from dotCooCoo/fix/generic-cmyk-solver-converges
Color: Generic CMYK separates nearby colors alike when an ink sits at 0 or 100%
2026-11-08 14:41:59 +08:00
BFlat 3fe5314fcc Merge pull request #6186 from dotCooCoo/fix/modal-dialogs-fit-content
Dialogs: New Workspace and New Toolbar fit their contents instead of opening 420 pt tall
2026-11-08 14:41:45 +08:00
BFlat 8c772c8a62 Merge pull request #6184 from dotCooCoo/feat/plugin-progress-cancel-log
Plug-ins: API level 2 lets a plug-in report progress, see Cancel and write log lines
2026-11-08 14:41:30 +08:00
BFlat cd4a23246d Merge pull request #6183 from dotCooCoo/feat/ai-legacy-binding-punctuation
.ai import: legacy binding punctuation opens as Burasagari's Force setting
2026-11-08 14:41:15 +08:00