Commit Graph
2197 Commits
Author SHA1 Message Date
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 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 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 e54519d6bd Merge main into feat/image-color-mask 2026-11-12 07:51:12 -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
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
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
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
dotCooCoo b4ffd4a97e MCP: a hidden path's file: URL shows as the file name, and rewritten keys keep every field
Under automation read roots, a reply replaced only the path inside a
`file:///outside/a.svg` URL, which left `file://a.svg`, a URL that names a
host. The whole URL of an absolute path, with `localhost`, another host or
no host, is now replaced with the file name, unless part of its scheme was
already replaced. A reply key rewritten to read the same as another key of
its object took that key's place and its field was lost; the rewritten key
now takes ` (2)`, ` (3)` and so on, and a key that is not rewritten keeps
its name.
2026-11-12 07:17:50 -08:00
dotCooCoo 07423c22d6 MCP: save and export replies keep the path the client gave under read roots
Under automation read roots, a reply shows each path outside the read roots
that the request sent by its file name. A save or export to a path the
client gave inside the write roots then answered with the bare file name in
`path`, where the save replies keep the given path. The `path` and `files`
entries of the reply's result, a `command.batch` step's result included,
that equal a path param the request gave inside the write roots now stay as
given; every other occurrence is still shown by its file name, and loaded
libraries outside the read roots keep their `loaded/<file name>` ids.
2026-11-12 07:17:50 -08:00
dotCooCoo 2ec278280a MCP: ui.dock targets, shortcut keys and native backslash paths keep hidden library ids
- ui.dock's move takes a hidden panel's shown id in target, as the other
  docking destinations do.
- Shortcut overrides keyed panel:<panel id>, saved and in an open
  Keyboard Shortcuts dialog, show the panel id shown for a library
  outside the read roots, also when nothing else refers to it.
- Outside Windows, a native path is matched only as written: a sent
  /out/weird/name.svg no longer renames a hidden library at
  /out/weird\name.svg, and a reply does not read one as a spelling of the
  other. Windows paths are still matched with either separator.
