Commit Graph
3066 Commits
Author SHA1 Message Date
Taha-Mahmoodi 00cbdecfe3 Merge remote-tracking branch 'origin/main' into fix/ruler-double-click-guide 2026-11-11 13:03:32 +04:30
BFlat b37241f5ae Merge pull request #6547 from dotCooCoo/fix/appearance-active-row-aligned-remove
Appearance: aligned Remove Item and Duplicate Item keep the active row
2026-11-11 15:33:06 +07:00
Taha-Mahmoodi 1d045ee7ba Merge remote-tracking branch 'origin/main' into fix/ruler-double-click-guide 2026-11-11 12:42:09 +04:30
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
Taha-Mahmoodi 3fed1a4cfd Merge remote-tracking branch 'origin/main' into fix/ruler-double-click-guide
# Conflicts:
#	docs/target-app-parity.md
2026-11-11 12:35:25 +04:30
BFlat 03266ce4b7 Merge pull request #6537 from dotCooCoo/fix/expand-tinted-symbol-adjustment
Expand Appearance: tinted symbols keep their colors under a color adjustment
2026-11-11 15:00:39 +07:00
dotCooCoo 99b7fb0ab8 Appearance: aligned Remove Item and Duplicate Item keep the active row
After an aligned Remove Item or Duplicate Item, the active row was
re-pointed by the indices of the first object in paint order. When the
first selected object paints above the others, its own rows that changed
are different ones, so the active row could be dropped or land on the
wrong row, and a later paint edit changed that row instead.

The active row now follows the rows removed or copied in the first
selected object's own stack.

