Commit Graph
6667 Commits
Author SHA1 Message Date
dotCooCoo 8f56899df9 Perspective Selection: Cmd/Ctrl+Alt-drag copies objects in perspective
With the Perspective Selection tool, Ctrl+Alt-drag (Command+Option-drag on
macOS) now copies objects on their perspective plane, as Alt/Option-drag
does. Before, Cmd/Ctrl lent the last selection tool even with Alt held, so
the drag made a flat copy. Cmd/Ctrl alone still lends the last selection
tool, and the cursor follows the same rule.
2026-10-30 23:57:36 +07:00
Don Omondi 66c797a59b .ai import: outlines from the editing data keep their look and threads; mesh corners with non-numbers are unread
Follow-ups to the review of #4697 and #4698:

- With textAs: outlines, a .ai saved without PDF compatibility, read
  from its editing data alone, has its type outlined too, as an empty
  page or a text-only placeholder already did.
- Threaded type read from the editing data holds its story in its first
  frame: it now flows through its frames before it is outlined, so each
  frame's outlines show the text it holds, and the outlined frames
  leave their threads.
- Each outline group keeps its type's opacity, blend mode, isolation,
  opacity mask and effects (the same carry-over the flattener uses).
- A gradient-mesh corner (/N) holding anything but numbers is unread,
  instead of being read with the numbers after it shifted into its
  colour and opacity.
2026-10-30 23:55:32 +07:00
Don Omondi 1d58ea947d fix(ai-import): pages cropped to the art in UserUnit units, and their copies' type
A page cropped to the art is recognised in a UserUnit page's units too,
when the art's box is the page in those units and the artboard isn't the
page in points. Such pages are taken only when every page is the art's
box, and only the first page's type is read: the later pages are copies
whose type was moved by the first page's offset and could fill the
layers' text objects twice.
2026-10-30 23:55:28 +07:00
Don Omondi 75958ce7da fix(ai-import): weigh unseen text again at the placed files' other placement
prune_unseen ran before the retry that moves placed files to their box's
corner, and that retry cloned the pruned layers: text an image covered
only at its first placement was already gone, so the file came in without
it or as its PDF part. Clone the layers before pruning and prune each
placement on its own.
2026-10-30 23:55:22 +07:00
Don Omondi 530605d4fc fix(ai-import): keep All Caps and Small Caps on type from the text document
Character attribute 12 of the editing data's text document is the case
(1 Small Caps, 2 All Caps). The reader skipped it, so type set in All Caps
came in as typed, in lower or mixed case where the page draws capitals.
Map it onto CharStyle::all_caps and CharStyle::small_caps.
2026-10-30 23:55:16 +07:00
dotCooCoo b4899e665d Pathfinder: batch steps set the operation Cmd+4 repeats
A successful command.batch now records its last Unite, Intersect or other
Pathfinder step as the operation Repeat Pathfinder runs, so playing an
action from the Actions panel updates it. A batch that fails and rolls back
leaves the previous operation in place. action.batch, which runs an action
over other files or data sets, does not set it.
2026-10-30 23:52:27 +07:00
dotCooCoo bad34b7115 Pathfinder: direct commands set the operation Cmd+4 repeats
Every successful Shape Mode or Pathfinder operation now sets the
operation that Repeat Pathfinder runs, including direct
object.pathfinder.* commands, not only the panel's buttons. Trap,
compound-shape edits and live effects leave it unchanged, and a failed
operation keeps the earlier one. The panel menu names the remembered
operation, and Repeat runs it on the current selection with the current
Pathfinder Options.

With too few objects selected, Cmd/Ctrl+4 leaves the art as it is and
shows the panel's selection message in the status bar. Adds the
"no Pathfinder operation applied yet" rows to the Catalan and Turkish
catalogs, and tests for direct and failed operations, Trap, compound
shapes, current options, a one-path selection and the default keys.
2026-10-30 23:52:26 +07:00
dotCooCoo 9b3e2d873b Pathfinder: Cmd+4 repeats the last Pathfinder operation 2026-10-30 23:52:26 +07:00
dotCooCoo 7d97c633b7 Pencil and Blob Brush: Alt smooths with the Smooth tool's Fidelity
When Alt switches the Pencil (with Alt key toggles to Smooth Tool on)
or the Blob Brush to the Smooth tool, the drag sent the drawing tool's
own Fidelity (1.5 by default) to path.smoothRegion. The Smooth tool
sends its own Fidelity (2.5 by default, set in Smooth Tool Options).

