Commit Graph
1514 Commits
Author SHA1 Message Date
dotCooCoo 7470505113 Render: cropped shadow and blur rasters are kept across pans within a margin
A Drop Shadow, Gaussian Blur, Feather or Photoshop-style filter raster
too large to keep whole is cropped to the view. It was drawn again
only while a later frame's rect, panned back, lay inside the frame it
was made in, so every pan that showed new pixels made it again. For a
Drop Shadow on a 6000 x 4000 pt image in a 2560 x 1440 view at 100% to
400%, a pan took 60 to 84 ms; with Gaussian Blur or Feather, a pan took
158 to 217 ms.

When such a raster is made again at the zoom and rotation of the one
kept for the object, it now also covers a margin around the view: up
to half the view's longer side, while the raster stays within the
8.4 million pixel budget at full size (441 pixels on each side of a
2560 x 1440 view for a 20 pt blur at 100%). Later pans that keep the
view inside the margin draw that raster. The first frame at a zoom, a
zoom step and the frames of a drag make the raster without the margin,
as before. A shadow made over an earlier cropped shadow covers only
the rect the earlier one was made for.

A kept raster is drawn again only after a pan by whole device pixels,
but the wheel, a trackpad and the scroll bars scrolled the view by
amounts that are not whole pixels. The canvas now moves the view by
whole device pixels when it scrolls or is dragged. A scroll by the wheel, a trackpad, a touch screen or a scroll
bar is rounded, and the part of a pixel left over is added to the next
scroll of the same view; it is dropped after a zoom, a turn, Fit or a
document switch. A Hand tool, Space or middle-button drag and a scroll
bar thumb drag round the distance from where the drag began.

The silhouette of a shadow or glow raster is now drawn with art culled
against the raster's own area instead of the view, as filtered content
already is. Before, a group member outside the view cast no shadow
into a raster kept whole, so a pan that showed the member drew it
without its shadow. A cropped raster kept across the margin would have
done the same. The moved silhouette that a drag compares is drawn the
same way.

Docs: docs/target-app-parity.md.
2026-10-26 20:43:54 +07:00
dotCooCoo 7a815b0acc Type: text.convertListToText moves the Type tool's caret past the markers
The Type tool's anchor and caret were moved past the inserted markers
only by the menu item in the desktop app. When text.convertListToText
came over MCP or the control channel while the Type tool was editing,
they kept their old byte offsets, and the inserted characters (a bullet
is 3 bytes) could leave an offset inside a character.

The command now ends the Type tool's typing, then moves its anchor and
caret past the characters inserted at or before them. In threaded type,
when the caret's character moved to another frame, the tool edits that
frame, which becomes the selection when it was not selected. The menu
item runs the command without adjusting the selection itself.

Docs: docs/mcp.md.
2026-10-26 19:38:12 +07:00
dotCooCoo 2f445e117f Type: Convert to Text makes a list's bullets and numbers characters of its text
The reference app's Type › Bullets and Numbering › Convert to Text turns
the bullets and numbers of the selected list paragraphs into editable
text. VectorCraft drew list markers but could not convert them.

Type › Bullets and Numbering › Convert to Text (type.convertListToText,
text.convertListToText) puts each list paragraph's marker at the start
of the paragraph as characters: the bullet, or the number and its
period as the paragraph showed it, then a tab, in the marker's font,
size and color. The paragraph leaves its list. Where the marker's tab
went to the left indent, the paragraph gets a plain left tab stop
there, so the text after the tab starts where it did. Where the
marker's tab went to a stop with a leader, or to a right, center or
decimal stop, a plain stop where the tab ended keeps the converted tab
there without the leader; right, center and decimal stops between the
marker and that place are removed. Past the left indent this applies
only to a paragraph with no tab of its own. In threaded type the
numbers are those the story counted, and a paragraph that goes on into
the next frame is converted once, where it starts. A right-to-left
paragraph with no direction set gets the Right to Left direction when a
letter or roman numeral in front of it would make it run left to right.
The change is one undo step. The Type tool's caret stays next to the
character it was next to, and in threaded type it goes with that
character to the frame it moved to, which becomes the selection when it
was not selected.

With the Every-line Composer a paragraph that holds a tab is broken
line by line, so a converted paragraph can break its lines at other
places than the list paragraph did.