Follows #5591.
2026-11-10 23:58:23 -08:00
BFlat 902f217ef6 Merge pull request #6539 from dotCooCoo/fix/break-link-keeps-new-art-selected
Symbols: Break Link keeps new art on a locked artboard selected
2026-11-11 14:52:56 +07:00
BFlat df7a185cb2 Merge pull request #6534 from dotCooCoo/fix/reshape-earlier-steps
Reshape: a step recorded without focal points plays by the earlier rule
2026-11-11 14:48:26 +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 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
BFlat dac55268e3 Merge pull request #6529 from dotCooCoo/fix/store-put-size-bound
Stores: saving a preset, profile or plug-in reads at most one byte past it from the file it replaces
2026-11-11 14:17:50 +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
dotCooCoo de5323efb6 Expand Appearance: tinted symbols keep their colors under a color adjustment
Expand Appearance on a symbol instance with a fill tint and a color
adjustment applied the adjustment to the untinted art, so the expanded
colors differed from the canvas. The expand path now passes the tinted
instance art to adjust_in_document.
2026-11-10 23:05:53 -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
dotCooCoo 9bfd6b7be5 Paths: describe the anchor added on a selected segment as an end of its halves
A selected segment that path.insertAnchor splits stays selected as its
two halves. The new anchor is the end both halves share, so it moves
with them, and Delete cuts both halves. docs/mcp.md and the comment on
renumber_after_insert called it a direct-selected anchor; they now
describe it as an end of the halves that moves with them.
2026-11-10 23:00:40 -08:00
dotCooCoo 988bfeb6ec Symbols: Break Link keeps new art on a locked artboard selected
Break Link to Symbol on an instance just placed on a locked artboard
selected nothing: the art that replaced the instance has a new id, so the
locked-artboard check did not see it as new art. The art of an instance
that was new art is now checked without the locked artboards, and the
session keeps it selected as new art. The art of an older instance on a
locked artboard, named by id, is still left out of the selection.
2026-11-10 22:54:05 -08:00
Taha-Mahmoodi 7ea98202ad Merge origin/main at 8b6c7444b into ruler guide fix 2026-11-11 11:19:54 +04:30
dotCooCoo 08387a22ec Merge main into feat/script-include-directives 2026-11-10 22:39:32 -08:00
dotCooCoo 1f1b7a8b7c Scripts: test that an include ending in a carriage return keeps the next line's number 2026-11-10 22:36:45 -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 4110f8c24e Reshape: a step recorded without focal points plays by the earlier rule
Before the Reshape tool had focal points it sent path.reshape without
focal or radius, and the command stretched an open path from the grabbed
point to its ends whatever the selection, and moved the anchors of a
closed path within half the diagonal of its bounding box with a
falloff. Such a step, in a saved action or a script, now moved a closed
path whole. A step without focal (or with focal null) and without
radius now plays by that earlier rule. The Reshape tool always sends
focal, an empty list included, so its drags keep the focal-point rule.
2026-11-10 22:30:19 -08: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 fdbf85d4c8 Stores: saving a preset, profile or plug-in reads at most one byte past it from the file it replaces
Before writing a PDF preset, ICC profile, plug-in, Color Settings,
disabled list or grants file, the store compared the new bytes with the
file already there by reading the whole file into memory, so a large file
left in the folder was read in full. The comparison now reads at most one
byte more than the new content.
2026-11-10 22:24:39 -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 fd9c7a2073 Merge main into feat/script-include-directives 2026-11-10 22:13:57 -08:00
BFlat 99cbdf9b73 Merge pull request #6520 from dotCooCoo/fix/break-link-selects-only-selectable-art
Symbols: Break Link selects no art inside a hidden or locked group
2026-11-11 13:05:00 +07: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
BFlat b34c652a60 Merge pull request #6514 from ruchirguitar/fix/5820-general-units-for-unitless-files
#5820: files that record no units open in Preferences › Units › General
2026-11-11 12:35:44 +07: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 d069e0e4be Symbols: Break Link selects no art inside a hidden or locked group
Break Link to Symbol on a selected group selected the art of every
instance it expanded that was itself shown and unlocked, including art in
a hidden or locked group inside the selection. The art now goes into the
selection only when it and every group and layer holding it are shown and
unlocked, the check Select All uses (select::is_selectable).
2026-11-10 21:08:57 -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 22ec820569 Merge pull request #6513 from dotCooCoo/fix/break-link-keeps-hidden-locked
Symbols: Break Link keeps a hidden or locked instance's art hidden or locked
2026-11-11 12:00:47 +07:00
BFlat acc6acfdb2 Merge pull request #6266 from Silvertree2010/fix/h13526-graph-csv-round-trip-drops-a-bla
Keep blank value row in single-column graph CSV round trip
2026-11-11 11:52:07 +07: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
ruchirguitar f5daa27a2f #5820: files that record no units open in Preferences › Units › General
A PDF, an EPS or .ai without ruler units, a raster image, a metafile, an
Affinity file or an importer plug-in's document opened (and reverted) in
points whatever the General unit was. They now open in the General unit,
as the reference app opens files that record no unit. Native, SVG and DXF
files and a .ai or EPS with %AI5_RulerUnits keep their own units. Only the
displayed units change, not the art.
2026-11-11 09:56:19 +05:30
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
NetterSilverandClaude Haiku 5.5 aaf27e1ec6 Keep blank value row in single-column graph CSV round trip
Found while testing crates/engine/src/cmd/graph/data.rs:51 (parse_csv); written by crates/doc/src/graph.rs:497 (GraphSpec::to_csv)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-11 04:16:30 +00:00
dotCooCoo 2faadd28f4 Symbols: Break Link keeps a hidden or locked instance's art hidden or locked
Break Link to Symbol on a selected group, and Delete Symbol with its
instances expanded, turned a hidden or locked instance into visible,
unlocked art. The art now keeps the instance's hidden and locked state,
as Object > Expand does, and Break Link leaves hidden or locked art out of
the selection.
2026-11-10 20:09:28 -08: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
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 a06ab45911 Scripts: every script label in a Scripts folder level stays distinct
A script renamed to its whole file name could take the label another
script kept, as with tidy.js, tidy.jsx and tidy.js.js in one folder.
The rename now repeats until no label is shared. A folder entry whose
type cannot be read now marks the listing as incomplete.
2026-11-10 18:48:59 -08: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