2026-11-12 07:17:48 -08:00
dotCooCoo d4bbce8982 MCP: hidden library names follow the platform's path rules
- Outside Windows a `\` stays part of a hidden library's or sent path's
  file name; another platform's absolute path is still split on `\`.
- A hidden relative path is matched after leading `./` and `../` parts
  only when they start the path, so `/work/./data/icon.svg` keeps its
  text.
- `ui.inspect` and `ui.docking` replies are hidden once, so a library
  at the top of the file system shows as `loaded/<file name>` with its
  separator.
2026-11-12 07:17:47 -08:00
dotCooCoo 6d7a8249a7 MCP: hidden library paths are matched before the paths a request sent
A sent path whose text overlapped part of a hidden library's path could
keep that path from being hidden; the hidden libraries' ids and paths
are now matched first. A hidden relative path is also hidden where a
reply shows the absolute path it reads as from the working folder, and
a hidden library sent by that other form shows as the sent path does.
2026-11-12 07:17:46 -08:00
dotCooCoo d1f7888ad4 MCP: a hidden library keeps the id it was first shown under
A library loaded from outside a confined client's read roots keeps its
`loaded/<file name>` id for the session, in ui.inspect, ui.docking and
the library commands, so an id taken from an earlier reply still finds
the same library after another library with the same file name is
loaded. swatch.library.copyToUser leaves out `path` when the file is
outside the read roots, as the saves do.

The ids come from the engine's concealed_library_ids, which now reads a
path written with either separator, counts another platform's absolute
path as outside the roots, and keeps each id in the session.
2026-11-12 07:17:46 -08:00
dotCooCoo d1e766173e MCP: a library saved with another platform's absolute path is hidden under a read root
Outside Windows, a library path that starts with a drive or a backslash counts as outside the read roots, since the file access check would read it as a name in the working folder.
2026-11-12 07:17:46 -08:00
dotCooCoo 62be2df058 MCP: replies hide each sent path the same way whatever the outcome
Each hidden id or path is replaced once, chosen from the reply as given,
so a hidden path inside another library's shown id is not replaced
again, and a readable id written with %XX escapes keeps the hidden path
it begins with. A path quoted with {:?} is matched with its quotes and
control characters escaped. A path outside the read roots that the
request sent is shown by its file name in a reply that succeeded as in
one that failed, and a path param counts with a relative path too. A
relative path is not replaced where it ends a longer path. Without a
read root, a file: URL that names another host stays in ui.inspect's
recorded steps.
2026-11-12 07:17:46 -08:00
dotCooCoo 61771e4ead MCP: a screenshot's reply hides library paths outside the read roots
The reply is sent after the request was handled, and now hides what any other reply hides.
2026-11-12 07:17:46 -08:00
dotCooCoo 13bee0d6ef MCP: a readable library id keeps its text when a space follows the hidden part
A hidden id or path stays only where it begins another loaded library's whole id with no `.` or `..` part, also when that id has a space after the hidden part.
2026-11-12 07:17:46 -08:00
dotCooCoo 00f5a16494 MCP: replies hide library paths outside the read roots in more forms
- Every request under a read root records the hidden libraries before it
  runs, and the reply hides those and the ones hidden after it. A panic
  is answered inside the request, so its error is hidden too.
- A hidden path followed by more path text stays only when the longer
  text is another loaded library's id with no `.` or `..` part.
- Encoded file data is skipped only for a base64 string under
  `dataBase64`, `pngBase64` or `thumbnailBase64`; objects and lists under
  those keys, and other keys ending in `Base64`, are searched.
- The error of a failed request hides a path outside the read roots that
  the request sent by its file name, so it reads the same whether or not
  a library was loaded from that path.
- Paths written with `%XX` escapes are hidden, and on Windows paths in
  another letter case.
- Recorded steps in `ui.inspect` leave out `~`, paths under `~` and paths
  starting with `./` or `../` outside the read roots under any param.
- Hidden libraries are numbered in load order and keep their id from one
  request to the next.
2026-11-12 07:17:46 -08:00
dotCooCoo a2c08dec27 MCP: replies hide a library path outside the read roots wherever it appears
Under the read roots, every control reply now shows a hidden library's
id as loaded/<file name> and its path as the file name in every string
and key: status text, dialogs, the command palette query, a script's
report, recorded steps and errors. The id and path are replaced at any
boundary, so a path between spaces, brackets or quotes, followed by a
period or by more path text (<path>.bak), or quoted with escaped
backslashes is hidden too. An occurrence that continues into a longer
path stays only when the request may read that longer path, so a
readable library's id that begins with a hidden one keeps its text.
The libraries hidden after the request ran are hidden, and for a
request that names one, those hidden before it too. A reply with no
path separator in it is not searched. Encoded file data (dataBase64,
pngBase64) is sent unchanged.

Recorded steps in ui.inspect leave out a path outside the read roots
under path, paths, file, files, folder and any param whose name ends in
Path, Paths, File, Files or Folder (diffPath, fontFiles,
destinationFolder), and an absolute path or file: URL outside the roots
under any other param or in any list. The file: scheme is matched in
any case, a URL's %XX escapes are decoded before the check, a file: URL
inside the roots stays, and a file: URL that
names another host is always left out. file_access::is_path_key holds the list of
path params, and testkit's is_path_key uses it.
2026-11-12 07:17:45 -08:00
dotCooCoo a1ece0052b MCP: hidden library ids name their library in requests and are rewritten only as whole ids
Follows #6608. ui.inspect shows a library loaded from outside the read
roots as loaded/<file name>. A request may now name the library or its
panel by that id in a panel, library or panels param, in a docking
destination (anchor, before, onto, above, below) and in
window.panel.layout's action: ui.set {panel} reopens the closed panel
instead of floating a new one. The reply to such a request, an error
included, shows the shown id.

ui.inspect rewrites only whole ids, and only in the fields that hold
library and panel ids, so a readable library's id that begins with a
hidden one keeps its path, and status text, the command palette query
and a script's report keep their text. A hidden library does not take
the id of a library loaded without a path.

ui.inspect also leaves out of recorded action steps the path and folder
params, params named like destinationFolder and the entries of a paths
list that lie outside the read roots, also inside a batch step's
commands. It hides a library id holding a path written with either
separator, and checks a folder preference against the roots as written,
without trimming spaces.
2026-11-12 07:17:44 -08:00
dotCooCoo d2e21a38bf Actions: recording, step exclusions and set edits keep sets that Load Actions reads
Load Actions refuses an action set file over 8 MiB, with more than 1,000
actions, or with an action of more than 10,000 steps. Several ways of
changing a set could pass those limits, leaving a set that Save Actions
refuses to write.

- While an action records, a command (a batch and Find Objects that
  selects included) whose step would give the action more than 10,000
  steps or its set's file more than 8 MiB does not run, and the recording
  goes on. A stop that playback reaches is left out then. A command whose
  step grows past a limit only as it runs keeps its edit; the status bar
  names the limit and Stop leaves the step out. Stop also leaves out any
  recorded step still past a limit. Steps recorded after an exclusion
  past an action's last step are included.
- An exclusion that would make the set's file larger than 8 MiB changes
  no checkmark; one that keeps the size or shrinks it always works.
- Begin Recording, New Action, Duplicate, renaming an action, Action
  Options, Set Options and New Set refuse a change that would give a set
  more than 1,000 actions or a file larger than 8 MiB. A change that
  leaves a set no further past a limit than it is now is allowed.
- Load Actions refuses a set, .aia sets included, that Save Actions would
  write larger than 8 MiB (a file with less white space, or a set name
  that gets a number added).

The limits are the existing ones from files.rs, and the errors reuse the
existing messages. docs/mcp.md and the commands' params text describe the
new errors.
2026-11-12 07:09:36 -08:00
Taha-Mahmoodi 7c6f51e8d6 Merge remote-tracking branch 'origin/main' into feat/glyph-alternates 2026-11-12 19:37:53 +04:30
dotCooCoo 8a6361b45f Global Edit: selecting one object highlights the similar objects before the start
With one object that Start Global Edit accepts selected with the Selection
tool, the canvas now highlights the other objects a start would take with the
current Global Edit Options, before Global Edit starts. The outlines are kept
per document revision and options, and none are shown during a drag.

Docs: docs/mcp.md (Global Edit), docs/gaps.md (G5).
2026-11-12 07:04:06 -08:00
BFlat f5c5d9a702 Merge pull request #6829 from dotCooCoo/feat/dynamic-text-point-type
Type: Dynamic Text turns point type into area type with Block on
2026-11-12 22:02:05 +07:00
BFlat ddafb28aeb Merge pull request #6888 from dotCooCoo/fix/read-roots-scripts-recovery
MCP: plug-in, recovery and script report replies leave out paths outside the read roots
2026-11-12 22:01:56 +07:00
BFlat a1abf13a8a Merge pull request #6852 from dotCooCoo/feat/objects-on-path-select-move-detach
Objects on Path: the Select/Move widget chooses an object and drags it to another place along the path
2026-11-12 22:01:35 +07:00
BFlat c607814697 Merge pull request #6798 from dotCooCoo/feat/brushes-dry-media-library
Brushes: a built-in Dry Media library of grainy chalk, pencil, crayon and charcoal art brushes
2026-11-12 22:01:26 +07:00
BFlat 8b6ed41ef0 Merge pull request #6846 from dotCooCoo/test/not-aligned-pixel-grid-kinds
Select: test Not Aligned to Pixel Grid with images, symbols, type and live objects
2026-11-12 22:01:15 +07:00
BFlat c44103f8c3 Merge pull request #6853 from dotCooCoo/feat/patterns-optical-effects
Swatch libraries: Patterns › Optical Effects adds wave, moiré and op-art patterns
2026-11-12 22:00:23 +07:00
BFlat 5c5bb69c37 Merge pull request #6671 from thisisgomaa/file/save-read-only-offers-save-as
Save on a read-only location offers Save As
2026-11-12 22:00:00 +07:00
dotCooCoo 6208a8cc3e EPS import: charpath, cshow, kshow and glyphshow read named CIDFont type by its CMap
- `charpath` in a CIDFont only named, over a predefined CMap, adds the
  outlines of the characters its codes stand for, placed as `show` sets
  them, and moves the point as `show` does. It added no outlines.
- `cshow` gives its procedure each code of such type, two bytes for a
  two-byte code, with the code's width. It split two-byte codes into
  single bytes.
- `glyphshow` sets the named character itself. It set the character's
  UTF-8 bytes as Latin-1 letters.
- `kshow` runs its procedure between each two codes of such type, with
  the two codes' values. It didn't run it. The procedure sees the font
  the file set as current, and a font it sets stays current.
- A name that ends in the row-and-cell CMap `H` or `V` splits off the
  CMap only when the file defines the CIDFont of that name (as a
  resource or with `definefont`), or the name has a hyphen and an
  installed face that covers Japanese has it. `Foo-Bold-H` stays a font
  of the whole name.
- In a CMap that can't be read (`GBT-H`), each code moves the point one
  em, along the line or down the column; a tab or carriage return byte
  is a code of its own.
- One parser reads the names of the predefined Unicode CMaps, for EPS
  and legacy `.ai` type.
- Outlines added to a path by `charpath` stop at the path's point limit.
- docs/file-format-parity.md, docs/gaps.md and docs/mcp.md describe type
  in named CIDFonts over the predefined CMaps.
2026-11-12 06:57:48 -08:00
dotCooCoo 91d705e155 Gradients: repeat or reflect a gradient's stops a set number of times
A linear, radial, conic or diamond gradient has a spread: Pad (the
default, as before), Repeat or Reflect, with a count of 1 to 100
(VectorCraft's own limit). Repeat and Reflect run the stops that many
times along the vector (around the turn for a conic) and keep going past
both ends, Reflect running every other run backwards, as SVG's
spreadMethod does.

The Gradient panel has a Spread menu and a Repeats field, and the
Gradient tool marks where the runs meet. paint.setFill and
paint.editGradient take `spread` and `repeats`; bad values are errors.
Presets, swatches, blends, strokes along or across a path, Outline
Stroke and Object › Expand follow the spread; Expand gives each run the
same whole number of objects, and Outline Stroke's mesh keeps the color
on each side of a sharp step between two stops at one offset.

SVG writes and reads spreadMethod: SVG import now reads a repeating or
reflecting gradient as one that repeats or reflects once, instead of
expanding its stops over the shape. CSS writes repeating gradients.
PDF writes a conic's sweep shading over one run. PDF, EPS, legacy .ai
and the .ai editing data write the other kinds with their stops
repeated across the shape: at most 256 runs and 16,384 stops (256 stops
in .ai files), and for a radial or diamond no farther than 65,536 runs
from its center, with a warning past those. PDF import now finds sharp
steps in any axial or radial shading instead of blurring them.

Docs: docs/mcp.md (Spread), docs/target-app-parity.md, docs/gaps.md.
2026-11-12 06:52:38 -08:00
dotCooCoo 3fdbb461fe Merge main into feat/outline-object-image-alpha 2026-11-12 06:33:36 -08:00
dotCooCoo 72fb8fe81d Image Tools: masked images count as see-through in legacy .ai and pattern tiles
- The legacy .ai and the check for see-through images in pattern tiles
  read a color-masked image's masked pixels, as the flattener does. A
  legacy .ai flattens a masked opaque image with the art under it, or
  leaves it out with `transparentImages: "omit"`, and a pattern tile that
  holds one is expanded before PDF/X-1a, PDF/X-3 and legacy .ai output
  flatten it.
- Printed separations check whether a colorize paint shows on the masked
  pixels, as the canvas does, rather than on the image's own pixels.
- A saved mask that leaves out `contiguous`, `tolerance` or `softness`
  reads them as the command's defaults: true, 10 and 10.
- Remove Background is unchanged on this branch. Its refusal of a
  grayscale image colorized with a process color is left for a separate
  pull request.

Tests: legacy_ai_flattens_a_masked_image_as_a_see_through_one,
a_pattern_tile_with_a_masked_image_counts_as_see_through,
pdf_x1a_and_x3_flatten_the_hidden_pixels (PDF/X-3 added),
separations_colorize_masked_pixels_whose_own_pixels_are_a_preview,
a_record_without_settings_reads_the_defaults, and the dialog's query on a
linked image at its preview.
2026-11-12 06:27:59 -08:00
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
dotCooCoo 102ad44304 Effects: an image's Outline Object outline follows new pixels under the same key
The canvas kept the art of an image whose own fill or stroke follows the
outline of its pixels for as long as the image object stayed the same. When
the document's pixels for the image changed under the same key (Update Link
replacing a preview with the linked file's pixels), the stroke kept the old
outline while hit testing and Use Preview Bounds used the new one. The
renderer now keys that art by the document's pixels for the image too.

- vectorcraft-effects: `follows_image_pixels` names such images.
- vectorcraft-render: `reads_outside` counts them, and the resources key
  hashes the address of the document's pixels for them; their walk is not
  kept between frames.
- A test places an off-center opaque area in a smaller copy of the pixels
  under a turned and reflected placement.
- Docs: the Outline Object params text names every case that keeps the frame
  and the 50% cutoff as VectorCraft's own; docs/mcp.md's `effect.apply` entry
  for Outline Object, how long an outline is kept and the 16-bit RGBA limit;
  docs/target-app-parity.md's evidence lines.
2026-11-12 06:04:34 -08:00
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
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