Both tools now smooth with the Smooth tool's Fidelity. The engine gives
them the stored Smooth Fidelity when it makes the tool, and again when
Smooth Tool Options changes while one of them is active. Each tool's
own Fidelity still sets how its strokes are fitted.
2026-10-30 23:52:26 +07:00
bflatastic 71f566c6aa Docs: keep the Knife entry to the documented behaviour 2026-10-30 23:52:26 +07:00
dotCooCoo 28936f6174 Knife: Alt counts only at the press and Shift+Alt steps from the canvas axes
A straight Knife cut now starts only when Alt is held at the press.
Alt pressed later in the drag, even before the pointer moves, leaves
the cut freehand. Releasing Alt during a straight cut keeps it
straight.

With Shift+Alt, the cut keeps to 45° steps from the horizontal and
vertical whatever the Constrain Angle. The Pencil's straight line
still steps from the Constrain Angle.

Tests cover Alt after the press, Alt only at the release, a 90° cut,
a 30° Constrain Angle, and the cut boundaries in the engine.

Docs: docs/target-app-parity.md.
2026-10-30 23:51:51 +07:00
dotCooCoo cd9eb0acd5 Knife: Alt cuts in a straight line and Shift+Alt cuts at 45° steps
The Knife cut along the freehand drag whatever keys were held. The
reference app cuts in a straight line with Alt-drag, and it cuts at 45
or 90 degrees with Shift+Alt-drag.

With Alt held at the press, or pressed before the drag has moved, the
Knife's stroke is the press point and the pointer: the dashed line
shows it while dragging, and the release sends path.knife with those
two points. With Shift held too, the line keeps to 45° steps from the
Constrain Angle, as the Pencil's Shift line does. Shift is read on each
drag event and at the release. The cut stays straight when Alt is let
go, a line taken back to its press point sends no command, and Shift
alone leaves the cut freehand.

Docs: docs/target-app-parity.md.
2026-10-30 23:51:51 +07:00
dotCooCoo aea9296fa2 Character and Paragraph Styles: a style made by the New style dialog or the panel menu is highlighted
Squashed from #4713 onto main.
2026-10-30 23:45:42 +07:00
dotCooCoo 29fb6bcd89 Images: color edits recolor a colorized image's fill
paint.invert and paint.complement on the Fill proxy, the Edit Colors
commands, the Blend commands and recolor.apply now recolor the color
that colorizes a grayscale or 1-bit image, as one undo step with the
other targets. Before, they left it unchanged. Expand Appearance and
Object > Expand bake color adjustment effects into that color too.

- A colorized image's pixels are not recolored; they stay the gray
  coverage of its color. A stroke-only pass reaches the image's stroke
  items and leaves its colorize color unchanged.
- A command that would leave a process color on a grayscale image with
  an alpha channel fails with the existing message and changes nothing.
  Object > Expand undoes its earlier steps when that happens.
- A colorized image counts as a filled object in a blend.
2026-10-30 23:44:19 +07:00
dotCooCoo 6c9933666b PDF: colorized images count as transparency for PDF 1.3 and PDF/X
A colorized grayscale or 1-bit image draws its white pixels transparent and is written to
PDF with the image as a soft mask. Node::shows_transparency did not count it, so a PDF 1.3,
PDF/X-1a or PDF/X-3 export whose only transparency was a colorized image was not flattened
and kept the soft mask. A legacy .ai save also wrote such an image as opaque.

- shows_transparency counts a visible image with a colorize paint.
- The legacy .ai writer flattens or leaves out colorized images like other see-through images.
2026-10-30 23:44:15 +07:00
dotCooCoo b3f1d57ecf Graphic Styles: addFromLibrary treats ids: null as left out
graphicStyle.addFromLibrary with apply: true and ids: null tried to
apply the style to no objects and failed with "no such objects" when
nothing was selected. A null `ids` now behaves as leaving `ids` out:
the style is applied to the selection when there is one, and only added
otherwise.
2026-10-30 23:44:10 +07:00
dotCooCoo ae0ce1888d Libraries: library loads check name before reading the file
swatch.library.load, graphicStyle.loadLibrary, symbol.loadLibrary and
brush.loadLibrary read the whole file or decoded data before checking
`name`, so a call with a `name` that is not a string read the file
first, and with a missing file reported the file error instead of the
parameter error. The shared loader now checks every parameter before it
reads anything.
2026-10-30 23:44:05 +07:00
dotCooCoo 16db8b6a1a PDF export: bound a colorized image's color channel
A colorized image's color channel is the paint's samples repeated once a
pixel, and nothing bounded its size: an image colorized in Registration in
a document with many spot swatches could allocate without limit, and an
overflowing length panicked inside repeat. The length is now computed with
checked arithmetic and refused above MAX_RASTER_ALLOC, the image's own
decode budget, and the export leaves such an image out with the existing
"an image couldn't be decoded" warning instead of drawing it uncolored.
2026-10-30 23:43:57 +07:00
BFlat 07188ce11b Merge pull request #4725 from dotCooCoo/feat/spiral-drag-winds-decay
Spiral tool: Alt-drag adds or removes winds and Ctrl/Cmd-drag changes the decay
2026-10-30 23:41:49 +07:00
dotCooCoo 88e2177fec Spiral tool: Alt-drag adds or removes whole winds of four segments
Alt in a spiral drag now rounds the fitted segment count to whole winds
of four segments, counted from the segment count when Alt went down.
Ctrl/Cmd takes precedence when both keys are held, and switching back to
Alt starts from the current count with the held inner end kept. Arrow
keys, Escape, release and a new drag clear the held Alt count.

