moscato/
glyph.rs

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}