Commit Graph
1424 Commits
Author SHA1 Message Date
dotCooCoo 4c5c54ccbc Fix #3799: Alt held at the press draws a straight Pencil line at any angle
With Alt key toggles to Smooth Tool off, holding Alt when a Pencil drag
starts now draws one straight segment from the press point to the
pointer, at the angle the pointer takes, as Shift does at 45° steps.
Pressed on an end of a selected open path, the line continues the path
from that end. Both ends snap to Smart Guides as a stroke's ends do, and
the line stays open when Alt is still held at the release. Shift and Alt
together keep the 45° steps.

Before, a drag started and released with Alt held drew a closed freehand
path. Alt pressed after the drag has started still closes the path at
the release, and with Alt key toggles to Smooth Tool on, Alt still switches
to the Smooth tool. Before a Pencil press, Alt no longer shows the closing
cursor.

Docs: docs/target-app-parity.md, docs/ui-parity.md.
2026-10-24 17:29:32 +07:00
Taha-Mahmoodi 23c0e8c501 Fix #3964: Create Outlines stacks each run's ruby right after that run's glyphs, as the canvas paints it 2026-10-24 17:29:32 +07:00
Taha-Mahmoodi cab62cbb18 Fix #3964: Create Outlines, EPS, EMF/WMF and legacy .ai keep the ruby where the canvas draws it 2026-10-24 17:29:32 +07:00
bflatastic 7f8bc837bd Save options test: take the file name after either path separator (Windows) 2026-10-24 17:29:32 +07:00
dotCooCoo 11c61c97b1 Save: a remembered artboard pick follows the artboards it named
A save without options reuses the options the document was last saved
with in that format. Their artboard, artboards and range name artboards
by number, so once artboards were deleted or moved, the save wrote
other artboards or was refused: with three artboards, a PDF saved with
range "2" wrote the third artboard after the first was deleted, and one
saved with range "1, 3" was refused after the third was deleted. The
same held for SVG saves, a legacy .ai, and .ai and native files saved
with separateArtboards. file.formatOptions and SVG Options showed the
same numbers.

The document now keeps the ids of the artboards it had when it was
saved, and the remembered pick follows them: an artboard deleted since
is left out, one that moved is named by its new number, and the rest of
the pick is kept. A range open at its end ("2-") is written out as the
artboards it named once artboards are added. When none of the artboards
the save used is left, the pick is left out, and the save writes the
artboards it writes when none is named. A range of "all" stays as it
is. An artboard given to the save is still refused when the document
does not have it.

A new artboard no longer takes the id of an artboard deleted earlier in
the same document (Document::retire_artboard_id), or of one an undo took
away: the highest id given out is shared with the undo history, so a
new artboard is not taken for an earlier one.

file.revert keeps the pick only when the file read back has the
artboards the document had at the save, with the same ids in the same
order. A PDF saved with a range holds only those pages, and one saved
without preserveEditing reads back with new ids in page order, so their
picks are left out.
2026-10-24 17:20:48 +07:00
dotCooCoo 3e0f9795c2 Threaded text: Create Outlines and Expand on a frame no longer duplicate its text
Create Outlines on a frame of threaded text removed the frame, and the
thread's re-flow then added the frame's text to the story, as it does
for a frame that was deleted. The other frames held that text a second
time while the outlines drew it. Object › Expand, and Expand Appearance
where it outlines type or groups it with a shadow, outer glow or Crop
Marks, did the same.

An outlined frame now leaves its thread with the text it shows, and the
other frames keep the text they hold. When the thread's last frame is
outlined, the text it has no room for goes after the text of the last
frame that stays. When Expand Appearance keeps a frame as type in a
group, the type takes the frame's place in the thread. A thread left
with one frame is no longer a thread, and undo restores the thread.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-24 17:20:47 +07:00
Dylan M. TaylorandClaude Opus 5.5 20bba9ebae Security: linear work for shortcut review, gradients, recovery names, include cycles, batch references, DOCX style ids, CAD layouts and long strokes
CodeRabbit findings #2, #16, #31, #103, #114, #124, #162, #179, #182, #183, #185:

