1use super::color::Command;
2use super::geometry::*;
3use core::ops::Range;
4
5#[derive(Copy, Clone, PartialEq, Eq, Debug)]
6pub enum Verb {
7 MoveTo,
8 LineTo,
9 QuadTo,
10 CurveTo,
11 Close,
12}
13
14#[derive(Copy, Clone, Debug)]
15pub enum Element {
16 MoveTo(Point),
17 LineTo(Point),
18 QuadTo(Point, Point),
19 CurveTo(Point, Point, Point),
20 Close,
21}
22
23#[derive(Clone, Default, Debug)]
24pub struct Glyph {
25 points: Vec<Point>,
26 verbs: Vec<Verb>,
27 paths: Vec<PathData>,
28 commands: Vec<Command>,
29}
30
31impl Glyph {
32 pub fn num_paths(&self) -> usize {
33 self.paths.len()
34 }
35
36 pub fn path(&self, index: usize) -> Option<Path> {
37 let data = self.paths.get(index)?;
38 Some(Path {
39 points: self.points.get(data.points.clone())?,
40 verbs: self.verbs.get(data.verbs.clone())?,
41 bounds: &data.bounds,
42 })
43 }
44
45 pub fn is_simple(&self) -> bool {
46 self.commands.is_empty()
47 }
48
49 pub fn commands(&self) -> &[Command] {
50 &self.commands
51 }
52
53 pub fn clear(&mut self) {
54 self.points.clear();
55 self.verbs.clear();
56 self.paths.clear();
57 self.commands.clear();
58 }
59}
60
61impl Glyph {
62 pub(crate) fn push_command(&mut self, command: Command) {
63 self.commands.push(command);
64 }
65}
66
67#[derive(Copy, Clone, Debug)]
68pub struct Path<'a> {
69 pub points: &'a [Point],
70 pub verbs: &'a [Verb],
71 pub bounds: &'a Bounds,
72}
73
74impl<'a> Path<'a> {
75 pub fn elements(&self) -> impl Iterator<Item = Element> + 'a + Clone {
76 let mut i = 0;
77 let copy = *self;
78 copy.verbs.iter().map(move |verb| match verb {
79 Verb::MoveTo => {
80 let p0 = copy.points[i];
81 i += 1;
82 Element::MoveTo(p0)
83 }
84 Verb::LineTo => {
85 let p0 = copy.points[i];
86 i += 1;
87 Element::LineTo(p0)
88 }
89 Verb::QuadTo => {
90 let p0 = copy.points[i];
91 let p1 = copy.points[i + 1];
92 i += 2;
93 Element::QuadTo(p0, p1)
94 }
95 Verb::CurveTo => {
96 let p0 = copy.points[i];
97 let p1 = copy.points[i + 1];
98 let p2 = copy.points[i + 2];
99 i += 3;
100 Element::CurveTo(p0, p1, p2)
101 }
102 Verb::Close => Element::Close,
103 })
104 }
105}
106
107#[derive(Clone, Default, Debug)]
108struct PathData {
109 points: Range<usize>,
110 verbs: Range<usize>,
111 bounds: Bounds,
112}
113
114pub(super) struct PathBuilder<'a> {
115 inner: &'a mut Glyph,
116 path: PathData,
117}
118
119impl<'a> PathBuilder<'a> {
120 pub fn new(inner: &'a mut Glyph) -> Self {
121 let path = PathData {
122 points: inner.points.len()..inner.points.len(),
123 verbs: inner.verbs.len()..inner.verbs.len(),
124 bounds: Bounds::default(),
125 };
126 Self { inner, path }
127 }
128
129 pub fn move_to(&mut self, p: Point) {
130 self.maybe_close();
131 self.inner.points.push(p);
132 self.inner.verbs.push(Verb::MoveTo);
133 }
134
135 pub fn line_to(&mut self, p: Point) {
136 self.inner.points.push(p);
137 self.inner.verbs.push(Verb::LineTo);
138 }
139
140 pub fn quad_to(&mut self, p0: Point, p1: Point) {
141 self.inner.points.push(p0);
142 self.inner.points.push(p1);
143 self.inner.verbs.push(Verb::QuadTo);
144 }
145
146 pub fn curve_to(&mut self, p0: Point, p1: Point, p2: Point) {
147 self.inner.points.push(p0);
148 self.inner.points.push(p1);
149 self.inner.points.push(p2);
150 self.inner.verbs.push(Verb::CurveTo);
151 }
152
153 pub fn close(&mut self) {
154 self.inner.verbs.push(Verb::Close);
155 }
156
157 pub fn maybe_close(&mut self) {
158 if self.inner.verbs.len() > self.path.verbs.start
159 && self.inner.verbs.last() != Some(&Verb::Close)
160 {
161 self.close();
162 }
163 }
164
165 pub fn finish(mut self) {
166 self.path.points.end = self.inner.points.len();
167 self.path.verbs.end = self.inner.verbs.len();
168 self.path.bounds = Bounds::from_points(&self.inner.points[self.path.points.clone()]);
169 self.inner.paths.push(self.path);
170 }
171}