Commit Graph
12247 Commits
Author SHA1 Message Date
makesomethingshit ec9a9fd3c9 Fix #6865: trust oversized editing artboards with capped PDF pages 2026-11-12 23:44:54 +09:00
dotCooCoo bf9baa0b85 Plug-ins: diffPath is a file key and Slice Options' url is not; the command sweep uses these keys
The sweeps in command_sweep.rs kept their own list of file and folder
keys (path, diffPath, folder, destinationFolder) in testkit's
safe_value and again in the temp-folder test, so a command whose file
key was not on the list was sent raw junk strings, and a key written as
`{path | name ...}` (document.open) was never swept.

- The engine exports the plug-in call rules' file keys as
  `cmd::key_location`, `cmd::location_in` and `cmd::location_keys`,
  which read every key a params description names, the keys of the
  commands its `...` entries name, and the schema. `diffPath` is a file
  key, so a plug-in call that carries it is refused; Slice Options'
  `url` and Export for Screens' `folders` name part of the document, so
  a call to object.slice.options with a top-level `url` is accepted.
- testkit's `param_keys` reads the keys the engine reads, and
  `junk_params_for_command` and `safe_value_for_command` send every
  string under a file or folder key, in arrays and in objects inside
  them, as a location in the sweep's temp folder. Each such key also
  gets a list of paths and a list of `{ids, path}` objects.
- Every catalog sweep, the serializability sweep included, uses them,
  and the temp-folder test checks every key the catalog names, at any
  depth.
2026-11-12 06:36:56 -08:00
dotCooCoo 94e9839438 Opacity masks: linked masks follow group effects through type, plug-ins and perspective
Type and live objects in the art of a linked opacity mask are outlined
and evaluated before a group's or layer's geometry effects run over it,
so the mask moves and bends with the art it masks. Before, the effects
reached only the paths in a mask's art.

- With Scale Strokes & Effects on, a Transform effect scales the strokes
  of an image's or symbol instance's linked mask as it scales those of a
  path's mask.
- A mask's art takes Transform copies in the form it had before the
  first effect, as the art it masks does.
- A linked mask whose art is one image or symbol instance takes a
  Transform effect's move and copies with the art it masks. Under any
  other geometry effect, which images and symbol instances do not take,
  art whose masks hold one keeps its shape.
- A symbol instance in perspective projects the linked masks in its art
  with that art.
- A live-effect plug-in that paints its pieces leaves art with linked
  masks as it is, since a mask can't take the pieces.

Docs: the docs/target-app-parity.md line moves next to the Transparency
entry and lists the cases where existing documents draw differently.
2026-11-12 06:35:37 -08:00
dotCooCoo 3fdbb461fe Merge main into feat/outline-object-image-alpha 2026-11-12 06:33:36 -08:00
dotCooCoo f1f9ecfc0f Cutting Tools: Weed Box and Lines leaves art in a hidden group unmeasured
Selected art inside a hidden group or layer is skipped before its outlines are read, so it no longer counts toward the outline point limit.
2026-11-12 06:29:39 -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 95d90511e8 Save: files written beside the path are checked against the file read from again
The merge of main kept main's calls to write_plan, which plan the save
with acknowledgeLoss set, so a save in the app no longer refused to
replace the file the document was read from when that file was one
written beside the path (an EPS artboard file). The save is planned
again without it before it is written, as before the merge.

The files a save writes beside the path still ask before replacing a
file that is there, except those the document's last save wrote. A new
test covers an EPS save with Use Artboards meeting artboard files from
another document: it asks, Cancel writes nothing, OK writes every file,
and the next Save does not ask.
2026-11-12 06:26:44 -08:00
dotCooCoo ccc962300c Effects: Object › Expand, Outline Stroke and 3D keep the raster effects a Transform effect moves
A raster effect listed before a Transform effect follows that Transform
effect on the canvas. Several commands apply and remove the geometry
effects, and they dropped the Transform effect while the raster effect
kept its old values: Object › Expand of a gradient or pattern fill,
Outline Stroke (also Expand's Stroke option and Flatten Transparency's
Convert All Strokes to Outlines) and the 3D effects. For a square with a
Drop Shadow and a 200% Transform effect, the canvas drew a 20 pt offset
and these commands gave a 10 pt one.

- These commands now keep the raster effects at the values the canvas
  uses (without_geometry).
- A fill's or stroke's own Transform effect with Transform Patterns or
  Scale Strokes & Effects on now transforms the raster effects listed
  before it, as one without these options does. Before, Scale Strokes &
  Effects only scaled them, and Transform Patterns left them as they
  were.
- In a fill's or stroke's own effects, a Transform effect that makes
  copies or moves at random keeps the raster effects before it from
  following the Transform effects after it, as in an object's effects.
- The params text and docs/target-app-parity.md say that pixel filters
  keep their angles and light directions.
2026-11-12 06:24:48 -08:00
ruchirguitar 5b2264bb8f Merge remote-tracking branch 'upstream/main' into fix/numfield-short-drag-1326
# Conflicts:
#	docs/gaps.md
#	docs/ui-parity.md
2026-11-12 19:52:50 +05:30
dotCooCoo 1854911078 Image Trace: gray photos are smoothed before tracing, as color photos are
The continuous-tone test asked whether 8 colors leave more than a tenth
of the error of one color. A gray picture's tones lie along one line,
where 8 colors come nearer to them, so some gray photos scored 0.078 to
0.093 and were traced as flat art, without the smoothing color photos
get. Their noise then mixed neighboring tones (a 16 Colors trace could
keep 10 or 12 colors) and stepped the edges.

