mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-12 19:22:48 +00:00
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:
@@ -24,7 +24,7 @@ use vectorcraft_doc::{LineCap, LineJoin, StrokeAlign, StrokeLayer};
|
||||
pub(crate) use vectorcraft_geom::bez::{kink, segments, subpaths, tangent, unit};
|
||||
|
||||
pub use arrow::Arrow;
|
||||
pub use dash::{Dashed, Dot, dash, dot_outline};
|
||||
pub use dash::{Dashed, Dot, dash, dash_kept, dot_outline};
|
||||
pub use gradient::{Slice, WrittenSlices, gradient_meshes, gradient_slices, written_slices};
|
||||
pub use outline::{OUTLINE_TOL, Written, WrittenShape, for_writer, is_plain, outline_region};
|
||||
pub use width::width_outline;
|
||||
@@ -111,11 +111,7 @@ pub fn line_outline(line: &BezPath, st: &StrokeLayer, width: f64, tol: f64) -> B
|
||||
}
|
||||
out
|
||||
}
|
||||
(None, Some(d)) => {
|
||||
let mut out = kurbo::stroke(d.path.iter(), &style(st, width), &kurbo::StrokeOpts::default(), tol);
|
||||
out.extend(dot_outline(&d.dots, width, st.cap, tol).iter());
|
||||
out
|
||||
}
|
||||
(None, Some(d)) => dashed_outline(&d, st, width, tol),
|
||||
(None, None) => {
|
||||
let mut out = plain_outline(line, &style(st, width), tol);
|
||||
out.extend(dot_outline(&point_dots(line), width, st.cap, tol).iter());
|
||||
@@ -124,6 +120,28 @@ pub fn line_outline(line: &BezPath, st: &StrokeLayer, width: f64, tol: f64) -> B
|
||||
}
|
||||
}
|
||||
|
||||
/// [`line_outline`] of a dashed line without a width profile, made of only the dashes and dots on
|
||||
/// the segments of `line` that `keep` accepts ([`dash_kept`]). `None` when `st` has no dash
|
||||
/// pattern or has a width profile, or when its pattern draws the line solid.
|
||||
pub fn dashed_line_outline_kept(line: &BezPath, st: &StrokeLayer, width: f64, tol: f64, keep: &dyn Fn(&PathSeg) -> bool) -> Option<BezPath> {
|
||||
if st.profile.is_some() {
|
||||
return None;
|
||||
}
|
||||
let d = dash_kept(line, st.dash.as_ref()?, keep)?;
|
||||
if width <= 0.0 || !width.is_finite() {
|
||||
return Some(BezPath::new());
|
||||
}
|
||||
Some(dashed_outline(&d, st, width, tol.max(1e-4)))
|
||||
}
|
||||
|
||||
/// The filled outline of the dashes and dots `d` of a stroke `st` without a width profile, at
|
||||
/// `width` and flattened/fitted to `tol`.
|
||||
fn dashed_outline(d: &Dashed, st: &StrokeLayer, width: f64, tol: f64) -> BezPath {
|
||||
let mut out = kurbo::stroke(d.path.iter(), &style(st, width), &kurbo::StrokeOpts::default(), tol);
|
||||
out.extend(dot_outline(&d.dots, width, st.cap, tol).iter());
|
||||
out
|
||||
}
|
||||
|
||||
/// The subpaths of `line` that never leave their first point (`m` then `L` to the same point, as
|
||||
/// `.ai` files write dots, #1613), as dots: kurbo strokes nothing for them, where PDF and SVG
|
||||
/// viewers paint the cap. They lie along the x axis, which a projecting cap's square follows
|
||||
|
||||
Reference in New Issue
Block a user