summaryrefslogtreecommitdiffstats
path: root/graphics/src/widget/canvas/path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/src/widget/canvas/path.rs')
-rw-r--r--graphics/src/widget/canvas/path.rs44
1 files changed, 44 insertions, 0 deletions
diff --git a/graphics/src/widget/canvas/path.rs b/graphics/src/widget/canvas/path.rs
index 4e4fd734..b52c1f90 100644
--- a/graphics/src/widget/canvas/path.rs
+++ b/graphics/src/widget/canvas/path.rs
@@ -7,7 +7,11 @@ mod builder;
pub use arc::Arc;
pub use builder::Builder;
+use crate::canvas::LineDash;
+
use iced_native::{Point, Size};
+use lyon::path::iterator::PathIterator;
+use lyon_algorithms::walk::{walk_along_path, RepeatedPattern};
/// An immutable set of points that may or may not be connected.
///
@@ -66,3 +70,43 @@ impl Path {
}
}
}
+
+pub(super) fn dashed(path: &Path, line_dash: LineDash) -> Path {
+ let segments_odd = line_dash.segments.len() % 2 == 1;
+
+ let segments = segments_odd
+ .then(|| [&line_dash.segments[..], &line_dash.segments[..]].concat())
+ .unwrap_or(line_dash.segments);
+
+ let mut points = vec![];
+
+ walk_along_path(
+ path.raw().iter().flattened(0.01),
+ 0.0,
+ &mut RepeatedPattern {
+ callback: |position: lyon_algorithms::math::Point,
+ _tangent,
+ _distance| {
+ points.push(Point {
+ x: position.x,
+ y: position.y,
+ });
+ true
+ },
+ index: line_dash.offset,
+ intervals: &segments,
+ },
+ );
+
+ Path::new(|builder| {
+ for (idx, point) in points.into_iter().enumerate() {
+ let is_even = idx % 2 == 0;
+
+ if is_even {
+ builder.move_to(point);
+ } else {
+ builder.line_to(point);
+ }
+ }
+ })
+}