Commit Graph
2020 Commits
Author SHA1 Message Date
BFlat 264ca9bf4e Merge pull request #6559 from dotCooCoo/fix/dimension-expand-keeps-live
Dimension tool: a dimension selected with its art stays live through Expand and Outline Stroke
2026-11-11 17:16:39 +07:00
BFlat 9a28264cfe Merge pull request #6557 from dotCooCoo/feat/script-alert-confirm-prompt
Scripts: alert, confirm and prompt open dialogs with Stop, and headless runs take their answers from script.run
2026-11-11 17:13:46 +07:00
BFlat e1c199a184 Merge pull request #6552 from dotCooCoo/docs/dynamic-symbols-edit-symbol-keeps-links
Docs: the Dynamic symbols entry says Edit Symbol keeps instances linked
2026-11-11 16:48:07 +07:00
dotCooCoo d13f7324f9 Dimension tool: a dimension selected with its art stays live through Expand and Outline Stroke
A dimension selected with the art it measures became a plain group of
paths and text when Object › Expand, Object › Expand Appearance or
Object › Path › Outline Stroke ran, so it no longer redrew when moved
or restyled.

These commands now leave such a dimension's lines and label as they
are, also inside selected groups without fills, strokes or effects of
their own, and change only the other art. The dimension keeps its
export assets and variable bindings. When the new art no longer fits
the dimension's link, for example because the outlined stroke has
other anchors, the dimension stays where it was, no longer linked, as
it does when its art is deleted. Undo links it again.

When the dimension is all the command would change, the command
changes nothing and reports the error it gives for a selection with
nothing to change. Object › Expand… is no longer dimmed for the label
of such a dimension. A dimension selected without the art it measures,
a part of one, and one inside a selected group with an appearance of
its own still become plain groups, and Type › Create Outlines still
outlines the label.

Docs: docs/dimensions.md, docs/mcp.md, docs/target-app-parity.md.
2026-11-11 01:26:12 -08:00
dotCooCoo c0adc6e9d7 Merge main into feat/script-alert-confirm-prompt 2026-11-11 01:09:54 -08:00
dotCooCoo 68042f0924 Docs: the Dynamic symbols evidence lists the Edit Symbol tests 2026-11-11 00:57:15 -08:00
dotCooCoo ba5eab7349 Docs: Edit Symbol keeps dynamic symbol instances linked
The Dynamic symbols entry still said Edit Symbol expands the symbol's
own art. Since #5064, Edit Symbol opens symbol editing mode: every
instance stays linked and a dynamic symbol's instances keep their
changes for the objects the edited art still has.
2026-11-11 00:36:07 -08:00
Fabio William Conceição 50bf4fc5a3 G5: built-in Inventory Icons symbol library 2026-11-11 08:34:55 +00:00
BFlat ed234780f2 Merge pull request #6540 from dotCooCoo/fix/pdfx1a-flatten-clipping
PDF export: PDF/X-1a, X-3 and 1.3 keep the art under the hidden part of cropped art
2026-11-11 15:08:42 +07:00
BFlat 05f2be5588 Merge pull request #6528 from dotCooCoo/fix/insert-anchor-keeps-selection
Paths: Add Anchor Point keeps the same anchors and segments selected
2026-11-11 14:48:16 +07:00
BFlat 7771355529 Merge pull request #6535 from jmverges/fix/3179-half-stroke-box
.ai import: stroked type in an envelope maps from its glyphs grown by half its stroke
2026-11-11 14:39:40 +07:00
BFlat 0127ed3ec9 Merge pull request #6536 from dotCooCoo/feat/script-include-directives
Scripts: #include and the other preprocessor lines run, and $.evalFile runs a file
2026-11-11 14:31:44 +07:00
BFlat 3e642efce6 Merge pull request #6530 from dotCooCoo/fix/vertical-path-sideways-glyphs
Type: on a vertical path, letters lie a quarter turn clockwise from upright glyphs, in a column centered on the path
2026-11-11 14:22:33 +07:00
dotCooCoo 22189986a9 PDF export: flattening for PDF/X-1a, X-3 and 1.3 keeps art across clipping layers
- PDF/X-1a, PDF/X-3 and PDF 1.3 files leave the layers they don't print
  out of the flattening. A flattened group no longer takes the place of
  art in a layer that doesn't print, so the art of a clipping layer over
  such a layer prints, and art of a layer that doesn't print stays out
  of the file.
