Commit Graph
1460 Commits
Author SHA1 Message Date
BFlat 7553c1f679 Merge pull request #7182 from dotCooCoo/feat/objects-on-path-detach
Objects on Path: Detach takes the chosen object off the path
2026-11-14 00:51:59 +07:00
BFlat c7adea5518 Merge pull request #7144 from dotCooCoo/fix/script-line-numbers
Scripts: $.line and $.stack give the line of the file the code is in
2026-11-14 00:51:19 +07:00
BFlat e41ef1ea62 Merge pull request #7148 from dotCooCoo/fix/blend-without-spine-widget
Blend: a blend without a spine shows the Appearance widget
2026-11-14 00:51:09 +07:00
BFlat 4f0d3f1eb3 Merge pull request #7111 from dotCooCoo/fix/freehand-tolerance-low-zoom
Pencil: Fidelity keeps its screen size at low zoom
2026-11-14 00:50:47 +07:00
BFlat 637d51df79 Merge pull request #7143 from dotCooCoo/feat/guides-layer-rows
Layers: ruler guide rows have their own eye and lock, and go to the trash
2026-11-14 00:50:35 +07:00
BFlat 8db4fe00dc Merge pull request #7179 from dotCooCoo/fix/place-read-own-document
Place: a file read apart from the session goes only into its document
2026-11-14 00:50:27 +07:00
BFlat 1f67fa13a5 Merge pull request #7190 from dotCooCoo/fix/item-4475
Expand: type reports a gradient only when Fill expands one of its outlines
2026-11-14 00:50:08 +07:00
BFlat 4f58b83c75 Merge pull request #7118 from dotCooCoo/fix/painted-effect-every-item
Effects: a later painted effect runs on every fill and stroke a piece returns
2026-11-14 00:49:38 +07:00
BFlat c1c06a839a Merge pull request #7183 from dotCooCoo/feat/pdf-long-pages-points-default
PDF: pages longer than 200 in are written at full size in points by default
2026-11-14 00:49:30 +07:00
BFlat 60fd4bd644 Merge pull request #7090 from dotCooCoo/feat/pixel-snapping-options
View: Pixel Snapping Options choose whether Snap to Pixel snaps drawing, moving and scaling
2026-11-13 23:58:35 +07:00
BFlat 6a1b4c42de Merge pull request #7040 from dotCooCoo/fix/nested-link-ids
Links: list and manage linked art in symbols, graph designs, patterns and masks by id
2026-11-13 23:58:20 +07:00
BFlat 4c135b0ab8 Merge pull request #7165 from dotCooCoo/fix/trace-current-pixels
Image Trace: a background trace applies only to the pixels it traced
2026-11-13 23:31:46 +07:00
BFlat e74c2d04df Merge pull request #7083 from dotCooCoo/fix/simplify-line-keeps-tangent
Simplify: a refitted curve becomes a line only when its joins stay smooth
2026-11-13 23:31:37 +07:00
BFlat 4c072b320c Merge pull request #7136 from dotCooCoo/fix/command-batch-artboards
Artboards: a batch's Fit to Artwork Bounds step fits every selected artboard
2026-11-13 23:31:28 +07:00
BFlat 538e471783 Merge pull request #7163 from dotCooCoo/feat/live-paint-bucket-cursor
Live Paint: the bucket shows a filled bucket over a face and a brush over an edge
2026-11-13 23:31:19 +07:00
dotCooCoo bc7eddeb5d Expand: type reports a gradient only when Fill expands one of its outlines
object.expand.info reported a gradient (and a fill) to expand for any
type whose characters have a gradient fill. Expand outlines type first,
and each outline then holds the run's gradient on its own box, so a
gradient that repeats or reflects in more than 256 runs across every
outline stays a gradient: the dialog enabled options that changed
nothing.

- The query now measures the paths type.createOutlines makes of the
  glyphs, ruby glyphs and underline and strikethrough bars, each with
  its run's paint, and reports a gradient when one of them expands. It
  lays the text out only when a run has a gradient fill, stops at the
  first outline that expands, and does not change the document. Type in
  symbol art, blends and repeats goes through the same check.
