Commit Graph
1529 Commits
Author SHA1 Message Date
dotCooCoo 6ed4608d82 Images: an image past the 2 GiB decode allowance draws at reduced size instead of a crossed box
A PNG, JPEG, GIF or WebP image that takes more than the decode
allowance as RGBA (2 GiB, 512 MiB in the web app), such as a 24000 ×
24000 JPEG, was placed with the warning "too large to draw" and then
drew as a crossed gray box on the canvas and was left out of raster
exports. A 16-bit PNG whose decoded samples were past the allowance
was shown the same way, with the same warning, although its RGBA fits.

The renderer now decodes such an image at the largest size, keeping its
proportions, that fits the allowance as RGBA. Each pixel of the result
is the mean of the image's pixels it covers. A PNG that isn't
interlaced is read a row at a time; other images are decoded whole when
their decoded samples fit the allowance. A 16-bit PNG that isn't
interlaced and whose RGBA fits is read a row at a time at its own size.
An image of more pixels than the allowance has bytes still draws as the
crossed box, and so does one whose decoded samples are past the
allowance, other than a PNG that isn't interlaced. The renderer
decodes an image at reduced size only while the result and the memory
reading it takes (the image decoded whole, or the PNG reader's row
buffers) fit beside the images being painted; otherwise the image is
not decoded on that render (on the canvas it draws as the crossed box)
and is tried again on the next render. The document keeps the whole
file for saving and export. A placed document's saved preview past the
allowance is decoded the same way, at the size it is drawn at or at the
reduced size when that is smaller.

Open, Place and the Links panel say "an image of W × H pixels is shown
at reduced size" for an image drawn smaller. They say nothing for an
image drawn at its own size, and they say "too large to draw" for one
that is not drawn at reduced size.

Docs: docs/mcp.md, docs/target-app-parity.md (the crossed box's line
now names an image over the allowance that can't be drawn at reduced
size).
2026-10-26 21:41:42 +07:00
nrq6993-a11y fff6227351 #4122: File → Open starts in the last opened file's folder
Squashed from #4263 onto main.
2026-10-26 20:34:53 +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
Caio Pontes 311b343219 Fix #4128: text.create and text.setStyle store a font style the family has
Given a family and no font style, text.create and text.createInPath
kept the default Regular, and text.setStyle kept the text's previous
style, even when the family has no such style. A family whose styles
are numbered (Hiragino W3, W6) has no Regular, so the file named a
font that isn't installed and opened with Missing Fonts.

They now keep the style when the family has it, else take the
family's closest one, as text.setRangeStyle already did. Its rule
moves to `textedit::fit_font_style`, which the three commands share;
Graph labels styled through text.setStyle follow it too. A style the
caller names is kept as given.

