Commit Graph
2169 Commits
Author SHA1 Message Date
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
Don Omondi 62c6d42dff Set Corners: round only the corners in an angle range (#5545)
Squashed from #5737 onto main.
2026-11-05 11:04:52 +07:00
Don Omondi 7aa759d4de Set Corners: round all, odd-numbered or even-numbered anchors (#5546)
addon.pathtools.cornerSet takes `every` ("all", "odd" or "even"; default
"all"), which keeps, of the anchors already chosen (named, direct-selected
or all), only the odd- or even-numbered ones, counted along each path from
its first anchor as number 1. Anchors that take no corner still count, so
the pattern follows the path's anchor order on open and closed paths; when
nothing is left the command says so. Unknown values are refused.

Object › Plug-ins › Path Precision Tools › Set Corners… (also a button in
the Anchor Inspector's Corners section) opens a dialog with Radius, Corner
kind and Anchors (All / Odd-Numbered / Even-Numbered) that previews on the
canvas and commits as one undo step.
2026-11-05 10:42:37 +07:00
bflatastic d62c90f41e Tests: Expand Appearance of a Transform's copies makes a group of them 2026-11-05 10:25:44 +07:00
Don Omondi 231e43a490 Effects: Expand Appearance makes each copy of a path's Transform effect an object of its own (#5612)
A path or compound path whose Transform effect made copies expanded to
one compound path of every copy. It now expands to a group of one object
per copy, each painted as the path, as gradient copies already did; a
second Transform effect's copies nest in a group per copy of the first.
Drawing is unchanged.

# Conflicts:
#	docs/effects-parity.md
2026-11-05 10:25:44 +07:00
FredApps ed78763866 Merge pull request #4784 from datatimp/fix/3260-halftone-radius-pixels
Color Halftone: Max Radius in pixels of the raster effects resolution
2026-11-05 04:09:48 +01:00
Don Omondi 23bcef97c7 Isolation mode: a locked or hidden layer keeps the isolated art from clicks and marquees (#5309)
Locking or hiding the layer (or a group) around the isolated object left
its art selectable with the Selection tool: the isolation branch of the
hit test only checked for a locked artboard, and the marquee's checked
nothing. Both now pass over isolated art that isn't editable.
2026-11-05 09:32:28 +07:00
Don Omondi ce4f16369e PDF import: a DeviceN gradient of a spot ink over process plates keeps the ink and the plates, and PDF export writes it as DeviceN again (#3235) 2026-11-05 09:09:53 +07:00
dotCooCoo f0335d2f17 Glyphs: a fallback face's consonant glyph is reported, not its vowel sign's
When a fallback face draws Ka with the vowel sign I, the vowel sign's
glyph comes first in Ka's cluster, and text.glyphAlternates reported it
for Ka, laid out or overflowing. The query now finds the face that draws
the character and takes that face's glyph for it by the same rule as
for the requested face.
2026-11-05 08:37:18 +07:00
dotCooCoo 8118b59d19 Glyphs: the Glyphs query reports the fallback glyph of an overflowing character
When the requested font has no glyph for a character, the text draws it
from a fallback face, and text.glyphAlternates reports that glyph. For
a character that overflows its area, the query shaped the character
alone but kept only a glyph of the requested face, so it reported the
requested face's default glyph (0). It now takes the first glyph drawn
for the character when the requested face draws none, as it does for
laid-out text.
2026-11-05 07:56:26 +07:00
dotCooCoo ee9cce43dc Symbols: an instance fill with no opacity keeps the art's swatch links
A symbol instance whose fill has an opacity of 0 no longer counts as
stained. Expand Appearance and the other places that build an
instance's art used to rebuild every solid paint as an unlinked color
even though the tint changed nothing, so the art lost its global and
spot swatch links.
2026-11-05 07:44:08 +07:00
dotCooCoo e33be0eea9 Glyphs: a character's glyph is the first of its glyphs in its cluster
Ka, the halant, Ka again and the vowel sign I are shaped as one cluster:
the vowel sign, the first Ka's half form, then the second Ka's default
glyph. The glyph lookup looked for the character's default glyph across
the whole cluster before its alternates, so for the first Ka it found
the second Ka's default glyph instead of the half form. It again goes
through the cluster in order, and takes the first glyph that is the
character's default glyph or one of its alternates and is not the
default glyph of another character of the grapheme, so a vowel sign's
glyph that the font also lists as an alternate of the consonant is not
reported for the consonant.
2026-11-05 07:30:43 +07:00
dotCooCoo ea75150131 Menus: Delete Empty Artboards and Save Gradient Preset decide their enabled state with less measuring
The enabled check of artboard.deleteEmpty built the full list of empty
artboards, measuring the visual bounds of the art against every
artboard, each time the Artboards panel menu was drawn. It now returns
false at once in a document with one artboard (that artboard is never
deleted). With two or more, it asks the new
Document::any_artboard_without_art whether any unlocked artboard has no
art, which is the same answer as a non-empty list.

Document::any_artboard_without_art builds the symbol boxes once for all
the artboards and first tests each path and compound path by a quick
box: its control points' box grown by the farthest its strokes reach
(Appearance::outset), with a margin for rounding. An artboard that no
quick box meets is reported empty without measuring along any path.
Only when every artboard may hold art is each one measured.
Document::artboard_has_art also skips measuring an object whose quick
box misses the artboard; its answers are unchanged.

The check of gradient.presets.save found the proxy paints through
Node::proxy_paint, which measures the object's geometric bounds for a
gradient box the check does not use. Node::proxy_paint_only picks the
same paint without measuring, and the engine's proxy_paint uses it, so
the Fill and Stroke proxies and the mixed-paint test no longer measure
each object either.

With an open stroked path of 200,000 anchors selected, the two checks
take under 0.01 ms instead of 21.9 ms and 17.2 ms in a release build, and
Delete Empty Artboards' check takes 0.85 ms instead of 42.1 ms with a
second, empty artboard.

Tests compare each check with what its command does (one artboard, all
empty, one empty, locked empty, nested art; with and without a
gradient), compare any_empty_artboards with the previous check and with
measuring every object on 120 seeded documents, compare the quick boxes
with the visual bounds on seeded strokes, and compare proxy_paint_only
with proxy_paint on seeded objects.

Docs: docs/target-app-parity.md, one line under Delete Empty Artboards.
2026-11-05 06:55:59 +07:00
dotCooCoo 8f8f71f803 Glyphs: the Glyphs query reports the glyph of an overflowing character
text.glyphAlternates reported the default glyph as `chosen` for any
character that overflows its area. A character whose style substitutes
another glyph (`salt`, or `vert` in vertical type) was reported with a
glyph it is not drawn with. The query now shapes such a character alone,
with the rest of its grapheme in their own styles and in the text's
writing direction, by the same helper text.setGlyphAlternate uses.

The helper also shapes the character in the direction its paragraph
sets it in, from its bidi level, so a parenthesis set right to left is
reported with its mirrored glyph in both commands.
2026-11-05 06:55:55 +07:00
dotCooCoo 1968077984 UI-1676: Ignore hidden symbol tint when expanding 2026-11-05 05:54:43 +07:00
dotCooCoo dcefceddf6 UI-1675: Preserve symbol tint when expanding effects 2026-11-05 05:52:34 +07:00
dotCooCoo 92ecb4a6b0 Glyphs: a consonant's ligature in a cluster with its vowel sign is its glyph
Ka with a nukta and the vowel sign I is shaped as one cluster: the vowel
sign's glyph, then the ligature of Ka and the nukta. The ligature is
neither Ka's default glyph nor an alternate, so the lookup found no
glyph for Ka: text.glyphAlternates reported the vowel sign's glyph and
text.setGlyphAlternate reported Ka's default glyph. When the cluster
holds neither, the lookup now takes the first glyph that is not drawn
for another character of the grapheme.
2026-11-05 05:20:03 +07:00
FractalEncrypt 77a86288e7 Transform Each: Relative and Absolute scaling, the scale link, and the documented panel order
Squashed from #5695 onto main.
2026-11-05 04:37:46 +07:00
dotCooCoo 67140d5e54 Glyphs: the Glyphs query reports a consonant's glyph, not its vowel sign's
text.glyphAlternates reported the first glyph of the character's
cluster as the chosen glyph. A vowel sign drawn before its consonant
(Devanagari Ka with the vowel sign I) comes first in that cluster, so
the query reported the vowel sign's glyph for Ka, while
text.setGlyphAlternate reported Ka's own glyph. Both commands now take
the character's glyph by the same rule, and so does the check in
text.setGlyphAlternate that the chosen glyph is drawn.

A character that overflows its area is shaped with its grapheme, and
each character of the grapheme now keeps its own style there, so a
nukta of another size no longer makes a ligature with its consonant
that the laid-out text does not draw. A test font with a Devanagari
nukta ligature checks both.
2026-11-05 04:11:37 +07:00
dotCooCoo af74427ef4 Appearance: edits to the active row reach the matching row in each selected object
Paint and effect edits matched the active row across all selected
objects at once, so one object without an equal row made every object
edit the row at the raw index. ItemTarget::per_target and
effect_targets now match each object against the first one on its own,
as items_per_target does. effect_targets also looks up the row in the
stack it belongs to when deciding whether an effect edit is
object-level, so an effect on a row that sits lower in another object's
stack no longer fails with "no appearance item".
2026-11-05 03:55:55 +07:00
dotCooCoo 0f99ca1895 Gradient: Perceptual PDF help says an RGB destination keeps RGB stops in RGB
The `method` text of `paint.editGradient` and two passages of
docs/mcp.md said a CMYK document writes RGB and Lab gradient stops in
CMYK. An export that converts colors to an RGB destination profile
converts them to that profile first, so in a CMYK document they stay
RGB and a Perceptual spot gradient with such stops is written as an
image with the spot warning. The texts now say so, and the test of RGB
stops in a CMYK document also checks the RGB destination case.
2026-11-05 03:55:52 +07:00
dotCooCoo ed3efcbd7d Render: a long dashed stroke is outlined only near the view after an edit
A dashed stroke of a path with more than 1,024 path elements was outlined
whole in every frame after an edit. It is now outlined in and around the
view like a solid stroke. dash_kept runs the pattern along every segment
and keeps only the dashes and dots on the segments near the view, so they
sit where dashing the whole path puts them and the pixels are the same.
A pattern too fine to draw is still drawn solid, and that solid stroke is
cropped too.

At 1600 x 1200 the frame after one anchor moves takes 14 ms instead of
102 ms on a filled closed path of 50,000 anchors with 6 pt dashes and
4 pt gaps. anchor_bench now includes that document.
2026-11-05 03:55:48 +07:00
dotCooCoo cd71257ac4 UI-5636: Preserve styled Type-range copies on canvas paste 2026-11-05 02:23:51 +07:00
dotCooCoo a5157654f4 Tests: the link-watch and place tests wait for the link scan instead of sleeping
The link-watch worker now signals a condition variable when it ends,
whether it stored its stamps or unwound, and Session::wait_link_scan
blocks until then. The place tests' idle helper waits on it once per look
in place of a 5 ms sleep under a 20 s wall-clock bound, and the engine's
link-watch and link-path tests wait on it in place of spinning under a
10 s bound. The link-watch tests date a rewritten file 2 s after the one
it replaces instead of sleeping 30 ms before writing it.
2026-11-05 02:23:48 +07:00
dotCooCoo 440b3b7444 Glyphs: overflowing vertical type keeps a chosen default glyph
Squashed from #5676 onto main.
2026-11-05 02:23:42 +07:00
dotCooCoo b0d1ca4419 Glyphs: a character with a combining mark reports the glyph it is drawn with
text.setGlyphAlternate looked for the character's glyph only in a
cluster as long as the character. A character followed by a combining
mark is shaped in one cluster with the mark, so the lookup found
nothing: under a substituting feature such as salt, `gid: null`
reported the default glyph instead of the one drawn, and a request for
the default glyph changed nothing.

The lookup now also takes a cluster that holds the character's
grapheme, and in a cluster of several glyphs takes the character's
default glyph or one of its alternates. Text that overflows its area
is shaped with the whole grapheme.
2026-11-05 01:56:16 +07:00
dotCooCoo 584b9706cc Gradient: Perceptual PDF help counts stops as written, CMYK documents included
The method help of paint.editGradient and docs/mcp.md said a Perceptual
gradient with spot stops becomes an image in PDF unless every other stop
is paper white, CMYK or gray. PDF export checks each stop's color as it is
written: a CMYK document, or an export that converts colors to a CMYK
destination profile, writes RGB and Lab stops in CMYK, so the gradient
becomes a DeviceN shading. Both texts now say so, and a test covers the
CMYK document and CMYK destination cases.
2026-11-05 01:31:24 +07:00
dotCooCoo be8438c13d Tabs: setting the stops a paragraph already has ends the typing session
text.tabs.set and text.tabs.clear return without an edit when every
targeted paragraph already holds the stops. That path skipped the
settlement Session::edit does first, so a typing session in progress
stayed open. The command now ends it first, as the Variables commands
do: the typing is its own undo step whether or not the stops change.
2026-11-05 00:55:35 +07:00
datatimp 1a1285fecd Merge remote-tracking branch 'upstream/main' into fix/3260-halftone-radius-pixels
# Conflicts:
#	crates/doc/src/limits.rs
#	crates/engine/src/cmd/fileio/tests_pdfedit.rs
#	crates/format/src/lib.rs
#	docs/target-app-parity.md
2026-11-04 12:30:23 -05:00
dotCooCoo f026ebe686 Tests: an RGB spot color converts with Document Color Mode and stays spot
A spot swatch defined in RGB keeps its spot flag and its own plate when
the document changes to CMYK, and its definition converts like any other
swatch: a fill that uses it and a 40% tint stroke take the converted
color. The Lab spot test's comment now says it covers a Lab definition.
2026-11-04 23:58:58 +07:00
dotCooCoo fae49d31fd Glyphs: the default glyph can be chosen back under a substituting feature
Follows #5442.

- text.setGlyphAlternate keeps the default glyph as a choice when a
  feature of the character's style (salt, a stylistic set) draws another
  glyph for it, so the default glyph is drawn. A character that is not
  laid out (overflowing text) is shaped alone in its style to decide.
  gid: null reports the glyph the style draws.
- The Glyphs panel's alternates grid shows the default glyph first when
  the font does not list it, so a chosen alternate can be put back.
- A test for a chosen character that starts a longer grapheme (f with a
  combining acute), which is not split from its mark.
- The alternates tests in the engine hold the shared font lock while
  they add fonts to the global font database.
2026-11-04 23:58:54 +07:00
dotCooCoo a9eae3a333 Appearance: Add New Fill and Add New Stroke comment names the paint they take
The comment in add_item said a new fill or stroke is a copy of the top
one. The code takes only the top item's paint, and for a stroke its
weight. The comment now says so, as the params text does.
2026-11-04 23:44:58 +07:00
ruchirguitarandClaude Opus 5.5 6e1c1c9377 Select by Artboards: test that a symbol instance is measured by its art (#5525)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 22:57:59 +07:00
ruchirguitarandClaude Opus 5.5 7e016a0bcc Select by Artboards: select objects overlapping, inside or outside several artboards (#5525)
addon.select.byArtboards {artboards, relation} in a new Selection Tools
add-on. Overlapping is All on Active Artboard's test, now one shared
helper (select::on_artboard); Fully inside is within one artboard, edges
included; Fully outside is on none. Objects are those Select All takes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 22:57:57 +07:00
dotCooCoo aee5671734 File formats: Pixar tile pointers into the header or tile table are refused
A nonzero tile pointer below the end of the tile pointer table made the reader decode header or table bytes as pixels. The table end is now computed with checked arithmetic, and such a pointer is refused as damaged image data.
2026-11-04 22:57:53 +07:00
dotCooCoo 88b5170622 Glyphs panel: alternates for the current text selection
Squashed from #5442 onto main.
2026-11-04 22:29:53 +07:00
dotCooCoo 0990bfb244 .ai save: the editing copy keeps transparency, clipping and opacity masks
The editing copy of the art that a PDF-compatible .ai carries now holds:

- Transparency: `mode opacity isolate knockout shape Xy` (the blending
  mode's number, Knockout Group 0 off, 1 on, 2 neutral), written when it
  changes: in a path's paint after its colors, before a guide, and after
  a group's end followed by `0 0 Xd` and `6 () XW`. A group without
  transparency of its own ends `9 () XW`, and a group's name comes
  before its state block. A layer's transparency follows its art: `Xy`,
  `0 0 Xd`, `7 () XW`, `LB`.
- Clipping groups as `q`, the art, the clipping path or compound path last
  with `h` (or `H`) and `W` before its painting operator, `Q`, as section
  5.6.2 of the version 7 specification shows them
  (http://mercator.elte.hu/~saman/hu/okt/AI7FileFormat.pdf). A clipping
  layer whose clipping object is a path or compound path sets the last
  `Lb` flag and writes its clipping path last.
- Opacity masks as an `AI9_Mask` entry in the object's dictionary: the
  mask's art between `X=` and `X+`, and Clipping, Inverted, Disabled and
  Linked.

Before, clipping groups were written as their art cut to the clipping
path, and transparency and opacity masks were left out. Still left out,
with a warning: the opacity and blending mode of single fills and
strokes, opacity masks on layers (disabled ones too), and opacity masks
nested more than 8 deep. A clipping group or layer whose clipping object
isn't a path or compound path is written as a group of the art cut to
that object, in a layer that doesn't clip, and so are the clipping
groups inside that art. A clipping path's paint that a plain fill and
line can't draw is written as paths inside the clipping, fills under the
art and strokes over it, each side in a group of its own when it has
several, with the clipping path's transparency, lock and hidden state;
the clipping path's opacity mask stays on the clipping path, with a
warning. A clipping group without members is an empty group, and an
empty clipping layer is an empty layer.

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

Reading .ai editing data: an `Xy` after a layer's last group or compound
path, followed by the layer's `7 () XW`, is the layer's (a following
`6 () XW` keeps it the group's); groups, compound paths and layers keep
Opacity & Mask Define Knockout Shape.

The `.ai` option `editingData` and docs/file-format-parity.md describe
what the copy now holds.
2026-11-04 22:29:43 +07:00
d8abyte-dkandClaude Opus 5.5 b9594b233c Plug-ins: color parameters, and filters that make guides and lock
A `color` parameter shows a color button that opens the color picker in plug-in
dialogs and the Appearance panel's effect editor; its default and values may be
a color object or a hex string, and the plug-in gets a color object. A filter's
returned objects may set `guide` and `locked`; objects it locked or made guides
are left out of the selection after the run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 22:29:38 +07:00
dotCooCoo 3c80b314e1 Select: All on Same Layers takes the layers of objects that can be selected
Select > Object > All on Same Layers took the layer of every selected
object, including one that select.set had kept while it is hidden or
locked, on a template layer, on a locked artboard, or outside the
isolated group. That object's layer then decided which art was
selected. The command now takes the layers only of the selected
objects that the Select commands could select. When the selection
holds no such object, it clears the selection.
2026-11-04 22:29:22 +07:00
dotCooCoo eb03e8943f Gradient: PDF shading notes name linear and radial gradients and DeviceN
The PDF writer writes a spot gradient as a Separation or DeviceN shading
only when it is linear or radial; freeform gradients and dithered fills
are written as images in process colors.

- `paint.editGradient`'s method help and the Method paragraph in
  docs/mcp.md limit the Perceptual exception to linear and radial
  gradients.
- The Linked gradient stops paragraph in docs/mcp.md no longer says the
  writer has no DeviceN: a gradient mixing spot inks with other spot,
  CMYK or gray inks exports as a DeviceN shading, and only a mix with RGB
  or Lab colors is written in process colors, with a warning.
2026-11-04 21:58:59 +07:00
dotCooCoo be52e4e8af Tabs: setting the stops a paragraph already has records no undo step
text.tabs.set and text.tabs.clear return without an edit when every
targeted paragraph already holds the stops. A Ctrl-drag that the 0 pt
bound keeps from moving, or a drag released where it started, no longer
adds an undo step that changes nothing. When one targeted paragraph
holds other stops, the command still sets them all.
2026-11-04 20:51:10 +07:00
dotCooCoo 535d423d6c Appearance: Add New Fill and Add New Stroke params text match the code
appearance.addFill copies the active fill row only when the call has no
`ids`, no `id` and no `target: "contents"`; the params text now names
`id` too. appearance.addStroke gives the new stroke at least 1 pt, so a
0.5 pt top stroke gives a 1 pt stroke; the params text now says so.

Tests pin both: `id` alone leaves the active row alone and puts the new
fill on top, and Add New Stroke on a 0.5 pt stroke adds a 1 pt one.
2026-11-04 20:51:07 +07:00
dotCooCoo dd41552c30 PDF export: warn about spot stops in freeform gradients without points
A freeform gradient whose field has no points of its own takes its
colors from the stops, so spot-linked stops in it are written in
process colors too. The export now warns in that case, as it does for
the other gradients drawn as images.
2026-11-04 20:36:11 +07:00
Don Omondi 33b57fb581 Batch Trace Folder: move to Object › Plug-ins as an add-on
Batch Trace Folder replaces a script, so it is now a Document Tools
add-on command, addon.document.batchTraceFolder, under Object ›
Plug-ins › Document Tools (as Export All Open Documents is), and no
longer in Object › Image Trace. Behaviour, caps and the refusal of a
folder too big to list in full are unchanged; the tests move with it.

The status messages have @msgplural rows in every catalog, as does the
menu label. When some images trace and some don't, the status is one
counted message ("Traced {n} images; not traced: {failed}") so it
translates as a whole.
2026-11-04 20:12:07 +07:00
Don Omondi 7790c37eb3 Batch Trace Folder: refuse a folder too big to list in full
list_dir cuts its listing before sorting, so a cut listing could skip any image. The batch now
stops with an error instead of tracing part of the folder.
2026-11-04 20:12:06 +07:00
Don Omondi 7c04fd8973 Fix #4921: Image Trace > Batch Trace Folder
imageTrace.batchFolder opens each image in a folder, traces it with a
preset (optionally expanded), saves it into a destination folder under
its own name (vectorcraft, svg, pdf, ai or eps; taken names numbered so
nothing is replaced) and closes it again whether it traced or not; the
active document stays active. Object > Image Trace > Batch Trace Folder
asks for both folders. Not on the web.
2026-11-04 20:12:05 +07:00
Don Omondi ed634a78f4 Guide clipboard: Paste after a guides-only Copy takes the guides, not older system clipboard content
A Copy of ruler guides alone left the system clipboard as it was, so the
next Paste took whatever another app had copied before instead of the
guides. The guides-only Copy now empties the system clipboard (on the
web, empty text through egui with Copy As SVG on), as any Copy replaces
what the clipboard held, and drops an earlier Copy's formats not written
yet. What another app copies afterwards still pastes.
2026-11-04 20:12:01 +07:00