1use crate::PathCommand;
2use makepad_geometry::{Point, Transform, Transformation};
3use makepad_internal_iter::{
4 ExtendFromInternalIterator, FromInternalIterator, InternalIterator, IntoInternalIterator,
5};
6use std::iter::Cloned;
7use std::slice::Iter;
8
9#[derive(Clone, Debug, Default, PartialEq)]
12pub struct Path {
13 verbs: Vec<Verb>,
14 points: Vec<Point>,
15}
16
17impl Path {
18 pub fn new() -> Path {
20 Path::default()
21 }
22
23 pub fn points(&self) -> &[Point] {
25 &self.points
26 }
27
28 pub fn commands(&self) -> Commands {
30 Commands {
31 verbs: self.verbs.iter().cloned(),
32 points: self.points.iter().cloned(),
33 }
34 }
35
36 pub fn points_mut(&mut self) -> &mut [Point] {
38 &mut self.points
39 }
40
41 pub fn move_to(&mut self, p: Point) {
43 self.verbs.push(Verb::MoveTo);
44 self.points.push(p);
45 }
46
47 pub fn line_to(&mut self, p: Point) {
49 self.verbs.push(Verb::LineTo);
50 self.points.push(p);
51 }
52
53 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 pub fn close(&mut self) {
62 self.verbs.push(Verb::Close);
63 }
64
65 pub fn clear(&mut self) {
67 self.verbs.clear();
68 self.points.clear();
69 }
70}
71
72impl ExtendFromInternalIterator<PathCommand> for Path {
73 fn extend_from_internal_iter<I>(&mut self, internal_iter: I)
74 where
75 I: IntoInternalIterator<Item = PathCommand>,
76 {
77 internal_iter.into_internal_iter().for_each(&mut |command| {
78 match command {
79 PathCommand::MoveTo(p) => self.move_to(p),
80 PathCommand::LineTo(p) => self.line_to(p),
81 PathCommand::QuadraticTo(p1, p) => self.quadratic_to(p1, p),
82 PathCommand::Close => self.close(),
83 }
84 true
85 });
86 }
87}
88
89impl FromInternalIterator<PathCommand> for Path {
90 fn from_internal_iter<I>(internal_iter: I) -> Self
91 where
92 I: IntoInternalIterator<Item = PathCommand>,
93 {
94 let mut path = Path::new();
95 path.extend_from_internal_iter(internal_iter);
96 path
97 }
98}
99
100impl Transform for Path {
101 fn transform<T>(mut self, t: &T) -> Path
102 where
103 T: Transformation,
104 {
105 self.transform_mut(t);
106 self
107 }
108
109 fn transform_mut<T>(&mut self, t: &T)
110 where
111 T: Transformation,
112 {
113 for point in self.points_mut() {
114 point.transform_mut(t);
115 }
116 }
117}
118
119#[derive(Clone, Debug)]
121pub struct Commands<'a> {
122 verbs: Cloned<Iter<'a, Verb>>,
123 points: Cloned<Iter<'a, Point>>,
124}
125
126impl<'a> Iterator for Commands<'a> {
127 type Item = PathCommand;
128
129 fn next(&mut self) -> Option<PathCommand> {
130 self.verbs.next().map(|verb| match verb {
131 Verb::MoveTo => PathCommand::MoveTo(self.points.next().unwrap()),
132 Verb::LineTo => PathCommand::LineTo(self.points.next().unwrap()),
133 Verb::QuadraticTo => {
134 PathCommand::QuadraticTo(self.points.next().unwrap(), self.points.next().unwrap())
135 }
136 Verb::Close => PathCommand::Close,
137 })
138 }
139}
140
141#[derive(Clone, Debug, Eq, Hash, PartialEq)]
142enum Verb {
143 MoveTo,
144 LineTo,
145 QuadraticTo,
146 Close,
147}