ttf_parser/tables/
glyf.rs

1// https://docs.microsoft.com/en-us/typography/opentype/spec/glyf
2
3use 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, // `bool` is faster than `Option` or `is_default`.
12    pub bbox: Option<BBox>, // Used only by `gvar`.
13    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    // Useful links:
78    //
79    // - https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
80    // - https://stackoverflow.com/a/20772557
81    #[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        // A direct float comparison is fine in our case.
184           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            // Finish the iterator even if stream still has some data.
263            self.stream.jump_to_end();
264        }
265
266        Some(CompositeGlyphInfo {
267            glyph_id,
268            transform: ts,
269            flags,
270        })
271    }
272}
273
274
275// Due to some optimization magic, using f32 instead of i16
276// makes the code ~10% slower. At least on my machine.
277// I guess it's due to the fact that with i16 the struct
278// fits into the machine word.
279#[derive(Clone, Copy, Debug)]
280pub struct GlyphPoint {
281    pub x: i16,
282    pub y: i16,
283    /// Indicates that a point is a point on curve
284    /// and not a control point.
285    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, // Number of points left in the glyph.
297}
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        // TODO: skip empty contours
315
316        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/// A simple flattening iterator for glyph's endpoints.
329///
330/// Translates endpoints like: 2 4 7
331/// into flags: 0 0 1 0 1 0 0 1
332#[derive(Clone, Copy, Default)]
333struct EndpointsIter<'a> {
334    endpoints: LazyArray16<'a, u16>, // Each endpoint indicates a contour end.
335    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                // Malformed font can have endpoints not in increasing order,
355                // so we have to use checked_sub.
356                self.left = end.checked_sub(prev).unwrap_or(0);
357                self.left = self.left.checked_sub(1).unwrap_or(0);
358            }
359
360            // Always advance the index, so we can check the current contour number.
361            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    // Number of times the `flags` should be used
378    // before reading the next one from `stream`.
379    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, // Points are stored as deltas, so we have to keep the previous one.
417}
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        // See https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#simple-glyph-description
431        // for details about Simple Glyph Flags processing.
432
433        // We've already checked the coords data, so it's safe to fallback to 0.
434
435        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// https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#simple-glyph-description
469#[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// https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description
483#[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
496// It's not defined in the spec, so we are using our own value.
497pub 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>(); // number_of_contours
522    // It's faster to parse the rect directly, instead of using `FromData`.
523    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    // It's faster to parse the rect directly, instead of using `FromData`.
546    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        // Simple glyph.
555
556        // u16 casting is safe, since we already checked that the value is positive.
557        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        // Composite glyph.
564        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        // An empty glyph.
575        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    // Contours with a single point should be ignored.
592    // But this is not an error, so we should return an "empty" iterator.
593    if points_total == 1 {
594        return Some(GlyphPointsIter::default());
595    }
596
597    // Skip instructions byte code.
598    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
616/// Resolves coordinate arrays length.
617///
618/// The length depends on *Simple Glyph Flags*, so we have to process them all to find it.
619fn 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        // The number of times a glyph point repeats.
631        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        // No need to check for `*_coords_len` overflow since u32 is more than enough.
643
644        if flags.x_short() {
645            // Coordinate is 1 byte long.
646            x_coords_len += repeats;
647        } else if !flags.x_is_same_or_positive_short() {
648            // Coordinate is 2 bytes long.
649            x_coords_len += repeats * 2;
650        }
651
652        if flags.y_short() {
653            // Coordinate is 1 byte long.
654            y_coords_len += repeats;
655        } else if !flags.y_is_same_or_positive_short() {
656            // Coordinate is 2 bytes long.
657            y_coords_len += repeats * 2;
658        }
659
660        flags_left -= repeats;
661    }
662
663    Some((x_coords_len, y_coords_len))
664}