Commit Graph
4323 Commits
Author SHA1 Message Date
jmverges 6cf6dbb08d Merge remote-tracking branch 'upstream/main' into fix/ai-type-pattern-paint
# Conflicts:
#	docs/file-format-parity.md
2026-11-12 14:14:56 +00:00
jmverges 023edbb02f Merge remote-tracking branch 'upstream/main' into fix/remaining-type-envelopes
# Conflicts:
#	docs/file-format-parity.md
#	docs/target-app-parity.md
2026-11-12 14:14:56 +00:00
ruchirguitar 3adadd52f4 UI: a tap within 1 pt still selects a numeric field's value (#1326)
Review feedback: with no tolerance, pen or trackpad jitter turned a tap
into a drag and the value was no longer selected. A release within 1 pt
of the press is a tap; anything further keeps the caret.
Regression test: a_tap_with_a_pixel_of_jitter_still_selects_all_on_release.
2026-11-12 19:40:04 +05:30
dotCooCoo c024fca8f3 Keyboard Shortcuts: a command that a menu bar item runs can take a shortcut, Set Corners… among them
A shortcut given to Set Corners… (`addon.pathtools.cornerSet`) ran nothing,
on a single key or a chord. The keymap is built from the list in Edit ›
Keyboard Shortcuts, and that list left the command out. An engine command
without a menu path of its own was listed only when it had a default key,
or when it was an undoable command, not an alias, whose params doc ends
each field with `?`. A UI command was listed only when it had a default
key or a params doc of `{}` or `{path…}`, or was Rename. Set Corners…
needs a radius, so it was left out. The same rules left out other
commands that items of the menu bar run:

- View › Perspective Grid's Lock Grid, Lock Station Point, Show Rulers and
  Snap to Grid, and Object › Perspective's Attach to Active Plane, Move
  Plane to Match Object and Edit Text.
- Edit › Edit Custom Dictionary…, a query.
- UI commands: Recolor Artwork…, the Edit menu's four preset dialogs,
  Apply SVG Filter…, Export As…, Export Selection…, Edit Original, Apply
  Bullets, Apply Numbers, the four library saves, and the Window menu's
  New Toolbar…, Double Column, Keep Tools Beside the Canvas, New
  Workspace…, Float in Window and Consolidate All Windows.

Such a command is now listed when an item of the menu bar runs it as a key
press would: with no params, or with the one set of params all its items
give. `needs_a_value` already used this check, and it moves into
`a_menu_bar_item_runs` so that both use it. The command is listed in the
group named by the first part of its id, next to the commands of its
family that were listed before (Set Corners… under Addon with Corner
Tool, the grid toggles under Perspective).

File › Export Selection… was the row of `document.exportSelection`, which
no item of the menu bar runs. That row now runs `file.exportSelection`, as
the menu item does, and `document.exportSelection` is listed as Document ›
Export Selection…. A shortcut already given to it keeps running it. The
Window menu's Learn item gets no row, because the Learn panel's row
already has its name.

Tests: on F and on a chord, Set Corners…, Edit Custom Dictionary…, Recolor
Artwork…, the four preset dialogs and Apply SVG Filter… open the dialog a
click on their menu item opens. Snap to Grid turns off and on from F, and
Export Selection… on F opens Export for Screens. Every command the menu
bar runs this way is listed, none of them shares its group and label with
another entry, and a shortcut on four of them is kept through a saved
set's export and import. The other Object › Plug-ins dialogs, Select by
Link Status… and Composite Fonts… already opened from a shortcut and are
checked the same way.
2026-11-12 06:06:39 -08:00
dotCooCoo baa7ada7a1 Automation: errors name a path outside the read roots by its file name
Under --automation-read-root, an error about a file or folder the client
did not give now names it whole only when it is inside the read roots.
Outside them it names the file or folder by its file name, or as "a file
or folder outside the read roots" when it has none, and keeps the roots
and the reason. A path the client gives stays whole.