Tests cover both keys together, a switch mid-drag, Escape, the 2 to 1000
bounds and the committed path's anchor count. docs/mcp.md and
docs/target-app-parity.md describe the rule.
2026-10-30 23:17:01 +07:00
dotCooCoo 856c602310 Spiral tool: Alt-drag adds or removes segments, and Ctrl/Cmd-drag changes the decay
The reference app adds or subtracts winds from a spiral with Alt-drag
and changes its decay rate with Ctrl/Cmd-drag. VectorCraft's Spiral
tool did nothing with either key during a drag.

While a spiral is dragged out, Alt or Ctrl/Cmd keeps the spiral's
inner end at the distance from the center it had when the key went
down, and the outer end follows the pointer. With Alt the number of
segments changes to the nearest whole number that fits, within 2 to
1000, so dragging outward adds segments and dragging inward removes
them. With Ctrl/Cmd the decay changes to fit, within 5 to 99.99
percent, the decays a spiral is drawn with. When both keys are held,
Ctrl/Cmd changes the decay. Up/Down with a key still held move the
held radius to the new segment count. The new values stay when the
key is let go, and as the Spiral tool's segments and decay options
for the next spiral. Both keys also work with a 5 percent decay and
hundreds of segments.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-30 23:17:01 +07:00
BFlat f30a77e2d4 Merge pull request #4724 from storytold/fix/3d-on-live-type
3D Extrude & Bevel, Inflate and Rotate apply to type, which stays editable (#4715)
2026-10-30 23:16:42 +07:00
bflatastic f4be2b9006 3D Extrude & Bevel, Inflate and Rotate apply to type, which stays editable (#4715) 2026-10-30 23:03:51 +07:00
BFlat b151163183 Merge pull request #4721 from storytold/feat/addon-live-halftone
Add-ons: Color Effects — live Vector Halftone effect
2026-10-30 22:39:49 +07:00
bflatastic f4c245286e Add-ons: Color Effects — live Vector Halftone effect
Effect › Color Effects › Vector Halftone… (addon.color.halftone, also in
Object › Plug-ins › Color Effects) draws its object as the halftone dots
Object › Vector Halftone makes, live: mono (one dot colour, or each dot in
the art's colour under it) or CMYK screens, the five dot shapes,
frequency, angle, invert and clip to the art's outline.

- The screens, dots and caps move to vectorcraft_effects::addons::halftone,
  shared by the command (its behaviour and tests unchanged) and the effect.
- The renderer samples the art (vectorcraft_render::addons::halftone) and
  keeps the dots by the object's content and what it reads from the
  document, so unchanged art isn't sampled again; past 100000 cells per
  screen the object draws as it is.
- Expand Appearance turns the object into its dots, and the SVG, PDF, EPS
  and AI exporters write them as paths.
- Its dialog reuses the command's fields, without Keep Original.

Deferred: stochastic and radial patterns, a dot-gain curve, per-screen
separation settings, type or symbols as dots.
2026-10-30 22:13:33 +07:00
BFlat efcc334553 Merge pull request #4486 from dotCooCoo/feat/text-styles-select-all-unused
Text styles: Select All Unused highlights the unused styles, and Delete deletes them all
2026-10-30 21:35:34 +07:00
dotCooCoo 3b724a0a79 Text styles: Select All Unused highlights the unused styles, and Delete deletes them all
Squashed from #4486 onto main.
2026-10-30 21:16:33 +07:00
BFlat 6049ddbcd8 Merge pull request #4709 from storytold/feat/addon-parametric-shapes
Add-ons: Parametric Shape Tool — re-editable stars, polygons, rings, arrows, gears and more
2026-10-30 21:15:21 +07:00
bflatastic 27ed249b1f Add-ons: Parametric Shape Tool — re-editable stars, polygons, rings, arrows, gears and more
Path Precision Tools gains the Parametric Shape Tool: ten kinds of shape
(rectangle, ellipse, polygon, star, ring, arrow, cross, heart, gear,
speech bubble) that stay editable as numbers.

- Geometry in vectorcraft_pathops::addons::pathtools::shapes: each kind's
  outline, corner rounding limited to the middle of a side, a fingerprint
  of the outline, recovery of centre, size and rotation after a move,
  turn or scale, and recognition of plain rectangles, ellipses and
  regular polygons.
- The tool (parametricShape, All Tools drawer and Object › Plug-ins ›
  Path Precision Tools only, no shortcut): drag from the centre (Shift:
  45° steps), arrow keys change the count and values while dragging,
  handles edit a selected shape, double-click places one.
- Commands addon.pathtools.shape.create / .set / .convert, one undo step
  each; params checked (counts 3..1000, sizes up to 16384 pt).
- A shape keeps its numbers in one object-data entry (vc-pathtools-shape)
  that SVG export already leaves out; anchor edits make it a plain path.
- Parametric Shape panel, cursor stand-in, catalog rows in all 25
  languages, docs and tests.
2026-10-30 20:55:14 +07:00
BFlat b496226ab5 Merge pull request #4463 from danngreen/feat/library-drop-place
Libraries panel: art and colors dragged in are added where they are dropped
2026-10-30 20:52:36 +07:00
BFlat ce8e344735 Merge pull request #4691 from kler/swedish-ui-2026-10-30
i18n(sv): translate 32 new strings, use the agreed terms in 11
2026-10-30 20:52:20 +07:00
Dan Green 10838300f1 Libraries: an add that cannot be placed makes no "My Library"
With no library yet, library.add made and saved "My Library" before it
looked for the group or item to place the new one by, so a bad `group`,
`before` or `after` failed but left an empty library behind. The new
library is now kept only once the item is in it.
2026-10-30 20:20:17 +07:00
Dan Green 7688b41a40 Libraries panel: art and colours dragged in are added where they are dropped
Art dragged off the canvas and colours dragged in from elsewhere (swatches, another library's)
used to be added at the end of the ungrouped items, wherever they were dropped. They now land
as items dragged within the list do: on another item of their kind, just before or after it by
the pointer's half and in its group; on a group, into it; away from the items, ungrouped at the
end as before.

library.add takes group and before/after, placed as library.moveItem places an item (the
placement is shared). A library change that fails partway now leaves the library as it was.
2026-10-30 20:20:17 +07:00
Patrik LermonandClaude Opus 5.5 d38994c77d i18n(sv): translate 32 new strings, use the agreed terms in 11
Brings the Swedish catalog up to date with upstream main (a8ec515e1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 20:20:14 +07:00
BFlat 435fa962dd Merge pull request #4701 from ashokram-si/feat/gradient-presets-g13
Gradient panel: presets to apply, save and delete (G13)
2026-10-30 20:17:44 +07:00
BFlat 3b743f4543 Merge pull request #4561 from adambelis/fork/feat/control-bar-distribute
feat: show six Distribute Objects buttons in Control bar when 2+ objects selected (Illustrator parity)
2026-10-30 20:17:28 +07:00
BFlat 63caf3f047 Merge pull request #4702 from mockydevs/fix/pdf-large-mesh-shading
PDF import: large mesh shadings and mesh-painted strokes come in as gradient meshes
2026-10-30 20:17:14 +07:00
BFlat 865df773ed Merge pull request #4698 from mockydevs/fix/ai-empty-page-followups
.ai import: an empty page with skipped content isn't taken for empty; outlines asked for are given
2026-10-30 20:16:58 +07:00
BFlat 0e49b47167 Merge pull request #4697 from mockydevs/fix/ai-mesh-unread
.ai/EPS import: read gradient meshes in named colours, mixed colour spaces and large grids
2026-10-30 20:16:43 +07:00
bflatastic 051b5d8583 Docs: one area-table row each for Path operations and Colour again 2026-10-30 19:50:57 +07:00
ashokram-si 7a2fc777f4 Gradient panel: presets to apply, save and delete (G13)
People reuse the same gradients across documents and rebuilt them by
hand. The Gradient panel now has a Presets menu: the presets of the
app's built-in gradient libraries, grouped by library (theme), then
the saved ones. Choosing one gives the gradient behind the active
proxy (or a solid paint) the preset's type, stops, method and dither,
keeping its placement, as one undo step, through paint.editGradient.
The panel menu saves the current gradient as a preset (named in a
dialog) and deletes saved ones; Hide/Show Presets toggles the row.

Saved presets are kept with the preferences, next to the other user
preset lists (width profiles, flattener, perspective). Stops linked to
a document swatch keep their colour, unlinked, since a preset is used
in other documents. Built-in presets can't be deleted; names are
unique.

Commands: gradient.presets.list, .apply, .save and .delete. The menu's
rows are drawn only while in view, as its headings are.

Tests: engine tests for list, apply (fill and stroke, placement kept,
one undo step), save (unique names, unlinked swatch stops) and delete;
panel tests for applying from the menu and saving, deleting and
hiding presets from the panel menu, including scrolling the menu to
the saved presets. Docs: gaps G13, target-app and UI parity, ROADMAP.
2026-10-30 19:50:25 +07:00
Adam 55bfb7033e feat: show six Distribute Objects buttons in Control bar when 2+ objects selected (Illustrator parity)
Squashed from #4561 onto main.
2026-10-30 19:50:23 +07:00
bflatastic b127918be5 PDF import: a mesh-painted stroke's outline keeps dash and tolerance in reason 2026-10-30 19:45:52 +07:00
Don Omondi 75e8f69734 PDF import: large mesh shadings and mesh-painted strokes come in as gradient meshes
Patch and triangle mesh shadings of more than 4,096 patches, and strokes
painted with a mesh shading, came in as a flat grey. Illustrator writes
meshes of up to 14,355 patches, and writes a freeform gradient on a
stroke as a stroke painted with a type 7 shading.

- MAX_PATCHES is 16,384, as in the .ai editing-data reader.
- A stroke painted with a mesh shading is the meshes clipped to the area
  the stroke paints (stroke_outline: width, caps, joins, miter limit and
  dashes, built in the path's space and then transformed); draw_meshes
  always clips a stroke's meshes.
2026-10-30 19:44:50 +07:00
Don Omondi 4f5d270ae9 .ai import: an empty page with skipped content isn't empty; outlines asked for are given
Two follow-ups to the empty-page fallback:

- A page counts as empty only when nothing on it was skipped: its only
  notes are the page's own (art off the artboards, art past the page). A
  page whose only content couldn't be read, such as an image that can't
  be decoded, keeps its notes and goes through the usual check against
  the editing data, instead of being replaced by it unchecked.
- With textAs: outlines, the document read from the editing data alone
  has its type outlined. The usual path takes outlines from the page,
  but an empty page (or a text-only placeholder, #1387) has none to give.
2026-10-30 19:44:45 +07:00
Don Omondi c0ee9c1986 .ai/EPS import: read gradient meshes in named colours, mixed colour spaces and large grids
A mesh in the editing data that the reader couldn't read made the whole
file come in as its page or PDF part, without its layers. Three cases
were rejected that files write routinely:

- A mesh starts grey, and `/CS` is written only where the colour space
  changes, before the corner it applies to, even within a patch. Meshes
  with no `/CS`, or one that changed between corners, were unread.
- Named colours (`[c m y k /DeviceCMYK (name) /Process]` or `/Spot`) and
  `/NChannel` inks: each corner gives the tint, 1 being the full colour.
- Grids over 64 patches a side or 4,096 patches (files have 97 x 72).

Each corner now takes the colour space last set before it; named
colours paint at their tint and inks overprint at theirs; the limits
are 128 a side and 16,384 patches.
2026-10-30 19:44:41 +07:00
BFlat ed733b7d91 Merge pull request #4703 from storytold/feat/smart-pen-marquee
Smart Pen: an Alt-drag away from paths selects the points inside a marquee
2026-10-30 19:41:40 +07:00
bflatastic 884966c161 Smart Pen: an Alt-drag away from paths selects the points inside a marquee 2026-10-30 19:10:45 +07:00
BFlat 3dc3550c2f Merge pull request #4700 from storytold/fix/presentation-mode-artboard
Presentation Mode fits the active artboard and hides selections, guides, grids and artboard edges
2026-10-30 19:02:28 +07:00
BFlat e1f4e65030 Merge pull request #4699 from storytold/feat/addon-color-select
Add-ons: Color Effects — select by color kind (spot colors, color effects, RGB, CMYK and grayscale images)
2026-10-30 19:02:12 +07:00