- A flattened group goes into a lower layer only when that layer prints,
  shows and is a template as the clipping layer does, the clipping layer
  and the groups it leaves have no opacity, blend mode or isolation, and
  the clipping path has no fill. Otherwise the group holds only the art
  inside the clipping layer, drawn over the clipping path's fill and the
  art below, and the art below is flattened on its own. Before, the fill
  covered the group, the group lost the layer's opacity, or the clipping
  path cut the art below.
- Transparent art that a clipping path hides entirely, such as one of
  area type holding only a space, is removed. Before, the export failed
  because the art kept its transparency.

Object › Flatten Transparency follows the same rules. Documents without
clipping layers or layers that don't print export the same bytes as
before.
2026-11-10 23:08:31 -08:00
BFlat fe346e53be Merge pull request #6527 from dotCooCoo/fix/dimension-follow-both-ends
Dimension tool: both ends of a dimension follow the art it measures
2026-11-11 14:03:40 +07:00
jmvergesandClaude Opus 5.5 6701a1f8e5 .ai import: stroked type in an envelope maps from its glyphs grown by half its stroke
With Distort Appearance, the stroked candidate for type in an envelope
mapped from the type's bounds with strokes, which for a stroke on the
type's appearance (or on a group round it) reach as far as a miter join
may at a corner, the miter limit times half the weight. In users' files
the drawn art maps from the glyphs grown by what the strokes paint along
a side: half the weight of a centred stroke. The candidate now uses that
box. Character strokes keep the measure the type's bounds with strokes
already give them (they have no miter allowance), and other objects in
the contents keep their bounds with strokes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 06:49:26 +00:00
dotCooCoo 2fc07fe3c0 Merge main into feat/script-alert-confirm-prompt
# Conflicts:
#	crates/engine/src/tests.rs
#	crates/ui-egui/src/app.rs
#	docs/target-app-parity.md
2026-11-10 22:40:45 -08:00
dotCooCoo 08387a22ec Merge main into feat/script-include-directives 2026-11-10 22:39:32 -08:00
BFlat b421c03d03 Merge pull request #6525 from dotCooCoo/feat/scripts-folder
Scripts: File › Scripts lists the Scripts folder, subfolders as submenus
2026-11-11 13:33:56 +07:00
dotCooCoo 5a8a57d5f6 Type: upright glyphs on a vertical path keep vertical point type's cells, and the caret spans the column
On a vertical path, an upright glyph is now placed in its column as
vertical point type places it, then the column is centered on the path.

- Its cell starts at its place on the path; it started 0.12 em earlier
  with fonts whose cell top is less than a full cell above the baseline.
- A baseline shift moves it across the column instead of along the path.
- A horizontal scale widens it evenly about the column's center.
- A combining mark stays on its upright letter.
- The caret and the selection highlight span the column, half its em on
  each side of the path, instead of the font's ascent and descent.

