File > Document Color Mode and document.open {colorMode} converted the
colors of the layers, symbols, pattern tiles and swatches only. Graph
designs, graphic styles, the art of opacity masks, the tile that
pattern editing's Cancel puts back and the art of brushes kept their
old color model (only a tint of a global swatch in a graphic style or
a mask followed the swatch), so a CMYK document could still apply,
place or print RGB colors from them.
These now convert with the rest, in the same undo step: their solid
colors, gradient stops, text runs and mesh points, nested masks
included. A Hue Shift brush's key color takes the converted color of
the art color it matches, a tint of a global swatch included. The
brush library is stored again only when one of its colors changed. A
tint of a global swatch in any of these places becomes the converted
swatch's color at its tint, as in the layers. The reply's changed
count covers the colors of the layers, symbols, graph designs, pattern
tiles and opacity masks; the colors of graphic styles and brushes
convert without being counted.
Docs: docs/mcp.md, docs/target-app-parity.md.
A desktop portal older than 0.9 ignores handle_token and answers on a
request path of its own. save_file subscribed to that path only after
SaveFile returned it. zbus makes three bus round trips to set up that
subscription. A Response that arrived during them was dropped, and the
save waited forever. On CI the test
the_answer_is_awaited_on_the_path_the_portal_returns waited until the
job limit.
save_file now makes one stream for every Response from the portal
before it calls SaveFile, and takes the first Response whose path is
the returned handle and whose sender is the connection that sent the
reply. A Response that comes before the reply stays queued in the
stream.
The mock portal now creates its message stream before it starts its
thread and before the client connects, so a SaveFile call that arrives
before the thread runs is no longer dropped. A new mode sends the
Response before the reply, and the D-Bus tests fail after 30 seconds
instead of waiting without end.
remote_call_reports_nothing_sent_when_reconnect_is_refused set up the
closed connection once, so only its first run went through the
stale-connection probe. Each run now sets up its own closed connection
before the timed call.
The vectorcraft-mcp tests of the remote backend in tests.rs gave a fake
app 2 or 5 s to accept a connection or to read a request, and waited
2 s for a connection to end or a line to arrive. When a busy machine
held the client's thread for longer, the fake app gave up and the test
failed. These waits now use WAIT (20 s).
remote_connect_fails_fast asserted that a refused connect returned
within 5 s, and remote_call_reports_nothing_sent_when_reconnect_is_refused
asserted that the call returned within 2 s. On Windows a refused local connect
ends at the backend's own 800 ms connect timeout. A connect without
that timeout takes about 2 s. The 5 s bound did not tell the two apart,
and the 2 s bound left 1.2 s for any pause of the thread. Both tests
now bound the connect by FAILED_CONNECT (1.5 s) and run it up to five
times, until one run is under the bound. The second test checks the
error of every run.
While an opacity mask or a pattern is edited, a press on a selected Shaper
original shape now moves it when it is not the first selected object or
shares the selection with shapes of another Shaper Group. An object in
front of the Shaper Group at the pointer is selected instead.
While an opacity mask or a pattern was edited, a Shaper double-click
selected a Shaper Group's original shape without isolating the group's
original shapes. A Selection tool press on that shape then selected and
moved the whole Shaper Group over the art the group shows, and started
a marquee over a part of the shape the group does not show.
A press on the selected original shape now holds it for a move, and
the pointer shows the move cursor over it.
While an opacity mask or a pattern was edited, a Shaper scribble and
Object › Shaper › Release and Expand ended isolation, and a Shaper
double-click on a Shaper Group isolated the group's original shapes.
Each replaced the editing layer's isolation while the document stayed
in mask or pattern editing. A click on the Shaper Group's mode widget
did the same through object.isolate.
A scribble, Release and Expand now keep the editing layer isolated in
these modes, and end isolation as before outside them. A double-click
with Shaper selects the original shape under the pointer without
isolating the group's original shapes, and the mode widget does not
show while a mask or a pattern is edited.
Docs: docs/shaper.md, docs/target-app-parity.md.
object.isolate's errors "type objects can't be isolated", "the object
is hidden or locked" and "missing id" had no row in any catalog, so the
status bar showed them in English in every language. The same was true
of layer.target's "the object is outside the isolated group", the other
isolation-mode error in the commands.
Each of the four messages now has an @msg row in every catalog that
translates all status and error messages and in Bulgarian, Danish,
Indonesian and Dutch. layer.target also gives "the object is hidden or
locked", and several other commands that take an id also give "missing
id", so the same rows translate those errors.
Docs: docs/target-app-parity.md.
The Live Paint Selection tool acted only on the press, so a drag
selected at most the one face or edge under the pointer. The reference
app selects every face and edge a marquee touches, partly enclosed ones
included, and a Shift-drag adds them to the selection or removes them.
A drag of 3 pixels or more now draws a marquee. On release, select.set
selects the faces and edges it touches, or select.none runs when it
touches none. With Shift held at the press, select.toggle runs with
what it touches, and nothing runs when it touches none. A face that holds the whole marquee counts. Select Fills off
leaves faces out, and Select Strokes off leaves edges out.
A click now changes the selection on release instead of on the press,
so Escape between the press and the release, which also removes the
marquee, leaves the selection as it was. The tool no longer highlights
or selects the faces and edges of a Live Paint group that is locked, on
a locked layer or on a locked artboard, or that is outside the isolated
art in isolation mode.
Docs: docs/mcp.md, docs/target-app-parity.md.
On a machine busy with other builds, four tests each failed once and
passed when run again alone.
The two render tests that count the rasters a drag moves draw content
painted with a pattern or showing a symbol, whose raster key holds the
font generation. The fonts change even while a test holds
fonts_steady(): the first lookup by family name catalogs the installed
fonts, and resolving a cataloged family or a fallback character loads a
face. When that happened between the two frames of a drag, the count
was 0. The new with_fonts_unchanged runs a step up to 100 times, until
the generation is the same after a run as before it, and the two tests
take their frames from it. The second render test,
a_moved_group_draws_the_shadow_of_the_instance_art_in_it_while_interacting,
was not seen failing but has the same fault.
The screenshot test's allow_due moved the capture's due time but not
its 8 s wall-clock deadline, so on a slow run the reply was the timeout
error. allow_due now also sets the deadline to f64::MAX; the two timeout
tests set it in the past themselves.
The persistent control server test gave the server 2 s to wait for
each request, 120 ms to read a line and 150 ms to write a reply. It now
gives the line and the reply 1 s each and the wait 30 s. The handler
sleeps 1.25 s, longer than both budgets, so a deadline kept from the
first request still runs out.
The idle expiry test read until the server closed the connection after
its 150 ms idle budget, and the client gave up after 3 s, so a pause of
about 3 s in the server's thread failed it with TimedOut. Every test in
control_server/tests.rs that waits for the server to reply, to close a
connection or to return its slot now waits up to WAIT (20 s), and
line_timeouts() gives the wait for a request and the reply 30 s. The
budgets under test stay 120 and 150 ms (1 s in the persistent test).
The two nested_instances_..._culled_in_bounded_time tests in the
renderer's tests checked that a frame with 2^30 differently placed
symbol instances finishes within 30 s of wall-clock time. On a loaded
machine the frame took longer than that, and both tests failed. The
time bound also passed when the frame did far more work than it should:
with the 4,096 limit on measured placements raised to 65,536, the frame
measured symbol art 131,118 times and finished in under 2 s.
SymbolBoxes now counts how many times measure_art runs a measure on
symbol art (art_measured), and FrameStats::symbol_art holds the count
for the frame's symbol boxes. The tests assert that the frame measures
symbol art at most 20,000 times. It measures it 8,234 times, and 4,160
times when each instance has a Transform effect of its own. The wait
for the frame is 300 s, as a guard against a frame that never ends.
A new test in vectorcraft-doc checks that each symbol's art box is
measured once however many instances of it are measured.
On a corner whose legs are too short for the side tile, the tile is
squeezed along the path but its stroke keeps its width. The mask round
each slice was squeezed with the tile, so it cut off the stroke at the
slice's far end. Its margins along the tile now grow by as much as the
tile is squeezed.
After a click picked the first object with the Blend tool, Escape did
nothing: the pick stayed, and the next click on another object blended
the two. After a blend was made, Escape did not stop the next click
adding to it either.
Escape now drops the object picked first and stops the next click
adding to the blend just made, as a click on empty canvas does, so the
next click picks a new first object. The document and the selection
stay as they are, and no undo step is added.
Docs: docs/mcp.md, docs/target-app-parity.md.
OK used to save None for a corner tile the dialog showed as None because
the brush had no art or source for it, so that corner stopped drawing the
other kind of corner's art once the brush got some. It also copied the
art a corner borrows from the other kind of corner when that corner kept
its art. Now OK saves a corner tile's choice only when it was set from its
menu or with `ui.dialog.set`, or when the art it borrows goes away.
Pattern Brush Options has a menu below the Outer Corner Tile and the Inner
Corner Tile. Each can be the brush's own corner art (Original), None, or one
of four tiles made from the side tile at each corner of the path:
- Auto-Centered stretches one side tile around the corner, centered on it.
- Auto-Between bends a side tile on each side into the corner, the two
meeting on the corner's diagonal.
- Auto-Sliced lays a side tile on each side past the corner and masks it
at the diagonal, so the two meet like a mitered frame.
- Auto-Overlap lays a side tile on each side past the corner, overlapping.
The tiles are straight at the corner and follow the path towards the side
tiles, so they meet a curve that runs into the corner. A side tile taller
than the corner can reach is stretched along until the two sides meet. On a
short path, a corner's tile is squeezed along so that it covers at most the
path up to an open path's end and half way to the next corner, and its two sides still meet on the
corner's diagonal.
The definition stores the choice as `outer_source` and `inner_source`
(`none`, `autoCentered`, `autoBetween`, `autoSliced`, `autoOverlap`), which
`brush.options` sets. Corner art wins over a source. A brush saved without
a source draws as before: a kind of corner without art takes the other
kind's art. None leaves that kind of corner empty.
Docs: docs/mcp.md, docs/target-app-parity.md.
The chips drew the first selected object's fill and stroke. They now show
the paints the Fill and Stroke proxies show, a group's painted art
included, and a "?" when the selected objects' paints differ. A click on
either chip shows the Swatches panel through `window.panel.activate`, so
it also appears when the panel is floating, closed or in an expanded dock
column; an open flyout stays open. The progress doc describes the
reference app's bar in its own words.
The task bar's Fill chip had no Stroke counterpart. A Stroke chip now sits
beside it, drawn as a ring with the selected object's stroke paint, as the
Control bar's Stroke chip is. A click on it brings the Stroke proxy forward
and opens the Swatches panel, as a click on the Fill chip does for the
Fill proxy. The chip is left out with the Artboard tool, as Fill is.
The bar's width estimate, which centers the bar under the selection, grows
by the chip's width. The drag test's first square moves 20 pt right so its
bar still starts inside the canvas.
Enter Isolation Mode worked while an opacity mask was edited, and Edit
Opacity Mask and View Opacity Mask worked in isolation mode, so each
mode replaced the other's isolated art. In the reference app, isolation
mode can't be entered while a mask is edited, and mask editing can't be
entered in isolation mode.
object.isolate and perspective.editText, which shows type in isolation
mode, are now off while an opacity mask is edited, and a call returns
an error that ends "stop editing the opacity mask first". In isolation
mode transparency.editOpacityMask and transparency.viewOpacityMask are
off, and transparency.makeOpacityMask refuses one target, an object or
a layer, which it would take into mask editing; a call returns an error
that ends "exit isolation mode first". Make Opacity Mask with two
objects still masks one with the other. Pattern editing mode does not
count as isolation mode for these commands.
Object > Perspective > Edit Text, the canvas context menu and the
Transparency panel's menu and Make Mask button follow the commands'
enablement. A click or Alt-click on the mask thumbnail in isolation
mode shows the error and does not edit the mask. While a mask is
edited, the Contextual Task Bar leaves out Isolate, and the Properties
panel's Quick Actions leave out Isolate Group.
Docs: docs/mcp.md, docs/target-app-parity.md.
Escape during a Selection tool move or Alt-drag copy, a bounding-box
scale or rotation, a marquee, or a drag of a corner widget, a pie widget
or the brackets of type on a path did nothing, and the release then
applied the drag. Only a ruler guide, mirror axis or grid repeat drag
and the loaded text took Escape.
Escape in any of these drags now cancels it, the way Direct Selection
cancels its drags: the art returns to its state at the press, an
Alt-drag leaves no copy, no undo step is added, and the release does
nothing.
Outside a drag Escape works as before.
Docs: docs/mcp.md, docs/target-app-parity.md.
Character Rotation turned a glyph's baseline shift and scaling with the glyph, and the Skew path effect slants a glyph's height away from the path's normal, so the x-height guide moved off the glyphs. Each positioned glyph now carries the transform that removes its Character Rotation (PositionedGlyph::unturned), and the guide goes through the glyph's x-height point placed without it, measured across the baseline. Snap to Glyph also takes Smart Guides being on in the tools, as View › Snap to Glyph already does in the engine.
With View › Snap to Glyph and Smart Guides on, a point drawn near a single
line of live type now also lands on the anchor points of its glyphs and lines
up with its x-height (raised or lowered by Baseline Shift) and with the edges
of each character's advance width along the baseline (proximity guides). In
rotated type the baseline, x-height and proximity guides run at the type's
angle, and type of one glyph also has angular guides along the glyph's slanted
straight segments; a segment that Shift keeps to its angle slides onto them.
A paragraph shows glyph bounds only, so its baselines are no longer guides.
FontFace::x_height gives a face's x-height in font units.