Render: stroke outline reuse leaves the shared imports and the dashed-outline branch as they were

The moved-outline key is imported where it is used, and the outline is
stored through one helper, so the change touches fewer lines that other
work on the renderer also changes.
This commit is contained in:
dotCooCoo
2026-11-05 10:26:08 +07:00
committed by bflatastic
parent e6331e559a
commit a4e74ed0f0
3 changed files with 33 additions and 31 deletions
+3 -5
View File
@@ -75,8 +75,8 @@ pub struct Renderer {
/// tolerance level): panning re-renders reuse them instead of re-expanding every stroke.
strokes: PtrMap<StrokeKey, StrokeEntry>,
/// The key in `strokes` of the latest outline of each stroke of an object, under its
/// [`MovedKey`]: a moved copy of the object draws that outline moved ([`Self::moved_outline`]).
moved_strokes: PtrMap<MovedKey, StrokeKey>,
/// [`frame::MovedKey`]: a moved copy of the object draws that outline moved ([`Self::moved_outline`]).
moved_strokes: PtrMap<frame::MovedKey, StrokeKey>,
/// Expanded character stroke outlines, with the glyph geometry kept in `texts` they belong to,
/// keyed by ([`Self::stroke_owner`] of that geometry, run, width bits, tolerance level): type
/// that doesn't change draws them again instead of expanding its strokes in every frame. Within
@@ -218,9 +218,7 @@ mod threads;
pub use bounds::{drawn_bounds, drawn_outline, effect_bounds, painted_bounds};
pub use frame::FrameStats;
use frame::{
ClipEntry, ClipPaintEntry, Frame, FxArtEntry, GeomEntry, MovedKey, PlacedEntry, PlacedKey, PtrHasher, PtrMap, SliceEntry, StrokeEntry, StrokeKey,
};
use frame::{ClipEntry, ClipPaintEntry, Frame, FxArtEntry, GeomEntry, PlacedEntry, PlacedKey, PtrHasher, PtrMap, SliceEntry, StrokeEntry, StrokeKey};
#[cfg(test)]
use frame::{OFFSCREEN_PIXELS, Slices};
pub use geometry::region_pixels;
+6 -3
View File
@@ -1,8 +1,8 @@
use super::blobs::{blob_key, blob_pixmap, image_mip, lookup, mask_value, mip_level, plain_image, shape_masked_image, white_shape_mask};
use super::clock::now;
use super::frame::{
ClipEntry, ClipPaintEntry, Frame, FrameStats, GeomEntry, MAX_INLINE_DEPTH, MISSING_INLINE_LOGGED, MovedKey, PlacedEntry, PlacedKey, PtrMap,
SliceEntry, Slices, StrokeEntry,
ClipEntry, ClipPaintEntry, Frame, FrameStats, GeomEntry, MAX_INLINE_DEPTH, MISSING_INLINE_LOGGED, PlacedEntry, PlacedKey, PtrMap, SliceEntry,
Slices, StrokeEntry,
};
use super::geometry::{MAX_GUIDE_DASHES, polygon_length, rects_overlap, region_pixels};
use super::node_checks::{
@@ -18,13 +18,16 @@ use super::{
group, ink, kurbo, live, lru, peniko, proof, vello_cpu,
};
#[cfg(test)]
pub(crate) use paint::{STROKES_OUTLINED, offset_between};
mod images;
mod nodes;
mod paint;
mod text;
#[cfg(test)]
pub(crate) use paint::{CROP_STROKES, STROKES_OUTLINED, crop_line, offset_between};
pub(crate) use paint::{CROP_STROKES, crop_line};
impl Renderer {
pub fn new() -> Self {
+24 -23
View File
@@ -1,8 +1,9 @@
use super::{
Affine, AppearanceItem, Arc, BezPath, BlendMode, Compose, FillRule, Frame, Ink, Mix, MovedKey, Node, Rect, RenderContext, Renderer, Shape,
SliceEntry, Slices, StrokeAlign, StrokeEntry, StrokeLayer, TextGeom, blend_mode, drawable, effects, fill_rule, fx, kurbo, lru, owns_stroke,
peniko, rects_overlap,
Affine, AppearanceItem, Arc, BezPath, BlendMode, Compose, FillRule, Frame, Ink, Mix, Node, Rect, RenderContext, Renderer, Shape, SliceEntry,
Slices, StrokeAlign, StrokeEntry, StrokeLayer, TextGeom, blend_mode, drawable, effects, fill_rule, fx, kurbo, lru, owns_stroke, peniko,
rects_overlap,
};
use crate::frame::{MovedKey, StrokeKey};
use crate::paint;
impl Renderer {
@@ -277,8 +278,7 @@ impl Renderer {
if let Some(mk) = moved
&& let Some((outline, crop)) = self.moved_outline(mk, &node, st, line, v)
{
self.strokes.insert(key, StrokeEntry { node, outline: outline.clone(), stamp: self.stamp, crop, line: kept });
self.keep_latest(mk, key);
self.keep_stroke(key, StrokeEntry { node, outline: outline.clone(), stamp: self.stamp, crop, line: kept }, moved);
return Some(outline);
}
#[cfg(test)]
@@ -288,33 +288,34 @@ impl Renderer {
// [`crop_line`] otherwise).
let region = v.inflate(v.width(), v.height());
let tol = 2f64.powi(level);
let (outline, crop) = if crops()
if crops()
&& line.elements().len() > CROP_ELEMENTS
&& st.dash.is_some()
&& st.profile.is_none()
&& let Some(outline) = crop_dashed(line, st, width, region, crop_reach(st, width, f.px, tol), tol)
{
(Arc::new(outline), Some(region))
} else {
let cropped = (crops() && line.elements().len() > CROP_ELEMENTS && st.dash.is_none() && st.profile.is_none())
.then(|| crop_line(line, region, crop_reach(st, width, f.px, tol), width))
.flatten();
match cropped {
Some(part) => (Arc::new(effects::stroke::line_outline(&part, st, width, tol)), Some(region)),
None => (expand(), None),
}
};
self.strokes.insert(key, StrokeEntry { node, outline: outline.clone(), stamp: self.stamp, crop, line: kept });
if let Some(mk) = moved {
self.keep_latest(mk, key);
let outline = Arc::new(outline);
self.keep_stroke(key, StrokeEntry { node, outline: outline.clone(), stamp: self.stamp, crop: Some(region), line: kept }, moved);
return Some(outline);
}
let cropped = (crops() && line.elements().len() > CROP_ELEMENTS && st.dash.is_none() && st.profile.is_none())
.then(|| crop_line(line, region, crop_reach(st, width, f.px, tol), width))
.flatten();
let (outline, crop) = match cropped {
Some(part) => (Arc::new(effects::stroke::line_outline(&part, st, width, tol)), Some(region)),
None => (expand(), None),
};
self.keep_stroke(key, StrokeEntry { node, outline: outline.clone(), stamp: self.stamp, crop, line: kept }, moved);
Some(outline)
}
/// Lists `key` as the latest outline under `mk`, and drops the line kept with the outline listed
/// there before, which no moved copy draws from any more: one line is kept per [`MovedKey`].
fn keep_latest(&mut self, mk: MovedKey, key: crate::frame::StrokeKey) {
if let Some(before) = self.moved_strokes.insert(mk, key)
/// Keeps outline `e` in `strokes` under `key`, and lists `key` as the latest outline under
/// `moved` ([`MovedKey`]), dropping the line kept with the outline listed there before, which
/// no moved copy draws from any more: one line is kept per [`MovedKey`].
fn keep_stroke(&mut self, key: StrokeKey, e: StrokeEntry, moved: Option<MovedKey>) {
self.strokes.insert(key, e);
if let Some(mk) = moved
&& let Some(before) = self.moved_strokes.insert(mk, key)
&& before != key
&& let Some(e) = self.strokes.get_mut(&before)
{