makepad_vector/path/
line_path.rs

1use crate::path::LinePathCommand;
2use crate::geometry::{Point, Transform, Transformation};
3use crate::internal_iter::{
4    ExtendFromInternalIterator, FromInternalIterator, InternalIterator, IntoInternalIterator,
5};
6use std::iter::Cloned;
7use std::slice::Iter;
8
9/// A sequence of commands that defines a set of contours, each of which consists of a sequence of
10/// line segments. Each contour is either open or closed.
11#[derive(Clone, Debug, Default, PartialEq)]
12pub struct LinePath {
13    verbs: Vec<Verb>,
14    points: Vec<Point>,
15}
16
17impl LinePath {
18    /// Creates a new empty line path.
19    pub fn new() -> LinePath {
20        LinePath::default()
21    }
22
23    /// Returns a slice of the points that make up `self`.
24    pub fn points(&self) -> &[Point] {
25        &self.points
26    }
27
28    /// Returns an iterator over the commands that make up `self`.
29    pub fn commands(&self) -> Commands {
30        Commands {
31            verbs: self.verbs.iter().cloned(),
32            points: self.points.iter().cloned(),
33        }
34    }
35
36    /// Returns a mutable slice of the points that make up `self`.
37    pub fn points_mut(&mut self) -> &mut [Point] {
38        &mut self.points
39    }
40
41    /// Adds a new contour, starting at the given point.
42    pub fn move_to(&mut self, p: Point) {
43        self.verbs.push(Verb::MoveTo);
44        self.points.push(p);
45    }
46
47    /// Adds a line segment to the current contour, starting at the current point.
48    pub fn line_to(&mut self, p: Point) {
49        self.verbs.push(Verb::LineTo);
50        self.points.push(p);
51    }
52
53    /// Closes the current contour.
54    pub fn close(&mut self) {
55        self.verbs.push(Verb::Close);
56    }
57
58    /// Clears `self`.
59    pub fn clear(&mut self) {
60        self.verbs.clear();
61        self.points.clear();
62    }
63}
64
65impl ExtendFromInternalIterator<LinePathCommand> for LinePath {
66    fn extend_from_internal_iter<I>(&mut self, internal_iter: I)
67    where
68        I: IntoInternalIterator<Item = LinePathCommand>,
69    {
70        internal_iter.into_internal_iter().for_each(&mut |command| {
71            match command {
72                LinePathCommand::MoveTo(p) => self.move_to(p),
73                LinePathCommand::LineTo(p) => self.line_to(p),
74                LinePathCommand::Close => self.close(),
75            }
76            true
77        });
78    }
79}
80
81impl FromInternalIterator<LinePathCommand> for LinePath {
82    fn from_internal_iter<I>(internal_iter: I) -> Self
83    where
84        I: IntoInternalIterator<Item = LinePathCommand>,
85    {
86        let mut path = LinePath::new();
87        path.extend_from_internal_iter(internal_iter);
88        path
89    }
90}
91
92impl Transform for LinePath {
93    fn transform<T>(mut self, t: &T) -> LinePath
94    where
95        T: Transformation,
96    {
97        self.transform_mut(t);
98        self
99    }
100
101    fn transform_mut<T>(&mut self, t: &T)
102    where
103        T: Transformation,
104    {
105        for point in self.points_mut() {
106            point.transform_mut(t);
107        }
108    }
109}
110
111/// An iterator over the commands that make up a line path.
112#[derive(Clone, Debug)]
113pub struct Commands<'a> {
114    verbs: Cloned<Iter<'a, Verb>>,
115    points: Cloned<Iter<'a, Point>>,
116}
117
118impl<'a> Iterator for Commands<'a> {
119    type Item = LinePathCommand;
120
121    fn next(&mut self) -> Option<LinePathCommand> {
122        self.verbs.next().map(|verb| match verb {
123            Verb::MoveTo => LinePathCommand::MoveTo(self.points.next().unwrap()),
124            Verb::LineTo => LinePathCommand::LineTo(self.points.next().unwrap()),
125            Verb::Close => LinePathCommand::Close,
126        })
127    }
128}
129
130#[derive(Clone, Debug, Eq, Hash, PartialEq)]
131enum Verb {
132    MoveTo,
133    LineTo,
134    Close,
135}