A linear dimension between two clicked points, or dragged out from a
segment, always measured the straight distance between its points and
drew its line parallel to them, so two points at different heights gave
only a slanted dimension. The linear dimensions help describes aligned,
horizontal and vertical linear dimensions: after the second click,
clicking again gives an aligned one and moving the pointer gives a
horizontal or vertical one.
https://helpx.adobe.com/illustrator/desktop/measure-and-align/plot-and-measure/plot-linear-dimensions-of-objects.html
While a linear dimension is being placed, the pointer's position sets
whether it is aligned, horizontal or vertical. The rule is VectorCraft's
own. With the pointer beside the two points (the nearest point of the
line through them lies between them) or on that line, the dimension is
aligned. Past either point, the line through the points and the
perpendicular through that point bound a quarter on each side of the
line. The quarter that holds the direction straight up or down gives
the horizontal distance, and the quarter that holds the direction
straight left or right gives the vertical distance. A click within
reach of the second point, or of where the pointer was for the second
click, places it aligned. Points on one horizontal or vertical line
give an aligned dimension. The dimension stays linked to the anchors it
measures.
- Dimension recipes carry an orientation (aligned by default; files
without it open as before). The line runs along the axis, and each
extension line runs from its point to it.
- dimension.create and dimension.update take orientation: aligned,
horizontal or vertical, for linear dimensions only. Any other value
is an error. A new orientation keeps the line on the side of the
points it was on, and an update that changes nothing records no
undo step.
- A horizontal or vertical dimension keeps its orientation when it or
the art it measures turns, and shows 0 when its points come into line
across its axis. A line that lay outside the points stays outside
them after a turn.
- The hint bar names the two-click placement.
Docs: docs/dimensions.md, the Evidence list in docs/target-app-parity.md.
The check that refuses a symbol instance before its art is placed
counted only the symbol's own objects. Placing art through 9-slice
guides can make up to 28 objects of each one, and an instance's
dynamic-symbol overrides can turn a path that would be cut at the
guides into clip groups in every cell it reaches. Such an instance
passed the check, and its art was placed in full before the work
limit refused it.
The check now counts the symbol's own objects first, then the most
objects placing makes (NineSliceMap::most_placed) of the art with the
instance's overrides applied, and refuses the instance with the same
message before anything is placed.
transparency.makeOpacityMask read `clip` and `invert` with bool_or,
transparency.setOpacityMask read `clip`, `invert`, `disabled` and
`linked` with as_bool, and the New Opacity Masks and page toggles read
`value` with bool_or, so a value of the wrong type was dropped:
"clip": "false" made a clipping mask, "invert": "yes" next to another
flag was ignored, and "value": "on" toggled the page knockout group.
They are now read with switch_or, and such a value is an error that
names the param, before anything changes. Omitting a param or giving
null keeps its default.
A plug-in that went on calling after a failed `vc_call` still had each
later call made on the document, although the run fails and is undone
at its end. After the run's first failed call, `vc_call` now returns
`-11` (CALL_NO_CONTEXT) and the host makes no further call; the run
still fails with the first call's reason.
object.path.offsetPath, object.path.simplify, object.path.splitIntoGrid,
object.path.cleanUp, object.pathfinder.trap and addon.contour.set read
their params with helpers that fell back to the default for a value of
the wrong type: "offset": true offset by 10 pt, "joins": 3 gave mitered
joins, "addGuides": "yes" added no guides. Each such value is now an
error naming the param, and the document and the undo history stay as
they were. An omitted or null param keeps its default, and a distance
still takes a string with a unit ("5 mm"). An unknown `joins` name is
refused as well.
Make Compound Path leaves each member's graphic style id in place. A
member copied or cut on its own took the compound's appearance but kept
that old id, so the clipboard carried an unrelated style and the pasted
path was linked to a style that did not match its look.
The copied member or piece now takes the compound's link while it has
that style's look, and no link otherwise (no style on the compound, or
a gradient pinned to the compound's bounds). It also takes the
compound's knockout setting with the rest of its transparency.
object.expand read `object`, `fill` and `stroke` with bool_or, `steps`
with f64_or and `gradient` with str_param, so a value of the wrong type
fell back to the default: "fill": "yes" expanded the fill, "steps": "16"
made 255 strips and "gradient": 3 made strips. They are now read with
switch_or, number_or and text_param, and such a value is an error that
names the param, before anything changes. Omitting a param or giving
null keeps its default.
A 3D effect on a symbol instance placed a copy of the symbol's whole art
before counting it against the effect's work limit, so a symbol far past
the limit was copied in full on every check and redraw before it was
refused. The symbol's objects are now counted first, and a symbol that
would pass the limit is refused with the same message without being
placed.
Three Extrude & Bevel dialog tests used a clipping group as their example
of an object a 3D effect refuses, and clipping groups now apply. Their
helper now places an image, and they check for the image message ("can't
build a solid from an image") in place of "requires a path".
They switch the process-wide Color Settings away from the defaults, which
every colour the engine's unit tests show or render goes through, so they
move to tests/color_settings.rs as the note on colormgmt's GLOBAL asks. The
round-trip test now also unregisters the loaded profile before the next
session, so it shows the profile store registering it again before the saved
settings name it.
A drop guard puts the default settings back, unregisters the loaded profile
and deletes the temporary files, so a failed assertion no longer leaves the
process-wide colour state changed for the next test holding GLOBAL.
The interpreter runs skipped every test with a missing built-in's name
anywhere in a string literal, so a test that only mentions Boolean in
a message or in text data was never run. A string now counts when it
is the name alone (a property key such as this["Map"]), or when the
test or an included harness file can run strings as code (eval,
Function or a constructor property, by name or by string key).
Identifiers and property names count as before, and a source that does
not tokenize as ES5 is still skipped.
At tc39/test262 d53ebc8b, language/types/string/S8.4_A6.1.js and
S8.4_A6.2.js now run and pass: the language run goes from 2,459 tests
(205 skipped) to 2,461 (203 skipped), and the failure lists are
unchanged.
A call whose arguments hold a file or folder key at any depth, such as an
effect's textureImage.path, is refused before the command runs; the walk
keeps its own stack. Each call also runs with automation file access
confined to no roots, so every checked read or write a command makes is
refused, whichever param carried the path.
Create Gradient Mesh, a Mesh tool click and Object > Expand of a gradient
to a mesh gave each border edge one cubic fitted between two mesh points
and picked the corners from the bounding box, so the border cut off
corners and curves: 49 pt off a five-point star, 54 pt off a notch.
- The border follows the outline of the largest subpath by length; border
points sit on it and an edge with no anchor inside is the exact piece
of its segment.
- Where no single cubic follows a run within 0.1 pt (a thousandth of the
size on a small outline), a mesh line goes through an anchor, the
sharpest corner first; at most 256 lines each way. Rectangles and
ellipses keep the rows and columns asked for.
- Smooth runs keep their end tangents; border handles are no longer made
collinear.
- To Center and To Edge highlight placement accounts for the extra lines
(for_path_shaded, also used for gradient fills).
- Non-finite points give no mesh; a degenerate outline keeps the old
bounding-box mesh.
Holes of a compound path are still left out, as before.
Docs: docs/target-app-parity.md.
- PDF 1.3 and 1.4 files, PDF/X-1a, PDF/X-3, PDF/X-4 and PDF/A-2b at
PDF 1.4 among them, write a page longer than 14,400 pt in points
again, now with a warning that apps that keep to the limit cut it to
200 in. Only a page that failed with
"PDF writer error: Limit(TooLargeFloat)" gets the new error: one
whose size or art needs a real number past 32,767, the most PDF 1.4
holds. Whole numbers are written as integers, so a page of whole
points past 32,767 is written as before.
- A page whose side is past 32,767 pt and not a whole number of points
is refused before the thumbnails are drawn and the transparency is
flattened.
- A PDF 1.5 file written as PDF 1.6 for a long page keeps PDF 1.5's
encryption (128-bit RC4), which the Save PDF dialog shows.
- A long page whose short side would be under 3 units at its UserUnit
(ISO 32000-1, Annex C.2), such as 50 m x 4 mm, gets a smaller
UserUnit that keeps the short side at 3 units, with a warning.
- The warnings give a page's size rounded up, as the error does.
A page of 14,400 pt or less is written as before. The new warning has
rows in every complete catalog. Docs: docs/mcp.md,
docs/target-app-parity.md and the document.exportPdf params.
`Session::history_budget` (default `default_history_budget()`) caps the
memory the undo steps of all open documents keep together. After each
command, tool edit, interaction commit, direct edit, framed script run
and closed undo group, `Session::trim_histories` drops the oldest steps
of any document first, undo steps before redo steps. Each document keeps
its last eight undo steps and next eight redo steps, and a held history
keeps all of its steps. While a script runs or an undo group is open,
no steps are dropped, so a canceled group leaves the other documents'
steps in place. Closing a document frees its share. The steps are not
counted again while neither the budget nor any history changed. Each
document's own `byte_budget` stays as its ceiling.
edit.colorSettings set only the process-wide colour settings, so the RGB and
CMYK working spaces, intent and black point compensation went back to the
defaults at every start, although the profiles color.loadProfile loads are
kept (#2168, #2174). The engine now writes them to a settings file when they
change (Session::attach_color_settings), and the desktop app and
vectorcraft-cli keep that file as `Color Settings.json` next to the
preferences, attached right after the profile store so a saved working space
may be a loaded profile. Saved settings that can't be used (a profile that is
gone, a damaged or oversized file) leave the defaults with a log record, and
the next change writes over them. Nothing is read or written with
VECTORCRAFT_NO_PREFS.
A compound member copied or cut on its own now keeps the compound's
gradient fitted where it was: an unplaced gradient is pinned to the
compound's bounds, measured once per compound.
Clear that deletes every anchor or segment of every member of a compound
path now removes the compound too, as Cut does, instead of leaving an
empty compound in the layer.
The edit.copy and edit.clear descriptions, docs/mcp.md and the progress
line now say that selecting the compound copies it whole, that isolation
mode takes each member as itself, and how a compound of one and Paste in
Front with the copied member still selected behave.
Two installed versions of one font are two fonts of the set, so each
keeps its own /5. The generated variable test font now has a version
(name ID 5), and the test checks each variable record writes it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vc_call returning -11 (from the start function, or in a run that can't make
calls) now fails the run like every other code, so a plug-in that ignores
it can't report success for a call that never ran. Calls are allowed once
the module has loaded, so a start-function call gets -11 instead of
trapping.
A run that calls imageTrace.make used to take the trace the app handed in
for the command, and a failed run did not give it back. The trace is now
set aside while the run goes and handed back after it.
The message for a group member that can't become a solid now names groups
and clipping groups too. docs/three-d.md states that an image left out of a
clipping group also needs no visible fills or strokes of its own.
A compound-path member selected on its own, whole with Direct Selection
or with Group Selection, is now copied as an ordinary path instead of
promoting the selection to its compound. Cut removes the same objects
Copy takes, so the other members stay a compound path, a compound of
one included. The compound is still taken whole when every member is
selected whole, or when the compound itself is selected.
A copied member or piece takes the compound's paint, opacity, blending
mode, opacity mask, pixel alignment and fill rule.
Tests that pinned the earlier rule from #786 now check the new one.