Paragraph settings given to all of a graph label's text with
text.setFormat (indents, spacing, hyphenation, Justification options,
composer, direction, kashida, kinsoku, mojikumi, burasagari and the
rest) and the label's anti-aliasing method were lost when the graph
drew its labels again, because the graph kept only a character style
for each kind of label. Each kind now also keeps its paragraph settings
and anti-aliasing method, saved with the graph in its label styles, and
the graph still sets each label's alignment for its place.
The legend spaces its entries by the kept legend settings: Legend
Across Top measures each label with its indents and spacing, both
legend layouts make room for extra leading or paragraph spacing, and a
label with a negative indent or negative space before moves right or
down so it stays clear of its swatch and of the entry above it.
In horizontal type, tracking and manual kerning are now thousandths of
the em as the Horizontal Scale draws it: at 50%, a tracking of 100 adds
0.05 em after each character. They were added at the full em while the
glyph advances took the scale, so narrow tracked type drifted from the
page of users' .ai files letter by letter. That page writes such type's
character spacing as the tracking itself in a text space as wide as the
scale, which PDF scales by it (ISO 32000-1 9.4.4). Vertical type keeps
the full em: its advances down the column don't all take the scale.
vectorcraft_text::spacing_scale gives the factor. Shaping, inline
graphics and the Optical pairs use it, and so do the conversions from
points back to thousandths of an em: the automatic kerning the Character
panel reads and Touch Type's limits (glyph_em), Combine Point Text, and
PDF import, whose tracking is now the file's Tc. Scale Text Attributes
now keeps tracked type where a horizontal stretch drew it.
SVG export writes letter-spacing in thousandths of the font size it
writes (the vertical scale), so uniformly scaled type keeps its spacing
in a viewer.
Type with both a Horizontal Scale other than 100% and tracking or manual
kerning lays out differently than before, in every document.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 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.
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.
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>
Merges of main kept both sides of conflicting edits to the milestone
table, so M3, M7, M10, M11 and M13 appeared two to four times, each
copy with a different subset of later edits. Keep one row per
milestone. For M3, M10, M11 and M13 the kept row already contains every
statement in the removed copies. For M7 no copy held them all: the kept
row gains the Hyphenation and Justification clause that only the
second copy carried.
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.
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.
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.
While the app draws a document on screen, the live-effect plug-in runs of
its first view share a 2,000 ms budget (VectorCraft's own value); each run
takes the lesser of its 5,000 ms limit and what is left. A stage left out
for time, or one that times out, fails, has no plug-in or meets Safe Mode,
draws its input art unchanged and is deferred, and the status bar says how
many. Later drawings leave a deferred stage as it is until its input or
parameters change.
- effect.deferredStatus lists the deferred stages with object, effect
index, fill or stroke, plug-in and reason, objects in symbol, pattern,
brush and opacity-mask art included.
- Effect › Refresh Deferred Effects (effect.refreshDeferred {ids?}) runs
them again with a fresh budget and returns {refreshed, stillDeferred,
failed}.
- Each document has its own budget and deferred stages; exports, Expand
Appearance and commands run every stage under the per-call limit.
- The web build has no clock for the budget: its first view runs no
plug-in effect, and a refresh runs them.
Docs: docs/mcp.md, docs/plugins.md, docs/target-app-parity.md.
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.
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.
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.
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.
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.
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.
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.
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.
The panel's note and the doc comment on ui.copyScriptConsole now say the
count of dropped and cut lines appears only when there are any, and the
returned lines count leaves that line out.
A copy of every Script Console line starts with the count of dropped and
cut lines only when there are any, and the returned lines count leaves
that line out. The end-line text is described without a code span that
ends in a space.