- Shortcut import review: example names for each code in one pass over the rows.
- Gradients: a midpoint stop is mixed from its two stops; freeform recolor samples its
  increasing positions with one advancing search (`Gradient::sample_increasing_with`).
- Recovery: image entry names are looked up by address, and dead ones swept when the map
  doubles, not on every image.
- Script checker: include cycles from strongly connected components (iterative Tarjan), not
  a reachability row per file.
- Batch step references copy at most 256 MB of values for one step.
- DOCX: style ids over 256 bytes are ignored where defined and where used.
- DXF: layouts keep at most 4 MB of names; a hatch's loops count against the node limit.
- Freehand and Liquify: past 1000 samples a drag previews every n/1000 samples, strokes keep
  at most 100,000 samples, and the stroke kept is previewed in full before it is committed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 17:19:59 +07:00
Dylan M. TaylorandClaude Opus 5.5 03d2f0e83c Security: file authority for stored paths, linked files, placed documents, font folders, recovery areas and atomic saves
CodeRabbit findings #7, #72, #92, #94, #95, #99, #100, #140, #158, #174:

- Link search hashes at most the size it looked at (a growing file no longer matches).
- Resolving links reads, decodes and previews each linked file once, shared by every key.
- Placed documents read inside one another resolve links at most 8 deep, never one already
  being read.
