An edge that two contours of an area type frame share lies inside the
frame, and lines already run across it. Inset Spacing still kept text
clear of it, so a frame of contours that meet along an edge left a gap
of twice the inset at the seam. The inset now applies only beside the
stretches of edges that bound the frame, counted by parity as the line
spans are. A negative text wrap offset no longer shrinks a wrap object
beside an edge two of its contours share.
Linked images and placed documents in the art of the stored brushes (a
scatter or art brush's art, a pattern brush's tiles) are listed in the
Links panel after the other stored art, one row per linked or placed
object in each brush tile, with the brush as owner
(`{kind: brush, name, index, tile?}`). Check Links, the missing and
modified files reported on open, the link watch, Find in Folder, Relink
(including Relink All Instances), Update, Embed, Placement Options, Link
Info and Go To act on them, and their tooltip names the brush.
- vectorcraft-doc: `Document::mounted_art` holds art kept outside the
document's trees while a command looks it up by id; the stored-art
lookups, link visitors and `art_roots` include it, and
`number_mounted_art` gives its objects ids of their own.
- vectorcraft-brush: `stored_art::StoredArt` mounts the art of the
brushes that hold images or placed documents and writes back only the
entries whose art changed. Entries that do not read as a brush are left
as stored. `brush::store` keeps ids of their own in that art, so a row
keeps its id between commands.
- vectorcraft-engine: the links commands, opening a document, saving a
placed document's source, output of linked files and placed documents,
color masks after Update or Relink, and Package relinking go through
the mounted art.
Brush art rows follow the general Links rule as VectorCraft's own
application of it.
action.batch drops Open steps before it plays each file or data set, and
returned the per-file error of command.batch unchanged, so `batch step N`
counted from 0 within the filtered steps. A failed step is now named
``action step N (`id`) failed: reason``, N being its place in the
`commands` the caller sent, from 1, with skipped Open steps counted.
The batch's own open, data set choice and destination steps keep their
unnumbered errors, and command.batch messages are unchanged.
A prefs.import step, which command.batch refuses when it reaches that
step, rolling the batch back, is now refused before any file opens
instead of failing each file or data set the batch plays.
Docs: action.batch params text, docs/mcp.md, docs/target-app-parity.md.
Paragraphs in a modern .ai text document now keep their East Asian line
breaking settings: the Kinsoku set (None, Hard or Soft), Kinsoku Shori
Type, Burasagari and Bunri-Kinshi. Each comes from the paragraph, else
its paragraph style or a style that one is based on, else the document's
defaults, as the other paragraph settings do. A value that cannot be read
takes the paragraph style's value.
A paragraph whose Kinsoku set is a custom set takes its paragraph
style's set, and the import warns that custom Kinsoku sets were left out.
.ai export does not write these settings.
With a gray among the colors, an anti-aliased edge pixel of black on
white is also a mix of black and gray, or of gray and white, and the
unmixing took the mix with the smallest error, which often held the
gray. A black disc and a gray square on white traced the gray as the
square plus 8 to 24 slivers around the disc, with the colors found or
named exactly.
When another mix of two classes also reproduces an edge pixel, the pixel
now takes it if that mix's classes lie nearer in the flat areas around
the pixel and the pixel has a neighbor on each side of the left-out
class, along the line between the other two. Pixels within a few levels
of a class outside a flat area are checked the same way, and they now
count toward the number of pixel values that decides when a busy image
is averaged down further. A flat area that stands for no class, as with
colors named some levels off, counts as holding the classes of its mix,
and so do the pixels of exactly its color joined to it. Whether a
hard-edged image is softened is still judged from each pixel's best mix.
The slivers are removed around sharp edges and edges blurred by up to
about half a pixel; an edge blurred by a pixel or more, or pixel noise
of a level or more, can still leave some. Gray strokes two and three
pixels wide beside black stay gray, and so does a one-pixel gray line
between black and white of at least 13 joined pixels. These trace as
black and white: a shorter one-pixel line, or one that falls between
pixels or is blurred; a soft-edged gray stroke about two pixels wide
touching black; and most or all of a soft-edged stroke about three
pixels wide touching black, 12 pixels long or less.
Docs: docs/image-trace-adjustments.md, docs/target-app-parity.md.
An undoable command without a menu path or a default key was listed only
when every field of its params doc ended with `?`. A typed optional field
such as `on?: bool`, `ids?: [id…]` or `artboard?: index=0` counted as
required, so Fractional Widths, System Layout, Align to Pixel Grid, Embed
Image, Update Links, Delete Slices, Switch Orientation, Distribute Spacing
for artboards, Target Contents, Invert and other panel menu commands that
act on the selection could not be given a shortcut.
`runs_without_params` now reads the params doc with
`names_a_required_field`, the parser the editor already uses for menu
commands. The commands the new rule would list that set nothing, fail or
only give data back when a key runs them with no params (the panel
setters such as Fill and Character, the exports and saves without a path,
the undo group's begin and end, Create Dimension) join `NEEDS_A_PARAM`,
so they stay out of the list until the user gives one a key. New Symbol
joins it too, since the Symbols panel runs it through Symbol Options.
docs/mcp.md describes the rule and the full `NEEDS_A_PARAM` list.
Some SVG readers draw a masked group only inside the bounding box of its
shapes. A drop shadow, glow, blur or feather inside the group paints past
those shapes, so these readers left it out, while others drew it.
A masked group now starts with a rectangle over the mask's region,
unpainted (fill="none") and hidden (visibility="hidden"), when what it
holds has a visible raster effect: on a member at any depth, on a fill or
stroke, in a symbol's art, or in the art a blend or other live object is
written as. The rectangle widens the group's bounding box without drawing
anything, and import leaves it out. The masked groups of a knockout group
get the same rectangle when an element inside them has such an effect.
Other masked art, brushed strokes included, is written as before, and so
is an object whose own effects are written outside its mask.
Tests: a_masked_group_spans_its_region_when_its_art_paints_past_its_shapes
and a_knockout_group_spans_its_masks_when_an_element_paints_past_its_shapes
in crates/svg/tests/it/blend_export.rs.
When links.update or links.relink re-read a DCS file and Placement
Options also clipped the image (Fill with Clip, or an aspect change
that overflows), the placement rectangle replaced the file's clipping
path, so plate art outside that path showed and printed.
The file's clip group now stays around the image and the placement's
clip goes in a clip group around it. The clip group holding just the
file's group takes that clip, as one holding just an image does today,
else a new one does, so later updates reuse the same two groups. A
file that loses its clipping path leaves its group as a plain group
inside the placement's clip. The same applies in symbols, graph
designs, patterns and opacity masks.
Merge copied a face's or edge's appearance to the part it rebuilds in its
place, but not its visibility, opacity or blending mode. A half-transparent
face drawn by its stroke became opaque, and a hidden edge was shown again.
The DXF SPLINE line in docs/target-app-parity.md said a non-circular
ellipse keeps the existing fallback. crates/cad/src/scene.rs writes a
closed four-cubic ellipse, or a circle scaled out of proportion, as a
native ELLIPSE in R13 and later, unless its minor-to-major ratio is
below 1e-6, and only R12 keeps the fallback. The line now says so.
Since #7294, object.setLiveShape refuses a negative `radius` and a
`sides` that is not a whole number from 3 to 1000. Session::replay
applied the same checks, so a journal entry or action step recorded
before that change with such a value stopped with a parameter error.
On replay, a negative radius now counts as 0, which is how it drew
before. A whole side count below 3 or above 1000 is brought into that
range, and a fractional or negative one is ignored. Direct calls still
refuse these values.
An Art brush set to Scale Proportionately drew its art at the same size
on every stroke weight: the art was scaled across only by how much the
path stretched it along and by the brush's Width. Stretch to Fit Stroke
Length and Stretch Between Guides already multiply by the stroke weight.
Proportional art now does too, so a 3 pt stroke draws it three times as
wide as a 1 pt stroke, still as long as the path. The same applies to
each run with Overlap on and to a Width that follows the pen.
Existing Scale Proportionately art brush strokes at weights other than
1 pt draw scaled by the stroke weight. Strokes at 1 pt draw as before.
The ranges in the addon.shapes params text are in parentheses, so each
description reads as a params object. The configure description and
docs/mcp.md say that an omitted or null value keeps each shape's setting;
the defaults apply to the drawing commands only.
A filter or importer that changes a gradient paint unlinks each stop from
its swatch and resets its tint, but left the stop's process plates. The
PDF and EPS writers read plates only with a spot swatch, so the stop kept
a plates array with no ink, saved with the document and compared in later
edits. Unlinking now clears the plates too, in fills and strokes; a paint
returned unchanged keeps its link, tint and plates.
The plate clamping test now checks the decoded output, before admission.
With nothing selected, the Preferences button was drawn only after
Document Setup, so a bar with 90 to 111 points left showed neither,
although Preferences is 90 points wide and fits. The two buttons now
check the room left for each of them on their own.
An unlinked aligned dimension that was reflected on its own kept its
offset, which is measured along the left normal of a to b. A reflection
turns that normal to the other side, so a line 30 pt above two level
points stayed 30 pt above them after a flip top to bottom instead of
going below them. The offset now changes sign when the transform
reverses orientation, as a reflection or a scale by a negative factor
does. Other transforms leave it as before, and linked, horizontal and
vertical dimensions keep their own rules.
Docs: docs/dimensions.md.
The untranslated report listed 167 status and error messages with no
row in any complete-message catalog, and 11 more that other catalogs
translate but German did not, so with the interface in German these
messages showed in English.
- de.tsv gains 116 `@msg` rows for the listed messages: image export
and encoding errors, color profiles, color books and swatch exchange
files, binary DXF and DWG import, 3D and Revolve limits, and script,
zip and file errors. They sit in one commented block after the
existing message rows.
- de.tsv gains 10 `@msg` rows for the Banner Hems and Grommets errors
and the failed recovery save.
- The 51 listed messages that open #7211 and #7378 translate (composite
fonts and SVG filters), and the justification order error that open
#7116 translates, are left out, so no row is added twice.
- Placeholders, parameter names, command ids and literal values stay as
the English writes them. The translations use the catalog's existing
terms and typography.
- docs/localization-parity.md and docs/target-app-parity.md give the
German counts: 3,563 `@msg` and 48 `@msgplural` rows, 52 messages
still listed.
A COLRv1 linear or radial gradient whose color line repeats or reflects
made the whole glyph an image. Such a gradient now reads into a vector
gradient with the same spread. The COLR specification repeats the
interval from the first color stop to the last, so one run of the stops
spans the gradient's vector:
https://learn.microsoft.com/en-us/typography/opentype/spec/colr
A repeating or reflecting radial gradient that starts at a circle stays
an image, and so does a repeating or reflecting gradient with a stop
whose palette index is outside the palette. A color line with an extend
value the specification does not define now pads, as the specification
says, instead of making the glyph an image.
With a selection tool in use and no artwork in the document (layers and
guides only), the bar shows Draw (Pencil), which switches to the Pencil
tool, and Place Image, which picks files for the Place dialog, as the
help page lists for a new document:
https://helpx.adobe.com/illustrator/desktop/get-started/learn-the-basics/contextual-task-bar-overview.html
VectorCraft's own rules: the bar sits under the active artboard, or
under the canvas's center when the artboard is out of view, and leaves
out the Fill, Stroke, Recolor Artwork and Lock controls. Other tools, a
selection and a document with artwork keep their bars as before.
When the Opacity link and its field had no room, the Control bar also
skipped the Graphic Style check, so the narrower Style link and its chip
were left out even when they fit. The bar now leaves out only the
Opacity part and checks the room for Style on its own.
On the web, a document that opened with linked files it can't read and
linked files that changed on disk showed only the line about the changed
files when Update Links doesn't ask. The status bar now shows the line
about the unreadable files and lists the line about the changed files as
the first note in its hover, ahead of the open's notes. With Ask When
Modified the update question opens and the line about the unreadable
files stays, as before.
A copy of an image written whole already was cut to the painted bounds of
its opacity mask even when the mask was then left out, nested too deep or
past the object limit, so the file read back with a cropped image and no
mask. The copy is now cut to its mask only when the mask is written, and
otherwise written whole.
The progress-doc line now gives the measured total for the warped test
image's pieces: about 7 times the image's samples, not twice.
Expand kept a face only when its topmost fill had paint, and an edge only
when its topmost stroke had paint and a weight. A face or edge drawn by a
lower row under an unpainted top row was removed, and one whose only
painted row was hidden was kept as a visible path.
Expand now keeps a face or edge when it is shown, its opacity is above 0,
and any fill or stroke row is shown, has paint and an opacity above 0 (a
stroke also a weight above 0), with all of its rows. The rows are checked
with the new Appearance::has_drawn_fill and has_drawn_stroke.
Merge carried a face's topmost fill paint by the same topmost-row test.
It now carries every row of each face that draws by this rule, and of
each edge, pins their unplaced gradients to the old outline as
repaint_from does, and leaves the strokes' pen pressure, tilt, bearing
and rotation behind, since the rebuilt parts are other paths.
Docs: livePaint.expand params text, docs/mcp.md, and a line in
docs/target-app-parity.md, which also drops a repeated Live Paint
Selection marquee line.
A required index given as something other than a whole number of 0 or
more, such as "3", 2.5, -1 or true, was reported as missing: `anchor` of
path.setHandle, path.moveAnchor and text.setPathHandle, `segment` of
path.insertAnchor, and `to` of artboard.reorder, library.moveGroup and
graphicStyle.move. Each now refuses it with "`anchor` must be a whole
number", naming the key; left out or null, it is still missing.
An optional `subpath` of path.appendAnchor, path.close and path.reverse
given that way was read as left out, so the command extended, closed or
reversed the default subpath (path.reverse reversed every subpath). The
`artboard` of the ruler origin commands answered "index out of range"
for such a value and for null. Both now refuse such a value with the
same message and change nothing. A null `artboard` is artboard 0, as one
left out is; a whole number past the artboards is still out of range.