- docs/mcp.md says when gradient is false; docs/target-app-parity.md
  gets an evidence line.
2026-11-13 08:27:09 -08:00
dotCooCoo d41cf0d053 Merge main into feat/objects-on-path-detach 2026-11-13 08:26:49 -08:00
BFlat 43d0b50760 Merge pull request #7157 from dotCooCoo/fix/remove-anchors-one-pass
Paths: Remove Anchor Points removes many anchors of a subpath in one pass
2026-11-13 23:15:10 +07:00
dotCooCoo c764652469 Merge main into fix/script-line-numbers 2026-11-13 08:14:59 -08:00
dotCooCoo 4b695aafb1 Merge main into fix/painted-effect-every-item 2026-11-13 08:12:58 -08:00
dotCooCoo 3348b41796 Merge main into fix/freehand-tolerance-low-zoom 2026-11-13 08:12:01 -08:00
dotCooCoo cd7e209934 PDF: pages longer than 200 in are written at full size in points by default
PDF export without a PDF/X or PDF/A standard writes pages longer than
200 in at full size in points instead of with a UserUnit scale.
longPagesInPoints is now on by default in PdfSettings, the built-in
presets and the Save PDF dialog. Turning it off writes such a page with a
UserUnit from PDF 1.6 on, as before. PDF/A-2b files keep the UserUnit,
and .ai saves keep it unless longPagesInPoints: true is passed.

Docs: params text, docs/mcp.md, docs/target-app-parity.md.
2026-11-13 08:10:42 -08:00
dotCooCoo e13384ebb4 Merge main into fix/blend-without-spine-widget 2026-11-13 08:06:40 -08:00
BFlat 6326acb122 Merge pull request #7070 from dotCooCoo/feat/recolor-prominent-colors
Recolor Artwork: the Prominent Colors bar weighs the art's colors
2026-11-13 23:05:19 +07:00
BFlat d26413c3fb Merge pull request #7117 from dotCooCoo/fix/smooth-tool-smooths
Smooth tool: each drag smooths the path under it, and repeated drags keep smoothing
2026-11-13 23:04:21 +07:00
BFlat f525bd742e Merge pull request #7147 from dotCooCoo/fix/script-file-name
Scripts: $.fileName names the file of the code that reads it
2026-11-13 23:04:04 +07:00
BFlat dd8f8ed2bd Merge pull request #7115 from dotCooCoo/fix/settle-keeps-preview-warnings
Edit: settling an interaction keeps the warning of the preview it applies
2026-11-13 23:03:55 +07:00
BFlat ada78a07ba Merge pull request #7114 from dotCooCoo/feat/group-effect-after-members
Effects: a group's geometry effects reshape what its members draw
2026-11-13 23:03:46 +07:00
BFlat c68b2775e4 Merge pull request #7125 from dotCooCoo/fix/plugin-install-checks-first
Plug-ins: plugin.install writes nothing to the store until the module is checked
2026-11-13 23:02:12 +07:00
BFlat e9459df52b Merge pull request #7099 from jmverges/fix/7097-top-object-split-curve
Envelopes: a top object's side that is one split curve follows its parameter
2026-11-13 23:00:21 +07:00
dotCooCoo 9fad6eb952 Objects on Path: Detach takes the chosen object off the path
With one Objects on Path group selected and an object chosen with its
Select/Move widget, Detach in the Properties panel's Objects on Path
Options section takes that object out of the group
(`object.objectsOnPath.detach {member?}`). The object goes just above
the group in the Layers panel, stays where it is drawn and is selected
alone. The other objects move up the path in their order: Auto Space
spreads them evenly again, and a Space value and the start are kept.
The group and its path stay with one object or none left. Hidden or
locked objects and groups are refused, and Detach is one undo step.
When the group is itself on another group's path, the object goes
above the outer group so it does not join that path.