This covers a save without a path (the document's own file and the files
written beside it, also inside action.batch, and the refusal to write
over a file read with losses), file.revert, script.listInstalled,
plugin.reload without a path and plugin.list's folder report, and
links.relink with copy (the document's folder, its error when the
document's path has no folder, and the copies in the reply). Export for
Screens' refusal for an export preset's folder uses the same helper.
2026-11-12 06:05:56 -08:00
Taha-Mahmoodi d15b9f7f25 Merge remote-tracking branch 'origin/main' into feat/glyph-alternates 2026-11-12 18:35:54 +04:30
BFlat 71b889605d Merge pull request #6717 from dotCooCoo/feat/type-path-center-on-top
Type: Center on Top and Center on Bottom for type on a closed path
2026-11-12 21:04:31 +07:00
BFlat 9fcddf68d1 Merge pull request #6849 from dotCooCoo/feat/warp-images
Warp: the Warp effects bend an image's pixels with its frame
2026-11-12 21:04:22 +07:00
BFlat 16bb8c37dc Merge pull request #6843 from dotCooCoo/fix/read-roots-findfiles
Read roots: links.findFiles and image.info follow the configured read roots
2026-11-12 21:04:04 +07:00
BFlat cebc0b6f6c Merge pull request #6872 from dotCooCoo/docs/plugins-safe-mode-wrap
Docs: docs/plugins.md paragraphs wrap at the file's width
2026-11-12 21:03:53 +07:00
BFlat 6961a96f89 Merge pull request #6842 from dotCooCoo/fix/legacy-ai-vertical-roman-tcy
Legacy .ai: type keeps Standard Vertical Roman Alignment and Tate-chu-yoko
2026-11-12 21:03:45 +07:00
BFlat 032770e046 Merge pull request #6848 from dotCooCoo/test/direct-group-selection
Tests: Direct Selection marquee and hover and Group Selection pass through raster effects
2026-11-12 21:03:35 +07:00
dotCooCoo 2212739c54 MCP: plug-in, recovery and script report replies leave out paths outside the read roots
A client confined by --automation-read-root saw paths outside its read
roots that the person or an earlier request had put in the session:

- plugin.list: the plug-in folder last loaded and its failed files;
  plugin.list and plugin.info: a plug-in's source file; plugin.list,
  plugin.safeMode and plugin.setEnabled: the file of a plug-in turned
  off for the next launch.
- file.recovery.list and file.recovery.restore: a document's original
  file; file.recovery.list and file.recovery.save: the recovery folder.
- ui.inspect's scriptReport: the files a run wrote and the included
  file a failed run stopped in.

A folder outside the read roots is now null, and a file outside them is
named by its file name. plugin.setEnabled {file} takes that name. The
restored documents keep their files, and unconfined clients and the
app's own UI see the same replies as before.
2026-11-12 06:03:01 -08:00
dotCooCoo a0902005f7 Blend: the setEasing docs list the easing types and say when a blend made without a spine takes easing
docs/mcp.md lists the four easingType values. It and the
object.blend.setEasing params text say that a blend made without a
spine takes easingType and ramp once Replace Spine has given it one,
which the set_easing test now checks.
2026-11-12 06:00:56 -08:00
dotCooCoo e29f5e51a0 New Document: each preset category starts documents from its own profile
Each built-in category (Mobile, Web, Print, Film & Video, Art &
Illustration, Branding, Social) has a New Document profile, a native
document in the New Document Profiles folder next to the preferences.
file.new copies the profile's swatches, graphic styles, brushes, symbols,
patterns, character and paragraph styles, rulers, Document Setup options,
assigned color profiles and print settings into the new document. The
preset's size, units, artboards, bleed, background, color mode and
resolution still apply, and the profile's art and layers are not copied.

- file.newProfiles lists the profiles, file.newProfiles.edit opens one
  as a document (writing the shipped profile first), and
  file.newProfiles.reset deletes its file. file.new takes `profile`.
- Saved and Recent presets keep the profile of the preset they came from.
- A profile that cannot be read, is larger than 64 MiB or is not a native
  document leaves the defaults, and file.new reports it in profileError.
- New Document has a Manage Profiles pop-up with Edit and Reset.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-12 06:00:40 -08:00
dotCooCoo dc86048bb6 Merge main into feat/weed-box-and-lines 2026-11-12 05:59:30 -08:00
dotCooCoo 0576806e1a Merge main into feat/patterns-optical-effects 2026-11-12 05:55:42 -08:00
dotCooCoo 8db00cbbe2 Merge main into feat/linux-screen-color-portal 2026-11-12 05:54:25 -08:00
dotCooCoo 511ecdb6d3 Merge main into fix/read-roots-document-replies 2026-11-12 05:53:13 -08:00
dotCooCoo ac79ae55ba 3D and Materials: Expand as Wireframes keeps a layer's ruler guides and reshapes each face
- Expanding a layer removed its ruler guides with its members. The guides
  of the layer and of its sublayers now stay on the layer, after the edges.
- Geometry effects after a 3D effect reshaped all the faces as one path, so
  Offset Path merged faces that touch. Each effect now reshapes each face on
  its own, about the bounds of all the faces, within one shared budget of
  anchors, as it reshapes the drawn surface.

Docs: docs/mcp.md.
2026-11-12 05:52:39 -08:00
Taha-Mahmoodi ebad5d75c0 Use the unencoded fixture glyph in ligature range regression 2026-11-12 18:21:43 +04:30
dotCooCoo ba23477b23 Merge main into feat/brushes-ink-wash-library 2026-11-12 05:50:48 -08:00
dotCooCoo 8187f7ae00 Images: a CMYK JPEG turned by its EXIF orientation keeps its inks
A four-component JPEG whose EXIF orientation turns or flips it went
through the image decoder, which reads CMYK JPEGs as RGB, and was
stored as an RGB PNG without its inks. It is now stored the way a
turned CMYK TIFF is: its inks, 8 bits each, turned and written as a
CMYK TIFF with the turned resolution.

- vectorcraft_doc::cmyk::turned_cmyk turns the inks of a CMYK JPEG or
  TIFF, next to stored_cmyk_tiff; tiff_inks is private again.
- raster_image swaps the resolution axes inline, as its HEIF branch
  does.
- The links comment and the docs/target-app-parity.md line on EXIF
  orientation now describe the turned CMYK TIFF.
2026-11-12 05:45:26 -08:00
dotCooCoo 971c878402 Export for Screens: an export into a preset's folder runs in the background
With Background Export on, an Export for Screens call that gives only an
`exportPreset` whose preset keeps a folder ran at once on the UI thread,
because the background route looked at the call's own `folder` only. It
now takes the preset's folder as well and writes in the background with
the progress dialog and Cancel, as an export into a folder it names.

When that folder is outside an MCP client's read roots, the prepared
export carries the folder's shown name, so the reply written later lists
the files relative to the folder with no ZIP `path`, a refused write names
the folder by its name, and the status bar does the same, as for an
export made at once.

The status of a preset-only export made at once named an empty folder
("Exported 1 file to "); it now names the preset's folder.

- `Session::screen_export_folder` returns the folder an export writes
  into and its shown name when the reply leaves it out.
- `ScreenExport::write` applies the read-root rule decided when the
  export was prepared.
- docs/mcp.md and docs/target-app-parity.md describe the change.
2026-11-12 05:44:29 -08:00
dotCooCoo 6ccb7c9077 3D and Materials: Expand as Wireframes expands Revolve (Classic) and Rotate (Classic)
effect.expandAsWireframes returned "draws no faces" for an object with
Revolve (Classic). It now takes the faces of Revolve (Classic) with that
effect's own options, and Rotate (Classic) is expanded as Rotate is: every
fill and stroke turned as one plane.

Docs: docs/mcp.md, docs/three-d.md.
2026-11-12 05:36:03 -08:00
dotCooCoo 01ccb1d8ca Merge main into feat/3d-expand-as-wireframes 2026-11-12 05:35:05 -08:00
dotCooCoo 0b22997201 Docs: the Dynamic Text entries in docs/mcp.md name point type
The Dynamic Text: Block entry says the Contextual Task Bar offers the
item for point type too, and that turning it on makes point type area
type with Block on. The Dynamic Text entry no longer says point type in
the selection is left as it is.
2026-11-12 05:33:38 -08:00
dotCooCoo 1db5b2ce53 i18n: plug-in host errors are translated in every complete catalog
The plug-in host's manifest, module and run errors, the errors about an
importer's, exporter's or effect's output and the approval error had no
@msg row in most complete-message catalogs, and the reasons its error
helpers put inside them (bad(), wrong(), out_err(), in_range(), unit(),
read_packed()) were never scanned, so the status bar showed them in
English or mixed two languages.

- Every complete-message catalog gets the rows in a "Plug-in host
  messages" section, and the Hindi rows for these messages are fixed.
- The message scan reads the plug-in host's error helpers, and
  objects.rs writes its two duplicate-id errors as whole strings.
- message() leaves a captured JSON object or array as written.
- Templates that start with text match before templates that start
  with a placeholder, so a wrapping message uses its own row.
2026-11-12 05:32:03 -08:00
dotCooCoo 6e9ffa92cc Merge main into feat/brushes-dry-media-library 2026-11-12 05:31:21 -08:00
Ahmed Gomaa 421fead32b Merge upstream main into file/save-read-only-offers-save-as 2026-11-12 15:24:23 +02:00
dotCooCoo c9c5d83771 Scripts: a named engine keeps no source map for a run whose script does not compile
A run whose script fails to compile defines no code, so its source map
is not kept and the places of earlier runs stay within the engine's
budget. docs/mcp.md and the progress line say so, and the progress line
names the errors that are reported without a line and column.
2026-11-12 05:18:07 -08:00
dotCooCoo 0779da299b Image Tools: Color Mask hides chosen colors of an image while its pixels stay
Object › Plug-ins › Image Tools gains Color Mask… (`addon.image.colorMask`),
Remove Color Mask and Apply Color Mask. Color Mask hides colors of the
selected images without changing their pixels. It matches colors as Remove
Background does: the edge color, the corner color or picked colors, with
Contiguous, Match, Tolerance and Softness. The mask is kept with the image
object and saved with the document: its settings, and a PNG of the image's
pixels with the hidden colors made clear, at the source's depth with its
color profile and resolution. It is a VectorCraft addition.

- The canvas (clip groups and white-shape opacity masks included),
  printing and separations, PDF (soft masks of CMYK images included), SVG,
  EPS, the raster formats, the legacy .ai and .ai editing data, EMF/WMF,
  DXF and the flattener draw the masked pixels. A linked image stays
  linked, and an output that would refer to its file writes the masked
  pixels instead.
- Copy and paste, placing a document and placed documents carry the masked
  pixels with the image, under the names they are given there.
- The dialog opens on the selected image's mask settings, with a Preview.
  Without settings, the command returns them and changes nothing.
- Setting, removing and applying a mask are each one undo step, and no
  step is added when nothing changes. Apply makes the masked pixels the
  image's own and embeds a linked image. A mask that hides nothing is only
  taken off, and the image keeps its pixels and its link.
- When an image's own pixels are replaced (Update Link, Relink, Crop
  Image, a recolor, a linked file read again on open), its mask is made
  again for the new pixels, in every art tree and in opacity-mask art.
  Crop Image cuts the image's own pixels. When the new pixels can't be
  masked, the mask keeps its settings and hides nothing.
