Commit Graph
2112 Commits
Author SHA1 Message Date
dotCooCoo 8a730bab6b Reject invalid New Art Basic parameters 2026-11-06 11:15:35 +07:00
dotCooCoo b26bd3d472 Reject invalid Guide Lock parameters 2026-11-06 10:41:08 +07:00
dotCooCoo 398131b9cc Reject invalid Transparency Grid parameters 2026-11-06 10:12:42 +07:00
dotCooCoo 48a3710fae Reuse selected object locations for large transforms 2026-11-06 09:58:43 +07:00
dotCooCoo b4a4f2aa4f Reject invalid Slice toggle parameters 2026-11-06 09:42:35 +07:00
Don Omondi 97697420f9 Variables: Load Variable Library keeps a bound text variable the library declares (#4136)
Loading a variable library deleted every variable of the document with its
bindings, including a text variable of the same name that the library
declares. Text made dynamic and then given a library's variable name lost its
binding, so selecting the library's data sets changed nothing. Such a
variable now stays bound, and the library's data sets change its text; other
variables are deleted as before.
2026-11-06 07:45:21 +07:00
Don Omondi f987c2bbb0 Intertwine: the object brought over leaves no hairline of the one below (#5337)
The area an Intertwine member is drawn over another in was exactly the
overlap face, so its edge lay on the edge of the member below. Both edges
were anti-aliased, and the member below showed through as a thin line along
them. The area now reaches 2 pt past the face into the parts where only the
raised member paints (where drawing it again changes nothing), so its edge
lies inside that member.
2026-11-06 07:23:35 +07:00
Don Omondi dfe628e906 Blend spine: Shift-click picks several spine points, which drag together (#5285)
Direct Selection kept only one picked point of a blend's spine. Shift-click
now adds a point of the same spine or takes it away, and dragging any picked
point moves them all. object.blend.spine.moveAnchor takes `with`, the other
points to move by as much, with the key objects on them, in one undo step.
2026-11-06 07:23:19 +07:00
Don Omondi 483de72dbb Direct Selection: Cmd/Ctrl held lends the Selection tool and shows its bounding box (#3901)
Squashed from #5851 onto main.
2026-11-06 05:33:00 +07:00
Don Omondi b976de560d Join tool: scrubbing the ends of two crossing paths trims them and joins the paths at the crossing (#5844)
The Join tool drew a segment between the open ends of two crossing paths
instead of trimming what overhangs the crossing. path.joinScrub now looks for
two crossing open subpaths whose overhanging ends the scrub runs over, cuts
both at the crossing and joins the kept parts there with a corner, in one undo
step. Without a crossing the endpoint join is unchanged.
2026-11-06 05:32:24 +07:00
dotCooCoo c4d40de212 Links: the hashing limit is 1 GiB in params text and MCP docs
links.findFiles hashes files up to MAX_HASHED (1 << 30 bytes) and compares larger ones by size only. The params text, the module doc comment and docs/mcp.md said 1 GB; they now say 1 GiB.
2026-11-06 01:32:42 +07:00
FredAppsandClaude Opus 5.5 64f7b49dea Selection: a hover checks the bounds memo once, not once per object
Hovering looks up the bounds of every selected object, and each lookup
went through the memo key check, which compares the whole selection. That
made a hover quadratic in the selection: 1.5 s at 50,000 selected paths.

The walk now checks the key once and shares it across its lookups.

Part of #1280.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 01:07:34 +07:00
dotCooCoo 7d004de195 .ai import: graphic style libraries open with their styles
A .ai or EPS graphic style library holds graphic styles and their list
in its editing data but no layers, so it came in as its PDF part or
page with the default styles, and Other Library listed those. A file
read as its PDF part or page, because it has no layers or its layers
can't be used, now gets the styles of its list, in list order, as a
file read from its layers does: File > Open shows them in the Graphic
Styles panel and Other Library lists them in a library panel.

Style stroke weights and effects are scaled by the Large Canvas factor
of an EPS, and for a .ai whose editing data is in the units of its
pages by the pages' UserUnit or the declared Large Canvas scale.

Part of #3349
2026-11-06 00:55:18 +07:00
dotCooCoo c63ce28e84 Links: params text and MCP docs say parent folders are resolved
links.findFiles' params text and docs/mcp.md now say that the saved path's
parent-folder steps (.., or the empty components of a classic Mac :: run)
are resolved and that . components in a slash path are skipped before
folder names are compared.
2026-11-06 00:55:18 +07:00
Don Omondi 22a4dd6285 Libraries: spot colours stay spot colours in every document (#5812)
A library colour kept only its values, so a spot colour came back as a
process colour once its document was closed or in a new one. The library
now keeps a spot colour's ink name and tint (in the .vclibrary file too);
library.use links the paint to the document's spot swatch of that name,
adding it when the document has none of that colour, in one undo step.
A spot swatch dropped on the Libraries panel brings its name and tint.
2026-11-06 00:42:10 +07:00
dotCooCoo bed4154597 Links: Find Linked Files resolves parent folders in a saved path
A saved link path such as `Disk:Projects:Art::photo.png` (classic Mac OS)
or `/old/Projects/Art/../photo.png` names a file in `Projects`. Ranking
the files found compared `Art` first, so a file under a folder named
`Art` came before one under `Projects`. The `::` runs and `..` components
are now resolved before the folder names are compared.
2026-11-06 00:24:44 +07:00
dotCooCoo 934e6cba53 perf: reuse selected paint bounds for library gradients 2026-11-05 23:42:01 +07:00
Alex 9e2e0e0f69 Pencil: a new stroke with Keep selected off leaves nothing selected (#5752)
Drawing a new Pencil or Paintbrush stroke kept the earlier selection: the engine's
`insert_look` selects the new path only when `keepSelected` is on, and with it off left the
selection as it was. Illustrator starts such a stroke by dropping the selection, and the new
stroke is not selected with Keep selected off, so the command now clears the selection after
inserting a new path.

What stays as before: with Keep selected on a stroke selects only the path it draws (the
earlier selection is replaced); a stroke that continues or redraws a selected path with Keep
selected off deselects that path and keeps the rest of the selection. The Blob Brush keeps its
own Keep selected and Merge only with selection options.

`path.freehand`'s documentation, the engine test
`pencil_with_keep_selected_off_leaves_nothing_selected` and the Tool Options test
`the_new_path_is_selected_only_with_keep_selected_on` cover the three cases. Docs: roadmap,
target-app-parity and ui-parity carry the change.
2026-11-05 23:42:01 +07:00
Harley Hawk a77b9e37d3 Add customizable shape tools and 3D Box add-on
- Extend vectorcraft-geom::shapes with clean-room open/pie/chord/arc ellipse and rectangle builders, per-corner radii, polygon/star corner rounding and deterministic vertex randomization, logarithmic/Archimedean spiral divergence and inner radius, and perspective/isometric 3D box face builders.
- Isolate 3D Box and customizable shape parameters as a VectorCraft add-on under crates/*/src/**/addons/:
  - crates/tools/src/addons/box3d.rs (Box3dTool and CustomShape extras stored under Node::extras["vc-shape-tools"])
  - crates/engine/src/cmd/addons/shapes.rs (addon.shapes.rectangle, addon.shapes.ellipse, addon.shapes.polygon, addon.shapes.star, addon.shapes.spiral, addon.shapes.box3d, and addon.shapes.configure)
  - crates/ui-egui/src/addons/shapes.rs (Object > Plug-ins > 3D Box > 3D Box Tool and context-sensitive Control bar options)
- Keep crates/engine/src/cmd/create.rs, crates/tools/src/shape.rs, and crates/tools/src/draw2/family.rs byte-for-byte identical to main.
- Add translations for "3D Box" and "3D Box Tool" across all 26 .tsv catalogs in crates/ui-egui/src/i18n/.
2026-11-05 23:25:05 +07:00
dotCooCoo 84904020e8 Images: a colorized image's missing-link placeholder shows in its own colors
A linked 1-bit image mask from a .ai file keeps its fill color as a
colorize paint, so the image takes the color once its file is relinked.
Until then the image shows the missing-link placeholder, and the canvas
and PDF export colorized that placeholder too: its light tile turned
nearly transparent and its red cross took the fill color.

ImageBlob::takes_colorize is false for a preview whose pixels are not
grayscale. While it is false, the canvas draws the image and PDF export
writes it as it is, printed separations separate it as an uncolorized
image, and transparency flattening (EPS, PDF 1.3 and PDF/X-1a export,
Flatten Transparency) does not count its paint as transparency. The
paint stays on the image, and a grayscale preview is still colorized.
SVG and EPS export already write only grayscale images colorized.
2026-11-05 23:25:05 +07:00
dotCooCoo 456487b873 .ai import: the file opens on its active artboard
VectorCraft now reads `CropAreaActive`, an `/Int` in the dictionary of
the editing data that holds the `ArtboardArray`, as the index of the
active artboard in that array. The reader ignored it before, and every
file opened on its first artboard.

The opened document starts with that artboard active, so the view the
document opens at and the Artboards panel use it. The index counts
every entry of the array, so an artboard that is left out (one with no
area) does not shift it. When the entry is missing, is not an `/Int`,
or names an artboard that does not open, the first artboard is active,
as before. A file that comes in as its PDF part, with its pages placed
where its artboards are, opens on the page of the active artboard, also
when the reading stops before the artboards. The same reader serves the
editing data of EPS and PDF files.

The active artboard is kept on the opened document only; native files
do not save it.
2026-11-05 22:03:55 +07:00
dotCooCoo 48cf28fe48 Links: a classic Mac OS path is named by its file name
A linked image read from a version 7 `.ai` file can keep its path in
the classic Mac OS form, with colons between folders
(`Macintosh HD:Images:photo.tif`). The link's name was the whole path,
so the Links panel showed it as one long name, and Relink to Folder,
the search of the document's folder and Find Linked Files looked for a
file with that whole string as its name.

A path with a colon and no `/` or `\` is now read as a classic Mac OS
path. Its name is the part after the last colon, and `links.info` gives
the rest as `location`. Relink to Folder, the document-folder search and
`links.findFiles` look for that name, and Find Linked Files compares the
path's folders with the folders of the files it finds. The link keeps
the path as stored. Paths with a `/` or `\` keep those as separators,
so a file name may still hold a colon (`/Users/a/x:y.png`).

Docs: docs/mcp.md (Links), docs/file-format-parity.md (version 7
linked images).
2026-11-05 21:46:43 +07:00
Hamza 728352269d Color Effects: Apply Fill to Stroke and Apply Stroke to Fill become add-on commands
As asked in review: the reference app has no such commands, so they ship
in the Color Effects add-on. paint.fillToStroke / paint.strokeToFill are
now addon.color.fillToStroke / addon.color.strokeToFill in
cmd/addons/color.rs, listed in Object > Plug-ins > Color Effects instead
of the Color panel menu, with catalog rows in all 26 catalogs.

Two fixes from CodeRabbit's review:
- A graph's series marks and labels give the graph the copied paint in
  the same undo step (capture_series_paints / capture_label_styles, as
  paint.setFill does), so drawing the graph again keeps it. Targets go
  through graph::paint_targets, so a series group stands for its marks.
- A copy that would leave the effective paint as it is skips the object,
  so None copied onto a missing fill or stroke adds no item and records
  no undo step.
2026-11-05 21:46:43 +07:00
Hamza 0db0c7ddae Paint: Apply Fill to Stroke and Apply Stroke to Fill (#5530)
paint.fillToStroke and paint.strokeToFill copy each target's own top fill onto its top stroke, or the other way, so a mixed selection keeps each object's colour. They aim and undo like Swap Fill and Stroke: groups and compound paths by their members, each text run with its own paint, and only the characters the Type tool has selected. A stroke given paint at width 0 gets 1 pt, skipNone leaves objects whose source paint is None alone, and the defaults for new art change the same way. Both are in the Color panel menu after Invert and Complement.
2026-11-05 21:46:43 +07:00
bflatastic b700369227 Path menu: the path check stops at the first path it finds 2026-11-05 21:34:32 +07:00
NetterSilverandClaude Haiku 5.5 0001a1c702 Disable Object > Path items when no path is selected
Fixes #5796

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-05 21:34:32 +07:00
dotCooCoo 99169d5404 Reject malformed Batch Trace Folder options 2026-11-05 20:18:52 +07:00
FractalEncrypt 884a330fae Keep Group Selection drags on the selected outlined component
Squashed from #3272 onto main.
2026-11-05 20:00:12 +07:00
el-j 02a8928f8e M2.1: copy and cut direct-selected segments and anchors as independent paths (#2122)
Squashed from #3903 onto main.
2026-11-05 19:40:58 +07:00
el-j 08ff029ac2 fix(pathops): bound offset path complexity and handle arrangement failure safely (#4145)
Squashed from #4345 onto main.
2026-11-05 19:40:58 +07:00
KnottyDyes c9588457b9 Export: raster output defaults to the document resolution 2026-11-05 19:02:23 +07:00
dotCooCoo fdde506ec7 Refresh Find Font warnings after document changes
Squashed from #5773 onto main.
2026-11-05 18:23:06 +07:00
dotCooCoo 653e6ff7fb .ai save: the editing copy keeps images and linked files
The editing copy of a PDF-compatible .ai wrote every image as its outline
filled with its average color. Embedded images are now written with their
pixels, and linked images as placed files with a preview:

- Embedded images are rasters in the form of the version 7 specification
  (section 8, https://13thmonkey.org/documentation/fonts/AI7FileFormat.pdf):
  %AI5_BeginRaster, the color space, the image matrix and the XI operands
  of current files, then the samples in binary in a %%BeginData section.
  Gray, RGB and CMYK images keep their samples (CMYK images their ink
  amounts), and see-through images their alpha channel after the color
  samples. The matrix is written to ten decimals.
- Linked images are placed files (section 16): the matrix, the box of the
  file's pixels and its path, %%IncludeFile, the folder relative to the
  document's (when the relative path ends in the path's file name), and a
  preview of at most 256 pixels a side.
- Images that can't be decoded or have more than 33,554,432 pixels (the
  most the reader reads) are written as their outlines filled mid gray,
  images of 16 bits a channel (CMYK TIFFs included) at 8 bits, and linked
  images in opacity masks and pattern tiles as embedded images, each with
  a warning.

Each of these is written in the form VectorCraft's .ai reader reads, and
the tests read the written data back through that reader.

The reader now gives an image its name and opacity mask when the
operators that end its raster (XH, Xr and the N after %AI5_EndRaster) come
before its dictionary, reads an empty relative folder as the document's
own folder, and looks for the %%EndData that ends an image's samples
after the alpha channel its XI operands give it, preferring one whose next
line is XH, so samples that hold the marker's bytes are read whole.

Tests: the round trip of every kind of image and its state, a second write
of what is read back giving the same bytes, the raster and placed-file
forms, previews of large linked images, and the engine's editing copy with
every save option; a fuzz case for damaged images and placed files.

Docs: docs/file-format-parity.md.
2026-11-05 17:38:55 +07:00
dotCooCoo 6dd86b337a .ai/EPS import: type that names no style takes the normal styles
Type in the text document of a .ai or EPS file's editing data that names
no character or paragraph style, a story without style runs included, is
set in [Normal Character Style] and [Normal Paragraph Style]. The reader
took what such type leaves out from the text document's base attributes
instead, or built-in defaults for a story without paragraph runs, and it
did not read paragraph styles.

A Large Canvas file (1:10) holds the normal styles' lengths at the art's
scale (1.2 for 12 pt) and the base attributes' at the page's (12). The
reader scaled the base attributes' 12 by 10, so the type came in at
120 pt. In an EPS the page comparison then rejected the layers, and the
file opened as its printed page without its linked images.

In any file whose normal styles differ from the base attributes, such
type now takes what the normal styles set, such as font, size, colors,
stroke, alignment, indents, space before and after, and hyphenation.
2026-11-05 16:37:13 +07:00
dotCooCoo 1f68248bc5 .ai save: the editing copy keeps gradients and patterns
The editing copy for other apps now writes linear and radial gradients and
grid patterns as themselves instead of as average colors and cut tiles.

- Gradients the art uses are defined in the setup (`n Bn`, then
  `%AI5_BeginGradient` … `Bd`, the stops as `Bs` with their opacity and
  midpoints, `BD`), and gradient swatches nothing uses in a non-printing
  block. Stops keep gray, CMYK, RGB and spot colors at a tint. A
  gradient that isn't a swatch gets a name that no swatch or pattern of
  the document has.
- Each fill or stroke with a gradient is an instance around its painting
  operator (`Bb`, `Bh`, `Bg`, `Xm`, `Bm`, `Bc`, `BB`), on a compound
  path's last subpath and on clipping paths too. `Bg` places the gradient
  relative to the path: a linear one by its angle and its start and length
  as fractions of the path's extent along it, a radial one by the matrix
  that takes the unit circle onto its extent ellipse, its center as
  fractions of the path's bounds in that circle's space and its radius as
  a multiple of the one the center's distances to the right side and to
  the bottom give. In a pattern's tile the placement is mirrored top to
  bottom.
- Patterns whose tiles make a grid and hold their art are defined with
  `%AI3_BeginPattern` … `E`, the tile's box first, and fills and strokes
  paint with `p` and `P`; gradient and pattern swatches are in the palette.
- Freeform gradients, gradients along or across a stroke and gradients
  without stops, with more than 256 stops or without extent are written
  as their average color, and other patterns as their tiles cut to the
  shape, each with a warning. Gradients that dither or mix perceptually
  are written as classic ones, stops linked to global process colors as
  their colors, and pattern swatches without the placement that moves,
  turns or scales their pattern, with warnings.
- Reading: an unpainted box that a pattern's definition marks as its
  tile's box (`AIPattern_Editor_Backing_Tile_Rect`) is no longer read as
  art, and a linear gradient whose stops all lie at one place keeps each
  stop on its side.

The definitions, instances and patterns follow sections 3.4, 3.5 and 14
of the version 7 specification
(http://mercator.elte.hu/~saman/hu/okt/AI7FileFormat.pdf). The stop
opacity, `Bg`'s placement and the marked tile box follow the newer form
that current .ai files carry, which that specification predates.

Each of these is written in the form VectorCraft's .ai reader reads, and
the tests read the written data back through that reader.

Docs: docs/file-format-parity.md.
2026-11-05 15:38:38 +07:00
dotCooCoo bf7ca194bb Type: Convert to Text leaves a paragraph that starts in a locked frame of the selected story
While Select All holds a threaded story, a paragraph whose text starts in one of the
story's locked or hidden frames is no longer converted, and the empty parts of a converted
paragraph in such a frame are no longer restyled. Before, a locked frame whose first
paragraph took in the previous frame's empty last part was converted, and so was a
paragraph that ran on from a locked first frame into an editable one.
2026-11-05 14:34:27 +07:00
dotCooCoo 2c1f3d7605 Type: text cleanup and Convert to Text act on every frame of a selected story
After Select All in a frame of threaded text, Remove Line Breaks and
Remove Paragraph Breaks changed only the edited frame, and Convert to
Text over MCP converted only the selected frame. Both now act on the
text of every frame of the story as one undo step.

- addon.cleanup.removeBreaks reads the frames of the story as one text,
  so a break at the end of a frame before a word in the next one becomes
  a space. The same applies when every frame of a story is selected as
  objects.
- text.convertListToText without ids, id or a range converts every
  paragraph of the story. Locked and hidden frames of the selected story
  are not converted, even when ids names them. When the call converts
  the whole story, the story stays selected; before, the call reset the
  Type tool's selection to the edited frame.
- A selection inside one frame, and unthreaded type, behave as before.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-05 14:34:27 +07:00
dotCooCoo 96ca33b0ef Tests: the Devanagari fallback-glyph test passes when the fallback face substitutes the vowel sign
`the_fallback_glyph_of_a_consonant_after_its_vowel_sign_is_reported` expected
the fallback face's cmap glyph for the vowel sign I. On the Ubuntu runner the
fallback face is Noto Sans Devanagari, whose shaping draws the sign with
another glyph (545 instead of 32), so the test failed on `main`. It now checks
that two glyphs are drawn in Ka's cluster, the first is not Ka's and the
second is, and keeps the `text.glyphAlternates` checks.

Fixes #5750
2026-11-05 14:26:32 +07:00
dotCooCoo 19d9843971 Shape Builder: a merge or erase takes the stretch of every coincident line
Where two open paths lie along the same stretch, the planar map gave
that stretch to one of them only, so a merge or an erase across it left
the other path in place there. Every other open path along an edge now
has its own piece in `lines_under`, under a closed path's outline or
along a line in front. `lines`, `edges` and Live Paint's edges stay one
per stretch, and an Alt-click there still takes the piece in front.
2026-11-05 14:12:18 +07:00
ruchirguitarandClaude Opus 5.5 96505d3a77 Fix #5526: document the functions the link-status selection touches
Doc comments for the Select add-on commands, the Select by Link Status
dialog body, the Links panel menu and the test helpers (review: docstring
coverage).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 14:12:11 +07:00
ruchirguitarandClaude Opus 5.5 7dc66d660a Fix #5526: select images by link status
Selection Tools add-on: addon.select.byLinkStatus selects the image
objects and placed documents whose link is linked, embedded, missing or
modified (one status or several), as links.list reports it. Optional ids
limit the search, add adds to the selection, and zoom runs the existing
Zoom to Selection in the desktop app. Objects that are hidden, locked, on
a template layer or outside the isolated group are left out and returned
with the reason. Only the selection changes.

Select Linked / Embedded / Missing / Modified are in Object > Plug-ins >
Selection Tools and the Links panel menu. Each is off when no image has
that status, and Shift adds to the selection. Select by Link Status...
lists the images with name, status and format, with a name search, a
status filter, checkboxes with All / None and Zoom to Selection. The
status bar says what was selected and how many were left out, with
plural rows in every catalog.

Tests: engine (statuses, ids, add, zoom, skip reasons, bad params),
command sweep, and UI (message, list filtering, menu items, Links panel
menu, headless dialog frame). Docs: mcp, target-app-parity, ui-parity,
roadmap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 14:12:10 +07:00
NetterSilverandClaude Opus 5.5 568bb9315d Line a moved selection's edges up with ruler guides
Fixes #5746

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 13:45:49 +07:00
KindmarkandClaude Sonnet 5.5 db1ef1bfed Contour: make it a built-in add-on and translate its labels
Review of #5694 asked for two changes.

Add-on, not a core tool, as Enclosing Lasso is:
- The command is addon.contour.set, in an add-on module of its own
  (crates/engine/src/cmd/addons/contour.rs) with its tests beside it.
- The tool is listed under Object > Plug-ins > Contour and under its own
  "Contour" heading in All Tools. It has no Basic or Advanced toolbar
  slot and no default shortcut. The Contour bar is unchanged.
- The add-on drawer test lists Contour with the other add-on tools.
- Docs (mcp.md, the parity documents, ROADMAP) say add-on and use the
  new command name; mcp.md gains a Contour add-on section.

Translations: rows for "Contour", "Contour Tool", "Sharp", "Bake" and
"Turn the Contour into plain paths" in all 26 catalogs ("Round" and
"Square" already had them). Drafted from each catalog's own vocabulary
(for Bake, the verb it uses for Expand Appearance; a word other than the
catalog's Stroke or Path word for the tool's name where they collide);
they are not native-speaker reviewed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-05 12:57:51 +07:00
KindmarkandClaude Sonnet 5.5 8ce22e71eb Contour: keep a Contour's corners when dragged again; ignore a no-distance drag
Two fixes from review of #5694, each with a test that fails without it:

- Dragging a selected Contour sent the tool's own corner options, so a
  Round or Square Contour came back Sharp and lost its miter limit, and
  the Contour bar (which reads the effect) disagreed with the shape. The
  press now reads the Contour's own corners and miter limit and every
  preview of that drag carries them; a new Contour still takes the tool's
  options.
- A drag that never moved the distance (along the edge, or rounded to
  nothing by Shift) previewed offset 0 and committed an unchanged copy
  and an undo step. Nothing is previewed until the distance leaves where
  it started.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-05 12:57:51 +07:00
KindmarkandClaude Sonnet 5.5 8584bf1ab6 Contour: live offset tool with a floating bar and its own icon
Add a Contour tool (Modify group). Dragging away from a selected path or
shape's edge makes a copy of it that carries a live Offset Path effect,
grown by the drag; dragging toward the inside shrinks it. The result is
one undo step and stays editable until baked with Expand Appearance. A
second drag on a selected Contour changes its distance instead of
nesting another effect.

- object.contour: the command behind it (offset, sharp/round/square
  corners, miter limit), usable over MCP and the control channel too.
- Contour tool: live preview, Shift rounds to whole points, Escape
  cancels, a dashed guide with a white halo shows the outline the shape
  had, and a pill shows the distance.
- Contour bar: a floating bar above the selection with the offset box,
  Sharp / Round / Square and Bake (Expand Appearance).
- Toolbar slot under Modify (Basic and Advanced) and dc-contour.svg, an
  original icon with its ASSETS.md row.
- Tests for the command, the tool's pointer gestures and the bar; the
  border-with-a-gap recipe (two Contours, bake, Minus Front) is covered
  end to end.
- Docs: beyond-Illustrator row, revision histories and the ROADMAP log.

Beyond Illustrator: a VectorCraft design built on Offset Path. Scores and
estimates unchanged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-05 12:57:50 +07:00
dotCooCoo 30a2d85658 Global Edit: the enabled check decides without normalizing every anchor
The Control bar asks whether Select > Start Global Edit can run every
frame it shows a one-object selection. For a path, compound path or
symbol instance that check built the object's form: a copy of every
anchor and handle, normalized into a unit box. On a 200,000-anchor path
it took about 2.2 to 3.0 ms a frame.

The check now walks the object the same way and measures only the box
of those points, then applies the same size test, so it gives the same
answer for every object without allocating. Starting Global Edit still
builds the forms it compares.
2026-11-05 12:36:41 +07:00
jo-quast bddb834231 Part of #394: each run hyphenates in its own language; Default Language sets new type's
Squashed from #2818 onto main.
2026-11-05 12:17:33 +07:00
ruchirguitarandClaude Opus 5.5 e0645341a4 Document tabs: drag a tab along the strip to reorder the open documents (#5663)
A document tab dragged sideways along the tab strip moves its document to the
place an insertion line marks; the current document stays current. Dragged
above or below the strip, the tab still tears off into a floating window. The
views Window > New Window opened move with their document, and each document
keeps its own zoom, centre and artboard.

The move is the engine command `document.move {from?, to}`, so the control
channel, MCP and recordings reach it, and a replay moves the document before
the steps recorded after it. `sync_views` keeps the views with their documents
by uid when the documents change order.

Behaviour: https://helpx.adobe.com/illustrator/using/customizing-workspace.html

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 12:02:46 +07:00
NetterSilverandClaude Opus 5.5 1db874610f Keep Pencil and Paintbrush Fidelity in screen pixels at any zoom
Fixes #5729

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 11:52:34 +07:00
ruchirguitarandClaude Opus 5.5 528faa8e0a Fix #5532: Release Type on a Path splits type on a path into point type and its path
A Type Tools add-on command (Object › Plug-ins › Type Tools › Release Type on a
Path…, `addon.type.releasePath`): each selected type on a path becomes point
type with the same runs, character and paragraph attributes, on one straight
line whose baseline starts where its first character sat, and the plain path
it was set on, with its exact shape and transform, in its layer and stacking
place, with no fill or stroke. `mode` keeps both, the path only or the text
only; `keepOriginal` leaves the type on a path and adds the released objects
above it. Other objects are left alone, nothing to release makes no undo step,
the run is one undo step and the released objects are selected. The command
dialog previews it as Type on a Path Options does (#5360): Cancel leaves no
history, OK is one step. Tests, command_sweep cases, catalog rows in all 26
languages, docs/mcp.md and the parity docs (beyond Illustrator: scores
unchanged).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 11:17:09 +07:00