diff options
Diffstat (limited to '')
| -rw-r--r-- | graphics/src/widget/canvas.rs | 2 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/frame.rs | 11 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/path.rs | 44 | ||||
| -rw-r--r-- | graphics/src/widget/canvas/stroke.rs | 29 | 
4 files changed, 76 insertions, 10 deletions
| 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..357dfa62 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,  }; @@ -150,7 +153,7 @@ impl Frame {      /// Draws the stroke of the given [`Path`] on the [`Frame`] with the      /// provided style. -    pub fn stroke(&mut self, path: &Path, stroke: impl Into<Stroke>) { +    pub fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>) {          let stroke = stroke.into();          let mut buffers = tessellation::BuffersBuilder::new( @@ -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..1728f060 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::algorithms::walk::{walk_along_path, RepeatedPattern}; +use lyon::path::iterator::PathIterator;  /// 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 { +    Path::new(|builder| { +        let segments_odd = (line_dash.segments.len() % 2 == 1).then(|| { +            [&line_dash.segments[..], &line_dash.segments[..]].concat() +        }); + +        let mut draw_line = false; + +        walk_along_path( +            path.raw().iter().flattened(0.01), +            0.0, +            &mut RepeatedPattern { +                callback: |position: lyon::algorithms::math::Point, +                           _tangent, +                           _distance| { +                    let point = Point { +                        x: position.x, +                        y: position.y, +                    }; + +                    if draw_line { +                        builder.line_to(point); +                    } else { +                        builder.move_to(point); +                    } + +                    draw_line = !draw_line; + +                    true +                }, +                index: line_dash.offset, +                intervals: segments_odd +                    .as_ref() +                    .map(Vec::as_slice) +                    .unwrap_or(line_dash.segments), +            }, +        ); +    }) +} diff --git a/graphics/src/widget/canvas/stroke.rs b/graphics/src/widget/canvas/stroke.rs index 9f0449d0..6accc2fb 100644 --- a/graphics/src/widget/canvas/stroke.rs +++ b/graphics/src/widget/canvas/stroke.rs @@ -2,7 +2,7 @@ use iced_native::Color;  /// The style of a stroke.  #[derive(Debug, Clone, Copy)] -pub struct Stroke { +pub struct Stroke<'a> {      /// The color of the stroke.      pub color: Color,      /// The distance between the two edges of the stroke. @@ -12,37 +12,40 @@ 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<'a>,  } -impl Stroke { +impl<'a> Stroke<'a> {      /// Sets the color of the [`Stroke`]. -    pub fn with_color(self, color: Color) -> Stroke { +    pub fn with_color(self, color: Color) -> Self {          Stroke { color, ..self }      }      /// Sets the width of the [`Stroke`]. -    pub fn with_width(self, width: f32) -> Stroke { +    pub fn with_width(self, width: f32) -> Self {          Stroke { width, ..self }      }      /// Sets the [`LineCap`] of the [`Stroke`]. -    pub fn with_line_cap(self, line_cap: LineCap) -> Stroke { +    pub fn with_line_cap(self, line_cap: LineCap) -> Self {          Stroke { line_cap, ..self }      }      /// Sets the [`LineJoin`] of the [`Stroke`]. -    pub fn with_line_join(self, line_join: LineJoin) -> Stroke { +    pub fn with_line_join(self, line_join: LineJoin) -> Self {          Stroke { line_join, ..self }      }  } -impl Default for Stroke { -    fn default() -> Stroke { +impl<'a> Default for Stroke<'a> { +    fn default() -> Self {          Stroke {              color: Color::BLACK,              width: 1.0,              line_cap: LineCap::default(),              line_join: LineJoin::default(), +            line_dash: LineDash::default(),          }      }  } @@ -103,3 +106,13 @@ impl From<LineJoin> for lyon::tessellation::LineJoin {          }      }  } + +/// The dash pattern used when stroking the line. +#[derive(Debug, Clone, Copy, Default)] +pub struct LineDash<'a> { +    /// The alternating lengths of lines and gaps which describe the pattern. +    pub segments: &'a [f32], + +    /// The offset of [`LineDash::segments`] to start the pattern. +    pub offset: usize, +} | 