- Objects in `ids` that are not images, CMYK images, linked images that
  show their preview, images past the decode allowance, masks that would
  hide every pixel, and grayscale images colorized with a process color
  are refused. The Eyedropper, Object Mosaic, Create Gradient Mesh, Crop
  Image's trim and Image Trace read the image's own pixels.
- An image is selected by a click anywhere in its frame, as before.

Remove Background now also refuses a grayscale image colorized with a
process color. Its result has an alpha channel, and a process color is
refused on a grayscale image with transparency.

Docs: docs/mcp.md (Image Tools add-on › Color Mask),
docs/target-app-parity.md.
2026-11-12 05:17:01 -08:00
dotCooCoo 88841aa803 Window menu: a panel's entry shows the panel Tab hid instead of closing it
The Window menu checked a panel whenever it was in front in the layout,
even while Tab, Shift+Tab or Presentation Mode hid every panel, so
choosing it, or pressing its function key, closed the panel it was
meant to show.

- A new panel_docking::visible adds the dock and Presentation Mode to
  showing. The Window menu's check marks and the toggle use it, and
  window.panel puts a flyout or floating panel away only while it can
  be seen. With the dock hidden, the dock shows again with the panel in
  its earlier place; the toolbar and the Control bar stay as they are.
- In Presentation Mode window.panel fails with "panels can't be shown
  in Presentation Mode" and changes nothing.
