makepad_vector/path/
path.rs

1use crate::path::PathCommand;
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/// curve segments. Each contour is either open or closed.
11#[derive(Clone, Debug, Default, PartialEq)]
12pub struct Path {
13    verbs: Vec<Verb>,
14    points: Vec<Point>,
15}
16
17impl Path {
18    /// Creates a new empty path.
19    pub fn new() -> Path {
20        Path::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    // Adds a quadratic Bezier curve segment to the current contour, starting at the current point.
54    pub fn quadratic_to(&mut self, p1: Point, p: Point) {
55        self.verbs.push(Verb::QuadraticTo);
56        self.points.push(p1);
57        self.points.push(p);
58    }
59
60    // Adds a quadratic Bezier curve segment to the current contour, starting at the current point.
61    pub fn cubic_to(&mut self, p1: Point, p2: Point, p: Point) {
62        self.verbs.push(Verb::QuadraticTo);
63        self.points.push(p1);
64        self.points.push(p2);
65        self.points.push(p);
66    }
67
68
69    /// Closes the current contour.
70    pub fn close(&mut self) {
71        self.verbs.push(Verb::Close);
72    }
73
74    /// Clears `self`.
75    pub fn clear(&mut self) {
76        self.verbs.clear();
77        self.points.clear();
78    }
79}
80
81impl ExtendFromInternalIterator<PathCommand> for Path {
82    fn extend_from_internal_iter<I>(&mut self, internal_iter: I)
83    where
84        I: IntoInternalIterator<Item = PathCommand>,
85    {
86        internal_iter.into_internal_iter().for_each(&mut |command| {
87            match command {
88                PathCommand::MoveTo(p) => self.move_to(p),
89                PathCommand::LineTo(p) => self.line_to(p),
90                PathCommand::QuadraticTo(p1, p) => self.quadratic_to(p1, p),
91                PathCommand::CubicTo(p1, p2,  p) => self.cubic_to(p1, p2, p),
92                PathCommand::Close => self.close(),
93            }
94            true
95        });
96    }
97}
98
99impl FromInternalIterator<PathCommand> for Path {
100    fn from_internal_iter<I>(internal_iter: I) -> Self
101    where
102        I: IntoInternalIterator<Item = PathCommand>,
103    {
104        let mut path = Path::new();
105        path.extend_from_internal_iter(internal_iter);
106        path
107    }
108}
109
110impl Transform for Path {
111    fn transform<T>(mut self, t: &T) -> Path
112    where
113        T: Transformation,
114    {
115        self.transform_mut(t);
116        self
117    }
118
119    fn transform_mut<T>(&mut self, t: &T)
120    where
121        T: Transformation,
122    {
123        for point in self.points_mut() {
124            point.transform_mut(t);
125        }
126    }
127}
128
129/// An iterator over the commands that make up a path.
130#[derive(Clone, Debug)]
131pub struct Commands<'a> {
132    verbs: Cloned<Iter<'a, Verb>>,
133    points: Cloned<Iter<'a, Point>>,
134}
135
136impl<'a> Iterator for Commands<'a> {
137    type Item = PathCommand;
138
139    fn next(&mut self) -> Option<PathCommand> {
140        self.verbs.next().map(|verb| match verb {
141            Verb::MoveTo => PathCommand::MoveTo(self.points.next().unwrap()),
142            Verb::LineTo => PathCommand::LineTo(self.points.next().unwrap()),
143            Verb::QuadraticTo => {
144                PathCommand::QuadraticTo(self.points.next().unwrap(), self.points.next().unwrap())
145            }
146            Verb::Close => PathCommand::Close,
147        })
148    }
149}
150
151#[derive(Clone, Debug, Eq, Hash, PartialEq)]
152enum Verb {
153    MoveTo,
154    LineTo,
155    QuadraticTo,
156    Close,
157}