Commit Graph
8584 Commits
Author SHA1 Message Date
dotCooCoo 804d7cee57 fix: preserve queued key order before tool selection 2026-11-05 22:17:33 +07:00
dotCooCoo 869d558d66 fix: follow active flyout tab for thumbnail work 2026-11-05 22:17:33 +07:00
BFlat 550186c582 Merge pull request #5808 from dotCooCoo/feat/ai-active-artboard-reader
.ai import: the file opens on its active artboard
2026-11-05 22:17:23 +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
BFlat d6ef516bff Merge pull request #5807 from dotCooCoo/fix/link-classic-mac-path
Links: a classic Mac OS path is named by its file name
2026-11-05 22:00:48 +07:00
BFlat da604a816b Merge pull request #5806 from dotCooCoo/fix/layers-thumbs-close-running-job
Layers: closing a document drops its running thumbnail job's image
2026-11-05 22:00:28 +07:00
BFlat 54c71ab55d Merge pull request #5776 from Hamza0101/feat/paint-fill-to-stroke
Color Effects: Apply Fill to Stroke and Apply Stroke to Fill (#5530)
2026-11-05 22:00:09 +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
dotCooCoo 8caa0e0e59 Layers: closing a document drops its running thumbnail job's image
A thumbnail job that was running when its document closed still sent
its image back, and the image stayed with the worker until a panel next
collected results. ThumbWorker::forget now drops the jobs of the picked
slots, queued or running, and the Layers panel uses it when a document
closes, keeping the same worker. The close test now goes through
File > Close with no panel drawn afterward.
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
BFlat 2f5d746ee9 Merge pull request #5805 from Silvertree2010/fix/5796-object-path-menu-items-must-not
Disable Object > Path items when no path is selected
2026-11-05 21:46:32 +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
BFlat 8a39f75b5c Merge pull request #5803 from dotCooCoo/chore/read-file-head-test-file
Tests: the read_file_head test creates its file exclusively and removes it on failure
2026-11-05 21:33:54 +07:00
BFlat 37498594d6 Merge pull request #5802 from dotCooCoo/fix/thumb-worker-hidden
Stop queued Layers thumbnails when both thumbnail panels are hidden
2026-11-05 21:33:37 +07:00
BFlat fb6eb76965 Merge pull request #5801 from dotCooCoo/fix/ai-legacy-text-masks
.ai import: legacy type used as a mask clips its clipping group
2026-11-05 21:33:19 +07:00
dotCooCoo 877b3de3ad Tests: the read_file_head test creates its file exclusively and removes it on failure 2026-11-05 21:18:44 +07:00
dotCooCoo 52438c7cea Fix item 1747: stop hidden thumbnail panel jobs 2026-11-05 21:18:44 +07:00
dotCooCoo 6e2a32c2a0 .ai import: legacy type used as a mask clips its clipping group
In the legacy format, `Tr` sets the rendering mode of the type that
follows. Section 5.7 of the version 7 specification says that modes 4 to
7 make the text object a mask: 4, 5 and 6 also fill, stroke, or fill and
stroke it, and 7 paints nothing. Sections 15.3.2 and 15.4.5.1 add that
these modes are used in pattern definitions, and the reader does not
read type in a pattern. The reader painted 4 to 6 like 0 to 2 and never
clipped, so the art a text mask clips showed whole.

A text object with characters in modes 4 to 7 is now a clipping path of
its clipping group (`q` ... `Q`, or the layer), as a path painted with
`W` is, and the whole object is the mask. Beside other clipping paths it
nests as they do, and the mode lasts into later text objects. Area type
with linked areas (threaded frames, also when the reader's limits keep
one frame), and type in wraparound text or in a compound path, a group
inside them included, doesn't clip, with a warning.

A `Tr` operand that is not a whole number from 0 to 9 now leaves the
mode as it was; before, 4.5 read as 4 and -4 hid the type.

The new warning and the reader's warning about linked type areas left
out get rows in every catalog.
2026-11-05 21:18:44 +07:00
BFlat cbb09c70d2 Merge pull request #5800 from dotCooCoo/feat/ai-global-name-suffix
.ai import: gradients and patterns are named up to the newline in their names
2026-11-05 21:18:35 +07:00
dotCooCoo e55c6d9d12 .ai import: gradients and patterns are named up to the newline in their names
The Adobe Illustrator File Format Specification 7.0, section 4 (p. 51),
says the name shown for a global object is the part of its name in the
file before the newline
(https://13thmonkey.org/documentation/fonts/AI7FileFormat.pdf). The
legacy reader kept the whole name, so swatches and patterns came in
named "Sky\n1". The reader now applies this rule to the files of every
version it reads.

- Gradient swatches, gradient fills, pattern definitions, pattern fills,
  palette cells and art-style pattern fills use the part before the
  newline. Lookups inside the reader still use the whole name.
- When that name is taken, the first free "Sky 2", "Sky 3" is used.
  Taken names are None and Registration, the palette's own swatch and
  group names, the default swatches when no palette replaces them,
  named colors (color operators, gradient stops, version 7 pattern
  strings, the header's and an EPS program's custom colors), the names
  of gradients and patterns that have no newline, and the names given
  to earlier gradients and patterns. Only content the reader reads
  counts: not the alternates of versioned content, the prolog, skipped
  sections or what follows the trailer.
- A name with nothing before the newline comes in as "Gradient" or
  "Pattern". Names without a newline do not change.
- docs/file-format-parity.md lists the rule.
2026-11-05 21:06:27 +07:00
BFlat b3193416b1 Merge pull request #5799 from dotCooCoo/fix/action-set-load-bounded-read
Actions: loading an action set checks its size before reading it
2026-11-05 21:04:24 +07:00
dotCooCoo 2cd68fbdcb Actions: loading an action set checks its size before reading it
Load Actions… read the whole file before checking the 8 MiB limit, so
picking a very large file could take a lot of memory before it was
refused. A new read_head service reads at most a given number of bytes;
the desktop app provides it, and loading an action set reads one byte
past 8 MiB with it. A larger file is refused without reading the rest.
Hosts without the service keep reading the whole file. Automation
roots apply to read_head as they do to read.
2026-11-05 20:55:58 +07:00
BFlat d63ce36b05 Merge pull request #5798 from devius/ka-update-2026-11-05
i18n(ka): Georgian for 1 new string
2026-11-05 20:55:50 +07:00
Davit Matchakhelidze e271e5eb18 i18n(ka): Georgian for 1 new string
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YMTAbGNRxnMEzRvYnQGphF
2026-11-05 20:47:12 +07:00
BFlat a479c8baa1 Merge pull request #5795 from dotCooCoo/fix/layers-thumbs-close-cache
Release Layers thumbnails when a document closes
2026-11-05 20:30:52 +07:00
BFlat 927ed8f236 Merge pull request #5794 from dotCooCoo/fix/image-trace-batch-options
Reject malformed Batch Trace Folder options
2026-11-05 20:30:37 +07:00
dotCooCoo d9332c806b UI-1746: Release closed document layer thumbnails 2026-11-05 20:18:52 +07:00
dotCooCoo 99169d5404 Reject malformed Batch Trace Folder options 2026-11-05 20:18:52 +07:00
BFlat d168d6d417 Merge pull request #3273 from FractalEncrypt/fix/thin-curved-stroke-coverage
Preserve raster coverage of thin curved strokes
2026-11-05 20:18:39 +07:00
BFlat f88cfdc24e Merge pull request #3272 from FractalEncrypt/fix/outline-stroke-open-fills
Keep Group Selection drags on the selected outlined component
2026-11-05 20:18:22 +07:00
FractalEncrypt e0ad7ccf16 Preserve raster coverage of thin curved strokes
Squashed from #3273 onto main.
2026-11-05 20:00:21 +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
BFlat f1ee91fcd9 Merge pull request #5793 from dotCooCoo/feat/ai-tz-encodings
.ai import: a re-encoded font's own encoding pairs decode its type
2026-11-05 19:53:56 +07:00
BFlat 9f753225f0 Merge pull request #3903 from el-j/feat/copy-cut-direct-selection
M2.1: copy and cut direct-selected segments and anchors as independent paths (#2122)
2026-11-05 19:53:40 +07:00
BFlat 63909c6be6 Merge pull request #4345 from el-j/fix/offset-path-transform-ram-spike
fix(pathops): bound offset path complexity and handle arrangement failure safely (#4145)
2026-11-05 19:53:24 +07:00
dotCooCoo 7973439cc2 .ai import: a re-encoded font's own encoding pairs decode its type
In the legacy format, `TZ` makes a re-encoded font from an existing one
and can give it encoding pairs of its own, which change only that font's
encoding. Its `useDefault` operand says whether the file's `TE` encoding
also applies to the font (Adobe Illustrator File Format Specification
7.0, section 3.3.1,
https://13thmonkey.org/documentation/fonts/AI7FileFormat.pdf). The
reader skipped the body of `%AI3_BeginEncoding` sections and ignored
`TZ`, so every string was decoded with `TE`'s encoding.

Strings in a re-encoded font are now decoded with its own pairs, then
with `TE`'s encoding when `useDefault` is 1, and as Windows-1252 for the
codes left. Strings in other fonts keep `TE`'s encoding. The reader
reads `TZ` in the body of an `%AI3_BeginEncoding` section and wherever
else it appears in the script, with or without the direction operand
and the Multiple Master weight vector. The font names are the last two
names, and only numbers and the weight vector may follow them; the
reader does not use a `TZ` of another shape. The first `TZ` for a font
is used.

`TZ`'s font names also map the re-encoded font to the font it was made
from, as the `%AI3_BeginEncoding` comment does. Type in a re-encoded
font that no such comment names now opens in the font `TZ` names; when
both name the font, the first one read is used.
2026-11-05 19:40:58 +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
BFlat c98007a43d Merge pull request #5792 from dotCooCoo/fix/ai-legacy-ts-te
.ai import: type with the older TS, Te and TM operators opens
2026-11-05 19:40:48 +07:00
dotCooCoo ab86a62ea0 .ai import: type with the older TS, Te and TM operators opens
The version 7 and version 3 file format specifications list three text
operators the editing-data reader did not dispatch, so a file whose type
used any of them on a visible layer did not open from its editing data:

- `(text) justified TS` (special characters): the reader adds its
  characters to the story, as it does for `Tx` and `Tj`.
- `Te` (end render) is read and ignored. The reader accepts it with any
  number of operands.
- `TM` (pop text matrix) is read and ignored.

Tests cover each operator in a text object, `TS` without a string and
outside a text object, and `Te` inside a tab definition. The import fuzz
tests add the operators to the legacy type tokens.
2026-11-05 19:28:59 +07:00
BFlat c547dacad6 Merge pull request #3071 from KnottyDyes/squad/raster-export-default-ppi
Export: raster output defaults to the document resolution
2026-11-05 19:14:05 +07:00
BFlat 184c591d56 Merge pull request #5791 from sadkotheguest/feat/layers-panel-nonprinting-italic
Layers panel: a layer that does not print shows its name italic
2026-11-05 19:13:48 +07:00
KnottyDyesandClaude Opus 5.5 65b8192b7e Docs: a document at another resolution exports at it, not 72 ppi
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 19:02:23 +07:00
bflatastic 3f940efae1 Layers: the italic layer comments name Layer Options › Print 2026-11-05 19:02:23 +07:00
KnottyDyes c9588457b9 Export: raster output defaults to the document resolution 2026-11-05 19:02:23 +07:00
Alex 82251c8e8b Layers: a layer that does not print shows its name italic (#5739)
Layer Options › Print off means the layer's art does not print. The Layers panel now paints
that layer's name italic, as Illustrator shows non-printing layers, and the ghost of a row
being dragged keeps the italic. A printing layer's name stays upright, and ticking Print
again restores it.

Row names are painted rather than widgets, so the italics come from a layout job's text
format (egui slants the glyphs itself; no italic face is needed).

Tests: panels::layers::tests::a_layer_that_does_not_print_has_its_name_italic covers Print
off, Print on again, and a plain printing layer; the layers suite (64 tests) passes.
Docs: roadmap, target-app-parity and ui-parity carry the change.
2026-11-05 19:02:23 +07:00
BFlat 2030536afe Merge pull request #5790 from dotCooCoo/fix/ai-os22-g13
.ai import: 1-bit image masks open colorized by their fill color
2026-11-05 19:02:13 +07:00
dotCooCoo d5473acb09 .ai import: 1-bit image masks open colorized by their fill color
The version 7 file format specification gives `XI` and `XF` an
ImageMask operand: 0 is an opaque image, 1 is an image that is
transparent and can be colorized (sections 8.1, 8.2 and the 1-bit
examples in 8.4,
https://13thmonkey.org/documentation/fonts/AI7FileFormat.pdf). The
reader ignored the operand, so a 1-bit image mask opened as an opaque
black-and-white image.

A 1-bit gray image with ImageMask 1 now opens with the fill color set
before it as the color that colorizes it. A spot or global color keeps
its swatch and tint. When the fill is a pattern, a gradient or none,
the image is colorized black. VectorCraft's own rule is that the pixels
that open black with ImageMask 0 take the color and the others are
transparent. A linked image (`XF`) keeps the same color for when its
file is relinked. 8-bit gray, RGB and CMYK images, and images with
ImageMask 0, open as before.
2026-11-05 18:50:05 +07:00