- reveal_panel, the Gradient and Magic Wand tool double-click, the
  Character field shortcuts and the Corner and Shared Edge Merge tool
  items show a panel the dock hid instead of reporting it open or
  closing a floating Anchor Inspector.

Docs: window.panel params text, docs/mcp.md, docs/target-app-parity.md.
2026-11-12 05:16:43 -08:00
Taha-Mahmoodi 0014d19257 Merge remote-tracking branch 'origin/main' into fix/macos-tmp-symlink-tests
# Conflicts:
#	docs/development.md
2026-11-12 17:45:37 +04:30
Taha-Mahmoodi 2585d819cd Merge remote-tracking branch 'origin/main' into feat/glyph-alternates
# Conflicts:
#	docs/gaps.md
#	docs/target-app-parity.md
2026-11-12 17:42:44 +04:30
dotCooCoo 6849bd5422 Docs: docs/plugins.md paragraphs wrap at the file's width
Rewrap the prose in docs/plugins.md whose lines broke well short of
the file's 120-column width or ran past it, including the Safe Mode
sentence, the permission-name and install-confirmation sentences, and
the grants.json paragraph. Each rewrapped line is at most 120 columns.
No words, punctuation, code blocks or tables change.
2026-11-12 05:12:10 -08:00
dotCooCoo b9b1a1e967 Effects: linked opacity masks follow group effects, Free Distort and envelopes
A linked opacity mask moves with the art it masks, and an unlinked one
stays in place. Geometry effects on a group or layer reshaped its
members but left their linked masks where they were, Free Distort left
a linked mask behind, and an envelope bent unlinked masks too.