A picture with at least 95% of its opaque pixels within 8 levels across
their channels now also counts as continuous tone when 8 colors leave
more than 0.065 of the error of one color, unless 16 colors leave at
most a fifth of the error of 8. These are VectorCraft's own values. The
exception keeps gray flat art of up to 16 clean levels on its old
route. Pictures with more than 5% of their opaque pixels outside that
8-level range are unchanged.

Anti-aliased or noisy gray flat art can now take the smoothed route as
well. Very noisy gray scans of flat art get fewer specks and staircase
edges; some gray illustrations and sketches get more anchors and
staircase edges at 16 Colors and High Fidelity Photo. Some 16 Colors
and High Fidelity Photo palettes of gray photos grow toward the
requested count, with more anchors and regions, and some 6 Colors
traces get more staircase edges.
2026-11-12 06:16:48 -08:00
dotCooCoo f00ebc60b4 Merge main into fix/warp-styles-map 2026-11-12 06:16:40 -08:00
ruchirguitar be1b946b1e Docs: revision rows for the numeric-field tap tolerance (#1326) 2026-11-12 19:46:23 +05:30
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
dotCooCoo 634cfd053d Cutting Tools: Weed Box and Lines refuses a path past the point limit before copying it
A path or compound path with more anchors than the outline points left to measure is refused before its outlines are copied and followed.
2026-11-12 06:13:46 -08:00
dotCooCoo c1fee5d7a3 Palette: picks and shortcuts skip menu rows that name user data
The menu items that a pick or a shortcut reads are read once. Rows that
show a name that is user data (a custom toolbar under Window › Toolbars,
a script under File › Scripts, a recent file, a saved selection) are now
left out of them, as rows that list a plug-in already are, so a pick of
Show Toolbar no longer runs with the name of a toolbar that existed when
the items were read.

While a menu item is dimmed and the engine gives no reason (a UI
command, or an Appearance command with nothing targeted), a pick or a
shortcut now opens no dialog and shows "command `<id>` is not available
right now". The message has a row in every catalog that has the
engine's longer "not available right now" message.
2026-11-12 06:10:30 -08: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 072c0b79b9 Stroke: an arrowheads file whose data goes on past the size limit is not read
A compressed arrowheads file is refused when the data after its document, the preview included, unpacks to more than 64 MB, so the whole stream is read and its checksum checked. Other files are read as before.
2026-11-12 06:06:11 -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 e280b28393 Merge pull request #6871 from dotCooCoo/fix/eps-predefined-cmap-type
EPS import: CIDFonts only named, over a predefined CJK CMap, set their characters as live type
2026-11-12 21:04:13 +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 705503da6d Objects on Path: plug-ins may call Select and Move Object on Path
object.objectsOnPath.selectMember and object.objectsOnPath.moveMember
change only the document and its selection, as the other Objects on
Path commands do, so both join the commands a plug-in may call when its
manifest lists them.
2026-11-12 06:02:04 -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 c6579f147f Cutting Tools: Weed Box and Lines refuses a Spacing below 0
The dialog sent the Count instead of a Spacing that was not above 0, so a Spacing below 0 ran with the Count. Now only a Spacing of 0, or none, leaves the Count in use, and any other Spacing goes to the command, which refuses one below 0.
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 43b6a793b4 Color: the screen color sampler's bus tests wait for the answer without a time limit
The tests call the sampler's pick directly instead of giving it 30 seconds on another thread.
2026-11-12 05:54:24 -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 909f0ff301 SVG import: the path a text follows counts toward the <use> text limit
A text on a path that many <use> elements show was laid out along the
whole path once per <use>, and the path was found in the file and parsed
again each time, while the 1 MiB limit on texts built for <use> elements
counted only the text's nodes and characters. A file with a short text on
a very long path and many <use> elements of it could keep the importer
busy far past that limit.

- The elements of the path a <textPath> follows now count toward the
  limit. Past it, the remaining <use> elements show the text with its own
  properties, and the warning names text paths as well as text.
- The path of each <textPath> is found and parsed once and shared by
  every <use> that shows its text.

Files within the limit import as before.
2026-11-12 05:43:42 -08:00
dotCooCoo 97eecdb21e Stroke: a group used as a clipping path adds nothing to a custom arrowhead
A custom arrowhead takes a clipping path's own fills and strokes only where the clipping path paints them on the canvas. A group used as the clipping path paints nothing, so its members' fills no longer widen the head past the clipped art.
2026-11-12 05:37:07 -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 f317aefa44 Tests: the file-dialog menu test reruns while fonts or plug-ins change
`the_menu_bar_is_inert_while_a_file_dialog_is_open` excused a missing
menu row when the composite font or plug-in it named was gone at the
time of the check. A test running alongside can remove such a font and
define it again between the menu read and the check, and the test then
failed. It now runs inside `undisturbed`, as the file's other tests that
compare menu reads do. When the shortcut, plug-in or font generation
changes during a run, the test runs again on a new app. Every row from
before the dialog must then be back as it was.
2026-11-12 05:32:35 -08:00