Docs: docs/mcp.md, docs/target-app-parity.md. Detach and its undo name
have rows in every catalog, and the new message in the complete-message
catalogs.
2026-11-13 07:54:06 -08:00
dotCooCoo a12de6a39a Merge main into feat/guides-layer-rows 2026-11-13 07:51:49 -08:00
dotCooCoo 036079902b Merge main into feat/pixel-snapping-options 2026-11-13 07:46:25 -08:00
dotCooCoo 39441540f7 Merge main into fix/nested-link-ids 2026-11-13 07:44:19 -08:00
dotCooCoo 5f78e1fca7 Merge main into fix/simplify-line-keeps-tangent 2026-11-13 07:41:05 -08:00
dotCooCoo fdbe4ea32d Merge main into fix/command-batch-artboards 2026-11-13 07:36:48 -08:00
dotCooCoo 4cd998dce0 Place: a file read apart from the session goes only into its document
Session::place_read and Session::place_queue_read placed a file, or
loaded the place cursor, in whichever document was active when the read
finished. A job prepared in one document could land in another one that
was activated meanwhile, or that stayed open after the first was closed.
Replace did not stop it when the other document held an equal object
under the same id.

PlaceJob, QueueJob and QueueRead now keep the uid of the document they
were prepared in. Both calls refuse a read whose document is not the
active one with "the document it was prepared for is no longer active",
before any selection, edit, tool change or journal entry. Switching back
to the original document places the file as before.
2026-11-13 07:28:07 -08:00
BFlat 77970c6924 Merge pull request #7082 from dotCooCoo/fix/smooth-resets-anchor-selection
Smooth tool: smoothing a path deselects its direct-selected anchors
2026-11-13 22:26:18 +07:00
dotCooCoo 08e1b7af80 Image Trace: a background trace applies only to the pixels it traced
A trace made away from its command (the background trace, #3098) counted
as current when the object, its image record and the settings were
unchanged, without looking at the image data. When other pixels came to
sit under the same image key (Rasterize after an undo reuses the key and
the id, Update Link, a replaced blob), the finished trace applied its old
paths to the new image.

The trace's inputs now include the encoded bytes it decodes, compared by
allocation first and then by content. TraceRun::current and the hand-off
in imageTrace.make and imageTrace.makeAndExpand both use them, so a stale
trace is dropped and the command traces the pixels there now. Equal bytes
in another allocation still count as the same image.
2026-11-13 07:18:53 -08:00
dotCooCoo ccb14182e9 Plug-ins: plugin.install approves from the grant it checks again, and others wait for its store writes
Without a plug-in store, plugin.install read the process grant once
for its later check and again for its approval. A grant another session
recorded between the two reads approved the module; when that session
revoked it before the install, the check saw the grant it first read
and the install recorded the revoked grant again. The approval now comes
from the first read.

plugin.install published the plug-in before it wrote the module and its
grant to the Plug-ins folder. A plugin.remove in another session in
between removed the plug-in, its file and its grant, and the install then
wrote both back, so the plug-in loaded with its grant at the next launch.
A session attaching the folder in between loaded the old version, which
kept running while the folder held the new one. plugin.remove, loads of
the stored plug-ins and loads of a plug-ins folder now wait until an
install has written the folder, and an install waits for them.

Docs: docs/plugins.md, docs/target-app-parity.md.
2026-11-13 06:56:24 -08:00
dotCooCoo 4fae51023e Paths: Remove Anchor Points removes many anchors of a subpath in one pass
Object > Path > Remove Anchor Points removed each selected anchor with
its own Vec::remove, shifting the rest of the subpath every time, so
removing k anchors from an n-anchor subpath took O(k*n) moves.

- pathops: remove_anchors removes a subpath's anchors the last first,
  reading each anchor's current neighbors, handles, length and closed
  state as removing them one at a time does, and compacts the anchor
  list once. remove_anchor and remove_anchors share one refit, so the
  result is bit for bit the same.
- engine: the command groups the selected anchors by subpath, works out
  the next selected anchor with each subpath reading only its own
  selected anchors, and takes emptied paths out of the selection
  together (Selection::remove_all).
- Tests compare remove_anchors bit for bit with remove_anchor over 600
  generated subpaths and focused cases, count the anchors moved (2001
  anchors, every other one removed: at most one move per anchor left,
  500,500 one at a time), and compare the next-anchor selection and
  the command on many paths and subpaths with removing one at a time.
2026-11-13 06:54:55 -08:00
dotCooCoo 5700b0d8c1 Live Paint: the bucket shows a filled bucket over a face and a brush over an edge
The Live Paint Bucket drew the crosshair in place of its own cursor. It
now shows what a click paints: a filled paint bucket over a face it
fills (of a Live Paint group, or a region of the selected paths), a
brush over an edge it paints, and an empty bucket where it paints
nothing. The cursor follows Paint Fills, Paint Strokes and Shift, and
shows with Highlight off too. Alt still shows the Eyedropper, and Use
Precise Cursors shows the crosshair.

With a Live Paint group and ordinary paths selected, a region of the
paths outside the group is now highlighted, as a click there fills it.

The help page: https://helpx.adobe.com/illustrator/desktop/paint-and-fill/learn-painting-basics/paint-with-the-live-paint-bucket-tool.html
2026-11-13 06:30:43 -08:00
dotCooCoo 4091f110b1 Scripts: $.line and $.stack give the line of the file the code is in
$.line and $.stack counted lines in the run's expanded source. In code
that comes after an #include they gave lines that match no file, and
this included code in a file $.evalFile ran and code a named engine
kept from an earlier run.

Both now map each frame through the run's source maps, as uncaught
errors already were. $.stack writes each frame as name@file:line,
outermost first, with the run's name as the file of a script given as
source. Code that eval or Function compiled keeps the line of the
source they compiled, in [eval]; code whose place a named engine no
longer keeps is at line 0 of [unknown]. The 64-frame limit, [global]
and [anonymous] are unchanged.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-13 06:19:54 -08:00
dotCooCoo 75c74557bb Scripts: $.fileName names the file of the code that reads it
$.fileName gave the file being run, so a function defined in a file
that #include inserted, in a file $.evalFile ran, or in an earlier run
of a named engine reported the calling file instead of its own.

- vectorcraft_js: HostItem::SiteGetter gives a getter the CallSite
  (source tag, line, column) of the code that reads it.
- $.fileName maps that place through the run's source maps, or the
  maps a named engine kept, to the file the code is in. It is empty in
  code from a script given as source and in kept code whose map was
  dropped. Code that eval or Function compiled still gets the file
  being run.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-13 06:19:23 -08:00
dotCooCoo fc70b08f71 Blend: a blend without a spine shows the Appearance widget
A blend made with Create Spine set to Never now shows the Appearance
widget with the Selection and Blend tools, so its color Shift can be
dragged on the canvas as on a blend with a spine. The Easing widget
stays hidden, since easing needs a spine.

The widget sits 16 px above the halfway point, by length, of the
straight lines between the key centers that the steps are laid out
along, and a drag follows those lines' direction there. The lines are
not drawn. `blend_layout_line` exposes that line; `blend_spine` still
returns `None` for such a blend.
2026-11-13 06:17:47 -08:00
dotCooCoo fb41d79f28 Layers: ruler guide rows have their own eye and lock, and go to the trash
The eye and lock on a guide's row in the Layers panel hide or lock that
guide alone, in one undo step, and a drag down either column takes guide
rows along with the other rows it passes. A hidden guide is not drawn and
does not snap, and its row is dimmed; a locked guide is drawn and snaps
but can't be selected, moved or deleted. Both can be changed while the
guide's layer is hidden or locked, and the guide shows or can be edited
only when its layer allows it as well. The state is kept through save
and reopen.

- layer.setProps takes ruler guide node ids; every other command still
  refuses them.
- guide.list rows carry the guide's node id and its own hidden and
  locked state.
- Alt-click and Ctrl/Cmd+Alt-click on a guide row's eye or lock act on
  the other layers, as on any row in that layer.
- Object > Lock > Selection and Object > Hide > Selection lock or hide the
  selected ruler guides with the selected art, in one undo step, outside
  isolation mode. Unlock All and Show All, document scope, also unlock or
  show guides locked or hidden on their own and select them as guides.
- Guide rows dropped on the Layers panel's trash delete their guides
  (guide.remove {indexes}). A click on a guide row clears the highlighted
  rows, so Delete deletes the guide; with no row highlighted the trash
  deletes the selected guides.
- guide.remove and guide.setLayer refuse index together with indexes and
  an indexes value that is not a list, and count a repeated index once.
  guide.select, guide.remove and guide.setLayer refuse an indexes list of
  more than 10,000 entries; guide.setLayer cut such a list short before.
- Moving, deleting or moving to another layer a guide that is hidden or
  locked on its own fails with "the guide is hidden or locked"; a guide
  on a hidden or locked layer still fails with "the guide is on a hidden
  or locked layer".

Docs: docs/mcp.md, docs/target-app-parity.md, docs/ui-parity.md.
2026-11-13 06:07:27 -08:00
dotCooCoo d211e2f613 Artboards: a batch's Fit to Artwork Bounds step fits every selected artboard
A Fit to Artwork Bounds step of `command.batch` that names neither
`index` nor `indices` now fits the artboards the Artboard tool has
selected when the step runs (two or more), as the command does when the
app runs it on its own. Before, the step took the batch's `artboard` as
its `index`, so an action played from the Actions panel fitted only the
active artboard while several were selected.

- A step's own `index` or `indices` is kept, and the batch no longer adds
  an unused `index` to a step that names `indices`.
- The batch's journal entry records the `indices` the step took, so a
  replay fits the same artboards. An action leaves them out and fits the
  artboards selected when it plays.

Docs: command.batch params text, docs/mcp.md, docs/target-app-parity.md.
2026-11-13 05:35:28 -08:00
dotCooCoo 53e8391e41 Recolor Artwork: the Prominent Colors bar keeps the Edit tab's height
- With art, the bar is 10 pt tall and the Edit tab leaves out the gaps
  above the wheel and above the sliders. The dialog is as tall on the
  Edit tab as on the Assign tab, and all of it but the color chips fits
  a 1024 by 576 screen.
- recolor.weigh counts a use for the first row that is not excluded
  when an excluded row lists the same color first.
2026-11-13 05:34:30 -08:00
dotCooCoo 6f3ffeb393 Plug-ins: plugin.install writes nothing to the store until the module is checked
plugin.install wrote the module and its grant to the Plug-ins folder,
attached the plug-in's settings and cache and turned a disabled plug-in
on before the registry's last approval check. When another session
revoked the grant, or recorded one for other bytes, after the command
recorded its own grant and before that check, the install was refused
but left the new module and grant in the folder for the next launch.
A plug-in another session installed under the same id between the
command's checks and the install took no part in the decision, so the
install replaced it without `replace: true`.

- registry::install_checked records the grant (or forgets it) and
  installs the plug-in as one step, after a caller check that sees the
  plug-in installed under the id and its grant; a refusal changes
  nothing.
- plugin.install commits through it before any store write, refusing
  with the existing messages when another plug-in now needs `replace`
  or the grant its approval came from changed. The store writes, the
  put-back on a failed write and the disabled-list update now run after
  the commit; their logic is unchanged.
- The grant call-site audit also counts registry::install_checked.

Docs: docs/plugins.md, docs/target-app-parity.md.
2026-11-13 05:25:16 -08:00
dotCooCoo 3aa7ea2f78 Recolor Artwork: a weighed color recolors with the row it moved to
- recolor.weigh drops another row's entry for a color that moved, so
  recolor.apply recolors it with the row it moved to and the shares
  describe the recolor. A color that the first color of another row
  with a new color also lists stays where it is.
- Linked swatch colors are grouped through a map, so a row with many
  unlinked colors no longer compares each one with every group.
- The Prominent Colors bar reads the shares again when a row gains or
  loses a new color, since that changes which row takes a shared color.
2026-11-13 04:58:39 -08:00