The test builds a family with W3 and W6 and no Regular in code
(`test_fonts::numbered_font`), so no font file is added.
2026-10-26 18:12:51 +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
dotCooCoo 389dce727d Undo: a canceled undo scope drops the journal entries it cut from open undo groups
When an undo scope that joined an open undo group was canceled, the
journal was cut back to where the scope began, but the group still
listed the cut entries' numbers. The next command took one of those
numbers, so a later cancel of the group also removed that command's
entry, even when it ran in another document, and a replay of the
journal no longer matched the documents. end_undo_scope now removes
the cut numbers from every open undo group's journal entries and batch
steps.
2026-10-26 16:58:49 +07:00
Taha-Mahmoodi de151f849a Type: the thread-break comments describe the behaviour in our own words
Review follow-up (CodeRabbit, clean-room): two doc comments quoted the
cited help page. Comments only.
2026-10-26 16:00:39 +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
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
ham9zah 9a05383f34 Import: live blend check follow-ups
Review follow-ups to the live blend import (#4127):

- The check's grid saturates its neighbours' keys: a step far out (a
  coordinate like 1e300) saturates its cell, and the cells round it
  overflowed (a panic in debug builds, a wrong cell in release).
- Each laid object matches one drawn step: two drawn steps near one laid
  object no longer both take it, so a drawing the blend doesn't lay out
  isn't taken for it (the drawn steps stay).
- A blend's record is read to the length its XP gives: hex digits after
  it on the last line no longer spoil it.

Tests: a laid object matches one drawn step, 1e300 coordinates in the
check and in the import fuzz property, and a record line longer than
the record.
2026-10-26 15:11:45 +07:00
ham9zah 4214d4c9d3 Import: live blends are checked in bounded time and keep no stray art
Review follow-ups for the live blend import:

- The check of a blend against its drawn steps matched every drawn step
  against every laid one and measured centres inside the loop, so a
  crafted blend (64 keys, 1,000 steps between each) could stall the
  import. Centres and fills are now measured once, and each drawn step
  finds its neighbours through a grid of cells the tolerance wide.
- A blend lays out at most 5,000 objects to be made live, and all the
  blends of one import at most 50,000 (each laid out twice, once per
  orientation); past either, the drawn steps stay, with the note. The
  live steps take the place of drawn steps already counted against the
  reader's object limit.
- A fill the check can't compare (a gradient, a pattern) or a missing
  one no longer passes: the fills must both be none or solid colours
  within the tolerance.
- When what follows the blend's own art isn't a group of drawn steps,
  that art (its keys and spine) goes too, with the note, instead of
  staying drawn.
- The spine test can no longer pass without asserting: a spine written
  backwards keeps the keys' order (live), and a curved spine is read
  exactly while its straight-drawn steps stay drawn. New tests for steps
  with a gradient, for the blend's art when its steps aren't a group,
  and for the budget; import_fuzz gains a mutated-blend property and a
  large-blend test (998 steps live, 1,500 kept drawn, both quickly).
2026-10-26 14:10:37 +07:00
ham9zah f8bcf69b23 Import: Illustrator blends come in as live blends
A blend in a .ai file's editing data came in as plain art twice over:
the blend's own art (its key objects and spine, on `%_` lines) and its
drawn steps were both kept visible, so the keys lay doubled under the
drawn ones and the spine showed as a stray path, and nothing was live.
The spine itself was read exactly (its line and curve segments match).

The `(Adobe Path Blends) 1 0 n XP` record is now read (n bytes of hex on
the `%` lines after it, capped, checked: `DCBA`, version 1, the key
count and a record per key starting with its id). Each object's
dictionary names its part (`ShapeBlendPathType` K or S) and a key's id
(`ShapeBlendPathID`); the keys the record lists and the spine become one
live blend, the keys sitting on the spine's anchors. The record's other
fields aren't known, so the spacing is the drawn steps between two keys
(Specified Steps) and the orientation whichever lays the blend out as
drawn; the blend replaces the drawn steps only when it comes out as
drawn (each step within 0.5 pt and 0.02 of its colour). Otherwise the
drawn steps stay, without the blend's own art over them, with a note.
Behaviour as documented: https://helpx.adobe.com/illustrator/using/blending-objects.html

Save As .ai writes the PDF-compatible part only (no editing data), so a
blend is written back as its steps drawn, not live.

Hand-written tests: two keys and a straight spine as one live blend with
three steps and interpolated colours; a curved spine (l, c, L) in both
directions keeping its points and the keys' order; a garbled or short
record, a key without an id and ids the record doesn't list keeping the
drawn steps with a note; moving a key moving the steps; record parsing
on hostile input. The import fuzz target gains the record and the new
mesh keys.
2026-10-26 14:10:37 +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
ncicandClaude Opus 5.5 21a9e854e1 Tools: only the freehand tools get every move of a frame (#4227 review)
Every pointer move of a frame went to whatever tool was active, so with
a fast mouse (or a pen) a tool whose drag preview is costly (the
Selection tool moving a large selection, Free Distort, the Width tool)
redid it for each, up to 64 times a frame.

Tool::wants_samples (default false) says a tool builds a stroke from
the drag's samples: the Pencil, Paintbrush, Blob Brush, Eraser, Knife,
Smooth and Path Eraser answer true (the Paintbrush through its wrapper),
the Join tool doesn't. The canvas still reads the frame's moves every
frame, so the macOS feed's pressures stay paired, but replays them only
to such a tool; every other tool gets one drag a frame at the latest
position. A frame whose moves end where the last frame's did still
reaches the tool.

Tests: only_the_freehand_tools_get_every_move_of_a_frame (Pencil,
Paintbrush and Blob Brush get the 19 moves before the last, Selection,
Direct Selection and Width none),
a_mouse_stroke_keeps_a_frame_that_ends_where_it_started,
the_freehand_tools_want_every_sample, and
a_mouse_stroke_keeps_every_move_of_a_frame now checks every position in
order, not only the count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 13:31:52 +07:00
nrq6993-a11y c640f40ce1 G4: draw loaded-text cursor for threaded overflow
Squashed from #4229 onto main.
2026-10-26 13:09:22 +07:00
ncicandClaude Opus 5.5 21e9c8ff31 Pencil: Live preview option, a thin line while drawing when it is off
A Pencil stroke always previewed as the path it draws, with its full
appearance: with a fill set, the fill flipped between the shape and its
inside-out as the stroke crossed itself or curved back, and hid the line
being drawn.

Pencil Tool Options get a Live preview checkbox, above Live curve
fitting, on by default and kept with the tool's other options
(`livePreview`, settings.rs). With it off, the stroke previews nothing
while it is drawn: a thin line follows the pen (the drag overlay the
Knife and Blob Brush already show), and the release, or a switch of
tool mid-stroke, draws the path with its fill and stroke, as one undo
step, as before. Escape still cancels the stroke. With it on nothing
changes. The Paintbrush has no such option and keeps previewing.

Public reference: Draw and edit paths using the Pencil tool,
https://helpx.adobe.com/illustrator/using/tool-techniques/pencil-tool.html
(lists Live preview and Live curve fitting among the Pencil's options).

The checkbox label is translated in all 24 catalogs.

Tests: pencil_with_live_preview_off_shows_a_thin_line_until_the_release
(tools), pencil_with_live_preview_off_draws_the_filled_path_on_release
(engine), and the freehand dialog test shows the checkbox for the Pencil
only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 12:52:32 +07:00
ncicandClaude Opus 5.5 20476760bc Pencil: Edit Selected Paths redraws a selected compound path's member paths
A selected compound path (a shape with a hole, such as one made with
Object › Compound Path › Make) could not be redrawn with the Pencil or
the Paintbrush: at the press, find_redraw looked only for selected
objects that are paths themselves, and a compound path's paths are its
children. The stroke then drew a new path, which Keep selected selected
in place of the compound path, so every later stroke near the shape drew
a new path too: redrawing seemed to stop working.

- find_redraw takes a selected compound path's member paths as well,
  the nearest one within Edit selected paths within of the press.
- path.freehand's redraw keeps the compound path selected (or, with Keep
  selected off, takes it out of the selection) when the redrawn path is
  one of its members, so the next stroke redraws it too.

Test: pencil_redraws_a_selected_compound_path redraws the outer path and
then the hole of a selected compound path; it fails without this change
(the first stroke draws a new path).

cargo xtask ci: every step passes except one test in `test`,
vectorcraft-pdf tests_import_fidelity::text_becomes_point_type, which
fails the same way on unmodified main on this machine; it is unrelated
to this change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 11:49:03 +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
bflatastic a54251a18a Revert "Merge pull request #4200 from storytold/fix/sonar-s2208-engine-tests"
This reverts commit d7a2591dc0, reversing
changes made to e63c26ff15.
2026-10-26 09:56:24 +07:00
Dylan M. Taylor 2b72794251 lint(engine): explicit imports in engine modules and tests (S2208)
Replace glob `use super::*` with the names each module uses, so the
module's imports are visible at the top of the file (Sonar rust:S2208).
No code changes.
2026-10-26 09:52:47 +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
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
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
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
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 056274f5d6 Undo: canceling an undo group keeps a batch's steps in other documents
A command.batch that edited a document with an undo group and then a
document without one was dropped from the journal as a whole when the
group was canceled, so a replay lost the second document's edit, which
the session kept. Each batch step is now noted in the undo groups it
belongs to, by the same rule as a top-level command, and a cancel takes
only those steps out of the batch's journal entry. A step that changed
the active document becomes that change. Undo groups that stay open
follow the entry and step numbers that a cancel changes.
2026-10-26 09:09:45 +07:00
dotCooCoo 6c9ac54b22 Shape Builder: a merge across an overlap thinner than the precision gives one path
Two shapes that overlap by less than the region precision (0.01 pt) leave
their overlap out of the Shape Builder's regions as a sliver. Merging the
regions on both sides of it united only the picked faces, so the result
was a compound path with a hairline gap where the overlap had been.

A merge now takes in each dropped sliver next to a merged face when only
the merged faces' shapes fill it, both from the arrangement and from the
planar map used when open paths are selected. A thin cutout that no shape
fills stays a hole. What is left of a shape after the merge takes in a
sliver only where the shape covers it and the merged shape does not take
it in, so the two do not overlap. Pathfinder operations and Live Paint do
not use the merger and are unchanged; Live Paint's planar map does not
test which shapes cover a sliver.
2026-10-26 09:09:45 +07:00
dotCooCoo b92f394c0b Shape Builder: erasing picks a region narrower than twice the tolerance
In erase mode the tool tests each point for a line piece or an edge
within the tolerance before the region under it. Every point of a region
narrower than twice the tolerance is that close to its edges, so an
Alt-click, the Alt hover and an Alt-drag over a thin overlap touched its
edges and not the overlap, and the overlap was left behind.

A point in a region now touches the region when the region is no more
than twice the tolerance across there, measured from the nearest point
of its outline through the point to the outline on the other side. This
covers a drag at any angle, a drag that starts or ends in the region,
and a thin shape inside another or on its own. Near an edge of a wider
region, the edge is touched as before.
2026-10-26 09:09:44 +07:00
dotCooCoo c527082ff1 Shape Builder: a click merges over the map the tool built for the hover
shapeBuilder.merge built the planar map of the selection again, on the
thread that runs the command, although the Shape Builder tool had just
built the same map for its hover. The tool now returns its map from a
new Tool::shape_builder_map, and the command uses that map when its
inputs are the merge's inputs and its gap is the merge's gap; otherwise
it builds its own as before. The tool's map has the outline edges, so
erasing and splitting a stroke use it too.
2026-10-26 09:09:44 +07:00
dotCooCoo 3567e5be7d Live Paint: a plain group named "Live Paint..." is not a Live Paint group
A group counted as a Live Paint group when its name started with "Live
Paint". A plain group named, for example, "Live Painting" was then read
as one. With it and another shape selected, the Shape Builder found no
regions in it, and a merge on the other shape deleted the group and its
paths. Make Live Paint took the group as a Live Paint group to merge
into, and its paths did not become sources.

A Live Paint group now also needs its sources group, the group named
"Live Paint Sources" that Make Live Paint puts in it. A plain group with
such a name is traversed like any other group.
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
Dylan M. Taylor 46ece73197 lint: method references and elided const lifetimes (S1612, S8863) (#4204)
Use function paths where a closure only forwarded its argument
(PoisonError::into_inner, OsStr::to_str, FindRange::is_empty), and drop
redundant 'static on associated and module consts. No behaviour change.
2026-10-25 22:08:44 -04:00
NetterSilverandClaude Haiku 5.5 b089b7e948 Join the selected end points of two paths with Ctrl+J
Fixes #4163

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-26 08:18:33 +07:00
NetterSilverandClaude Haiku 5.5 6259448c39 Reset stroke weight to zero when the stroke colour is removed
Fixes #4109

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-26 08:18:32 +07:00
Dylan M. Taylor 0eebd533c5 security(pathops): signed zeros, reported budget rejections, and a fill-only fallback
Boxes that touch at -0.0/+0.0 now count as overlapping, so the pair cap cannot be skipped. try_boolean_n, try_unite_all and try_area report a refused input, and the Pathfinder shape-mode unite and the Blob Brush use them to show an error. When the planar map is over its budget, the fallback leaves out paths that fill nothing so a flood of cutting lines cannot take the filled shapes down with it.
2026-10-25 16:04:29 -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 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 Thomas c5c44e0dfb Merge main into fix/h2473-safe-file-name-leaves-a-windows
Combines this branch's screens.rs test module with the one #4123 added.
2026-10-25 10:38:39 -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
Brandon Thomas dda90f0f4f Merge pull request #4060 from dotCooCoo/feat/unknown-command-suggestion
Commands: an unknown command id is answered with the nearest command id
2026-10-25 10:37:54 -04:00
Brandon Thomas 774314a351 Merge pull request #4050 from dotCooCoo/fix/screens-filename-is-file-name
Export for Screens: <filename> takes the saved document's file name
2026-10-25 10:37:45 -04:00