From a4e74ed0f0fedfe81bf1ddab76e31d838b5dac7d Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Wed, 4 Nov 2026 16:07:11 -0800 Subject: [PATCH] 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. --- crates/render/src/lib.rs | 8 ++--- crates/render/src/renderer.rs | 9 ++++-- crates/render/src/renderer/paint.rs | 47 +++++++++++++++-------------- 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/crates/render/src/lib.rs b/crates/render/src/lib.rs index cace4f165..b9852d0a1 100644 --- a/crates/render/src/lib.rs +++ b/crates/render/src/lib.rs @@ -75,8 +75,8 @@ pub struct Renderer { /// tolerance level): panning re-renders reuse them instead of re-expanding every stroke. strokes: PtrMap, /// 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, + /// [`frame::MovedKey`]: a moved copy of the object draws that outline moved ([`Self::moved_outline`]). + moved_strokes: PtrMap, /// 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; diff --git a/crates/render/src/renderer.rs b/crates/render/src/renderer.rs index 638de74e8..534568a14 100644 --- a/crates/render/src/renderer.rs +++ b/crates/render/src/renderer.rs @@ -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 { diff --git a/crates/render/src/renderer/paint.rs b/crates/render/src/renderer/paint.rs index 875b39bca..cf66c5098 100644 --- a/crates/render/src/renderer/paint.rs +++ b/crates/render/src/renderer/paint.rs @@ -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) { + 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) {