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    arc_params: Vec<ArcParams>,
16}
17
18#[derive(Clone, Debug, Default, PartialEq)]
19struct ArcParams {
20    pub xr: f64, // x_axis_rotation
21    pub l: bool, // large_arc
22    pub s: bool, // sweep
23}
24
25impl Path {
26    /// Creates a new empty path.
27    pub fn new() -> Path {
28        Path::default()
29    }
30
31    /// Returns a slice of the points that make up `self`.
32    pub fn points(&self) -> &[Point] {
33        &self.points
34    }
35
36    /// Returns an iterator over the commands that make up `self`.
37    pub fn commands(&self) -> Commands {
38        Commands {
39            verbs: self.verbs.iter().cloned(),
40            points: self.points.iter().cloned(),
41            arc_params: self.arc_params.iter().cloned(),
42        }
43    }
44
45    /// Returns a mutable slice of the points that make up `self`.
46    pub fn points_mut(&mut self) -> &mut [Point] {
47        &mut self.points
48    }
49
50    pub fn arc(&mut self, e: Point, r: Point, xr: f64, l: bool, s: bool) {
51        self.verbs.push(Verb::ArcTo);
52        self.points.push(e);
53        self.points.push(r);
54        self.arc_params.push(ArcParams{ xr, l, s });
55    }
56
57    /// Adds a new contour, starting at the given point.
58    pub fn move_to(&mut self, p: Point) {
59        self.verbs.push(Verb::MoveTo);
60        self.points.push(p);
61    }
62
63    /// Adds a line segment to the current contour, starting at the current point.
64    pub fn line_to(&mut self, p: Point) {
65        self.verbs.push(Verb::LineTo);
66        self.points.push(p);
67    }
68
69    // Adds a quadratic Bezier curve segment to the current contour, starting at the current point.
70    pub fn quadratic_to(&mut self, p1: Point, p: Point) {
71        self.verbs.push(Verb::QuadraticTo);
72        self.points.push(p1);
73        self.points.push(p);
74    }
75
76    // Adds a quadratic Bezier curve segment to the current contour, starting at the current point.
77    pub fn cubic_to(&mut self, p1: Point, p2: Point, p: Point) {
78        self.verbs.push(Verb::QuadraticTo);
79        self.points.push(p1);
80        self.points.push(p2);
81        self.points.push(p);
82    }
83
84
85    /// Closes the current contour.
86    pub fn close(&mut self) {
87        self.verbs.push(Verb::Close);
88    }
89
90    /// Clears `self`.
91    pub fn clear(&mut self) {
92        self.verbs.clear();
93        self.points.clear();
94        self.arc_params.clear();
95    }
96}
97
98impl ExtendFromInternalIterator<PathCommand> for Path {
99    fn extend_from_internal_iter<I>(&mut self, internal_iter: I)
100    where
101        I: IntoInternalIterator<Item = PathCommand>,
102    {
103        internal_iter.into_internal_iter().for_each(&mut |command| {
104            match command {
105                PathCommand::MoveTo(p) => self.move_to(p),
106                PathCommand::LineTo(p) => self.line_to(p),
107                PathCommand::ArcTo(e, r, xr, l, s) => self.arc(e, r, xr, l, s),
108                PathCommand::QuadraticTo(p1, p) => self.quadratic_to(p1, p),
109                PathCommand::CubicTo(p1, p2,  p) => self.cubic_to(p1, p2, p),
110                PathCommand::Close => self.close(),
111            }
112            true
113        });
114    }
115}
116
117impl FromInternalIterator<PathCommand> for Path {
118    fn from_internal_iter<I>(internal_iter: I) -> Self
119    where
120        I: IntoInternalIterator<Item = PathCommand>,
121    {
122        let mut path = Path::new();
123        path.extend_from_internal_iter(internal_iter);
124        path
125    }
126}
127
128impl Transform for Path {
129    fn transform<T>(mut self, t: &T) -> Path
130    where
131        T: Transformation,
132    {
133        self.transform_mut(t);
134        self
135    }
136
137    fn transform_mut<T>(&mut self, t: &T)
138    where
139        T: Transformation,
140    {
141        for point in self.points_mut() {
142            point.transform_mut(t);
143        }
144    }
145}
146
147/// An iterator over the commands that make up a path.
148#[derive(Clone, Debug)]
149pub struct Commands<'a> {
150    verbs: Cloned<Iter<'a, Verb>>,
151    points: Cloned<Iter<'a, Point>>,
152    arc_params: Cloned<Iter<'a, ArcParams>>,
153}
154
155impl<'a> Iterator for Commands<'a> {
156    type Item = PathCommand;
157
158    fn next(&mut self) -> Option<PathCommand> {
159        self.verbs.next().map(|verb| match verb {
160            Verb::MoveTo => PathCommand::MoveTo(self.points.next().unwrap()),
161            Verb::LineTo => PathCommand::LineTo(self.points.next().unwrap()),
162            Verb::ArcTo => {
163                let ArcParams{ xr, l, s } = self.arc_params.next().unwrap();
164                PathCommand::ArcTo(self.points.next().unwrap(), self.points.next().unwrap(), xr, l, s)
165            }
166            Verb::QuadraticTo => {
167                PathCommand::QuadraticTo(self.points.next().unwrap(), self.points.next().unwrap())
168            }
169            Verb::Close => PathCommand::Close,
170        })
171    }
172}
173
174#[derive(Clone, Debug, Eq, Hash, PartialEq)]
175enum Verb {
176    MoveTo,
177    LineTo,
178    ArcTo,
179    QuadraticTo,
180    Close,
181}