Commit Graph
11985 Commits
Author SHA1 Message Date
BFlat a6aac579c0 Merge pull request #6904 from dotCooCoo/feat/ai-editing-data-s6c
.ai save: the editing copy keeps brushes and brushed paths
2026-11-12 23:53:38 +07:00
BFlat ab50f06909 Merge pull request #6914 from dotCooCoo/fix/kept-tiles-test-flake
Render tests: the kept-tile decode-failure test passes while other tests add fonts
2026-11-12 23:53:22 +07:00
BFlat e618783377 Merge pull request #6084 from Taha-Mahmoodi/feat/glyph-alternates
Glyphs: alternates keep the word joined (feature values, one-piece shaping, unencoded glyphs)
2026-11-12 23:53:13 +07:00
BFlat 1c50241ddd Merge pull request #6702 from danngreen/fix/mac-cursor-after-move
macOS: the canvas cursor stays after the pointer moves (#6362)
2026-11-12 23:53:03 +07:00
BFlat 5f3c7f5425 Merge pull request #6906 from ruchirguitar/fix/pdf-indic-text-5235
PDF import: Indic type that would not draw as the file does keeps the file's glyphs (#5235)
2026-11-12 23:52:49 +07:00
dotCooCoo 89e52eaabc MCP: a folder preference is checked as trimmed, and only a %XX escape is decoded
Under automation read roots, `ui.inspect` kept a folder preference whose
stored value was readable even when the trimmed path the app uses was
not: ` /outside/fonts` reads as a name in the working folder, while the
app uses `/outside/fonts`. A folder preference now stays only when both
forms are readable. A reply string is decoded for path matching only when
it holds a `%XX` escape, so a string such as `width="100%"` is no longer
decoded and thrown away. The library list line in the progress doc now
states when a hidden library's `loaded/<file name>` id moves.
2026-11-12 08:50:46 -08:00
dotCooCoo 0ae706c592 Docs: the file-format doc's editing-copy paragraph and summary rows appear once
docs/file-format-parity.md held 36 copies of the paragraph on the
editing copy of a file. #6202 and #6249 each added a combined copy
without removing the copies it replaced, so the count went from 34 to
35 and then to 36. The section now holds one copy: #6249's combined
copy, with the Align to Path distance clause that seven of the other
copies carry from #6247. Every other clause of the removed copies is in
the kept one, word for word or in the newer, longer form another copy
wrote. The older Align to Path clause, with its measurements for one
font at 24 pt, is removed because #6247's wording replaces it. The
paragraph now starts with a capital letter.

The summary table also repeated its "Formats opened or placed" and
"Formats saved (Save As)" rows. The older row of each is removed: the
one that still lists HEIC/HEIF as missing, and the one that lists fewer
contents of the editing copy that `.ai` saves write.
2026-11-12 08:50:41 -08:00
dotCooCoo 9df4a83f07 Merge main into feat/blend-canvas-easing-handles 2026-11-12 08:46:06 -08:00
dotCooCoo fc1a08edbd Merge main into feat/brushes-ink-wash-library 2026-11-12 08:46:00 -08:00
dotCooCoo 5006ba5a2e Merge main into feat/eps-save-use-artboards 2026-11-12 08:45:42 -08:00
dotCooCoo 1bb6582194 .ai import: cite the sources of the Distort & Transform effect keys
The doc comments of the Transform, Free Distort, Tweak and Zig Zag
readers, and the Pucker & Bloat and Twist arms, now name the public
pages that list each effect's dictionary keys. No code changes.
2026-11-12 08:38:10 -08:00
dotCooCoo 66f6be77ee .ai save: RGB and named colors keep their CMYK equivalents when a reopened file is saved
The .ai writers write RGB and Lab values to four decimals next to a CMYK
equivalent, but converted that equivalent from the color at full precision.
When a file was read back and saved again, its CMYK equivalents differed in
the fourth decimal (for example 0.6831 and 0.6832). In the editing data this
affected plain RGB colors, RGB gradient stops, global process and spot colors
and the header's custom colors; in the legacy .ai writer it affected RGB
gradient stops.

The CMYK equivalent of an RGB color, and of a global process or spot color,
is now converted from the values as they are written, so both saves convert
the same values. Lab values of global process and spot colors are now written
clamped to the range the reader reads (L 0 to 100, a and b -128 to 127).

A plain Lab fill or stroke and a Lab gradient stop are still written as RGB
with a CMYK equivalent converted from the Lab values. The reopened file holds
them as RGB, so their CMYK equivalents change once on its next save.

The art style round-trip test now compares the program exactly; its blanked
CMYK values and the four-decimal tolerance are no longer needed.
2026-11-12 08:35:39 -08:00
dotCooCoo cc761c359e Color: a recent color drags into the Swatches panel to become a swatch
A Recent Colors chip in the Color or Swatches panel now starts a paint
drag. Dropped on the Swatches panel's list it becomes a swatch of its
color, in its color model, through swatch.new as one undo step: on a
color group or one of its swatches it joins that group, elsewhere it
joins the ungrouped swatches. A click on a chip still paints the
selected art, and a drag does not.

A paint Alt-dropped on Registration now becomes a new swatch instead of
ending in a "can't be edited" error from swatch.edit.
2026-11-12 08:35:15 -08:00
dotCooCoo 766e291e3c Save and Export: notes of what the file loses come before notes on options
Each writer marks its notes as a loss (something of the document that the
file leaves out or that reaches it changed) or as a note on the options
(an option it didn't apply or applied another way while the art reaches
the file as it looks, or something an option turns off). The PDF, SVG,
EPS, legacy .ai, DXF and HP-GL writers return their notes on the options
in a list of their own (`setting_notes`) beside `warnings`, and the
engine's `Encoded` does the same.

The replies of the save and export commands, and of
`clipboard.exportPdf` and `clipboard.exportPng`, list the losses first,
each kind in the order the writers gave them, across every file that
Export for Screens writes. The status bar names the first note, so an
export to lossy WebP of type in a font that isn't installed now names the
fallback-font note instead of the lossy WebP note. A print to a file
keeps the order its notes are given in.
2026-11-12 08:33:57 -08:00
dotCooCoo ff6dac4a5d Shaper: a click on an original shape's outline enters Construction mode
With a Shaper Group or one of its faces selected, a Shaper click within
3 screen pixels of one of the group's original shapes' outlines enters
Construction mode with that shape selected, also where the outline runs
through a merged face. shaper.select takes a tolerance in points
(default 3, at most 1000); hidden and locked shapes are skipped, and a
Shaper Group above the selected one still takes the click.
2026-11-12 08:33:29 -08:00
jmverges e0c5b0818a Merge remote-tracking branch 'upstream/main' into fix/ai-type-pattern-paint
# Conflicts:
#	docs/file-format-parity.md
2026-11-12 16:30:04 +00:00
dotCooCoo a17acb852f Selection: Show Bounding Box While Moving and Drawing shows the box during moves and shape drawing
The new General preference Show Bounding Box While Moving and Drawing
(`boundingBoxWhileMovingAndDrawing`, off by default) keeps the bounding
box and its handles visible during two kinds of drag, with View › Show
Bounding Box on. While a drag moves the selection (a Selection tool
move, an Alt-drag copy, or a shape tool's move by the center point),
the box is drawn where the drag has moved the selection. The box is
measured once when the drag starts and offset by each step's move.
While the Rectangle, Rounded Rectangle, Ellipse, Polygon and Star tools
draw a shape, the box is drawn around the shape. A rotation and a
widget drag still hide the box until the release. The Line Segment
tool, the Pen, the Pencil and the Paintbrush draw no box.

With the preference off, the box hides during a move (#737, for #712)
and while a shape is drawn (#5839), as before. A Selection tool move
with Real-time Drawing off still moves the box with the pointer, and a
shape tool's move by the center point hides it in both modes.

With Real-time Drawing off, the box of a shape being drawn is measured
from the pending preview, in the color of the layer the shape goes on.
A shape being drawn shows no box until a preview step has succeeded,
so a failed preview does not show the box of the selection from before
the drag. The preference's label has a row in every catalog.

Session::deferred_move() is replaced by Session::move_drag_box(), which
returns the moved box, and Session::deferred_transform_box() now also
returns the layer color of the box.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-12 08:28:21 -08:00
dotCooCoo 1bf8bce083 Actions: Begin Recording params name the command that passes a limit only as it runs
ui.action.record's params text now says that a recorded command whose
step passes a limit only from the values it adds as it runs keeps its
edit and result, that later recorded commands are an error and do not
run, and that ui.action.stop leaves its step out.

crates/mcp/src/ui_catalog.rs now matches the desktop table again
(cargo xtask ui-commands --check), including the action-limit params
texts of the earlier commit.
2026-11-12 08:27:21 -08:00
dotCooCoo a5541ab42a Blend: steps of brushed strokes interpolate the pen pressure, tilt and angles
A blend between two strokes drawn with a pressure-sensitive brush gave
every step the pen recording of the nearer key, so the brush jumped at
the middle step. The steps now interpolate the pressure, tilt, bearing
and rotation at every position either key has a sample. A key without a
recording counts as half pressure, half tilt and 0 degrees, as brushes
read it. Angles turn the shorter way round, and steps and whole turns in
a recording stay in the steps. Different brushes still switch halfway.
2026-11-12 08:26:32 -08:00
BFlat 932830283d Merge pull request #6841 from dotCooCoo/feat/docinfo-spot-color-objects
Document Info: Spot Color Objects lists the objects that use spot colors
2026-11-12 23:10:59 +07:00
BFlat b85f546ace Merge pull request #6893 from dotCooCoo/test/command-sweep-path-keys
Plug-ins: `diffPath` is a file key and Slice Options' `url` is not; the command sweep uses these keys
2026-11-12 23:10:48 +07:00
BFlat fbcf7e9f5f Merge pull request #6879 from dotCooCoo/fix/palette-opens-menu-dialog
Palette: a pick opens the dialog its menu item opens
2026-11-12 23:10:36 +07:00
BFlat cc6509827d Merge pull request #6878 from dotCooCoo/fix/opacity-mask-follows-reshape
Opacity masks: linked masks follow group effects, the Free Transform distort and envelopes
2026-11-12 23:10:24 +07:00
dotCooCoo 45dd24d905 .ai save: a stroke the object's art style keeps no longer warns
A path with an effect, or a path linked to a graphic style, can have a
solid stroke a plain line can't draw, such as one with a width profile.
When the reader reads the path back from an art style, the path is
written with that style, and the style holds the stroke. The path's
drawn look still writes the stroke as a filled outline, and the save
warned that such strokes are written as filled outlines.

The warning is now left out while a drawn look is written, as the
effects warning already is. A styled group's style holds no fills or
strokes, and its members are written again after the look, so a
member's stroke still warns. Strokes that no art style holds (gradient
or pattern strokes, for example) still warn.
2026-11-12 08:10:15 -08:00
BFlat 0cb73d0d66 Merge pull request #6845 from dotCooCoo/feat/linux-screen-color-portal
Color: Sample Color from Screen works on Linux through the desktop portal
2026-11-12 23:10:13 +07:00
BFlat 3df161a972 Merge pull request #6903 from dotCooCoo/feat/gradient-repeat
Gradients: repeat or reflect a gradient's stops a set number of times
2026-11-12 23:10:02 +07:00
BFlat 12d72b3eb0 Merge pull request #6901 from dotCooCoo/fix/trace-smooth-area-contours
Image Trace: band borders in smooth areas follow the image's contours
2026-11-12 23:09:43 +07:00
BFlat 4920df33c0 Merge pull request #6885 from dotCooCoo/fix/screens-preset-folder-background
Export for Screens: an export into a preset's folder runs in the background
2026-11-12 23:09:16 +07:00
BFlat 39045f8542 Merge pull request #6778 from dotCooCoo/fix/warp-styles-map
Warp: bend each style as one Bézier patch, and keep saved warps' look
2026-11-12 23:09:04 +07:00
BFlat da3affd8bf Merge pull request #6897 from dotCooCoo/fix/number-wheel-smoothing-tail
Number fields: the rest of a wheel notch a field took no longer scrolls the panel
2026-11-12 23:08:54 +07:00
BFlat 3a1426eff3 Merge pull request #6898 from dotCooCoo/feat/justify-cluster-gap
Type: letter spacing and Full Justify keep shaped clusters together
2026-11-12 23:08:43 +07:00
BFlat a38903aa72 Merge pull request #6900 from dotCooCoo/feat/global-edit-highlight-similar
Global Edit: selecting one object highlights the similar objects before the start
2026-11-12 23:08:32 +07:00
BFlat f43d00aa11 Merge pull request #6902 from dotCooCoo/fix/eps-named-cid-show-operators
EPS import: charpath, cshow, kshow and glyphshow read named CIDFont type by its CMap
2026-11-12 23:08:23 +07:00
dotCooCoo 2defb49002 Font menu: one wide layout wherever it opens, with larger samples
The font menu opened at its field's width, so from the Control bar's narrow
Character field the filters wrapped one chip per line and family names were
cut off after a few letters.

- The filters keep the same four rows wherever the menu opens: the scripts;
  the star, Any Kind, Serif / Mincho, Sans Serif / Gothic and Rounded;
  Script / Brush, Monospaced and Decorative; Font Technology with Variable.
- The menu opens at least wide enough for those rows and for a family name
  up to 220 points wide with room for its sample, up to 60% of the window,
  and stays in the window. A field wider than that keeps its width.
- Where the row has room, the sample starts after the widest name instead of
  halfway along the row. It takes the row's whole height instead of 4 points
  less, so samples draw larger at every Font Preview Size.

Requested by POGO.
2026-11-12 08:06:24 -08:00
dotCooCoo 71851c251f Render tests: the kept-tile decode-failure test passes while other tests add fonts
pattern::tests::kept_tiles_count_the_images_they_could_not_decode
draws a pattern whose art is an image three times and expects one tile
to be rasterized. A tile of art with an image is kept only while
FontDb::global().generation() is the one it was drawn at (Deps::current
in pattern.rs). The render tests that hold adding_fonts() add fonts,
which increases it (tests/fontchange.rs, tests/typeedges.rs,
tests/alternate.rs, tests/colrglyphs.rs and tests/bitmapglyphs.rs).
When one of them added a font between the frames, the next frame drew
the tile again and the test failed with left 2 or 3, right 1. Run with
the tests in tests/fontchange.rs and tests/typeedges.rs, it failed in
23 of 30 runs on main.

The test now holds fonts_steady() and takes its counts from
with_fonts_unchanged(), as the other render tests that count kept work
do. Each run builds a new document, so its first frame does not find a
tile from an earlier run. Run with the same tests, it passed in all 30
runs.
2026-11-12 08:02:32 -08:00
dotCooCoo e242eeb609 Actions: progress doc names the command that passes a limit only as it runs
A recorded command whose step passes a limit only from the values it adds
as it runs keeps its edit. The status bar names the limit, later recorded
commands do not run, and Stop Playing/Recording leaves its step out.
2026-11-12 08:01:39 -08:00
dotCooCoo d3b18465f9 New Document: file.new and artboard.new take the same largest artboard side
file.new refused a side over 163,830 pt, while artboard.new took larger
artboards. Both now take each side more than 0 and at most 3,999,856 pt:
the 4,000,000 pt the canvas reaches from the origin, less a 72 pt bleed
on both sides. A side outside that range is refused with an error that
names the limit in points and, when the document's units are not points,
in those units, rounded down so the value shown is accepted.

artboard.new now refuses a supplied width or height of 0 or less instead
of making a 1 pt side, and refuses a size taken from a larger artboard.
Saved and Recent presets are read with sides up to the new limit.

Follows #6643.
2026-11-12 07:45:32 -08:00
makesomethingshit c36f863073 Merge upstream/main into fix/6865-ai-oversized-artboard 2026-11-13 00:44:37 +09:00
dotCooCoo 5a8cb30259 3D and Materials: Expand as Wireframes reshapes edges by the effects after the 3D effect drawn
With two 3D effects on an object, the geometry effects after the first one
reshaped the edges, even when the second one (Revolve, which is drawn first)
built the faces. A geometry effect between the two then moved the profile and
the edges both. The edges now take only the effects after the 3D effect that
built them.
2026-11-12 07:44:35 -08:00
dotCooCoo fc8d4472e6 Color management: assigning the working profiles keeps the active color settings
edit.assignProfile replaced the active color context whenever it tagged a
document, even when the profiles it assigned were the working spaces
already in use. The new context has the same settings, but renderers key
their cached effect images on it, so every open document was redrawn and
every cached blur, shadow or glow image was drawn again.

The command now sets the active settings, and raises the open documents'
revisions so they redraw, only when the working spaces it assigns differ
from the active ones, as edit.colorSettings already does.

This also fixes an intermittent failure of the test
canvas::tests::a_drag_over_a_wide_blur_draws_the_blur_from_the_still_frame.
The Document Setup tests assign the working profiles while it runs, and
its drag frames then drew the blur again instead of reusing the still
frame's image.
2026-11-12 07:34:57 -08:00
dotCooCoo 55a80ca480 3D and Materials: Expand as Wireframes looks up swatches for plug-ins after a fill's 3D effect
A live-effect plug-in after a fill's or stroke's 3D effect (Extrude & Bevel,
Inflate, Rotate or Revolve) that links its pieces to a swatch or pattern was
run without the document, so its result was refused and the edges kept the
shape before it. The document now goes to those effects, as it does for the
effects after an object's 3D effect.
2026-11-12 07:31:39 -08:00
ruchirguitar b732d4f4b2 Merge remote-tracking branch 'upstream/main' into fix/pdf-indic-text-5235
# Conflicts:
#	docs/file-format-parity.md
2026-11-12 21:01:38 +05:30
dotCooCoo 04fd1b127b Brushes: Art Brush Options' Width can follow the pen's tilt, bearing and rotation
The Width menu now offers Tilt, Bearing and Rotation beside Fixed and
Pressure, each with the second width. Tilt goes from Width with the pen
lying flat to the second width upright; Bearing and Rotation go from
Width at -180 degrees to the second width at 180 degrees, as Scatter
Brush Options' modes do. A stroke drawn without that input is half way
between the two widths. brush.options takes width_mode tilt, bearing
or rotation.
2026-11-12 07:28:26 -08:00
dotCooCoo 2e968acc47 Align: the Align panel aligns and distributes the selected artboards
With the Artboard tool chosen, the Align panel's Align Objects,
Distribute Objects and Distribute Spacing buttons, their UI commands and
the Control bar's Align and Distribute buttons act on the artboards the
tool has selected, as the public page describes:
https://helpx.adobe.com/illustrator/desktop/create-manage-artboards/organize-manage-artboards/align-and-distribute-artboards.html

- artboard.align, artboard.distribute and artboard.distributeSpacing
  move whole artboards with their guides, and with the art inside them
  when Move Artwork with Artboard is on, in one undo step. No undo step
  is recorded when no artboard moves.
- Align To offers Align to Selection and Align to Artboard. Align to
  Artboard keeps the active artboard in place, and the Distribute
  buttons then send the Distribute Spacing value. A locked artboard
  stays where it is. These rules are VectorCraft's own.
- The Control bar shows the Align buttons, the Align To menu and the
  Distribute buttons after the artboard controls while it has room.

Docs: docs/mcp.md, docs/ui-parity.md.
2026-11-12 07:28:16 -08:00
ruchirguitar f18fb4e92d PDF import: Indic type that would not draw as the file does keeps the file's glyphs (#5235)
Gujarati text from a PDF came in jumbled even with its fonts installed:

- A glyph with no advance (a vowel sign or anusvara set over its letter)
  was taken for vertical type and opened as an object of its own, which
  type then drew on a dotted circle. In a font the file writes
  horizontally it now stays on its line.
- A line read glyph by glyph is not always the text that was set: the
  file draws a vowel sign before the consonant it follows, and may not
  name a conjunct. A line with characters of U+0900 to U+0DFF is now set
  again and its glyphs compared with the ink the file drew; when they
  differ the line keeps the file's glyphs as outlines, with a note.

Tests: crates/pdf/src/tests/reshaped.rs (two fail without the change).
2026-11-12 20:56:16 +05:30
Taha-Mahmoodi 2d62c35d69 Merge remote-tracking branch 'origin/main' into feat/glyph-alternates
# Conflicts:
#	docs/gaps.md
#	docs/roadmap.md
#	docs/target-app-parity.md
2026-11-12 19:55:05 +04:30
dotCooCoo 5d40a1c6d0 View: the art keeps its size at a zoom whatever the UI Scaling
Preferences > User Interface > UI Scaling sets egui's zoom factor, and the
canvas mapped one document point to one of the interface's points at
100%. A document point then covered UI Scaling times as many device pixels,
so the art grew and shrank with the interface.

The canvas now maps the document at the view's zoom divided by the UI
zoom (View::screen_zoom, Xf::at). The rendered frame, the pointer, rulers,
grids, Fit and Actual Size, pan, scroll, zoom and turn about a point, the
Zoom tool's marquee, Pixel Preview's check, tiled panes, the Navigator's
view box and the tools' tolerances use that mapping. The zoom value means
the same at every UI Scaling, and the interface still follows UI Scaling.
fit_zoom, zoom_about, rotate_about, pan_pixels and scroll_by take the UI
zoom, and Xf::new is now test-only.

Found while looking into a report by bortek about the art's size at 100%.
2026-11-12 07:24:43 -08:00
BFlat 10ea235ee4 Merge pull request #6659 from ruchirguitar/fix/numfield-short-drag-1326
Numeric fields: a sub-threshold pointer movement keeps its caret (#1326)
2026-11-12 22:21:11 +07:00
dotCooCoo fd81eae9b5 Type: text.create and the type style commands refuse a size outside 0.1 to 1296 pt
text.create clamped a size above 1296 pt to 1296 without an error, so a
request for 2835 pt type returned 1296 pt type. text.createInPath,
text.setStyle and text.setRangeStyle clamped the same way. Each now
refuses a size outside 0.1 to 1296 pt with "`size` must be from 0.1 to
1296" and changes nothing. Both ends of the range are still taken.

Follows #6643.
2026-11-12 07:20:37 -08:00
dotCooCoo fa0a0753bb Merge main into feat/weed-box-and-lines 2026-11-12 07:20:06 -08:00