1use super::geometry::{Point, Transform};
4use super::path_builder::PathBuilder;
5
6use core::borrow::Borrow;
7
8#[derive(Copy, Clone, PartialEq, Debug)]
10pub enum Command {
11 MoveTo(Point),
13 LineTo(Point),
15 CurveTo(Point, Point, Point),
18 QuadTo(Point, Point),
21 Close,
23}
24
25impl Command {
26 pub fn verb(&self) -> Verb {
28 use Command::*;
29 match self {
30 MoveTo(..) => Verb::MoveTo,
31 LineTo(..) => Verb::LineTo,
32 QuadTo(..) => Verb::QuadTo,
33 CurveTo(..) => Verb::CurveTo,
34 Close => Verb::CurveTo,
35 }
36 }
37
38 #[inline]
40 pub fn transform(&self, transform: &Transform) -> Self {
41 use Command::*;
42 let t = transform;
43 match self {
44 MoveTo(p) => MoveTo(t.transform_point(*p)),
45 LineTo(p) => LineTo(t.transform_point(*p)),
46 QuadTo(c, p) => QuadTo(t.transform_point(*c), t.transform_point(*p)),
47 CurveTo(c1, c2, p) => CurveTo(
48 t.transform_point(*c1),
49 t.transform_point(*c2),
50 t.transform_point(*p),
51 ),
52 Close => Close,
53 }
54 }
55}
56
57#[derive(Copy, Clone, PartialEq, Eq, Debug)]
59pub enum Verb {
60 MoveTo,
61 LineTo,
62 CurveTo,
63 QuadTo,
64 Close,
65}
66
67#[derive(Clone)]
68pub struct PointsCommands<'a> {
69 points: &'a [Point],
70 verbs: &'a [Verb],
71 point: usize,
72 verb: usize,
73}
74
75impl<'a> PointsCommands<'a> {
76 pub(super) fn new(points: &'a [Point], verbs: &'a [Verb]) -> Self {
77 Self {
78 points,
79 verbs,
80 point: 0,
81 verb: 0,
82 }
83 }
84
85 #[inline(always)]
86 pub(super) fn copy_to(&self, sink: &mut impl PathBuilder) {
87 self.copy_to_inner(sink);
88 }
89
90 #[inline(always)]
91 fn copy_to_inner(&self, sink: &mut impl PathBuilder) -> Option<()> {
92 let mut i = 0;
93 for verb in self.verbs {
94 match verb {
95 Verb::MoveTo => {
96 let p = self.points.get(i)?;
97 i += 1;
98 sink.move_to(*p);
99 }
100 Verb::LineTo => {
101 let p = self.points.get(i)?;
102 i += 1;
103 sink.line_to(*p);
104 }
105 Verb::QuadTo => {
106 let p = self.points.get(i + 1)?;
107 let c = self.points.get(i)?;
108 i += 2;
109 sink.quad_to(*c, *p);
110 }
111 Verb::CurveTo => {
112 let p = self.points.get(i + 2)?;
113 let c2 = self.points.get(i + 1)?;
114 let c1 = self.points.get(i)?;
115 i += 3;
116 sink.curve_to(*c1, *c2, *p);
117 }
118 Verb::Close => {
119 sink.close();
120 }
121 }
122 }
123 Some(())
124 }
125}
126
127impl Iterator for PointsCommands<'_> {
128 type Item = Command;
129
130 #[inline(always)]
131 fn next(&mut self) -> Option<Self::Item> {
132 use Command::*;
133 let verb = self.verbs.get(self.verb)?;
134 self.verb += 1;
135 Some(match verb {
136 Verb::MoveTo => {
137 let p = self.points.get(self.point)?;
138 self.point += 1;
139 MoveTo(*p)
140 }
141 Verb::LineTo => {
142 let p = self.points.get(self.point)?;
143 self.point += 1;
144 LineTo(*p)
145 }
146 Verb::QuadTo => {
147 let p = self.points.get(self.point..self.point + 2)?;
148 self.point += 2;
149 QuadTo(p[0], p[1])
150 }
151 Verb::CurveTo => {
152 let p = self.points.get(self.point..self.point + 3)?;
153 self.point += 3;
154 CurveTo(p[0], p[1], p[2])
155 }
156 Verb::Close => Close,
157 })
158 }
159}
160
161#[derive(Clone)]
162pub struct TransformCommands<D> {
163 pub data: D,
164 pub transform: Transform,
165}
166
167impl<D> Iterator for TransformCommands<D>
168where
169 D: Iterator + Clone,
170 D::Item: Borrow<Command>,
171{
172 type Item = Command;
173
174 fn next(&mut self) -> Option<Self::Item> {
175 Some(self.data.next()?.borrow().transform(&self.transform))
176 }
177}