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