The development guide and the progress doc now name all 23 languages in
COMPLETE_MESSAGES: Hindi was missing from the first, and Georgian, Hindi,
Turkish and Catalan from the second. The localization summary adds
Bosnian to the languages marked full that are not in the list.
The untranslated report listed 167 status and error messages that no
complete-message catalog translated. pt-br.tsv now has an @msg row for
the 114 of them that no open pull request already translates: messages
of the 3D and Revolve effects, the image encoders, color profiles, swatch
exchange files, color books and DXF import. Placeholders, parameter names
and literal values stay as the English writes them.
The other 53 (composite font, SVG filter, read root and graph design
messages) are translated by open #7211, #7378 and #7405; adding them here
too would make bundled_catalogs_are_consistent fail on a duplicate row
once those merge.
With Smart Guides on, the Dimension tool's second point snapped onto the
construction guides through the first point (Smart Guides › Construction
Guides), so a click beside a segment straight below a first point that
was not on an anchor stayed on the vertical guide instead of landing on
the segment.
The second point now has no construction guides through a first point
that is not on an anchor. After a first point picked on an anchor, the
construction guides through it still apply. The second point still snaps
to anchors, centers and alignment lines, and with Snap to Perpendicular
or Snap to Tangent on it lands where the line from the first point meets
a segment square or grazes a curve.
Docs: docs/dimensions.md, docs/target-app-parity.md.
The continuous-tone check exempts a neutral or single-curve picture when
sixteen colors leave at most a fifth of the error of eight, but only
applied the exemption below the 0.1 ratio. Clean gray, sepia, single-hue
and duotone art of 10 to 16 evenly spaced levels lands above it, so it
was smoothed before tracing. The exemption now applies in both branches.
At 16 Colors, 12 sepia and 16 gray or sepia levels crossed by 1 px lines
keep every region the lines cut, and Automatic traces 16 clean sepia
levels in 9 colors instead of 4. Art in several unrelated colors is
unaffected.
Two faults in the editing data writer's text wrap handling:
- A clipping path inside art cut to an outer clipping object is written
as its fill and its stroke. The stroke's text wrap options were
dropped whenever the path had a fill, so when the outer object cut
the fill away entirely, the stroke was written without them and the
options were lost. The stroke now drops them only after the fill
writes an object.
- When a symbol definition had no room left under the object limit,
`define_symbol` returned without restoring the drawn-art counter it
had cleared. A live instance inside drawn art (a stained instance's
art) then left the counter at zero, and the art around it subtracted
from zero: a panic in a debug build. That path now restores the
counter as the other exits do.
The preset paragraphs say that the enhanced versions use the same Paths,
Corners and Noise, and that Corners 50 applies to the other eight
presets. The quality notes add the staircase and anchor rises in Line
Art, Outline, 3 Colors, Sketched Art and Silhouettes, and say which
figures were measured at the earlier values. The anchor-limit comments
name the same settings in both places.
path.setHandle checked for a no-op by running the handle edit on a copy
and comparing the whole anchor. On a smooth anchor the edit recomputes
the other handle, so when that handle was not exactly in line, or the
recomputed value rounded differently, a request for the handle's own
point realigned the other handle and recorded an undo step.
The check now compares the requested point with the handle itself, and
still lets independent turn a smooth anchor into a corner.
A clipping path with Roughen, Transform or another effect that reshapes
a path drew its own fill and stroke reshaped, but the canvas and raster
export still clipped the art by the plain path. SVG and PDF export bake
the effect into the path before writing the clip path, so the screen
and a saved SVG showed different art.
effects::clip_outline now applies the live geometry effects in the
clipping path before taking its region: the path's or compound path's
own effects, the effects of its fills and strokes (the region is then
the union of the paths they give, as an export bakes them), the effects
of a compound path's paths, of a group's visible members and of a
nested clip group's clipping path, shown or hidden, and a group's own
effects as an export evaluates them. Raster effects such as Gaussian
Blur leave the region as it is. The renderer, the engine commands that
measure a clip region (flatten, arrowheads, cutting) and the writers use
it; the writers receive the baked document, so their output for a path
with effects does not change.
The renderer measures a clip group by the region its clipping path's
effects give it, so a view or tile that shows only the moved part of
the clip still draws the clipped art, and it drops cached clip regions
that hold a plug-in effect when plug-ins change.
Two rules change in every export as well as on the canvas:
- When the clip group, or a group around it, has a geometry effect of
its own, the clipping path's effects apply first and its gradients
move with them. #7114 left the clipping path's effects live under the
group's effect, so they applied after it.
- Type used as a clipping path keeps its own effects when a group's
effect outlines it. #2073 and #2290 outlined it without them, to
match the plain clip the canvas drew.
At a Volume of 0 % no shape puffs, so the eye does not depend on the
other shapes. Each shape's membrane is now solved as its solid is taken,
and a caller that stops at the object's face limit solves none of the
shapes after it. With any volume every puff is still solved first, since
the highest one places the eye, and the solids are unchanged bit for bit.
The shadow no longer builds the solid of a fully transparent fill or
stroke: its puff still places the eye, and at 0 % volume it is not
solved either.
When a recovery copy fails because a folder on the way to the recovery
folder is a file or is missing, the error names that folder, not the
recovery folder. Replies to a client confined to read roots hid only
the recovery folder itself, so the full path of that ancestor stayed
visible. A reply now also hides each ancestor of a recovery folder that
it writes as a whole path. The check compares text only and does not
look anything up on disk.
Follows #7287.
With apply "opacity", Sort Objects compared each object's opacity with the
value it gets as a percentage, within 1e-6. An evenly stepped value can
differ from a mark's percentage by more than that while it rounds to the
same stored opacity: marks at 30%, 65% and 100% sorted by x with
distribute on keep their opacities, yet the 65% mark counted as changed.
The sort then made an undo step and replaced the opacity the graph stores
for the series (30%) with 65%.
The sort now compares each object's stored opacity with the opacity it is
given, as stored, both to skip a run that changes nothing and to pick the
marks whose opacity the graph keeps.
When a blend starts a key's path at another anchor or runs it the other
way, the steps already read that key's width profile and pen recordings
along the turned path. Its stroke gradient and dashes still followed the
key's own direction, so steps near that key showed them flipped or
shifted.
- A gradient along the path starts where the turned path starts and
runs backwards on a reversed one; a gradient across the path swaps
sides on a reversed one. Stops that reflect an even number of times
are left as they are.
- Dashes run backwards on a reversed path, and exact dashes start where
the turned path starts, when every subpath needs the same offset.
- Two gradients with different stop counts keep a step (two stops at
one offset) when they are resampled to common stops.
In a composite font the file carries (FMapType 2 or a CMap), cshow ran
its procedure once for each byte of the string, with that byte's width
in the composite font and the composite font still current. It now runs
once for each character the font maps, with the last byte of its code
and its width, and with the descendant that draws it current, at the
size the composite font sets it, while rootfont gives the composite
font (PLRM 3rd ed., cshow and rootfont).
While the procedure runs, showing the byte it was given in that
descendant shows the character the code maps to: a CMap's CID,
base-font code or glyph name. In a CIDFont any other string is a
rangecheck error.
On main, the untranslated report lists 167 status and error messages
under "messages, all 23 languages checked": no complete-message catalog
has a row for them, so the Japanese interface shows them in English.
- ja.tsv gains 114 @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, line and file errors. The 53 listed messages that #7211, #7378
and #7405 translate are left out.
- It gains 10 @msg rows for messages other catalogs translate and
Japanese lacked: the Banner Hems and Grommets errors, a parameter
range and the failed recovery save. The three script and RTF parsing
errors that #7314 adds are left out.
Placeholders, parameter names, command ids and literal values stay as
the English writes them, and the rows follow the catalog's Japanese
message conventions.
Two intervals at the middle of a band joined whenever their crossings
came out at the same x, even when the two edges are not along one line
and only round to that x. A slanted edge whose crossings of the band all
round to the x of a separate contour's edge then let a line run across
the gap between the contours.
The crossings now carry the line they were found along. Intervals join
at an x only when both crossings are along one line (contours that meet
along an edge) or both lie exactly at that x.
After Select All in a frame of threaded text, Convert to Text skipped
the story's locked and hidden frames, even when `ids` named them, and
left a paragraph whose text started in one as a list. Remove Line
Breaks and Remove Paragraph Breaks also kept the breaks in those frames.
A selected story is one text, as it already is for Apply Bullets and
Apply Numbers and the Character and Paragraph panels, so both commands
now change every frame of the story, as one undo step.
- text.convertListToText converts every list paragraph of the story,
locked and hidden frames included; `ids` naming a locked or hidden
frame converts its paragraphs too. A call that changes nothing adds
no undo step.
- addon.cleanup.removeBreaks removes the breaks in every frame of the
selected story.
Docs: docs/mcp.md, docs/target-app-parity.md.
The script module docs, the script.run params text and the evidence line now
say that $.fileName in code that eval or Function compiled gives the file
being run, and the params text says that the empty name applies to code
compiled from a script given as text.
The anchor, pixel-difference and staircase figures for the new preset
values are measured again with JPEG block smoothing and the Limited
palette change in main. 16 Colors makes 20% fewer anchors, and Low
Fidelity Photo leaves 96 staircases of 2 px steps where it left 77.
Two windows or processes using one Plug-ins folder could interleave their
writes: an install from one could leave its module with the other's grant,
a grant written for one plug-in could drop one written for another, and
plug-in settings and cache changes could lose each other's keys or pass the
cache caps together.
Each change to the folder now runs in one turn on disabled.lock, the file
the disabled list was already locked with:
- plugin.install takes the turn before it reads the stored grants and holds
it through the module, grant, put-back and disabled-list writes;
plugin.remove holds it through grant removal and storage deletion.
- Grant writes, the disabled list, loading the folder, and the plug-ins'
settings and cache changes read and write in a turn.
- When disabled.lock can't be locked, plugin.install and plugin.remove fail
and change nothing, plugin.setEnabled keeps its change in the process, and
loading the folder writes nothing to it.
Docs: docs/plugins.md, docs/mcp.md, the plugin.install and plugin.remove
params text, docs/target-app-parity.md.
The For you and Skills tab buttons, a skill's row, a tutorial's row and
Back changed the Learn panel's view directly, so the control channel and
MCP could not choose a tab, open a skill's tutorials or go back.
- learn.tab {tab: forYou|skills} shows the panel on that tab; the Skills
tab keeps the skill and tutorial it had open.
- learn.skill {skill} shows the panel on the Skills tab with that skill's
tutorials and returns the skill as learn.list lists it.
- learn.back {} goes up one level, as Back does.
- A tutorial's row runs learn.show.
- The commands are listed in both UI command catalogs, and their labels
have a row in every catalog.
- Docs: docs/mcp.md, docs/target-app-parity.md, docs/ui-parity.md.
Reverse Path Direction reversed the anchors but left the stroke's width
profile, pressure, tilt, bearing and rotation running the old way, so a
tapered or pressure-drawn stroke changed shape. They now turn with the
path through the blend code's stroke reorientation (the width profile's
sides swap), and the stroke draws as before. A path whose subpaths do
not all turn alike keeps its stroke as it was, as blends do. Arrowheads
stay at the path's start and end.
The French row of docs/localization-parity.md gave the counts on 92594378a. After main was merged in, fr.tsv holds 9,166 rows, 3,436 of them @msg and 48 @msgplural, and the untranslated report lists 178 missing French messages: 11 for French alone and 167 that main added for every language.
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.
The browser build stamped each snapshot of the Web Locks held with
Date.now() and judged its age against Date.now(). After the system
clock was set back, an old snapshot read as fresh, so a tab could
report no lock on an area another tab still held. Snapshots are now
stamped and aged with vectorcraft_ui_egui::now_ms(), and a snapshot
stamped later than now is not trusted.
craft-svg builds against an older vectorcraft-geom and vectorcraft-pathops by git, so the
graph holds two packages of each name and `cargo check -p vectorcraft-geom` is ambiguous.
The wasm step now passes each workspace crate's package id.
Expand as Wireframes reshaped the faces of a 3D effect with the geometry
effects after it, but the faces it built carried no stroke. An Outline
Stroke after the 3D effect then outlined a plain 1 pt stroke with miter
joins, while the canvas outlines the round-joined stroke each face is
drawn with: the seam stroke (half the facet's thickness, 0.05 to 0.75 pt;
0.75 pt on Revolve) or the 0.5 pt wire edge of the Classic Wireframe
surface. The wireframe's faces now carry that stroke, so the expanded
edges lie where the drawn outlines lie.
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.
When a wrap object splits a line band, the lines in the spans after the
first shared the first line's baseline even when they held taller type.
Their ascent then ran into the line above the band. A further span now
goes only to a line whose own leading sets it no higher than the span's
baseline; a taller line leaves the span empty and goes on in the next
span or on the next baseline. Both composers follow the same rule.
A name ending in the row-and-cell CMap H or V split only when the file
defined the CIDFont or a face of that name was installed, so
/Ryumin-Light-H findfont in a file that only names it read its strings
byte by byte as a plain font: <467c> came in as "F|" instead of 日.
Ryumin-Light and GothicBBB-Medium, the Japanese CIDFonts a printer
carries (Adobe Technical Note #5014, appendix A.2), now split at H or V
as well. Latin names such as Foo-Bold-H still stay whole.
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.
The KSC-Johab CMaps had no code space listed, so type in a font over
KSC-Johab-H or KSC-Johab-V read every code as two bytes, so two ASCII
characters moved the point one em instead of two. The code
space now follows Adobe's KSC-Johab-H CMap: <00>-<80>, <8441>-<D3FE>,
<D831>-<DEFE> and <E031>-<F9FE>
(https://github.com/adobe-type-tools/cmap-resources/blob/master/Adobe-Korea1-2/CMap/KSC-Johab-H).
In area type of a shape other than a rectangle, or with text wrap, the
Single-line Composer placed each line at the metrics of its first
character and broke it in the room there. When a later character on the
line was taller, the baseline moved down by the difference without
measuring the room again, so the line could reach into a narrower part
of the frame or into a wrap object.
- A line that turns out taller than it was placed is placed again at
metrics that hold both and broken again in the room there.
- When that leaves the taller character for the next line, the line is
set at its own metrics where the room there is no narrower, and takes
the words before that character that fit there. Otherwise it stays
where it was placed.
Tests: crates/text/src/tests/combos.rs (a stepped frame and text wrap;
the two mixed-size tests now expect the Single-line Composer to break
as the Every-line Composer does there).
Docs: 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.
A path's guide lengths matched the brush's within 0.001, so on very short art guides at 30% and 35% of the art matched. The guides now also match as fractions of the art's length.
A geometry effect after an object's 3D effect, such as a Transform that
scales or rotates about the center, measures the drawn art, cast shadow
included. Expand as Wireframes measured the faces alone, so with a
shadow on, the expanded edges landed away from the surfaces on the
canvas. The faces are now reshaped together with the shadow the canvas
draws behind them (Extrude & Bevel, Inflate, Rotate and Revolve, on an
object, group or layer), and only the faces are kept.
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.
Near an anchor whose handle does not reach out, the curve starts more slowly than its control polygon, so the finely cut stretch could end before twice the reach and the turn there was measured along a long chord. The stretches past it are now cut as finely until the pieces reach three times the reach. docs/mcp.md says the one-eighth cap applies to a closed path the drag reaches all the way round.
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.
The untranslated report listed 167 status and error messages with no
row in any complete-message catalog, and 13 more that other catalogs
translate but Italian did not, so with the interface in Italian these
messages showed in English.
- it.tsv gains 114 `@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.
- it.tsv gains 12 `@msg` rows for the Banner Hems and Grommets errors,
three parameter checks and the failed recovery save.
- The rows sit in two commented blocks after the existing message rows.
- The 53 listed messages that open #7211, #7378 and #7405 translate
(composite fonts, SVG filters, read roots and graph designs), 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.
- docs/localization-parity.md and docs/target-app-parity.md give the
Italian counts: 3,560 `@msg` and 48 `@msgplural` rows, 54 messages
still listed.