1use alloc::vec::Vec;
6use zeno::{Bounds, PathData, Point, Transform, Verb};
7
8#[derive(Clone, Default)]
11pub struct Outline {
12 layers: Vec<LayerData>,
13 points: Vec<Point>,
14 verbs: Vec<Verb>,
15 is_color: bool,
16}
17
18impl Outline {
19 pub fn new() -> Self {
21 Self::default()
22 }
23
24 pub fn is_color(&self) -> bool {
26 self.is_color
27 }
28
29 pub fn len(&self) -> usize {
31 self.layers.len()
32 }
33
34 pub fn is_empty(&self) -> bool {
36 self.layers.is_empty()
37 }
38
39 pub fn get<'a>(&'a self, index: usize) -> Option<Layer<'a>> {
41 let data = self.layers.get(index)?;
42 let points = self.points.get(data.points.0..data.points.1)?;
43 let verbs = self.verbs.get(data.verbs.0..data.verbs.1)?;
44 let color_index = data.color_index;
45 Some(Layer {
46 points,
47 verbs,
48 color_index,
49 })
50 }
51
52 pub fn get_mut<'a>(&'a mut self, index: usize) -> Option<LayerMut<'a>> {
54 let data = self.layers.get(index)?;
55 let points = self.points.get_mut(data.points.0..data.points.1)?;
56 let verbs = self.verbs.get(data.verbs.0..data.verbs.1)?;
57 let color_index = data.color_index;
58 Some(LayerMut {
59 points,
60 verbs,
61 color_index,
62 })
63 }
64
65 pub fn points(&self) -> &[Point] {
67 &self.points
68 }
69
70 pub fn points_mut(&mut self) -> &mut [Point] {
72 &mut self.points
73 }
74
75 pub fn verbs(&self) -> &[Verb] {
77 &self.verbs
78 }
79
80 pub fn path(&self) -> impl PathData + '_ {
82 (&self.points[..], &self.verbs[..])
83 }
84
85 pub fn bounds(&self) -> Bounds {
87 Bounds::from_points(&self.points)
88 }
89
90 pub fn transform(&mut self, transform: &Transform) {
92 for p in &mut self.points {
93 *p = transform.transform_point(*p);
94 }
95 }
96
97 pub fn embolden(&mut self, x_strength: f32, y_strength: f32) {
100 for i in 0..self.len() {
101 if let Some(mut layer) = self.get_mut(i) {
102 layer.embolden(x_strength, y_strength);
103 }
104 }
105 }
106
107 pub fn clear(&mut self) {
109 self.points.clear();
110 self.verbs.clear();
111 self.layers.clear();
112 self.is_color = false;
113 }
114}
115
116#[derive(Copy, Clone)]
118pub struct Layer<'a> {
119 points: &'a [Point],
120 verbs: &'a [Verb],
121 color_index: Option<u16>,
122}
123
124impl<'a> Layer<'a> {
125 pub fn points(&self) -> &'a [Point] {
127 self.points
128 }
129
130 pub fn verbs(&self) -> &'a [Verb] {
132 self.verbs
133 }
134
135 pub fn path(&self) -> impl PathData + 'a {
137 (self.points(), self.verbs())
138 }
139
140 pub fn bounds(&self) -> Bounds {
142 Bounds::from_points(self.points())
143 }
144
145 pub fn color_index(&self) -> Option<u16> {
147 self.color_index
148 }
149}
150
151pub struct LayerMut<'a> {
153 points: &'a mut [Point],
154 verbs: &'a [Verb],
155 color_index: Option<u16>,
156}
157
158impl<'a> LayerMut<'a> {
159 pub fn points(&'a self) -> &'a [Point] {
161 self.points
162 }
163
164 pub fn points_mut(&'a mut self) -> &'a mut [Point] {
166 &mut *self.points
167 }
168
169 pub fn verbs(&self) -> &'a [Verb] {
171 self.verbs
172 }
173
174 pub fn path(&'a self) -> impl PathData + 'a {
176 (self.points(), self.verbs())
177 }
178
179 pub fn bounds(&self) -> Bounds {
181 Bounds::from_points(self.points())
182 }
183
184 pub fn color_index(&self) -> Option<u16> {
186 self.color_index
187 }
188 pub fn transform(&'a mut self, transform: &Transform) {
190 for p in self.points.iter_mut() {
191 *p = transform.transform_point(*p);
192 }
193 }
194
195 pub fn embolden(&mut self, x_strength: f32, y_strength: f32) {
198 let mut point_start = 0;
199 let mut pos = 0;
200 let winding = compute_winding(self.points);
201 for verb in self.verbs {
202 match verb {
203 Verb::MoveTo | Verb::Close => {
204 if let Some(points) = self.points.get_mut(point_start..pos) {
205 if !points.is_empty() {
206 embolden(points, winding, x_strength, y_strength);
207 }
208 point_start = pos;
209 if *verb == Verb::MoveTo {
210 pos += 1;
211 }
212 } else {
213 return;
214 }
215 }
216 Verb::LineTo => pos += 1,
217 Verb::QuadTo => pos += 2,
218 Verb::CurveTo => pos += 3,
219 }
220 }
221 if pos > point_start {
222 if let Some(points) = self.points.get_mut(point_start..pos) {
223 embolden(points, winding, x_strength, y_strength);
224 }
225 }
226 }
227}
228
229#[derive(Copy, Clone, Default)]
230struct LayerData {
231 points: (usize, usize),
232 verbs: (usize, usize),
233 color_index: Option<u16>,
234}
235
236impl Outline {
237 pub(super) fn set_color(&mut self, color: bool) {
238 self.is_color = color;
239 }
240
241 pub(super) fn move_to(&mut self, p: Point) {
242 self.maybe_close();
243 self.points.push(p);
244 self.verbs.push(Verb::MoveTo);
245 }
246
247 pub(super) fn line_to(&mut self, p: Point) {
248 self.points.push(p);
249 self.verbs.push(Verb::LineTo);
250 }
251
252 pub(super) fn quad_to(&mut self, p0: Point, p1: Point) {
253 self.points.push(p0);
254 self.points.push(p1);
255 self.verbs.push(Verb::QuadTo);
256 }
257
258 pub(super) fn curve_to(&mut self, p0: Point, p1: Point, p2: Point) {
259 self.points.push(p0);
260 self.points.push(p1);
261 self.points.push(p2);
262 self.verbs.push(Verb::CurveTo);
263 }
264
265 pub(super) fn close(&mut self) {
266 self.verbs.push(Verb::Close);
267 }
268
269 pub(super) fn maybe_close(&mut self) {
270 if !self.verbs.is_empty() && self.verbs.last() != Some(&Verb::Close) {
271 self.close();
272 }
273 }
274
275 pub(super) fn begin_layer(&mut self, color_index: Option<u16>) {
276 let points_end = self.points.len();
277 let verbs_end = self.verbs.len();
278 if let Some(last) = self.layers.last_mut() {
279 last.points.1 = points_end;
280 last.verbs.1 = verbs_end;
281 }
282 self.layers.push(LayerData {
283 points: (points_end, points_end),
284 verbs: (verbs_end, verbs_end),
285 color_index,
286 });
287 }
288
289 pub(super) fn finish(&mut self) {
290 let points_end = self.points.len();
291 let verbs_end = self.verbs.len();
292 if let Some(last) = self.layers.last_mut() {
293 last.points.1 = points_end;
294 last.verbs.1 = verbs_end;
295 } else {
296 self.layers.push(LayerData {
297 points: (0, points_end),
298 verbs: (0, verbs_end),
299 color_index: None,
300 });
301 }
302 }
303}
304
305fn embolden(points: &mut [Point], winding: u8, x_strength: f32, y_strength: f32) {
306 if points.is_empty() {
307 return;
308 }
309 let last = points.len() - 1;
310 let mut i = last;
311 let mut j = 0;
312 let mut k = !0;
313 let mut out_len;
314 let mut in_len = 0.;
315 let mut anchor_len = 0.;
316 let mut anchor = Point::ZERO;
317 let mut out;
318 let mut in_ = Point::ZERO;
319 while j != i && i != k {
320 if j != k {
321 out = points[j] - points[i];
322 out_len = out.length();
323 if out_len == 0. {
324 j = if j < last { j + 1 } else { 0 };
325 continue;
326 } else {
327 let s = 1. / out_len;
328 out.x *= s;
329 out.y *= s;
330 }
331 } else {
332 out = anchor;
333 out_len = anchor_len;
334 }
335 if in_len != 0. {
336 if k == !0 {
337 k = i;
338 anchor = in_;
339 anchor_len = in_len;
340 }
341 let mut d = (in_.x * out.x) + (in_.y * out.y);
342 let shift = if d > -0.9396 {
343 d += 1.;
344 let mut sx = in_.y + out.y;
345 let mut sy = in_.x + out.x;
346 if winding == 0 {
347 sx = -sx;
348 } else {
349 sy = -sy;
350 }
351 let mut q = (out.x * in_.y) - (out.y * in_.x);
352 if winding == 0 {
353 q = -q;
354 }
355 let l = in_len.min(out_len);
356 if x_strength * q <= l * d {
357 sx = sx * x_strength / d;
358 } else {
359 sx = sx * l / q;
360 }
361 if y_strength * q <= l * d {
362 sy = sy * y_strength / d;
363 } else {
364 sy = sy * l / q;
365 }
366 Point::new(sx, sy)
367 } else {
368 Point::ZERO
369 };
370
371 while i != j {
372 points[i].x += x_strength + shift.x;
373 points[i].y += y_strength + shift.y;
374 i = if i < last { i + 1 } else { 0 };
375 }
376 } else {
377 i = j;
378 }
379 in_ = out;
380 in_len = out_len;
381 j = if j < last { j + 1 } else { 0 };
382 }
383}
384
385fn compute_winding(points: &[Point]) -> u8 {
386 if points.is_empty() {
387 return 0;
388 }
389 let mut area = 0.;
390 let last = points.len() - 1;
391 let mut prev = points[last];
392 for cur in points[0..=last].iter() {
393 area += (cur.y - prev.y) * (cur.x + prev.x);
394 prev = *cur;
395 }
396 if area > 0. {
397 1
398 } else {
399 0
400 }
401}
402
403impl skrifa::outline::OutlinePen for Outline {
404 fn move_to(&mut self, x: f32, y: f32) {
405 self.move_to((x, y).into());
406 }
407
408 fn line_to(&mut self, x: f32, y: f32) {
409 self.line_to((x, y).into());
410 }
411
412 fn quad_to(&mut self, cx0: f32, cy0: f32, x: f32, y: f32) {
413 self.quad_to((cx0, cy0).into(), (x, y).into());
414 }
415
416 fn curve_to(&mut self, cx0: f32, cy0: f32, cx1: f32, cy1: f32, x: f32, y: f32) {
417 self.curve_to((cx0, cy0).into(), (cx1, cy1).into(), (x, y).into());
418 }
419
420 fn close(&mut self) {
421 self.close();
422 }
423}