- Geometry effects on a group or layer run over the art of the linked
  masks of the paths, compound paths and groups inside it, nested and
  inverted masks included. Each Transform copy of a masked path carries
  its own mask, and an image or symbol instance moved by a Transform
  effect carries its linked mask. The effects on an object do not move
  that object's own mask.
- When a mask can't take an effect as the art it masks does (a path in
  either would pass the geometry budget, or the mask would get fewer
  Transform copies), the art and its masks keep their shape under that
  effect. Mask art counts toward the budget.
- Free Distort (`object.distort`) warps a linked mask with its object;
  the params text says so.
- An envelope bends only a linked mask.

Docs: a line in docs/target-app-parity.md.
2026-11-12 05:12:05 -08:00
BFlat 89fba4ebfd Merge pull request #5446 from Taha-Mahmoodi/fix/import-document-title
Fix #3626: an imported document takes the title the file carries
2026-11-12 20:09:15 +07:00
dotCooCoo 6129853555 Effects: a Transform effect transforms the raster effects listed before it
Effects apply in the order they are listed, so a Drop Shadow, glow, blur,
Feather or pixel filter listed before a Transform effect paints art that
the Transform effect then transforms. VectorCraft drew such an
effect at its own distances around the transformed art: a square scaled
to 200% kept a 10 pt shadow offset. Now the effect follows the Transform
effects after it, with Scale Strokes & Effects on or off: its sizes scale
by the mean scale, and a Drop Shadow's offset turns, reflects and scales
with the art. Effects listed after the Transform effect keep their values,
and Transform Objects off changes nothing.

- raster_effects reads each raster effect through the Transform effects
  after it, so the canvas, export and the redraw region use the followed
  values.
- Where the geometry effects are applied and removed (Expand Appearance,
  baking for export, evaluated groups), the raster effects that remain
  carry the same transformation, hidden ones included.
- A Transform effect that makes copies or moves at random leaves the
  raster effects before it as they are. Rasterize and SVG filters keep
  their options.

Docs: the Transform effect's params text, docs/target-app-parity.md.
2026-11-12 05:07:12 -08:00
dotCooCoo 1996a6df52 Merge main into feat/objects-on-path-select-move-detach 2026-11-12 05:07:11 -08:00
Taha-Mahmoodi 5a88399677 Normalize Windows verbatim prefix in script path regression 2026-11-12 17:30:51 +04:30
dotCooCoo 480cd96035 Merge main into feat/dynamic-text-point-type 2026-11-12 05:00:38 -08:00
dotCooCoo b0ea8176e0 Merge main into feat/docinfo-spot-color-objects 2026-11-12 05:00:32 -08:00
dotCooCoo 72cf92e540 Document Info: Spot Color Objects lists colorized images and skips clear gradients
A grayscale or 1-bit image colorized with a spot color now counts as a
Spot Color Object. A gradient whose stops are all at an opacity of 0
draws nothing, so its spot stops no longer list the object.
2026-11-12 05:00:26 -08:00
dotCooCoo 5e80810605 Merge main into feat/custom-arrowheads 2026-11-12 05:00:21 -08:00
dotCooCoo 0a3abb8534 Stroke: custom arrowheads cap subpaths, file size and preview size
- A custom arrowhead path allows at most 4,096 subpaths; stroke.set
  refuses a longer one and reading drops it.
- A symbol whose shapes cannot be united or clipped is listed in
  skipped instead of becoming a head that misses part of its art.
- The arrowheads file is refused when its document unpacks to more
  than 64 MB.
- Edit Arrowheads creates the starter file only when none exists and
  otherwise opens the file unchanged.
- After a save to the arrowheads file, the heads are read back from
  the written file.
- The plug-in argument check accepts path under startArrow.Custom and
  endArrow.Custom in stroke.set.
- A custom head's menu preview is scaled to fit its box, and rows
  outside the visible part of the menu do not render previews.
2026-11-12 05:00:15 -08:00
dotCooCoo 1eaf4c4023 Merge main into fix/dialog-set-hidden-fields 2026-11-12 04:59:51 -08:00
dotCooCoo 61c37f0b2e Merge main into feat/type-path-center-on-top 2026-11-12 04:59:45 -08:00
dotCooCoo 67ebbf0b53 Merge main into feat/warp-images 2026-11-12 04:59:37 -08:00
dotCooCoo 337bc90d25 Merge main into test/direct-group-selection 2026-11-12 04:59:36 -08:00