Render: a long dashed stroke is outlined only near the view after an edit

A dashed stroke of a path with more than 1,024 path elements was outlined
whole in every frame after an edit. It is now outlined in and around the
view like a solid stroke. dash_kept runs the pattern along every segment
and keeps only the dashes and dots on the segments near the view, so they
sit where dashing the whole path puts them and the pixels are the same.
A pattern too fine to draw is still drawn solid, and that solid stroke is
cropped too.

At 1600 x 1200 the frame after one anchor moves takes 14 ms instead of
102 ms on a filled closed path of 50,000 anchors with 6 pt dashes and
4 pt gaps. anchor_bench now includes that document.
This commit is contained in:
dotCooCoo
2026-11-05 03:55:48 +07:00
committed by bflatastic
parent a2e98ac57c
commit ed3efcbd7d
7 changed files with 301 additions and 33 deletions
+19 -3
View File
@@ -1,6 +1,7 @@
//! `cargo run --release -p vectorcraft-engine --example anchor_bench` prints the wall time of the
//! engine steps of editing anchors with Direct Selection, on three synthetic documents: one closed path of
//! 50,000 anchors, 2,000 closed paths of 50 anchors each, and one open path of 200,000 anchors.
//! engine steps of editing anchors with Direct Selection, on four synthetic documents: one closed path of
//! 50,000 anchors, 2,000 closed paths of 50 anchors each, one open path of 200,000 anchors, and the closed
//! path of 50,000 anchors filled and with a dashed stroke.
//! `ITERS` sets the runs per step (default 7); each row is the median in ms.
// Example (dev tool): unwrapping and panicking on failure is fine here, unlike in shipped code (AGENTS.md › Robustness).
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
@@ -10,7 +11,7 @@ use std::time::Instant;
use serde_json::{Value, json};
use vectorcraft_color::{Color, Paint};
use vectorcraft_doc::{Appearance, Document, Node, NodeId};
use vectorcraft_doc::{Appearance, AppearanceItem, Dash, Document, Node, NodeId};
use vectorcraft_engine::tools::{Mods, PointerEvent, PointerKind};
use vectorcraft_engine::{Session, ViewInfo};
use vectorcraft_geom::{Affine, Anchor, PathData, Point, SubPath, Vec2};
@@ -70,6 +71,20 @@ fn one_outline() -> Shape {
}
}
/// [`one_outline`] filled, with a 1 pt stroke of 6 pt dashes and 4 pt gaps.
fn dashed_outline() -> Shape {
let mut shape = one_outline();
let mut look = Appearance::basic(Paint::solid(Color::rgb(0.8, 0.2, 0.2)), Paint::solid(Color::BLACK), 1.0);
for item in &mut look.items {
if let AppearanceItem::Stroke(st) = item {
st.dash = Some(Dash { pattern: vec![6.0, 4.0], offset: 0.0, align_corners: false });
}
}
shape.doc.node_mut(shape.ids[0]).unwrap().appearance = look.into();
shape.name = "one closed path, 50,000 anchors, filled, dashed stroke";
shape
}
fn many_paths() -> Shape {
let mut doc = Document::new(1600.0, 1200.0);
let ids: Vec<NodeId> =
@@ -317,4 +332,5 @@ fn main() {
bench(one_outline());
bench(many_paths());
bench(long_open_path());
bench(dashed_outline());
}