An Alt-click on an end of a selected open path makes that end the current
point without converting it, so the next click extends the path from it.
This applies to the other end too while one end is current; a plain click
there still closes the path. Alt-click on any other point still toggles it
between smooth and corner, and a double-click toggles any point, ends
included. An Alt-click that starts a new path places a corner point, as
later Alt-clicks do.
Changed behavior: an Alt-click on an end of a selected open path no longer
converts it; double-click converts it.
Help page: https://helpx.adobe.com/illustrator/desktop/draw-shapes-and-paths/draw-shapes/draw-shapes-with-the-curvature-tool.html
Follow-up to #6887.
- file.new installs the color profiles a New Document profile's file
carries when they are missing, as document.open does, so the new
document's assigned profile draws and a save embeds it. A color
profile that can't be used is listed in the result's `warnings` and
shown in the status bar.
- The new document's links find their files through relative paths
from the profile's file (`links_from`), as
edit.newDocumentFromState sets it.
- When the read roots leave out the profiles folder, profileError's
reason no longer names the folder's path.
A geometry effect on a symbol instance's topmost fill now reshapes the
filled shapes of the symbol's art, and one on its topmost stroke reshapes
the stroked shapes, keeping their colors, strokes and other detail. Only
a visible topmost fill or stroke with an opacity above 0 counts. Clipping
paths, guides and opacity-mask art keep their shapes; a group's own fills
and strokes in the art take the effects; a nested instance passes them on
to its own art, except one whose symbol holds the outer symbol.
The canvas, Use Preview Bounds and the drawn bounds, SVG and PDF export
and Object > Expand Appearance use the same art. Expand Appearance is
enabled for such an instance and turns it into an editable group in one
undo step. Bounds measure the art with a dynamic symbol's overrides, as
the canvas draws it.
Existing documents with a geometry effect on a symbol instance's fill or
stroke draw differently: before, the effect drew nothing.
The Colour, swatches, gradients, patterns, mesh, recolor row of
docs/target-app-parity.md now lists the outline fix and its two tests.
Score and hours are unchanged.
A 3D effect left an image in a clipping group out only when the image's
box missed the clipping path's box. An image in the corner of a round
clip's box, a turned image whose box reaches a clip but whose frame does
not, an image in an even-odd hole, or one inside each of two nested clips
but outside the area they show together was refused with the Image Trace
message, although it draws nothing.
The image's frame, the pixel rectangle as its transform places it, is now
cut to every clipping path around it in turn, each with its own fill rule,
and the image is left out when nothing is left. An image the clips show
any part of, a strip narrower than a hundredth of a point included, is
still refused. One effect's art cuts image frames at most 1,024 times;
past that, or when a cut fails, the art is refused.
The release frame's shortcuts run before the bar is drawn, with the
button already up, so they missed the drag and the Escape also reached
the active tool. The drag now counts as going on in that frame too.
A point exactly on a gradient mesh's outline located on the top and left
edges but not on the bottom and right ones, where the nonzero winding
number is 0. object.mesh.addLine and Create Gradient Mesh at a point there
reported the point outside the mesh, and the Eyedropper did not sample it,
while the hit test selects the mesh there.
locate_within now takes the nearest point of the edge for a point within
a millionth of a point of the outline, with any tolerance, and returns
nothing for a point that is not finite. A point just outside still needs
a tolerance.
A right-click on a row of the Artboards panel opens a menu with Rename,
which opens the Rename dialog (artboard.rename) for the selected
artboards: OK names them in one undo step, numbered in panel order when
there are several, and Cancel renames nothing. A right-click on a row
that is not selected first makes its artboard the active one and the
only selected one; on a selected row the selection stays.
A drag with the right button no longer moves a row: only the primary
button starts a row drag.
A value that nests past a command schema's 16-level limit was reported
as an internal error ("please report this bug"). It is now a parameter
error that names the value's path, like the schema's other refusals; a
schema that is wrong in itself is still an internal error.
The schema check now also refuses a list of ids or a point inside 16
lists, since every value of those types is a list and the value check
refuses a list at that depth. A color there still takes a string.
Docs: docs/mcp.md, docs/target-app-parity.md.
Type read from a text document's font record was set in whichever installed
face first answered to the record's PostScript name (ignoring case and
punctuation), and its family was then swapped for any available family
spelled alike but for case and punctuation (`FontDb::find_family`): a record
naming `SampleInk`, the PostScript name of `Sample/Ink`, set its type in
`SAMPLE INK`. Copies of one family and style under other PostScript names or
versions were not told apart either, so the type could set at other widths
than the file's own page.
- `named_font` / `document_font` (crates/eps/src/import/text.rs) give the
family and style of the installed face of exactly that PostScript name,
else one that differs only in case or punctuation, and name its version
when the family and style alone resolve to another installed copy.
- The font record's key 5, its version string (name ID 5), is read and picks
that version among the faces of the name. Each record is resolved once.
- `FontDb::postscript_faces` lists every installed face a PostScript name
answers to, loading their families; the import prefers among them one of
exactly that name.
- Type a PostScript program sets (EPS import) and legacy .ai type take the
face of their font's name the same way.
- The .ai save writes a static font's version (`/5`) when its PostScript name
alone would give the reader another installed copy (another version, or the
same name in another family), keeps the version in the style it compares,
and checks that the type comes back in the same family, style and face,
taking the record's version as the reader does (up to 256 bytes), so such
type round-trips without a note.
Measured on 224 users' files (used locally, never committed): 16 files set
some type in another face; 12 render differently against their own page,
10 closer and 2 further by 0.03% of the page; envelopes of type that open
live go from 154 to 159, none fewer in any file; no file opens another way.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With a 3D effect on one fill or stroke, the object's other fills and
strokes were drawn as nonzero paths, so an even-odd compound path or
path filled its holes in them. Extrude & Bevel, Inflate, Rotate,
Revolve and their Classic kinds now draw those items with the source's
fill rule, through the group code's shape_node helper.
`cargo clippy --target wasm32-unknown-unknown -p vectorcraft-ui-egui
-- -D warnings` stopped twice. In vectorcraft-text, MAX_FILE_SEARCHES
is used only by the system font search, which is not compiled for
wasm32, so it was dead code there. In vectorcraft-ui-egui, Runtime
holds only manual_window_open and status_message on wasm32, and the
hand-written Default set them to false and None, so clippy's
derivable_impls stopped the run.
- MAX_FILE_SEARCHES is compiled only for targets other than wasm32,
like the SysFallback struct next to it.
- Runtime derives Default on wasm32, and the hand-written Default,
which creates the updater, is compiled only for other targets.
The three envelope ink tests set "Type" in the default family and
unwrapped ink_bounds(). Without bundled fonts, craft-fonts or system
fonts (vectorcraft-effects' tests on a bare Linux host), no face draws
and the effects test panicked at the unwrap.
Each test now adds the Heighttest Sans face built from the bundled
Source Sans 3 (test-fonts feature, now also on vectorcraft-effects'
dev-dependency), sets the text in it, and computes the expected box
from the layout's glyph outlines. It checks that envelope_ink gives
that box as well as the before and after registration boxes, so a
change to the registered measure fails the test.
The status bar shows a failed script run as one line: the script's
name, the line and column (and the included file), the error and the
kind of failure, with any files the run left written. No catalog had a
row for that line, so the whole line stayed in English. The errors of
File, Folder, vc.run, $.evalFile, a script's $ object, its alert,
confirm and prompt dialogs, vc.document, vc.log, the limits a run can
pass and Drop Script Engine had no row in any complete catalog either,
and several were not listed by the untranslated-strings report.
- Every complete-message catalog has rows for these errors and for the
failed-run line at each place and for each kind (syntax, thrown,
limit, stopped, internal). The script's name, paths, numbers, code
names ($.flags, File, answers, true, null, UTF-8), command ids and
the text a script throws itself are kept.
- A failure with no line and column, such as an error in code eval
compiled, is shown with one colon after the script's name
("t.js: TypeError: no (thrown)" instead of "t.js:: TypeError: no
(thrown)").
- A placeholder that occurs twice in a message template matches only
the same text both times. Before, "{name}: the next answer in
`answers` is for {_1}, not {name}" matched a whole failed-run line
and dropped its line, column and kind.
- The message scan reads the script host's fail(, value( and .over(
helpers and the script interpreter's errors (the js crate), skips
*_tests.rs files and cfg(all(test, ...)) modules, and reads a
constant's text from the file or crate that declares it, so the
Scripts menu's headers are no longer listed as messages.
Tests: i18n::tests::script_errors_are_translated,
script_host_errors_are_translated,
a_repeated_placeholder_matches_the_same_text,
message_scan_reads_constants_of_the_file_and_its_crate,
message_scan_reads_script_interpreter_errors,
message_scan_skips_test_modules_with_any_test_cfg,
tests::script_run::an_error_without_a_place_names_the_script_and_kind.
A filter's or importer's output clamps each gradient stop's offset,
opacity, midpoint, tint and color, but kept its four process plates as
given, so a plate below 0, above 1 or infinite was stored in the
document. Each plate is now clamped to 0-1: a value that is not a
number becomes 0, and an infinite one becomes 0 or 1 by its sign.
Painted live effects still refuse such a stop.
Docs: docs/plugins.md, docs/target-app-parity.md.
The double-click right of an RGB field was the only way to switch R, G and B
between percent and 0 to 255 from the UI. ui.colorRgbPercent (Toggle RGB
Percent) is listed in the command palette and in Keyboard Shortcuts without a
default key, and switches the same setting. A parameter answers an error and
changes nothing. The label has a row in every complete catalog.
select.byNote compares letter case one character at a time, so a final
sigma matches σ, and Whole Word checks its boundaries against the
note's own characters, so İ neither ends a word early nor matches half
of itself. The search runs in time proportional to the note's length.
Set Selection passes its fields to ui.action.insertSelectObject as they
are, so a note or option of another type set through ui.dialog.set is
an error and the dialog stays open.
The Actions panel menu has Insert Select Path, after Insert Menu Item.
With one whole path or compound path selected, it inserts a Select
Path step into the action being recorded, or after the selected action
or step. Playing the step selects that path again.
- New engine command `select.storedPath {id, fingerprint}`. The step
stores the path's object id and a fingerprint of its geometry and
fill rule ("v1:" and 16 lowercase hex digits, FNV-1a 64). Playback
selects the path only while it exists unchanged and can be selected;
otherwise the step fails and the selection stays as it was. A path
on a locked artboard is refused in isolation mode too.
- Capture refuses an empty selection, several objects, selected
anchors or segments alone, groups, type, guides, a path selected
together with ruler guides, a member of a compound path, and hidden,
locked or template art.
- New UI command `ui.action.insertSelectPath {set?, action?, step?}`.
Step rows show "Select Path".
- `.vcactions` files that hold a Select Path step are written as
version 4. Reading accepts versions 1 to 4 and refuses a Select Path
step with invalid params.
- Rows for the new labels and messages in every catalog.
Docs: docs/mcp.md, docs/target-app-parity.md.
The comma in "more than 0, at most 100000" split the `spacing` entry in
the params text of `addon.cutting.weed`, so the params check read
"at most 100000 (...)" as a key and every_description_parses failed.
The range now reads "more than 0 and at most 100000".
Paste placed character and paragraph styles before the patterns, symbols
and brushes they use, and compared each one with the document's before a
pattern it painted with had its final name. A style that painted with a
pattern added as "Dots 2" kept painting with the document's own "Dots",
or was matched to a document style of its name that paints with that
"Dots". A symbol whose art paints with such a pattern, and a brush whose
art sets type in a style renamed on the way in, were matched the same way.
Paste, and the symbol, brush, pattern and Libraries imports that add art
through it, now place each style, symbol, pattern and brush after the
ones it uses, as Load Character Styles and Load Paragraph Styles already
did, and relink the styles they add at the end. Pasted back into its own
document, each definition stays the document's of its name.
View PDF after Saving checked only whether automation was acting at
that moment. When automation asked for Save as PDF without a path, the
save panel's answer arrives later, so the written PDF opened in the
system viewer. The check now uses automation_asked, which also covers
the answer of a save panel automation opened, in view_file and in
Export As.
File › Open already opened `.vcstyles` graphic style libraries in their
library panel and imported `.vcperspective` perspective grid presets, but
its dialog had no filter for either. It now lists "Graphic Style
Libraries" after "Swatch libraries" and "Perspective grid presets" after
"Print presets". "All readable files" still lists documents only.
Other Library… and Locate Library… in the swatch and graphic style
library panels list their library filter once; the swatch dialog listed
"Swatch libraries" twice.
A red, blue and green rectangle are made into an Intertwine group, and
red is brought over blue where they overlap. The green sliver meets that
overlap's edge over red only. The test checks that green still draws in
front of red within the 2 pt margin, that red's raised area takes in the
margin where only red paints, and that it leaves out the part where
green paints too.
With the Artboard tool chosen and Align to Selection, two selected artboards are the first and the last of the distribution, so the Align panel's and the Control bar's Distribute buttons are off until three are selected. With Align to Artboard the spacing places the second artboard from the active one, and two are enough.
The Distribute Spacing field takes negative values with the Artboard tool chosen, as artboard.distributeSpacing overlaps the artboards with a negative spacing. With other tools its lowest value stays 0.
Art inside two overlapping artboards now goes with the one first in artboard order when the artboard Align and Distribute commands move them, and stays when that artboard stays, as in the other artboard edits.
The per-item Revolve loop passed a copy of each fill or stroke to the
geometry context, which finds the item by identity in the object's
appearance, so a plug-in effect before the Revolve was told it sat on
the object. Each copy now keeps its original item beside it.
A glyph that justification widens to fill the line keeps its Insert Aki
before it at its width, and its own width, which ligature carets stand
in, now starts where the glyph is drawn. Optical kerning measures a pair
from the letter of a cluster rather than from a combining mark whose
advance holds the cluster's Aki.
The SVG test also checks centered and right-aligned lines with Insert Aki.
A command that needs a number, such as `x` of `shape.rectangle`, `intensity`
of `edit.colors.saturate` or `index` of `object.envelope.setMeshPoint`,
answered "missing number `x`" both when the key was left out and when it was
given as a value that is not a number, such as "40". A value that is given but
is not a number is now refused with "`x` must be a number, not "40"", the
message the optional number checks already use, showing the value as given.
A key left out or given as null is still a missing number. Neither error
changes the document or records an undo step.
Docs: docs/mcp.md, docs/target-app-parity.md.
Gradient Objects now leaves out fills and strokes at an opacity of 0,
so the test expects no gradient count once every fill and stroke of
the spot gradient object is clear.
A PDF of the art's bounds never carries Preserve Editing data, and the
export adds its warning only when Preserve Editing was on. docs/mcp.md
and the document.exportPdf params text now say so.