summaryrefslogtreecommitdiffstats
path: root/graphics
diff options
context:
space:
mode:
authorLibravatar Cory Forsstrom <cory.forsstrom@lich.io>2022-01-27 09:40:52 -0800
committerLibravatar Cory Forsstrom <cory.forsstrom@lich.io>2022-01-27 09:40:52 -0800
commite835cea03c5d6eeba2d76b52206516dcc2a6b628 (patch)
treeb54e2c27925284e16230f5d1eaf76ea9afe86860 /graphics
parent4aa943cbc63230dfcb995c469ceec9f74e6132e1 (diff)
downloadiced-e835cea03c5d6eeba2d76b52206516dcc2a6b628.tar.gz
iced-e835cea03c5d6eeba2d76b52206516dcc2a6b628.tar.bz2
iced-e835cea03c5d6eeba2d76b52206516dcc2a6b628.zip
Add line dash API
Diffstat (limited to 'graphics')
-rw-r--r--graphics/Cargo.toml6
-rw-r--r--graphics/src/widget/canvas.rs2
-rw-r--r--graphics/src/widget/canvas/frame.rs9
-rw-r--r--graphics/src/widget/canvas/path.rs44
-rw-r--r--graphics/src/widget/canvas/stroke.rs14
5 files changed, 72 insertions, 3 deletions
diff --git a/graphics/Cargo.toml b/graphics/Cargo.toml
index 12f38cce..07a19807 100644
--- a/graphics/Cargo.toml
+++ b/graphics/Cargo.toml
@@ -11,7 +11,7 @@ keywords = ["gui", "ui", "graphics", "interface", "widgets"]
categories = ["gui"]
[features]
-canvas = ["lyon"]
+canvas = ["lyon", "lyon_algorithms"]
qr_code = ["qrcode", "canvas"]
font-source = ["font-kit"]
font-fallback = []
@@ -39,6 +39,10 @@ path = "../style"
version = "0.17"
optional = true
+[dependencies.lyon_algorithms]
+version = "0.17"
+optional = true
+
[dependencies.qrcode]
version = "0.12"
optional = true
diff --git a/graphics/src/widget/canvas.rs b/graphics/src/widget/canvas.rs
index f9722f33..1016bbe3 100644
--- a/graphics/src/widget/canvas.rs
+++ b/graphics/src/widget/canvas.rs
@@ -35,7 +35,7 @@ pub use frame::Frame;
pub use geometry::Geometry;
pub use path::Path;
pub use program::Program;
-pub use stroke::{LineCap, LineJoin, Stroke};
+pub use stroke::{LineCap, LineDash, LineJoin, Stroke};
pub use text::Text;
/// A widget capable of drawing 2D graphics.
diff --git a/graphics/src/widget/canvas/frame.rs b/graphics/src/widget/canvas/frame.rs
index 4873e7fb..b98c3002 100644
--- a/graphics/src/widget/canvas/frame.rs
+++ b/graphics/src/widget/canvas/frame.rs
@@ -1,6 +1,9 @@
+use std::borrow::Cow;
+
use iced_native::{Point, Rectangle, Size, Vector};
use crate::{
+ canvas::path,
canvas::{Fill, Geometry, Path, Stroke, Text},
triangle, Primitive,
};
@@ -164,6 +167,12 @@ impl Frame {
options.end_cap = stroke.line_cap.into();
options.line_join = stroke.line_join.into();
+ let path = if stroke.line_dash.segments.is_empty() {
+ Cow::Borrowed(path)
+ } else {
+ Cow::Owned(path::dashed(path, stroke.line_dash))
+ };
+
let result = if self.transforms.current.is_identity {
self.stroke_tessellator.tessellate_path(
path.raw(),
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);
+ }
+ }
+ })
+}
diff --git a/graphics/src/widget/canvas/stroke.rs b/graphics/src/widget/canvas/stroke.rs
index 9f0449d0..5c20405e 100644
--- a/graphics/src/widget/canvas/stroke.rs
+++ b/graphics/src/widget/canvas/stroke.rs
@@ -1,7 +1,7 @@
use iced_native::Color;
/// The style of a stroke.
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone)]
pub struct Stroke {
/// The color of the stroke.
pub color: Color,
@@ -12,6 +12,8 @@ pub struct Stroke {
/// The shape to be used at the corners of paths or basic shapes when they
/// are stroked.
pub line_join: LineJoin,
+ /// The dash pattern used when stroking the line.
+ pub line_dash: LineDash,
}
impl Stroke {
@@ -43,6 +45,7 @@ impl Default for Stroke {
width: 1.0,
line_cap: LineCap::default(),
line_join: LineJoin::default(),
+ line_dash: LineDash::default(),
}
}
}
@@ -103,3 +106,12 @@ impl From<LineJoin> for lyon::tessellation::LineJoin {
}
}
}
+
+/// The dash pattern used when stroking the line.
+#[derive(Debug, Clone, Default)]
+pub struct LineDash {
+ /// The alternating lengths of lines and gaps which describe the pattern.
+ pub segments: Vec<f32>,
+ /// The offset of [`LineDash::segments`] to start the pattern.
+ pub offset: usize,
+}