- A data set's image path and the placed-document rereader follow stored paths through
  `document_path` (no other computer's share).
- The Links panel looks at a linked file within the roots of the automation caller that
  opened the document.
- A fonts folder set by a confined caller is scanned without following links out of it.
- Recovery refuses an area folder that is a link or another account's.
- Atomic saves keep the replaced file's group and Linux access ACL, or make the replacement
  owner-only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 17:19:59 +07:00
Dylan M. TaylorandClaude Opus 5.5 b12ee928f3 Security: document model generation budgets for live art, clipping runs, placed documents, graph masks, path reading and native entries
CodeRabbit findings #58, #75, #82, #113, #159, #175, #187:

- Live evaluation (expansion, envelope mapping and everything inside) makes at most 4M
  objects (`MAX_GENERATED`); deep expansion counts what each live object makes, and envelope
  image pieces count before they are cut.
- Clipping runs copy at most 8M clip path elements together; past it runs are plain groups.
- Exports read at most 256 placed documents; the rest show their previews.
- Graph design and marker budgets count opacity-mask art (`Node::count_with_masks`).
- Native files read at most 32M anchors (4M on wasm) of paths; the web build allows 1 GiB of
  entries after the JSON.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 17:19:16 +07:00
aiongg 8cc69ed45c CI: one test binary per crate, nextest, line tables only (#3855)
* CI: line tables only for workspace crates, no debug info for dependencies

* CI: one integration-test binary per crate

Each crate's tests/*.rs files become modules of tests/it/main.rs. Files that change
process-wide state (Color Settings, the font database, installed plug-ins, the working
directory), the fuzz sweeps and the test targets the Affinity corpus workflow names stay
their own binaries.

* Docs: name the integration tests' new paths

* CI: xtask test with nextest and doctests, one wasm check, clippy --keep-going

cargo xtask ci runs the tests with cargo nextest (cargo test when it is not installed),
builds them with --lib --bins --tests, runs the doctests as their own step, and checks
the wasm crates in one cargo check --keep-going call.
2026-10-23 21:36:10 -04:00
Taha-Mahmoodi 767f06b20e Fix #3828: New Document › Branding offers Business Card 91 × 55 mm 2026-10-24 07:12:16 +07:00
el-j 71a669635c M2.1: prevent click-through on open path fills and support segment toggle (#3405) 2026-10-24 06:00:23 +07:00
Jürg Lehni caaccaf5be Type: images in SVG glyph documents draw with the glyph
They were left out because glyph art had no document to keep them in; since #3879 they hold their own pixels until a document takes them in.
2026-10-24 06:00:22 +07:00
bflatastic a564fe5d8e PDF export: pattern fills are written as tiling patterns (#3849) 2026-10-24 05:59:04 +07:00
bflatastic b2835c4f2b Tests: engine tests that add fonts to the shared font database take one lock 2026-10-24 05:52:15 +07:00
bflatastic 4eec70e5cd Automation roots: rustfmt and clippy (redundant closure) 2026-10-24 05:16:21 +07:00
Dylan M. Taylor e95e8418ed Audit: automation roots follow file.showPackage, the Place queue, headless file methods, clipboard files, placed-document workers and caches, folder searches and the recovery folder 2026-10-24 05:16:20 +07:00
Angelo BernardiniandClaude Opus 5.5 52a43eefdb G12: ruler guides nudged with art keep to the page's axes at a turned Constrain Angle
With objects and ruler guides selected together, object.nudge moved the
guides by the art's delta turned through General > Constrain Angle, so at
90 degrees a Right nudge moved a horizontal guide vertically. The guides
in that edit now move by the page-axis delta, as guides selected alone
already did (CodeRabbit finding on #3745).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014gCpjL3yUhaH3jRp7ksufh
2026-10-24 04:59:57 +07:00
BFlat e0c1548049 Merge pull request #3896 from storytold/fix/3869-svg-type-features
SVG export: type with small capitals, superscript, subscript or tab leaders is written as outlines (#3869)
2026-10-24 04:51:54 +07:00
aiongg 6877d6535f Links: resolve stored paths with craft-docpath's resolve_absolute (#3267)
* Links: use resolve_absolute for stored paths

* CI: release only with git dependencies from storytold

* Release: check git sources from the parsed Cargo.lock and cargo config

The grep let any character stand for the dot in github.com, passed a missing or stale
Cargo.lock, and missed source replacement in .cargo/config.
2026-10-23 17:51:28 -04:00
bflatastic 166afce360 SVG export: type with small capitals, superscript, subscript or tab leaders is written as outlines (#3869) 2026-10-24 04:49:08 +07:00
Dylan M. Taylor 9843d5f1ab Audit: export names, linked-file ids and MCP prompt arguments in one pass 2026-10-24 04:49:07 +07:00
bflatastic c2ad9f8bbb Type: emoji go with type that effects reshape and Expand Appearance
Squashed from #3879 onto main.
2026-10-24 04:49:06 +07:00
bflatastic 8e8aaa8683 SVG: a Preserve Editing SVG reopened from disk saves as the full document again (#3867) 2026-10-24 03:52:24 +07:00
Jürg Lehni e372d00cb7 Type: tests pin colour glyphs in variable fonts, on paths and on the canvas
A variable font's COLR layers follow its instance, a colour glyph turns with type on a path, and the canvas draws an SVG glyph's art in its own colours and the type's fill.
2026-10-24 03:52:23 +07:00
bflatastic 9f1a001a2b Export for Screens: a per-artboard EPS takes the artboard as its page, so an empty artboard still writes 2026-10-24 03:52:22 +07:00
bflatastic d81145aee3 Artboard documents keep objects without measurable bounds (type in a missing font) 2026-10-24 03:52:22 +07:00
bflatastic 60107cd33a Export for Screens: a document row for an artboard keeps only that artboard's art (#3868) 2026-10-24 03:52:22 +07:00
bflatastic 0066447eac Global Edit: cache the highlight outlines per document revision 2026-10-24 03:09:12 +07:00
bflatastic 6e3ecc3adf Select: Start Global Edit edits the objects of the same shape together, each in proportion
Squashed from #3781 onto main.
2026-10-24 03:09:12 +07:00
dotCooCoo 2a2e63856c Type: the Paragraph panel's Bullets button turns paragraphs into a bulleted list
VectorCraft had no lists. A bullet could only be typed as a character,
and the tab after it did not stop at the left indent. The reference app
turns paragraphs into a bulleted list from the Paragraph panel, the
context menu and Type › Bullets and Numbering › Apply Bullets.

text.setFormat takes list ("none" or "bullet") and bullet ("none",
"dot", "dash", "circle" or "square"). The layout draws the bullet before
the first line of each list paragraph that has text, in the font, size
and color of its first character, and starts the text at the next tab
stop, with the left indent counted as a stop. Wrapped lines start at
the left indent, and type on a path draws the bullet too. In a
horizontal right-to-left list paragraph the indents are mirrored: the
bullet hangs at the right, and the wrapped lines start at the right
where the first line's text starts after the bullet. The bullet is not
a character of the text. A paragraph whose left and first-line indents
are both 0 gets 18 pt and -18 pt when it joins a list. Return continues
the list, paragraph styles carry it, Reset Panel turns it off, and the
native file saves it only when it is set.

The Paragraph panel has a Bullets button with a list of the five
presets, and Type › Bullets and Numbering › Apply Bullets and the
context menu run type.applyBullets. Live SVG text writes the bullet's
character, and SVG writes type on a path with bullets as outlines. DXF
writes the bullet as a TEXT entity of its own, and legacy .ai export
warns that bulleted lists are left out. The caret, selections, Touch
Type and Show Hidden Characters skip the bullet.

Live SVG text of horizontally scaled type now writes each tab in a
tspan of its own. Before, the characters before a tab shared its tspan,
and its textLength made a viewer stretch them across the tab's gap.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-24 03:09:11 +07:00
Taha-Mahmoodi 7da5e3062d Symbols: Window › Symbol Libraries opens symbol libraries whose symbols click into the document's Symbols
Window › Symbol Libraries and the Symbols panel's Symbol Libraries Menu open each symbol library
in a library panel of its own, on the shared library panel code the swatch and graphic style
libraries use (https://helpx.adobe.com/illustrator/desktop/manage-objects/traces-mockups-symbols/create-or-import-symbol-libraries.html,
.../symbols-panel-options.html, .../create-and-place-symbols.html).

- Basic Shapes: one original library generated in code (circle, squares, triangle, diamond,
  hexagon, star, burst, arrow); no other app's libraries.
- A click adds a library symbol to the document's Symbols as one undo step, with its Symbol
  Options and the resources it uses (nested symbols, patterns, swatches, brushes, graphic styles,
  images), and makes it the current symbol; one already there isn't added again, a clash of
  names numbers the library's. Shift/Cmd-clicks select for Add to Symbols. Dragging a library
  symbol onto the canvas adds it and places an instance there, in the same step.
- Save Symbols… (library menu, Window menu) and Save Symbol Library… (Symbols panel menu) write
  the document's symbols as a .vectorcraft document holding only them, into the user library
  folder (User Defined, window.userSymbolLibrary1-10) or a file; Other Library… reads the symbols
  of any document VectorCraft opens, and a file it can't read is an error.

Commands: symbol.libraries, symbol.library, symbol.addFromLibrary (place, x, y),
symbol.saveLibrary, symbol.loadLibrary; UI: window.symbolLibrary (.other), ui.saveSymbolLibrary
(dialog saveSymbolLibrary). i18n rows in every complete catalog; docs updated.
2026-10-24 03:09:10 +07:00
bflatastic f247772042 Type: selected type shows its in and out ports, and the in port threads backwards
Squashed from #3817 onto main.
2026-10-24 03:09:10 +07:00
Taha-Mahmoodi 7693aeb508 Smart Guides: Distance Guides follow what lies under a still pointer
One rule for the hover's context (PR review follow-ups): the target is
recomputed where the pointer is, or cleared, whenever what lies under it
can change while Alt is held.

- The tool hovers only where the pointer is on the canvas itself
  (`on_canvas`): under a floating panel, a menu, a popup or a dialog
  its hover ends (Tool::hover_ended), as when the pointer leaves the
  canvas or a pan, zoom or view-rotation press starts.
- The canvas keeps the hover's context: its rect, the view's centre,
  zoom and rotation, and the active document's id and revision (which
  moves with every edit, undo and selection change). When it changes
  under a still pointer, a tool that asks (Tool::wants_rehover; the
  Selection tool after an Alt hover) is hovered again at the pointer,
  so wheel, gesture, key or command scrolling and zooming, tab
  switches, edits and undos re-measure.
- Coming back onto the canvas re-hovers the tool.

canvas::tests::distance_guides_follow_what_lies_under_a_still_pointer:
a floating window over the pointer (fails without the on_canvas filter),
a 150 pt scroll that leaves empty artboard under it (fails without the
re-hover), a square made under it. select::tests::distance_guides_need_
alt_a_selection_and_smart_guides checks wants_rehover.
2026-10-24 03:09:09 +07:00
Taha-Mahmoodi 26bf324c81 Smart Guides: a pan, zoom or view-rotation press ends the Distance Guides hover
An Alt+Space pan press went to Drag::Pan and never reached the tool, so the Distance Guides stayed through the pan until the pointer left the canvas (PR review follow-up). One rule now covers all three cases: the tool's hover ends (Tool::hover_ended, renamed from pointer_left; Session::tool_hover_ended) when the pointer leaves the canvas with no press the tool holds, and when a press starts any drag that doesn't reach the tool (pan, middle-button pan, zoom box or scrub, view rotation, touch gesture). canvas::tests::distance_guides_go_when_the_hover_ends asserts they go at an Alt+Space press and stay gone panning out over a panel.
2026-10-24 03:09:09 +07:00
Taha-Mahmoodi 16b66e5f4b Smart Guides: Distance Guides also go when a pan, zoom or view-rotation drag leaves the canvas
The pointer-left check skipped every drag, so Alt+Space panning out over a panel kept the measurements (PR review follow-up). Only a press the tool holds (Drag::Tool, Drag::Art) keeps its state now; pan, zoom box, zoom scrub, view rotation, gesture and presentation drags never reach the tool. canvas::tests::distance_guides_go_when_the_pointer_leaves_the_canvas pans out with Alt+Space; it fails with the old drag.is_none() check.
2026-10-24 03:09:09 +07:00
Taha-Mahmoodi 822effa384 Smart Guides: Distance Guides go when the pointer leaves the canvas with Alt held
Leaving the canvas (for a panel, or out of the window) sent the tool no
hover event, so the Selection tool kept its Alt-hover target and went
on drawing the measurements (PR review finding).

- Tool::pointer_left: the pointer left the canvas with no button held;
  the Selection tool drops its Distance Guides target and its Smart
  Guides hover label. Session::tool_pointer_left reaches it.
- The canvas remembers whether the pointer was over it last frame: on
  leaving with no drag it calls tool_pointer_left; on coming back it
  re-hovers the tool even after a single jump egui doesn't count as
  moving, so the guides show again.

Tests: canvas::tests::distance_guides_go_when_the_pointer_leaves_the_
canvas (fails before: the label stayed over a panel with Alt held),
select::tests::distance_guides_need_alt_a_selection_and_smart_guides
(pointer_left clears them).
2026-10-24 03:09:09 +07:00
Taha-Mahmoodi a301760aa6 Smart Guides: Alt over another object or the artboard shows the selection's distances to it
Distance Guides, from the public "Use Distance Guides for accurate
placement" and "Smart Guides options" (Invoke Distance Guides) pages:
with Smart Guides on, something selected and the Selection tool,
holding Alt/Option over another object shows the horizontal and
vertical distances between the selection and it, and over an empty
part of an artboard the selection's distances from the artboard's left,
right, top and bottom edges.

- guides::distance_guides measures the selection's bounds to a box: on
  an axis on which they lie apart, the gap between their facing edges;
  otherwise the offsets of both pairs of matching edges. Each line runs
  across the middle of the overlap on the other axis (else the
  selection's middle), with a dashed line out to the target's edge when
  it passes beside it. An artboard is always measured edge to edge.
  Labels are in the General unit, in the smart guide colour.
- The Selection tool keeps what its Alt hover points at and draws the
  guides while idle; letting Alt go (the canvas re-hovers on a modifier
  change), a press or moving off clears them.
- Overlay::Distance: the line with end ticks and its length in a pill;
  the canvas draws it.
- Preferences › Smart Guides › Invoke Distance Guides (`distanceGuides`,
  on by default), with i18n rows; View › Smart Guides gates it too.
- Hover only, as the pages describe: nothing while moving or nudging.

Tests: select::tests::alt_over_* (gap and edges beside and below,
artboard edges in pt and mm), distance_guides_need_alt_a_selection_and_
smart_guides, tests_prefs::invoke_distance_guides_measures_the_selection_
to_the_object_under_alt, canvas::tests::alt_over_another_object_draws_
the_distance_guide_label (frame test of the drawn label and line).
2026-10-24 03:09:09 +07:00
Taha-Mahmoodi bfc2d6e439 Engine: a command that selects its ids first puts the selection back when it fails
Review follow-up (#3785, CodeRabbit): commands in SELECTS_GIVEN_IDS run select.set with the given ids before their body; when the body then returned an ordinary error, the ids stayed selected (and their layer current), while a panic restored the selection and refused ids never changed it. The dispatcher now keeps the active document's selection and current layer from before select.set and restores them when the body errors. This affects every command in SELECTS_GIVEN_IDS (Duplicate, Arrange, Clipping Mask, Compound Path, Group/Ungroup, Hide, Lock, Move, the Pathfinder panel commands including Trap, and the transforms). Tests: Trap with ids whose edges don't meet, and Intersect with ids of shapes that don't overlap, leave the selection as it was.
2026-10-24 03:09:08 +07:00
Taha-Mahmoodi fd345e0c56 Pathfinder: Trap spreads the lighter colour into the darker as an overprinting strip where solid colours meet
The Pathfinder panel menu's Trap… (object.pathfinder.trap) and Effect › Pathfinder › Trap… (pathfinder.trap, live on groups) share one geometry (vectorcraft_pathops::trap_band, vectorcraft_effects::trap): Thickness, Height/Width, Tint Reduction, Traps with Process Color and Reverse Traps, plus the effect's Precision and Remove Redundant Points. The panel's Trap is one undo step and groups the traps above the topmost selected object. Behaviour from https://helpx.adobe.com/illustrator/using/trapping.html and https://helpx.adobe.com/illustrator/using/pathfinder-panel-overview.html.
2026-10-24 03:09:08 +07:00
bflatastic 422ecc0c77 Artboards: Artboard Options shows video safe areas and sets the pixel aspect ratio that View › Rulers › Show Video Rulers counts the artboard in
Squashed from #3831 onto main.
2026-10-24 03:09:07 +07:00
Taha-Mahmoodi 7c8840b93a Tools: double-clicking the Line Segment, Arc, Rectangular Grid and Polar Grid tools opens their Tool Options
Step 3 of the Rectangular Grid tool and Arc tool help pages
(https://helpx.adobe.com/illustrator/using/tool-techniques/rectangular-grid-tool.html,
https://helpx.adobe.com/illustrator/using/tool-techniques/arc-tool.html)
and the Tools page (https://helpx.adobe.com/illustrator/using/tools.html)
say a double-click on the tool opens its Tool Options. For these four tools
the double-click (tool.options, and Enter once #2891 lands) said the tool
had no options (#2691).

The Tool Options are the tool's click dialog in dialogs/shapes.rs, opened
without a place to draw (shapes::open_options; a `__toolOptions` field
marks it), as the review of #2979 asked: no copied form code. Its OK runs
tool.setOption and draws nothing; Cancel changes nothing. The grids' dialogs
are titled Rectangular Grid / Polar Grid Tool Options there. The options
are what the next drag draws with and what a click's dialog opens at:
- Line Segment: Length and Angle (now kept by the tool and used by the
  click dialog) and Fill Line (new: shape.line {fill: true} gives the line
  the current fill; the click dialog has it too);
- Arc: lengths, Reference Point, Type, Base Along, Slope, Fill Arc;
- the grids: dividers, skews and switches, plus the Default Size and
  Reference Point, now kept by the tool (width, height, reference) for the
  click dialog; a drag leaves them out of its command.
The grids' Reference Point is drawn only as the 9-point locator (it also
showed as a plain number field).

New strings (Rectangular Grid Tool Options, Polar Grid Tool Options, Fill
Line) have rows in all 24 catalogs.

Verification:
toolbar::tests::double_clicking_the_line_arc_and_grid_tools_opens_their_tool_options
double-clicks each tool's toolbar button: the dialog and its title, Cancel
leaves the next drag as it was, OK draws nothing, the next drag uses the
option and a click's dialog opens at it (a grid at its Default Size);
line_segment_options_and_fill_line, grid_default_size_is_an_option_the_drag_leaves_out,
fill_line_gives_a_new_line_the_current_fill. Grid dialog tests now expect
the stored Default Size. Live: double-clicking the Rectangular Grid tool in
the release build opens Rectangular Grid Tool Options; OK with 2 and 3
dividers, then a drag, draws a 3 × 4 grid.
2026-10-24 03:09:07 +07:00
Marco Arnulfo c39be04573 Pencil: Shift held at the press draws a straight line at 45° steps (part of #3799) 2026-10-24 03:09:06 +07:00
bflatastic a8fd8ddeef Legacy .ai pattern flattening: skip the ancestry walk for leaves without a pattern fill 2026-10-24 02:06:54 +07:00
NetterSilverandClaude Opus 5.5 94759cbe71 Flatten transparent image pattern tiles in legacy .ai v7 export
Fixes #3666

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 02:06:40 +07:00
bflatastic 2e572c7805 Count Repeats inside symbol art toward the Repeat instance budget
Squashed from #3788 onto main.
2026-10-24 02:06:39 +07:00
Jürg Lehni c8fe9193d9 Type: colour glyphs go with type that effects reshape and Expand Appearance
COLR and SVG glyphs, which have no outlines, were left out wherever type was taken as its outlines: geometry effects, Expand Appearance, EMF/WMF export.
2026-10-24 02:06:11 +07:00
Taha-Mahmoodi 309119dc4c Docs: Simplify of part of a path is described in our own words, not the help page's
Review follow-up (CodeRabbit, clean-room): the test header, gaps.md and
target-app-parity.md quoted a phrase from the cited help page. Comments
and docs only.
2026-10-24 02:05:19 +07:00
Taha-Mahmoodi 606796b934 Simplify: with part of a path direct-selected, Object › Path › Simplify refits only the selected runs of segments
The Simplify help page says a path can be simplified whole or "a specific
path region with the Direct Selection tool"
(https://helpx.adobe.com/illustrator/desktop/draw-shapes-and-paths/modify-paths/manually-simplify-paths.html).
Simplify refitted every selected path whole, whatever part of it was
direct-selected.

object.path.simplify now looks at each path's direct selection: the
segments picked as segments, or else every segment with both anchors
selected. Each run of consecutive selected segments is refitted on its own
(vectorcraft_pathops::simplify_part) between its two end anchors, which stay
where they are with their handles on the side away from the run; every
other anchor and segment stays exactly as it was. A closed path's run may
cross its start point (the path then starts at the run's end anchor),
separate runs on one path simplify independently in one undo step, and the
runs stay direct-selected (as segments when segments were picked). A path
with only lone anchors selected still simplifies whole, as before, and
wholePaths: true simplifies partly selected paths whole. The slider, its
preview, Auto-Simplify and the Simplify dialog all run the command, so
they act on the part too. simplify_with now shares its run fitting with
the part refit (same results).

Verification: crates/engine/src/tests_simplify_part.rs (unselected anchors
and segments equal bit for bit, run end anchors fixed, the run within the
tolerance, two runs equal to each simplified alone in one undo step, a
closed run across the start point, picked segments, wholePaths, slider
preview and Auto-Simplify, a run that can't be simpler records no step)
and simplify_slider_and_dialog_simplify_only_the_direct_selected_part_of_a_path
(the slider's preview, Enter and the dialog's OK). Live: the release build's
slider at level 20 on a 91-anchor wave with anchors 30–60 selected refits
only that stretch.
2026-10-24 02:05:19 +07:00
dotCooCoo 2db1ada660 Open and Place: a file read in the background waits for a busy tool only during a drag
A file opened or placed off the UI thread waited while the active tool
reported busy. The Dimension tool also reports busy between its clicks,
so after one click a ready file stayed queued with its spinner until
the dimension was finished or canceled. Files also waited between the
clicks of the Blend tool.

The session now records whether the pointer button is held. A file
waits for a busy tool only while the button is held. A file that
opens between a tool's clicks resets the tool, as a switch of
documents does; a file placed in the active document leaves the
tool's clicks in place. Files still wait while a dialog is open, a
drag is under way or a preview is open, and a tool's preview between
its clicks counts as one (the Flare tool after its center drag, the
Dimension tool's line once the pointer moves after its second click).
2026-10-24 02:05:19 +07:00