Docs: docs/mcp.md, docs/target-app-parity.md.
i18n: Convert to Text in the 24 catalogs.
2026-10-26 19:38:12 +07:00
dotCooCoo bdba8c1cea Render: an image that can't be decoded shows as a crossed box and isn't decoded again
An image whose pixels can't be decoded, such as a PNG cut short by an
interrupted download, drew nothing on the canvas and the status bar
said nothing. Every render decoded it again, so each frame that drew it
paid for a decode that fails.

The renderer now notes such an image by its content and does not decode
it again. Each render still counts it in decode_failures, so an export
reports it as before. An image refused only because the images being
drawn leave it no room within twice the decoding allowance is not
noted, and the next render tries it again.

On the canvas the image draws as a light gray box crossed from corner
to corner, and the status bar says once for each image that it couldn't
be decoded. Exports still draw nothing there.

Docs: docs/target-app-parity.md.
2026-10-26 19:00:28 +07:00
Andrés Ortega 88060b199f Windows fonts: list the fonts only GDI has loaded, such as Creative Cloud's Adobe Fonts (#1258)
Squashed from #4130 onto main.
2026-10-26 17:51:42 +07:00
ashokram-si 87470ef0b7 View: all 25 saved views in the View menu; Edit Views… lists them
A document keeps up to 25 saved views, but the View menu listed only the
first 10, so views 11 to 25 could be saved and never chosen. All 25 are
listed now, by name, and choosing one changes the current window to its
zoom, centre and rotation (within the canvas's zoom range).

Edit Views… used to open the generic parameter dialog on the first view,
where the name of the view to change had to be typed. It now opens a list
of the document's views, like Edit Selection…: pick one to rename it or
delete it; OK applies every change as one undo step and Cancel leaves the
views as they were. view.saved.edit takes {edits: [{name, newName?,
delete?}…]} for that, the one-view form still works, and the command is
off while the document has no saved view.

A file's views are untrusted: on open at most 25 are kept, names are
trimmed, capped at 255 characters and unique, and views without a finite
centre and a positive zoom are dropped. New View… starts from the first
free "View N" and caps names the same way.

Behaviour from the public help page "Use multiple windows and views":
https://helpx.adobe.com/illustrator/using/viewing-artwork.html

docs/gaps.md (G7) and docs/target-app-parity.md take New View/Edit Views
off the missing list; docs/mcp.md documents the view.saved commands; the
catalogs get the Saved View 11-25 rows in the pattern of 1-10.
2026-10-26 17:40:42 +07:00
Taha-Mahmoodi 54d9fbc162 Type: a double-click on a threaded port breaks the thread there 2026-10-26 16:00:39 +07:00
dotCooCoo 45440b5444 Toolbar: double-clicking the Type on a Path tool opens Type on a Path Options
A double-click on the Type on a Path or Vertical Type on a Path tool
reported that the tool has no options. It now opens Type on a Path
Options for the selected type on a path, the same dialog as Type ›
Type on a Path › Type on a Path Options…. With nothing selected, or
with no type on a path selected, nothing opens and `tool.options`
returns the menu command's error, as the Rotate tool's double-click
does without a selection.

Docs: docs/control-protocol.md, the `tool.options` params doc.
2026-10-26 15:44:50 +07:00
Taha-Mahmoodi cfd085f34a Fix #3426: the Pathfinder panel's Pathfinder Options… sets Precision, Remove Redundant Points and Divide and Outline Will Remove Unpainted Artwork
Squashed from #4141 onto main.
2026-10-26 15:28:51 +07:00
Taha-Mahmoodi 0a241a7fdd Brushes: Window › Brush Libraries opens brush libraries whose brushes click or drag into the document's Brushes
Squashed from #4020 onto main.
2026-10-26 15:17:30 +07:00
Taha-Mahmoodi a34055beec Artboards: the Artboards panel's Delete Empty Artboards deletes every artboard with no artwork in one undo step
Squashed from #4142 onto main.
2026-10-26 14:10:36 +07:00
Taha-Mahmoodi 5b91057dca Repeat: a selected Grid Repeat has on-canvas handles for its rows, columns and spacing
With the Selection tool, a single selected grid repeat shows a handle below the grid (rows), one right of it (columns), one past its bottom-right corner (both) and sliders between its first two columns and rows (horizontal and vertical spacing), as the public Set grid repeat options page describes. Each drag previews object.repeat.options and commits as one Repeat Options undo step; Escape cancels, and a drag that ends where it began leaves no step. Bounding-box handles keep priority where they overlap, and the controls hide with the edges or the bounding box. Before, a drag there scaled the source or started a marquee.

Part of #2691.
2026-10-26 13:44:06 +07:00
dotCooCoo 64f29d5848 i18n: the message scan skips comments and reads EngineError::Disabled's reason
The message scan read the first argument of every error variant, so
for EngineError::Disabled it read the command id and missed the reason
the status bar shows. It also read error calls inside comments, such as
a commented-out bad(cmd, "..."), as messages that need catalog rows.
The scan now reads Disabled's second argument and removes // and
/* ... */ comments (nested ones included) before it looks for calls. A
// or /* inside a string or character literal does not start a comment.
2026-10-26 12:20:24 +07:00
skylar taylor-barrick 581c79dcb1 M14: distinguish qualification from publication (#4173) 2026-10-25 23:47:58 -04:00
Taha-Mahmoodi 502b204d74 Transform panel: the menu's Transform Object Only, Pattern Only, Both and Use Registration Point for Symbol act
Squashed from #4146 onto main.
2026-10-26 10:04:25 +07:00
dotCooCoo df716c3118 Image Trace: Document Library traces with a color group from the Swatches panel
Squashed from #3975 onto main.
2026-10-26 09:25:42 +07:00
vangel76 b54a5e6765 Artboards: canvas menu to lock and unlock artboards (#2531)
Squashed from #2532 onto main.
2026-10-26 09:25:35 +07:00
Angelo Bernardini ea36291f30 G12: General › Corner Radius is the Rounded Rectangle tool's radius (#394)
Squashed from #4074 onto main.
2026-10-26 09:09:47 +07:00
Drew Dibble f6a20c9f56 Web: shortcuts the browser also has run only in the app
Squashed from #4106 onto main.
2026-10-26 09:09:47 +07:00
dotCooCoo ad75ea5d06 Type: Highlight Substituted Fonts moves to Preferences › Type and applies to every document
Highlight Substituted Fonts is now a preference in Preferences › Type,
next to Highlight Alternate Glyphs, on by default and saved with the
other preferences (`prefs.set highlightSubstitutedFonts`). The canvas
reads it through `RenderOptions::highlight_substituted_fonts` for every
open document; a document's own setup no longer decides it. File ›
Document Setup no longer shows the checkbox and keeps Highlight
Substituted Glyphs.

A file saved with Document Setup's Highlight Substituted Fonts off now
shows the pink highlight when it opens, while the preference is on.
The file still opens with the stored value, and saving it again keeps
that value.

`document.setup` no longer reports `highlightSubstitutedFonts`. It
ignores the key and adds a `warnings` entry that names `prefs.set` to
its reply, so an older reply passed back still applies its other keys.

The raster cache of type under a raster effect now also redraws when
Highlight Alternate Glyphs changes.
2026-10-26 09:09:47 +07:00
dotCooCoo be5bd7dbf0 Pen tablets: a pen's eraser end selects the Eraser in the web build
Pointer Events report a press of a pen's eraser end as the eraser button
(button 5). The browser build ignored that press. It now presses like the
tip, and the web runner writes the pen's samples into a stylus feed with
the end they came from, so the canvas selects the Eraser tool before the
press and the press erases. The next press of the tip selects the tool
used before, as on Linux and macOS. A hovering pen keeps the end it last
pressed with, since Pointer Events report no end while a pen hovers. A
mouse or finger takes the pen out of the feed; a palm rejected while the
pen presses does not.

Docs: docs/hardware-parity.md, docs/gaps.md (G14),
docs/target-app-parity.md.
2026-10-26 09:09:47 +07:00
dotCooCoo dbc446329f Pen tablets: a pen's eraser end selects the Eraser on Windows
With Windows Ink, winit reports a pen as a touch and drops its pen
flags, so on Windows the eraser end of a pen draws with the current
tool. The message hook that reads the barrel button now also reads
each pen pointer message's POINTER_PEN_INFO and writes the pen's
pressure and end into the canvas's pen feed: PEN_FLAG_INVERTED or
PEN_FLAG_ERASER is the eraser end. The canvas then selects the Eraser
tool and the tip brings back the tool used before, as on Linux and
macOS. A pen leaving detection range or the window, another pointer,
or a mouse message that Windows did not make from a pen or a touch
clears the feed, so a mouse presses fully.
2026-10-26 09:09:47 +07:00
ncic 09b3b25004 Fix #3328: Pencil Fidelity down to 0.01 pt, with a logarithmic slider and key steps that fit the range
Squashed from #4196 onto main.
2026-10-26 09:09:47 +07:00
dotCooCoo 05e09039f5 Pencil: a stroke from an end of one selected path to an end of another connects them
Squashed from #4095 onto main.
2026-10-26 09:09:47 +07:00
dotCooCoo c9fa005a54 Pencil: the cursor shows a star before a press that draws a new path
Draw freeform paths with the Pencil tool says a small star appears on
the Pencil when it is ready to draw a freeform path, and Reshape paths
with the Pencil tool says the star disappears over a selected path the
drag reshapes. The Pencil cursor had no star.

- New Cursor::PencilNew: the Pencil's crosshair with a small star where
  the closing cursor has its ring. It becomes the crosshair with Use
  Precise Cursors and as a system cursor.
- The Pencil shows it before a press when neither find_extend nor
  find_redraw (the lookups the press uses, within Edit Selected Paths)
  finds a selected path under the pointer. Over such a path and while a
  stroke is drawn, the cursor has no star.

Docs: docs/target-app-parity.md.
2026-10-26 09:09:46 +07:00
Taha-Mahmoodi 0dc9d9abb4 Fix #1732: Transform Each opens on the values it was last confirmed with and has a Copy button
Squashed from #4175 onto main.
2026-10-26 09:09:46 +07:00
dotCooCoo 3d8c40f500 Eraser: Angle and Roundness in Eraser Tool Options shape the tip
Squashed from #4180 onto main.
2026-10-26 09:09:46 +07:00
dotCooCoo 7117c82cab Brushes: Art Brush Options' Width can follow the pen pressure
Art Brush Options' Width had no pen tablet option, so an art brush
drew at one width whatever the pressure. The Width row now has a
Fixed or Pressure menu and a second width. With Pressure the art is
Width wide at the lightest pen pressure and the second width at the
heaviest, following the pressure the Paintbrush recorded along the
stroke, and half way between the two on a stroke drawn without
pressure. brush.options takes width_mode and width_max; a brush
without them is saved as before.
2026-10-26 09:09:46 +07:00
dotCooCoo 60cb4c45ab Pencil: Live curve fitting in Pencil Tool Options
Pencil Tool Options has a Live curve fitting checkbox, on by default.
With it off, the path shown while a Pencil stroke is drawn joins the
stroke's points with straight segments, and the release fits the curve
at the Fidelity, as it does with the option on. Choosing another tool
while a stroke is drawn also keeps the stroke fitted. The option is
saved with the tool's other options.

path.freehand takes fit (true by default): with fit false, a new path,
a continued path and a redrawn section join the points with straight
segments.
2026-10-26 09:09:46 +07:00
dotCooCoo 5339fec9cd Type: typing "1. ", "A) " or "* " at the start of a paragraph starts a list
The reference app detects lists typed as 1., 1), A. or A), and makes
custom bullets from *, #, > or + followed by a space. In VectorCraft
the characters stayed as text.

When the Type tool types a space on its own after one of these at the
start of a paragraph in no list, the typing so far becomes one undo
step. The new command text.startList then removes the typed characters
and the space and makes the paragraph a numbered list in 1, 2, 3 or
A, B, C, or a bulleted list with the filled dot. A paragraph with no
indents gets the 18 pt hanging indent. One Undo puts the characters
back as text with no list, and the caret goes on after them; Redo
removes them again. The same characters later in a paragraph, list
characters pasted in one piece with the space and a paragraph already
in a list start nothing.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-26 09:09:46 +07:00
dotCooCoo 9f358a1d6d MCP: answer_dialog sets the fields of the app's open dialog and confirms or cancels it
Squashed from #4057 onto main.
2026-10-26 09:09:46 +07:00
dotCooCoo eadf7674f1 MCP: screenshot and render_preview can draw the Image Trace view
After imageTrace.setView, screenshot and render_preview still drew the
tracing result, because ui.render renders with the export options and only
the canvas turns on trace views. Only the app window showed the view.

ui.render now takes traceViews. With traceViews: true, Image Trace objects
draw in the view set with imageTrace.setView, as on the canvas, both
headless and in the running app. screenshot and render_preview take
traceViews and pass it on; without it they draw the tracing result, as
exports do. The trace-and-style prompt names the argument.

A supersampled render drew Outline view's lines, type outlines and dotted
guides as little as a quarter of an output pixel wide, so they came out
pale gray. The renderer now scales those widths and the guides' dashes by
the supersampling factor in the larger frame, so the lines stay one output
pixel wide.

Docs: docs/mcp.md (render_preview, screenshot), docs/control-protocol.md
(ui.render).
2026-10-26 09:09:45 +07:00
dotCooCoo 0641412cce Dialogs: ui.dialog.set returns an error for a field the open dialog does not read
ui.dialog.set stored any field name it was given, so a misspelled field
(`discrad` for `discard`) was kept without effect and the dialog then
ran with its old value. It now answers such a field with an error that
lists the dialog's fields, and leaves the dialog unchanged.

A dialog accepts the fields it holds, `__` fields, `discard` with a
discard button, `preview` with a live preview, the fields it reads
before a control adds them (each spec's `inputs`, for example Copy and
the object options of the Transform dialogs, Move's `distance` and
`angle`, the reference point, `path` of the export options dialogs,
`searchFolder`, Brush Options' `tips`, the Justification and
Hyphenation values that open blank, the Corners `kind` and `radius` of
corners that differ, the Gradient Stop popover's `color`, `opacity`,
`location` and `spread`, and a new artboard's `color` and display
marks), and the fields it passes to the command it runs: every
parameter of the generic `command` dialog's command, and the
`textureImage` that Load Texture… sets in the Glass and Texturizer
effects. Edit Selection now opens holding `deleted<i>` for each of its
rows, so setting a row number it does not have returns an error, and
Transparency Flattener Presets opens holding the selected preset's name
and options instead of adding them on its first frame.
2026-10-26 09:09:45 +07:00
dotCooCoo 3eda1b128c Image Trace: changes that wait with Preview off stay with their object
With Preview off, changes made in the Image Trace panel for one Image
Trace object were lost when another object was selected: selecting the
first object again showed its stored settings. The panel now keeps the
waiting changes for each object and shows them again when that object
is selected, unless the object's own settings changed in the meantime.
When Preview was turned on while another object was selected, the
object is traced with its changes when it is selected again.

Preview is now the UI command imageTrace.preview ({on?}: on, off or
toggle), and both the panel's checkbox and ui.set's imageTracePreview
run it. The command label has a row in every catalog.
2026-10-26 09:09:45 +07:00
dotCooCoo 58767abe0f Image Trace: the blended edge of a cut-out image adds no color to the palette
Squashed from #4075 onto main.
2026-10-26 09:09:45 +07:00
dotCooCoo c9cc2ef076 Image Trace: Document Library keeps neutral tones off saturated library colors
With the Document Library palette, each pixel took the library color
nearest in plain Oklab distance. A 50% gray lies nearer in that distance
to a saturated blue of the same lightness than to black or a light
cream, and a muted brown is also nearer to the blue than to either. With
a black, cream and blue library, both traced as the blue.

This changes how Document Library matches pixels: each pixel now takes
the library color nearest with differences in hue and chroma (Oklab a
and b) counted three times as much as lightness. The same measure picks
which library colors are used. Neutral and muted tones take a neutral
library color, and the other palettes are unchanged.
2026-10-26 09:09:45 +07:00
dotCooCoo 0629d4e9a5 Image Trace: Overlapping layers reach only under areas that hold their own color
With Method Overlapping, each color layer covered every pixel of the colors
above it in the stack. A small dot or square on a background was then traced
once in its own color and again, at the same bounds, in every color between
the background and it, and with Shapes on each copy became its own live shape.
Those layers also ended on edges they never touched and showed through the
anti-aliased rim there.

Each layer now leaves out every 4-connected part of its stacked area that holds
no pixel of its own color. This changes the result of many Overlapping traces,
the photo presets included: fewer paths (High Fidelity Photo 121 to 69.6 on its
own quality inputs, Low Fidelity Photo 37.1 to 26.1) and no rim, around a
shape, of a color that sits apart from it. One existing test that counted the
extra copies now expects one layer per area, and another that compared layer
pixel counts now checks that the bottom layer covers the whole image.
2026-10-26 09:09:45 +07:00
Angelo BernardiniandClaude Fable 5.1 a5806c8caa G11: the grid budget counts an item's distinct cells; parity row and evidence
CodeRabbit on #4080: `needed` summed footprint pieces before insertion
deduplicated them, so on a degenerate grid (ten collinear lines, 4,096 pieces
each in ten cells) every item exceeded the budget and went to the scanned list,
making the per-cell assertion vacuous. The cells are now collected in piece
order and consecutive repeats dropped before the budget check and the filing;
the horizontal fixture asserts `rest` is empty and that the lines are filed.
docs/target-app-parity.md: the Path operations area row, the Shape Builder
row and the evidence list record the bounded index (scores unchanged).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014gCpjL3yUhaH3jRp7ksufh
2026-10-26 09:09:44 +07:00
Angelo BernardiniandClaude Fable 5.1 6f8ac34f38 G11: Shape Builder's edge-source grid holds a bounded number of references
Follow-up to #4021. The grid filed each piece of a segment under its cells
without checking, so a degenerate grid (collinear horizontal lines: cells a
hundred points wide and a hair tall) stored one segment ~400 times per cell,
and coincident vertical segments (one column, a row per segment) filed every
segment under every row: a quadratic number of references, about a GiB for
16,384 segments within the Shape Builder's limit.

Now a segment is filed once per cell (its pieces come in order, so the cell's
last entry is enough to check), and the grid holds a budget of references
(64 per item plus four rows' or columns' worth, `reference_budget`); the
items past it go to the scanned list, so the index stays O(n·sqrt(n)) in
memory and every lookup still finds every segment through its point.

Regression: `rect_index_holds_a_bounded_number_of_references` (fails without
the change: 4,100 references per cell for ten collinear lines).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014gCpjL3yUhaH3jRp7ksufh
2026-10-26 09:09:44 +07:00
acosimati 03ab7bb805 MCP: doc_inspect reports opacityPct in the percent scale the drawing tools take
draw_path, draw_shape and object.setProps take opacity in percent (0-100),
but the document.inspect / document.node summary behind doc_inspect,
inspect_document and vectorcraft://object/{id} reported the stored 0-1
fraction under the same name. An agent that read 0.55 and wrote it back
got a nearly invisible object.

The summary now adds opacityPct (0-100, rounded to 1/100 of a percent)
beside the unchanged opacity, and the tool, resource and command
descriptions say which scale each field uses. Round-trip test in the mcp
crate: draw at 55 %, read 55 back from doc_inspect, inspect_document and
the object resource, write it back unchanged.
2026-10-26 09:09:44 +07:00
YOU WISH! GAMES aa7f6bb31d .ai import: editing data up to 512 MiB opens on 64-bit builds, so a card file with embedded rasters keeps its layers and text (part of #3510)
Squashed from #4177 onto main.
2026-10-26 08:18:31 +07:00
YOU WISH! GAMESandClaude Sonnet 5.5 9af023b084 .ai import: the -- placeholder in a gradient highlight and the XC operator no longer send the file to its PDF part (fixes #4176)
An undefined number (--) in `-- -- angle length Bh` is read as a radial
gradient with no highlight, and XC (a color space name after a linked
image's file name) is ignored like its neighbours. Either one used to make
the whole editing data unreadable, so the file opened as its PDF part and
lost its layers and live text. A -- anywhere else is still an operator the
reader doesn't know.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-26 08:18:25 +07:00
Louise FoxandClaude Opus 5.5 0bd011bd18 Plug-ins: compiling a plug-in's code takes none of a run's instructions
wasmi compiles each function of a plug-in when it is first called and,
by default, charges the run that calls it 7 instructions for each byte
of the function. The host hands a run its budget in 20 M-instruction
slices and resumes it when a slice runs out. But when a slice runs out
while a function compiles, wasmi returns an error from the call, not an
out-of-fuel pause, and the host reports it as Limit("instruction
budget"). So a plug-in's first run could fail with most of its budget
left, depending on where the slices fell, and the next run, with its
functions compiled, succeeded.

StitchCraft's PES exporter hit it on a design of 98 × 148 mm. In
VectorCraft 0.17.0's host its first export failed with 10 G and with
275 G instructions alike, and its second succeeded, taking under 1 G.
Run on wasmi directly, with the host's slices, the first export failed
in its 36th slice ("required_fuel=174139"), and with compiling free it
finished in 49.

Compiling now costs nothing: wasmi's fuel costs with no cost for
translating or validating, and its default cost for copying. A run pays
for its own instructions only, as many on its first run as on the next.
Compiling every function when the plug-in loads (CompilationMode::Eager)
also fixes it, but loads a 1.4 MB module in 42 ms instead of 10.

The new test fails without the change: a run that takes 1,040
instructions once its functions are compiled failed within them on a
plug-in just loaded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HhvnnnD5fTFupK8WWq35un
2026-10-26 08:18:24 +07:00
aiongg 714434527e Docking: panels on craft-ui's shared docking, floating panels in OS windows (#4135)
* Build: craft-libs at 2869b8cc

Pin craft-pdf, craft-print, craft-docpath, craft-ui, craft-keymap,
craft-window and the patched hayro/krilla backends to craft-libs
2869b8cc1077530bd07a7e192fb2b0e1304a1354, with the pdf-deps gate,
NOTICE, ASSETS.md and docs/pdf-backend.md at the same revision.

PDF: no modification date beyond the creation date, DeviceN images
are not JPEG-encoded, and clipping text draws nothing (its outlines
arrive as a clip path).

* Docking: compile against craft-ui at 2869b8cc

Floating windows are trees of groups: window_panels and window_active
read one as a flat group, and windows rebuilt from the legacy groups
keep their ids. Unknown dock actions are rejected, the new ones are
checked like the old, and every panel a close action removes keeps its
return location.

* Docking: panels and canvas on craft-ui's docking area

* Docking: tests for the dock area, flyouts, floating panels and the Tools panel

* Docking: catalogs without the old dock's strings

* Build: craft-libs at 8a503cfe

* Docking: floating panels in OS windows of their own on the desktop

* Docking: modal dialogs block panel windows; their keys and dropped files reach the main window

* Docking: art dragged onto a panel in its own window drops there

* Docking: module doc names the OS windows

* Build: craft-libs at a042cf26

* Docking: onto, above, below, collapsed, icon and column places on Float and Dock Panel; ui.docking

* Docking: command descriptions of Float, Dock, Move and Collapse Panel for the craft-ui layout

* Docking: control protocol describes the craft-ui layout, its commands and ui.docking

* Docking: rustfmt

* Docking: layouts saved before the canvas joined convert on load

Saved ui.json files and workspaces from before the shared layout held the
canvas (a dock-only tree plus floating_panels, docking_icons,
docking_collapsed, dock_collapsed and dock_width) convert into one layout:
the dock tree's groups in the main column, the icon column with the panels
dropped on it, floating groups and sets, sets docked as columns, collapsed
groups, the dock width and the places of closed panels. The legacy fields
are read, never written. A ui.json read only in part is copied to
ui.unreadable.json before anything saves over it.

* Docking: catalogs without the old collapse message

* Docking: converted floating sets start at most 720 points tall

* Docking: closed icon panels convert into the icon column; old floating rects, set heights and a copy of the file before conversion

* Build: craft-libs at 27e60765

* Docking: dock column places and icon count from the icon column; a docked column moves to a later place

* Build: craft-libs at d24e4bcc

* Build: craft-libs at 5bbe9f62

* Docs: floating panels in OS windows of their own close the other-monitor gap

* Docking: keys forwarded from a floating panel's OS window run shortcuts while the main window is unfocused
2026-10-25 15:25:35 -04:00
Dylan M. Taylor 6e7854967d Merge pull request #4113 from storytold/codex/egui-037-vectorcraft-20261023
Migrate VectorCraft input, text and capture to egui 0.37
2026-10-25 14:09:31 -04:00
Brandon Thomas f792c63597 Merge pull request #4090 from marcoarnulfo/feat/recolor-picker
Recolor Artwork: double-click a new color to pick it in the Color Picker, in the model it was picked in
2026-10-25 10:56:13 -04:00
Brandon Thomas e14b2b2c79 Merge pull request #4070 from marcoarnulfo/fix/direct-select-type-on-path
Direct Selection: an anchor of type on a path's path drags and the type reflows along it
2026-10-25 10:56:10 -04:00
Brandon ThomasandClaude Opus 5.5 f0a4f189f3 Docs: Direct Selection reshapes the path of type on a path outside perspective
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 10:44:35 -04:00
Brandon Thomas 70a05ba09b Merge pull request #4068 from dotCooCoo/fix/eps-no-art-central-file-text
EPS: the help text says no central file is written when no art shows
2026-10-25 10:38:12 -04:00
Brandon Thomas f0e5b5e902 Merge pull request #4069 from dotCooCoo/fix/set-paint-object-count
MCP: set_paint reports how many objects it painted
2026-10-25 10:38:01 -04:00