diff options
Diffstat (limited to 'graphics/src/widget')
| -rw-r--r-- | graphics/src/widget/canvas.rs | 20 | ||||
| -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 | ||||
| -rw-r--r-- | graphics/src/widget/qr_code.rs | 9 | 
5 files changed, 84 insertions, 29 deletions
diff --git a/graphics/src/widget/canvas.rs b/graphics/src/widget/canvas.rs index f9722f33..65d7e37e 100644 --- a/graphics/src/widget/canvas.rs +++ b/graphics/src/widget/canvas.rs @@ -9,10 +9,9 @@ use crate::{Backend, Primitive};  use iced_native::layout;  use iced_native::mouse;  use iced_native::{ -    Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Shell, Size, -    Vector, Widget, +    Clipboard, Element, Layout, Length, Point, Rectangle, Shell, Size, Vector, +    Widget,  }; -use std::hash::Hash;  use std::marker::PhantomData;  pub mod event; @@ -35,7 +34,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. @@ -212,6 +211,11 @@ where          use iced_native::Renderer as _;          let bounds = layout.bounds(); + +        if bounds.width < 1.0 || bounds.height < 1.0 { +            return; +        } +          let translation = Vector::new(bounds.x, bounds.y);          let cursor = Cursor::from_window_position(cursor_position); @@ -226,14 +230,6 @@ where              });          });      } - -    fn hash_layout(&self, state: &mut Hasher) { -        struct Marker; -        std::any::TypeId::of::<Marker>().hash(state); - -        self.width.hash(state); -        self.height.hash(state); -    }  }  impl<'a, Message, P, B> From<Canvas<Message, P>> diff --git a/graphics/src/widget/canvas/frame.rs b/graphics/src/widget/canvas/frame.rs index 08518f40..a3449605 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, +} diff --git a/graphics/src/widget/qr_code.rs b/graphics/src/widget/qr_code.rs index 285b8622..907794b7 100644 --- a/graphics/src/widget/qr_code.rs +++ b/graphics/src/widget/qr_code.rs @@ -5,8 +5,7 @@ use crate::Backend;  use iced_native::layout;  use iced_native::{ -    Color, Element, Hasher, Layout, Length, Point, Rectangle, Size, Vector, -    Widget, +    Color, Element, Layout, Length, Point, Rectangle, Size, Vector, Widget,  };  use thiserror::Error; @@ -74,12 +73,6 @@ where          ))      } -    fn hash_layout(&self, state: &mut Hasher) { -        use std::hash::Hash; - -        self.state.contents.hash(state); -    } -      fn draw(          &self,          renderer: &mut Renderer<B>,  | 