With Skew, 3D Ribbon and Stair Step on a path that runs to the left,
letters are a quarter turn counterclockwise from upright glyphs: Skew and
3D Ribbon mirror both kinds there, and Stair Step keeps letters level. The
test, the progress doc and the params text of Tate-chu-yoko Settings now
state these conditions and the block's directions on a path.
2026-11-10 22:27:53 -08:00
dotCooCoo f4496d61aa Paths: Add Anchor Point keeps the same anchors and segments selected
path.insertAnchor (the Add Anchor Point tool, the Pen's Auto Add, the
Smart Pen's Alt-click on a segment and Alt-click with the Scissors)
added the anchor without changing the selection, so the direct-selected
anchors and selected segments after it on the subpath kept their old
numbers and the selection shifted onto the next points along. It now
renumbers them with renumber_after_insert, the helper path.reshape
uses. A selected segment that the new anchor splits stays selected as
its two halves, and the new anchor is direct-selected with them. Undo
restores the path and the selection in one step.

Docs: params text, docs/mcp.md, docs/target-app-parity.md.
2026-11-10 22:17:08 -08:00
dotCooCoo 58623b34b1 Merge main into feat/script-alert-confirm-prompt 2026-11-10 22:14:59 -08:00
dotCooCoo df0373aa26 Scripts: alert, confirm and prompt open dialogs with Stop, and headless runs take their answers from script.run
alert(message[, title, errorIcon]), confirm(message[, noAsDflt, title])
and prompt(message, preset[, title]) are globals in a script run. In the
app the run waits at the call for the person's answer, spends no
instructions while it waits, and every dialog has Stop, which ends the
run and puts every document back. A run over MCP or the command line
takes its answers in order from script.run's answers, a list of
{kind, value} records; a missing, mismatched or unused answer ends the
run. The report lists each dialog with its answer in dialogs, with
dialogCount and dialogsTruncated.

The interpreter gains a host call that waits at the call for its
result, from the script's own code only; a dialog called in a callback
of a built-in, a getter or a conversion throws in the app.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-10 22:14:01 -08:00
dotCooCoo 693031c509 Scripts: #include and the other preprocessor lines run, and $.evalFile runs a file
Before a script runs, `script.run` reads its preprocessor lines (`#` or
`//@` at the start of a line, outside strings and comments):

- `#include` and `//@include` put another file's text in place of the
  line, looked for beside the including file, then in each
  `#includepath` folder, then in each `JSINCLUDE` folder. A later
  `#includepath` replaces the list.
- `#script` names the run unless `name` is given; `#target` takes any
  value; `#strict off` is taken. `#strict on`, `#targetengine` and
  `#engine` are refused as unsupported, and any other `#name` as
  unknown.

`$.evalFile(path, timeout?)` runs a file in the same global environment
and returns its last value, `$.fileName` is the file being run and
`$.includePath` the include folders.

A script run from a file reads these files only in its folder and the
folders below it. Paths with a `..` name, links or junctions that lead
out, device names, streams and network paths are refused; a script
given as text reads none. A run reads at most 64 files 16 levels deep,
32 MiB of source in all and 1,024 paths looked up. An error in an
included or evaluated file is reported at that file's line and column,
and the report's new `file` field names it.

Docs: docs/mcp.md (script.run, Script Console), docs/target-app-parity.md.
2026-11-10 21:59:22 -08:00
BFlat 0695db3ec0 Merge pull request #6519 from dotCooCoo/feat/reshape-focal-points
Reshape: a click sets a focal point and a drag moves every focal point
2026-11-11 12:53:37 +07:00
dotCooCoo f8307b19cd Type: on a vertical path, letters lie a quarter turn clockwise from upright glyphs, in a column centered on the path
Follows #5557. Letters and digits lying on their side in vertical type on
a path kept their top toward the path's end, opposite the upright glyphs.
They are now set as horizontal type on the path sets them: baseline along
the path, top to the path's left, a quarter turn clockwise from upright
glyphs (CSS Writing Modes 3, Unicode UAX #50).

- The column is centered on the path: upright glyphs, letters on their
  side and tate-chu-yoko blocks have their em box centers on the path
  line instead of a column one em wide to the path's right.
- Upright glyphs are turned in the path effect's glyph space, so with
  Skew on a curve their top runs back along the tangent and their x axis
  stays up the page, as letters keep theirs.
- Tate-chu-yoko blocks on a path stand upright, stay whole on a curve and
  move by Tate-chu-yoko Settings toward the path's start and left.
- A tate-chu-yoko block of mixed sizes sets every glyph in its first
  character's em, on a path and off it.

Existing vertical type on a path redraws with these placements.
2026-11-10 21:36:30 -08:00
dotCooCoo ef6d14dc22 Dimension tool: both ends of a dimension follow the art it measures
A linear dimension clicked from an anchor to a point that is not an
anchor (a point on a segment, or a point a Smart Guide gave) followed
the art at the anchor end only, so scaling the art turned it into a
long slanted dimension.

- A point on a segment is stored by its curve parameter on that
  segment, and stays on it when the segment's anchors or handles are
  edited.
- Any other point is stored against anchors (and, for a path whose
  anchors lie on one line, handles) of the path under it, or of the
  path at the other end, and moves, scales, turns and reflects with
  that path. Beside a path whose anchors and handles all lie on one
  line, such as a straight line, it keeps its distance along and
  across the path: a reflection moves it as a half turn does, and a
  scale that is not uniform moves it as a uniform scale does.
- When linked art is reflected, a linear dimension's line goes to the
  reflected side, except for art whose anchors and handles lie on one
  line.
- Deleting the art, changing its anchor count or whether it is closed,
  turning an angle's arm into a curve, or making a measured circle or
  arc no longer circular leaves the dimension where it was, no longer
  linked, instead of removing it. Undo links it again.

Docs: docs/dimensions.md, docs/target-app-parity.md.
2026-11-10 21:25:59 -08:00
dotCooCoo 39996d3d2c Merge main into feat/scripts-folder
# Conflicts:
#	crates/engine/src/cmd/scripts.rs
#	crates/engine/src/tests.rs
#	docs/gaps.md
#	docs/mcp.md
#	docs/target-app-parity.md
2026-11-10 21:08:10 -08:00
BFlat bc814012d9 Merge pull request #6511 from dotCooCoo/feat/artboard-color-labels
Artboards: an artboard's guide label colors its own guides
2026-11-11 11:27:16 +07:00
dotCooCoo bd39674469 Reshape: a click sets a focal point and a drag moves every focal point
A click with the Reshape tool on an anchor of a selected path makes it
the focal point, and a click on a segment adds an anchor there that
becomes the focal point. Shift-click adds an anchor or a point on a
segment to the focal points, or removes an anchor that is one already.
Each focal point shows a filled anchor square in a larger hollow one.
A drag from a focal point moves all of them; a drag from another point
moves that point alone, and Shift only keeps the drag's angle.

path.reshape takes the other focal points as focal: [[subpath,
anchor]...]. Anchors that are not direct-selected stay in place, and so
do the ends of an open path unless they are focal points. A selected
anchor between two focal points moves by the whole drag, and one
between a focal point and an anchor that stays takes u² (3 - 2u) of
the drag, as before. A closed subpath with every anchor selected moves
whole: a Reshape drag on a fully selected closed path, and path.reshape
without radius on a closed path selected whole or not selected, move
the whole path instead of a local area. With radius, only the grabbed
point's subpath changes, with the falloff as before.

- An anchor added on a segment of a partly selected path is selected,
  and the selected anchors and segments after it keep their points.
- A focal pair that names no anchor is refused ("`focal` names [0, 7],
  which is not an anchor of the path"), and so is focal with radius.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-10 20:18:23 -08:00
BFlat 726d2b6e13 Merge pull request #6508 from jmverges/fix/3179-warps-of-type-as-mesh
.ai import: warps of type open as mesh envelopes on their saved grid
2026-11-11 10:48:16 +07:00
BFlat 98fe060bb0 Merge pull request #6499 from dotCooCoo/feat/script-console
Scripts: Window › Script Console shows script output, errors and run reports
2026-11-11 10:48:06 +07:00
dotCooCoo beef32b8a3 Artboards: an artboard's guide label colors its own guides
Each artboard can carry a guide label: one of the layer colors or a
custom RGB. Guides that belong to an artboard draw in its label color,
and guides without an artboard, or on an artboard without a label, keep
the guide color from the preferences. Selected guides still draw in the
selection color.

- Artboard Options has a Guide Label row (None, the layer colors with
  swatches, or Custom with a color swatch).
- artboard.new and artboard.setProps take guideLabel: null, a layer
  color's name, or #rrggbb. Any other value is an error. The inspect
  summary lists guideLabel when one is set.
- The native format saves the label and skips it when unset; a preset
  index outside the layer colors reads as no label.
- artboard.setProps no longer adds an undo step when nothing changes.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-10 19:37:17 -08:00
dotCooCoo 259bd8ee25 Merge main into feat/scripts-folder 2026-11-10 19:10:00 -08:00
jmvergesandClaude Opus 5.5 d85a967fb7 docs: envelope grid orientation and retry budget for warps of type
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 03:06:48 +00:00
jmvergesandClaude Opus 5.5 8820a15e20 docs: warps of type as mesh envelopes on their saved grid
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 03:06:24 +00:00
BFlat ec89f3f26e Merge pull request #6501 from dotCooCoo/feat/prefs-export-import
Preferences: export and import preferences as a JSON file
2026-11-11 10:01:01 +07:00
dotCooCoo ea9b93d3ce Merge main into feat/scripts-folder 2026-11-10 18:28:59 -08:00
BFlat 4c2b8df865 Merge pull request #6498 from dotCooCoo/fix/smart-guides-snap
Smart Guides: tools do not snap to Smart Guides while Pixel Preview is on
2026-11-11 09:26:08 +07:00
dotCooCoo 04c20fc8b9 Merge main into feat/scripts-folder 2026-11-10 18:24:29 -08:00
dotCooCoo d426c70a92 Preferences: export and import preferences as a JSON file
Part of #6435. An optional VectorCraft feature: the Preferences dialog's
Export Preferences... saves the applied preferences to a JSON file (the
web build downloads it), and Import Preferences... applies such a file and
shows the imported values. They run the new commands prefs.export {path?}
and prefs.import {path | data}.

The file holds every preference prefs.list lists and the eyedropper,
perspectiveWidget, pathfinder and glyphSnap groups, without the four
folder preferences and saved presets. prefs.import reads at most 1 MB and
checks every value first: another format, a newer version, an unknown
preference, a bad value or a folder preference is an error, and nothing
changes. It keeps the open document's units, records no undo step, and is
refused as a command.batch step. prefs.set now rejects a group value that
is not an object.
2026-11-10 18:11:01 -08:00
BFlat af66951c41 Merge pull request #6496 from dotCooCoo/feat/ruler-artboard-guides
Guides: an option makes Cmd/Ctrl ruler drags artboard guides
2026-11-11 09:04:35 +07:00
dotCooCoo 5bc51a7c35 Merge main into feat/scripts-folder 2026-11-10 18:04:28 -08:00
BFlat 69d36e961d Merge pull request #6494 from dotCooCoo/feat/dimension-horizontal-vertical
Dimension tool: linear dimensions measure horizontally, vertically or aligned
2026-11-11 08:50:56 +07:00
dotCooCoo 899b7bdb3d Merge main into feat/scripts-folder 2026-11-10 17:47:11 -08:00
dotCooCoo 52efba54aa Scripts: File › Scripts lists the Scripts folder, subfolders as submenus
File › Scripts now lists the .js and .jsx files of the Scripts folder next
to the preferences, each named after its file without the extension, with
each subfolder as a submenu, above Check Script… and Other Script…. The
help page describes this listing:
https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/install-and-run-scripts.html

Choosing a listed script runs it through script.run without the warning
Other Script… shows. script.listInstalled returns the same listing, and
ui.runInstalledScript {path} runs one entry.

VectorCraft's own rules: the folder is read off the UI thread when the
app starts, when its window becomes active and when the File menu of the
window's menu bar opens; only names are read; links, junctions, hidden
and system entries are left out and checked again before a run; one read
stops at 2,048 entries, 512 scripts, 128 subfolders, 4 levels or 250 ms
and the menu then notes that some scripts were not listed. Under an
automation read root, script.listInstalled and ui.menu.list leave out a
folder outside the root.

#1183 (LloydNicholson) also proposed a Scripts menu listing a folder.
2026-11-10 17:46:36 -08:00
dotCooCoo c6e29fa227 PDF export: PDF/X-1a, X-3 and 1.3 keep the art under the hidden part of cropped art
Flattening for PDF/X-1a, PDF/X-3, PDF 1.3 and EPS rasterized a picture,
gradient, pattern, mesh or raster effect over its whole frame when a
clipping mask cropped it. The hidden part came out as opaque white and
covered the art under it, on the same page and on the next one.

- Flattening rasterizes clipped art only where its clipping path shows
  it, nested clip groups included.
- Art in a clipping layer is flattened as the layer's clipping path
  shows it. A flattened group that also holds art from outside the
  layer takes the place of that art, so the layer's clipping path no
  longer cuts it.

Documents in which no clip group hides flattened art, and no clipping
layer holds it, export the same bytes as before.
2026-11-10 17:44:40 -08:00
dotCooCoo 4060480ef1 Smart Guides: tools do not snap to Smart Guides while Pixel Preview is on
With View > Pixel Preview on, the tools still snapped to Smart Guides
and showed their guides; only the Object Highlighting outline was
hidden. Work with Smart Guides says Smart Guides cannot be used while
Snap to Grid or Pixel Preview is on.

ViewInfo has a pixel_preview field, and Session::with_tool_cx turns
Smart Guides (and Snap to Glyph, which needs them) off in the tools'
context while it is set. VectorcraftApp::view_info passes View > Pixel
Preview. View > Smart Guides keeps its setting.

Docs: docs/target-app-parity.md.
2026-11-10 17:43:29 -08:00
BFlat 4302b7bde4 Merge pull request #6492 from dotCooCoo/fix/reshape-stretches-whole-path
Reshape: a drag stretches an open path from the dragged point to its two ends
2026-11-11 08:31:45 +07:00
dotCooCoo df9c8d992d Merge main into feat/script-console 2026-11-10 17:27:35 -08:00