1use core::num::NonZeroU16;
4
5use crate::parser::{Stream, F2DOT14, LazyArray16, NumFrom};
6use crate::{loca, GlyphId, OutlineBuilder, Rect, BBox};
7
8pub(crate) struct Builder<'a> {
9 pub builder: &'a mut dyn OutlineBuilder,
10 pub transform: Transform,
11 is_default_ts: bool, pub bbox: Option<BBox>, first_on_curve: Option<Point>,
14 first_off_curve: Option<Point>,
15 last_off_curve: Option<Point>,
16}
17
18impl<'a> Builder<'a> {
19 #[inline]
20 pub fn new(
21 transform: Transform,
22 bbox: Option<BBox>,
23 builder: &'a mut dyn OutlineBuilder,
24 ) -> Self {
25 Builder {
26 builder,
27 transform,
28 is_default_ts: transform.is_default(),
29 bbox,
30 first_on_curve: None,
31 first_off_curve: None,
32 last_off_curve: None,
33 }
34 }
35
36 #[inline]
37 fn move_to(&mut self, mut x: f32, mut y: f32) {
38 if !self.is_default_ts {
39 self.transform.apply_to(&mut x, &mut y);
40 }
41
42 if let Some(ref mut bbox) = self.bbox {
43 bbox.extend_by(x, y);
44 }
45
46 self.builder.move_to(x, y);
47 }
48
49 #[inline]
50 fn line_to(&mut self, mut x: f32, mut y: f32) {
51 if !self.is_default_ts {
52 self.transform.apply_to(&mut x, &mut y);
53 }
54
55 if let Some(ref mut bbox) = self.bbox {
56 bbox.extend_by(x, y);
57 }
58
59 self.builder.line_to(x, y);
60 }
61
62 #[inline]
63 fn quad_to(&mut self, mut x1: f32, mut y1: f32, mut x: f32, mut y: f32) {
64 if !self.is_default_ts {
65 self.transform.apply_to(&mut x1, &mut y1);
66 self.transform.apply_to(&mut x, &mut y);
67 }
68
69 if let Some(ref mut bbox) = self.bbox {
70 bbox.extend_by(x1, y1);
71 bbox.extend_by(x, y);
72 }
73
74 self.builder.quad_to(x1, y1, x, y);
75 }
76
77 #[inline]
82 pub fn push_point(&mut self, x: f32, y: f32, on_curve_point: bool, last_point: bool) {
83 let p = Point { x, y };
84 if self.first_on_curve.is_none() {
85 if on_curve_point {
86 self.first_on_curve = Some(p);
87 self.move_to(p.x, p.y);
88 } else {
89 if let Some(offcurve) = self.first_off_curve {
90 let mid = offcurve.lerp(p, 0.5);
91 self.first_on_curve = Some(mid);
92 self.last_off_curve = Some(p);
93 self.move_to(mid.x, mid.y);
94 } else {
95 self.first_off_curve = Some(p);
96 }
97 }
98 } else {
99 match (self.last_off_curve, on_curve_point) {
100 (Some(offcurve), true) => {
101 self.last_off_curve = None;
102 self.quad_to(offcurve.x, offcurve.y, p.x, p.y);
103 }
104 (Some(offcurve), false) => {
105 self.last_off_curve = Some(p);
106 let mid = offcurve.lerp(p, 0.5);
107 self.quad_to(offcurve.x, offcurve.y, mid.x, mid.y);
108 }
109 (None, true) => {
110 self.line_to(p.x, p.y);
111 }
112 (None, false) => {
113 self.last_off_curve = Some(p);
114 }
115 }
116 }
117
118 if last_point {
119 self.finish_contour();
120 }
121 }
122
123 #[inline]
124 fn finish_contour(&mut self) {
125 if let (Some(offcurve1), Some(offcurve2)) = (self.first_off_curve, self.last_off_curve) {
126 self.last_off_curve = None;
127 let mid = offcurve2.lerp(offcurve1, 0.5);
128 self.quad_to(offcurve2.x, offcurve2.y, mid.x, mid.y);
129 }
130
131 if let (Some(p), Some(offcurve1)) = (self.first_on_curve, self.first_off_curve) {
132 self.quad_to(offcurve1.x, offcurve1.y, p.x, p.y);
133 } else if let (Some(p), Some(offcurve2)) = (self.first_on_curve, self.last_off_curve) {
134 self.quad_to(offcurve2.x, offcurve2.y, p.x, p.y);
135 } else if let Some(p) = self.first_on_curve {
136 self.line_to(p.x, p.y);
137 }
138
139 self.first_on_curve = None;
140 self.first_off_curve = None;
141 self.last_off_curve = None;
142
143 self.builder.close();
144 }
145}
146
147
148#[derive(Clone, Copy)]
149pub struct Transform {
150 pub a: f32, pub b: f32, pub c: f32,
151 pub d: f32, pub e: f32, pub f: f32,
152}
153
154impl Transform {
155 #[cfg(feature = "variable-fonts")]
156 #[inline]
157 pub fn new_translate(tx: f32, ty: f32) -> Self {
158 Transform { a: 1.0, b: 0.0, c: 0.0, d: 1.0, e: tx, f: ty }
159 }
160
161 #[inline]
162 pub fn combine(ts1: Self, ts2: Self) -> Self {
163 Transform {
164 a: ts1.a * ts2.a + ts1.c * ts2.b,
165 b: ts1.b * ts2.a + ts1.d * ts2.b,
166 c: ts1.a * ts2.c + ts1.c * ts2.d,
167 d: ts1.b * ts2.c + ts1.d * ts2.d,
168 e: ts1.a * ts2.e + ts1.c * ts2.f + ts1.e,
169 f: ts1.b * ts2.e + ts1.d * ts2.f + ts1.f,
170 }
171 }
172
173 #[inline]
174 fn apply_to(&self, x: &mut f32, y: &mut f32) {
175 let tx = *x;
176 let ty = *y;
177 *x = self.a * tx + self.c * ty + self.e;
178 *y = self.b * tx + self.d * ty + self.f;
179 }
180
181 #[inline]
182 fn is_default(&self) -> bool {
183 self.a == 1.0
185 && self.b == 0.0
186 && self.c == 0.0
187 && self.d == 1.0
188 && self.e == 0.0
189 && self.f == 0.0
190 }
191}
192
193impl Default for Transform {
194 #[inline]
195 fn default() -> Self {
196 Transform { a: 1.0, b: 0.0, c: 0.0, d: 1.0, e: 0.0, f: 0.0 }
197 }
198}
199
200impl core::fmt::Debug for Transform {
201 #[inline]
202 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
203 write!(f, "Transform({} {} {} {} {} {})", self.a, self.b, self.c, self.d, self.e, self.f)
204 }
205}
206
207
208#[derive(Clone, Copy, Debug)]
209pub(crate) struct CompositeGlyphInfo {
210 pub glyph_id: GlyphId,
211 pub transform: Transform,
212 pub flags: CompositeGlyphFlags,
213}
214
215
216#[derive(Clone)]
217pub(crate) struct CompositeGlyphIter<'a> {
218 stream: Stream<'a>,
219}
220
221impl<'a> CompositeGlyphIter<'a> {
222 #[inline]
223 pub fn new(data: &'a [u8]) -> Self {
224 CompositeGlyphIter { stream: Stream::new(data) }
225 }
226}
227
228impl<'a> Iterator for CompositeGlyphIter<'a> {
229 type Item = CompositeGlyphInfo;
230
231 #[inline]
232 fn next(&mut self) -> Option<Self::Item> {
233 let flags = CompositeGlyphFlags(self.stream.read::<u16>()?);
234 let glyph_id: GlyphId = self.stream.read()?;
235
236 let mut ts = Transform::default();
237
238 if flags.args_are_xy_values() {
239 if flags.arg_1_and_2_are_words() {
240 ts.e = f32::from(self.stream.read::<i16>()?);
241 ts.f = f32::from(self.stream.read::<i16>()?);
242 } else {
243 ts.e = f32::from(self.stream.read::<i8>()?);
244 ts.f = f32::from(self.stream.read::<i8>()?);
245 }
246 }
247
248 if flags.we_have_a_two_by_two() {
249 ts.a = self.stream.read::<F2DOT14>()?.to_f32();
250 ts.b = self.stream.read::<F2DOT14>()?.to_f32();
251 ts.c = self.stream.read::<F2DOT14>()?.to_f32();
252 ts.d = self.stream.read::<F2DOT14>()?.to_f32();
253 } else if flags.we_have_an_x_and_y_scale() {
254 ts.a = self.stream.read::<F2DOT14>()?.to_f32();
255 ts.d = self.stream.read::<F2DOT14>()?.to_f32();
256 } else if flags.we_have_a_scale() {
257 ts.a = self.stream.read::<F2DOT14>()?.to_f32();
258 ts.d = ts.a;
259 }
260
261 if !flags.more_components() {
262 self.stream.jump_to_end();
264 }
265
266 Some(CompositeGlyphInfo {
267 glyph_id,
268 transform: ts,
269 flags,
270 })
271 }
272}
273
274
275#[derive(Clone, Copy, Debug)]
280pub struct GlyphPoint {
281 pub x: i16,
282 pub y: i16,
283 pub on_curve_point: bool,
286 pub last_point: bool,
287}
288
289
290#[derive(Clone, Default)]
291pub struct GlyphPointsIter<'a> {
292 endpoints: EndpointsIter<'a>,
293 flags: FlagsIter<'a>,
294 x_coords: CoordsIter<'a>,
295 y_coords: CoordsIter<'a>,
296 pub points_left: u16, }
298
299#[cfg(feature = "variable-fonts")]
300impl GlyphPointsIter<'_> {
301 #[inline]
302 pub fn current_contour(&self) -> u16 {
303 self.endpoints.index - 1
304 }
305}
306
307impl<'a> Iterator for GlyphPointsIter<'a> {
308 type Item = GlyphPoint;
309
310 #[inline]
311 fn next(&mut self) -> Option<Self::Item> {
312 self.points_left = self.points_left.checked_sub(1)?;
313
314 let last_point = self.endpoints.next();
317 let flags = self.flags.next()?;
318 Some(GlyphPoint {
319 x: self.x_coords.next(flags.x_short(), flags.x_is_same_or_positive_short()),
320 y: self.y_coords.next(flags.y_short(), flags.y_is_same_or_positive_short()),
321 on_curve_point: flags.on_curve_point(),
322 last_point,
323 })
324 }
325}
326
327
328#[derive(Clone, Copy, Default)]
333struct EndpointsIter<'a> {
334 endpoints: LazyArray16<'a, u16>, index: u16,
336 left: u16,
337}
338
339impl<'a> EndpointsIter<'a> {
340 #[inline]
341 fn new(endpoints: LazyArray16<'a, u16>) -> Option<Self> {
342 Some(EndpointsIter {
343 endpoints,
344 index: 1,
345 left: endpoints.get(0)?,
346 })
347 }
348
349 #[inline]
350 fn next(&mut self) -> bool {
351 if self.left == 0 {
352 if let Some(end) = self.endpoints.get(self.index) {
353 let prev = self.endpoints.get(self.index - 1).unwrap_or(0);
354 self.left = end.checked_sub(prev).unwrap_or(0);
357 self.left = self.left.checked_sub(1).unwrap_or(0);
358 }
359
360 if let Some(n) = self.index.checked_add(1) {
362 self.index = n;
363 }
364
365 true
366 } else {
367 self.left -= 1;
368 false
369 }
370 }
371}
372
373
374#[derive(Clone, Default)]
375struct FlagsIter<'a> {
376 stream: Stream<'a>,
377 repeats: u8,
380 flags: SimpleGlyphFlags,
381}
382
383impl<'a> FlagsIter<'a> {
384 #[inline]
385 fn new(data: &'a [u8]) -> Self {
386 FlagsIter {
387 stream: Stream::new(data),
388 repeats: 0,
389 flags: SimpleGlyphFlags(0),
390 }
391 }
392}
393
394impl<'a> Iterator for FlagsIter<'a> {
395 type Item = SimpleGlyphFlags;
396
397 #[inline]
398 fn next(&mut self) -> Option<Self::Item> {
399 if self.repeats == 0 {
400 self.flags = SimpleGlyphFlags(self.stream.read::<u8>().unwrap_or_default());
401 if self.flags.repeat_flag() {
402 self.repeats = self.stream.read::<u8>().unwrap_or(0);
403 }
404 } else {
405 self.repeats -= 1;
406 }
407
408 Some(self.flags)
409 }
410}
411
412
413#[derive(Clone, Default)]
414struct CoordsIter<'a> {
415 stream: Stream<'a>,
416 prev: i16, }
418
419impl<'a> CoordsIter<'a> {
420 #[inline]
421 fn new(data: &'a [u8]) -> Self {
422 CoordsIter {
423 stream: Stream::new(data),
424 prev: 0,
425 }
426 }
427
428 #[inline]
429 fn next(&mut self, is_short: bool, is_same_or_short: bool) -> i16 {
430 let mut n = 0;
436 if is_short {
437 n = i16::from(self.stream.read::<u8>().unwrap_or(0));
438 if !is_same_or_short {
439 n = -n;
440 }
441 } else if !is_same_or_short {
442 n = self.stream.read::<i16>().unwrap_or(0);
443 }
444
445 self.prev = self.prev.wrapping_add(n);
446 self.prev
447 }
448}
449
450
451#[derive(Clone, Copy, Debug)]
452struct Point {
453 x: f32,
454 y: f32,
455}
456
457impl Point {
458 #[inline]
459 fn lerp(self, other: Point, t: f32) -> Point {
460 Point {
461 x: self.x + t * (other.x - self.x),
462 y: self.y + t * (other.y - self.y),
463 }
464 }
465}
466
467
468#[derive(Clone, Copy, Default)]
470struct SimpleGlyphFlags(u8);
471
472impl SimpleGlyphFlags {
473 #[inline] fn on_curve_point(self) -> bool { self.0 & 0x01 != 0 }
474 #[inline] fn x_short(self) -> bool { self.0 & 0x02 != 0 }
475 #[inline] fn y_short(self) -> bool { self.0 & 0x04 != 0 }
476 #[inline] fn repeat_flag(self) -> bool { self.0 & 0x08 != 0 }
477 #[inline] fn x_is_same_or_positive_short(self) -> bool { self.0 & 0x10 != 0 }
478 #[inline] fn y_is_same_or_positive_short(self) -> bool { self.0 & 0x20 != 0 }
479}
480
481
482#[derive(Clone, Copy, Debug)]
484pub(crate) struct CompositeGlyphFlags(u16);
485
486impl CompositeGlyphFlags {
487 #[inline] pub fn arg_1_and_2_are_words(self) -> bool { self.0 & 0x0001 != 0 }
488 #[inline] pub fn args_are_xy_values(self) -> bool { self.0 & 0x0002 != 0 }
489 #[inline] pub fn we_have_a_scale(self) -> bool { self.0 & 0x0008 != 0 }
490 #[inline] pub fn more_components(self) -> bool { self.0 & 0x0020 != 0 }
491 #[inline] pub fn we_have_an_x_and_y_scale(self) -> bool { self.0 & 0x0040 != 0 }
492 #[inline] pub fn we_have_a_two_by_two(self) -> bool { self.0 & 0x0080 != 0 }
493}
494
495
496pub const MAX_COMPONENTS: u8 = 32;
498
499#[inline]
500pub(crate) fn outline(
501 loca_table: loca::Table,
502 glyf_table: &[u8],
503 glyph_id: GlyphId,
504 builder: &mut dyn OutlineBuilder,
505) -> Option<Rect> {
506 let mut b = Builder::new(Transform::default(), None, builder);
507 let range = loca_table.glyph_range(glyph_id)?;
508 let glyph_data = glyf_table.get(range)?;
509 outline_impl(loca_table, glyf_table, glyph_data, 0, &mut b)
510}
511
512#[inline]
513pub(crate) fn glyph_bbox(
514 loca_table: loca::Table,
515 glyf_table: &[u8],
516 glyph_id: GlyphId,
517) -> Option<Rect> {
518 let range = loca_table.glyph_range(glyph_id)?;
519 let glyph_data = glyf_table.get(range)?;
520 let mut s = Stream::new(glyph_data);
521 s.skip::<i16>(); Some(Rect {
524 x_min: s.read::<i16>()?,
525 y_min: s.read::<i16>()?,
526 x_max: s.read::<i16>()?,
527 y_max: s.read::<i16>()?,
528 })
529}
530
531#[inline]
532fn outline_impl(
533 loca_table: loca::Table,
534 glyf_table: &[u8],
535 data: &[u8],
536 depth: u8,
537 builder: &mut Builder,
538) -> Option<Rect> {
539 if depth >= MAX_COMPONENTS {
540 return None;
541 }
542
543 let mut s = Stream::new(data);
544 let number_of_contours: i16 = s.read()?;
545 let rect = Rect {
547 x_min: s.read::<i16>()?,
548 y_min: s.read::<i16>()?,
549 x_max: s.read::<i16>()?,
550 y_max: s.read::<i16>()?,
551 };
552
553 if number_of_contours > 0 {
554 let number_of_contours = NonZeroU16::new(number_of_contours as u16)?;
558 for point in parse_simple_outline(s.tail()?, number_of_contours)? {
559 builder.push_point(f32::from(point.x), f32::from(point.y),
560 point.on_curve_point, point.last_point);
561 }
562 } else if number_of_contours < 0 {
563 for comp in CompositeGlyphIter::new(s.tail()?) {
565 if let Some(range) = loca_table.glyph_range(comp.glyph_id) {
566 if let Some(glyph_data) = glyf_table.get(range) {
567 let transform = Transform::combine(builder.transform, comp.transform);
568 let mut b = Builder::new(transform, None, builder.builder);
569 outline_impl(loca_table, glyf_table, glyph_data, depth + 1, &mut b)?;
570 }
571 }
572 }
573 } else {
574 return None;
576 }
577
578 Some(rect)
579}
580
581#[inline]
582pub fn parse_simple_outline(
583 glyph_data: &[u8],
584 number_of_contours: NonZeroU16,
585) -> Option<GlyphPointsIter> {
586 let mut s = Stream::new(glyph_data);
587 let endpoints = s.read_array16::<u16>(number_of_contours.get())?;
588
589 let points_total = endpoints.last()?.checked_add(1)?;
590
591 if points_total == 1 {
594 return Some(GlyphPointsIter::default());
595 }
596
597 let instructions_len: u16 = s.read()?;
599 s.advance(usize::from(instructions_len));
600
601 let flags_offset = s.offset();
602 let (x_coords_len, y_coords_len) = resolve_coords_len(&mut s, points_total)?;
603 let x_coords_offset = s.offset();
604 let y_coords_offset = x_coords_offset + usize::num_from(x_coords_len);
605 let y_coords_end = y_coords_offset + usize::num_from(y_coords_len);
606
607 Some(GlyphPointsIter {
608 endpoints: EndpointsIter::new(endpoints)?,
609 flags: FlagsIter::new(glyph_data.get(flags_offset..x_coords_offset)?),
610 x_coords: CoordsIter::new(glyph_data.get(x_coords_offset..y_coords_offset)?),
611 y_coords: CoordsIter::new(glyph_data.get(y_coords_offset..y_coords_end)?),
612 points_left: points_total,
613 })
614}
615
616fn resolve_coords_len(
620 s: &mut Stream,
621 points_total: u16,
622) -> Option<(u32, u32)> {
623 let mut flags_left = u32::from(points_total);
624 let mut repeats;
625 let mut x_coords_len = 0;
626 let mut y_coords_len = 0;
627 while flags_left > 0 {
628 let flags = SimpleGlyphFlags(s.read::<u8>()?);
629
630 repeats = if flags.repeat_flag() {
632 let repeats: u8 = s.read()?;
633 u32::from(repeats) + 1
634 } else {
635 1
636 };
637
638 if repeats > flags_left {
639 return None;
640 }
641
642 if flags.x_short() {
645 x_coords_len += repeats;
647 } else if !flags.x_is_same_or_positive_short() {
648 x_coords_len += repeats * 2;
650 }
651
652 if flags.y_short() {
653 y_coords_len += repeats;
655 } else if !flags.y_is_same_or_positive_short() {
656 y_coords_len += repeats * 2;
658 }
659
660 flags_left -= repeats;
661 }
662
663 Some((x_coords_len, y_coords_len))
664}