A path whose stroke has a gradient along or across it kept its slices under
the node's address, so every nudge made the slices again for the whole path,
although its stroke outline was already reused. The renderer now keeps the key
of a stroke's latest slices under the object's id, the stroke's place and the
tolerance level, and when the object has only moved (same stroke and gradient,
same fill rule, anchors moved by one offset) it draws those slices moved by the
offset, translating only the slices that reach the piece being clipped. Scale,
rotate, an anchor edit or a change to the stroke or its gradient makes the
slices again. The pixels are the same.
The outline cache kept a copy of each stroke's line to recognize a moved
path, and made that copy on every miss, so an anchor edit of a long path
paid for copying its whole line. The entry now records whether its outline
was made along a line of the object's own path. On a miss, the anchors of
the earlier object are compared with the new one's, stopping at the first
that differs, and the earlier line is made again from the object and its
stroke only when they match.
Strokes with arrowheads keep the reuse: the check uses the untrimmed path.
A path object that moves without changing shape drew its stroke by
outlining the whole line again, because the stroke outline cache is
keyed by the node. The renderer now keeps, per object, stroke and
outline width, the latest outline with the line it was made from. When
the new line is that line moved, it draws the kept outline moved by the
same offset, and moves the region a long path was outlined in with it.
Scaling, rotating or editing the path, changing the stroke's width,
join, cap, dashes or profile, a zoom that changes the outline's
tolerance, and a move that takes the view past the outlined region
still outline the stroke again. Only the latest outline of each stroke
keeps its line.
The Navigator panel menu's Panel Options… is enabled and opens a dialog with
the view box color (a preset or a custom color; Light Red, today's color, is
the default) and Draw Dashed Lines as Solid Lines, off by default, which draws
dashed strokes without their dashes in the panel's thumbnail only. The
options are kept with the UI state, and ui.navigatorPanelOptions sets them.
RenderOptions::solid_dashes draws dashed strokes as solid lines, including
type strokes and the silhouettes of stroke effects.
The renderer outlined the whole stroke of an edited path on every frame,
so dragging one anchor of a path with many anchors re-outlined every
segment. A stroke line of more than 1,024 elements without dashes or a
width profile is now outlined only for the segments within the stroke's
reach of the view, inflated by the view's own size on each side. The
cached outline keeps that region, and a frame outside it outlines the
stroke again. Closed subpaths that a wide stroke crosses over stay whole,
and a cut closed subpath is walked from a removed segment so no cut lands
where it starts and ends. The pixels are the same.
At 1600 x 1200, the frame after one anchor moves takes 28 to 30 ms
instead of 103 ms on an open path of 200,000 anchors, and 10 ms instead
of 30 ms on a closed path of 50,000 anchors (the new anchor_bench
example: cargo run --release -p vectorcraft-engine --example anchor_bench).
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.