ttf_parser/tables/
glyf.rs

1//! A [Glyph Data Table](
2//! https://docs.microsoft.com/en-us/typography/opentype/spec/glyf) implementation.
3
4use 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, // `bool` is faster than `Option` or `is_default`.
13    // We have to always calculate the bbox, because `gvar` doesn't store one
14    // and in case of a malformed bbox in `glyf`.
15    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    // Useful links:
75    //
76    // - https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
77    // - https://stackoverflow.com/a/20772557
78    #[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        // A direct float comparison is fine in our case.
181           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            // Finish the iterator even if stream still has some data.
260            self.stream.jump_to_end();
261        }
262
263        Some(CompositeGlyphInfo {
264            glyph_id,
265            transform: ts,
266            flags,
267        })
268    }
269}
270
271
272// Due to some optimization magic, using f32 instead of i16
273// makes the code ~10% slower. At least on my machine.
274// I guess it's due to the fact that with i16 the struct
275// fits into the machine word.
276#[derive(Clone, Copy, Debug)]
277pub(crate) struct GlyphPoint {
278    pub x: i16,
279    pub y: i16,
280    /// Indicates that a point is a point on curve
281    /// and not a control point.
282    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, // Number of points left in the glyph.
294}
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        // TODO: skip empty contours
312
313        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/// A simple flattening iterator for glyph's endpoints.
326///
327/// Translates endpoints like: 2 4 7
328/// into flags: 0 0 1 0 1 0 0 1
329#[derive(Clone, Copy, Default)]
330struct EndpointsIter<'a> {
331    endpoints: LazyArray16<'a, u16>, // Each endpoint indicates a contour end.
332    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                // Malformed font can have endpoints not in increasing order,
352                // so we have to use checked_sub.
353                self.left = end.checked_sub(prev).unwrap_or(0);
354                self.left = self.left.checked_sub(1).unwrap_or(0);
355            }
356
357            // Always advance the index, so we can check the current contour number.
358            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    // Number of times the `flags` should be used
375    // before reading the next one from `stream`.
376    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, // Points are stored as deltas, so we have to keep the previous one.
414}
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        // See https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#simple-glyph-description
428        // for details about Simple Glyph Flags processing.
429
430        // We've already checked the coords data, so it's safe to fallback to 0.
431
432        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// https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#simple-glyph-description
466#[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// https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description
480#[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
493// It's not defined in the spec, so we are using our own value.
494pub(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); // Skip bbox. We use calculated one.
511
512    if number_of_contours > 0 {
513        // Simple glyph.
514
515        // u16 casting is safe, since we already checked that the value is positive.
516        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        // Composite glyph.
523        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                    // Take updated bbox.
531                    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    // Contours with a single point should be ignored.
555    // But this is not an error, so we should return an "empty" iterator.
556    if points_total == 1 {
557        return Some(GlyphPointsIter::default());
558    }
559
560    // Skip instructions byte code.
561    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
579/// Resolves coordinate arrays length.
580///
581/// The length depends on *Simple Glyph Flags*, so we have to process them all to find it.
582fn 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        // The number of times a glyph point repeats.
594        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        // No need to check for `*_coords_len` overflow since u32 is more than enough.
606
607        // Non-obfuscated code below.
608        // Branchless version is surprisingly faster.
609        //
610        // if flags.x_short() {
611        //     // Coordinate is 1 byte long.
612        //     x_coords_len += repeats;
613        // } else if !flags.x_is_same_or_positive_short() {
614        //     // Coordinate is 2 bytes long.
615        //     x_coords_len += repeats * 2;
616        // }
617        // if flags.y_short() {
618        //     // Coordinate is 1 byte long.
619        //     y_coords_len += repeats;
620        // } else if !flags.y_is_same_or_positive_short() {
621        //     // Coordinate is 2 bytes long.
622        //     y_coords_len += repeats * 2;
623        // }
624
625        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/// A [Glyph Data Table](
640/// https://docs.microsoft.com/en-us/typography/opentype/spec/glyf).
641#[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    /// Parses a table from raw data.
655    #[inline]
656    pub fn parse(loca_table: loca::Table<'a>, data: &'a [u8]) -> Option<Self> {
657        Some(Table { loca_table, data })
658    }
659
660    /// Outlines a glyph.
661    #[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}