read_fonts/tables/
glyf.rs

1//! The [glyf (Glyph Data)](https://docs.microsoft.com/en-us/typography/opentype/spec/glyf) table
2
3pub mod bytecode;
4
5use bytemuck::AnyBitPattern;
6use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Sub};
7use types::{F26Dot6, Point};
8
9include!("../../generated/generated_glyf.rs");
10
11/// Marker bits for point flags that are set during variation delta
12/// processing and hinting.
13#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
14pub struct PointMarker(u8);
15
16impl PointMarker {
17    /// Marker for points that have an explicit delta in a glyph variation
18    /// tuple.
19    pub const HAS_DELTA: Self = Self(0x4);
20
21    /// Marker that signifies that the x coordinate of a point has been touched
22    /// by an IUP hinting instruction.
23    pub const TOUCHED_X: Self = Self(0x10);
24
25    /// Marker that signifies that the y coordinate of a point has been touched
26    /// by an IUP hinting instruction.
27    pub const TOUCHED_Y: Self = Self(0x20);
28
29    /// Marker that signifies that the both coordinates of a point has been touched
30    /// by an IUP hinting instruction.
31    pub const TOUCHED: Self = Self(Self::TOUCHED_X.0 | Self::TOUCHED_Y.0);
32
33    /// Marks this point as a candidate for weak interpolation.
34    ///
35    /// Used by the automatic hinter.
36    pub const WEAK_INTERPOLATION: Self = Self(0x2);
37
38    /// Marker for points where the distance to next point is very small.
39    ///
40    /// Used by the automatic hinter.
41    pub const NEAR: PointMarker = Self(0x8);
42}
43
44impl core::ops::BitOr for PointMarker {
45    type Output = Self;
46
47    fn bitor(self, rhs: Self) -> Self::Output {
48        Self(self.0 | rhs.0)
49    }
50}
51
52/// Flags describing the properties of a point.
53///
54/// Some properties, such as on- and off-curve flags are intrinsic to the point
55/// itself. Others, designated as markers are set and cleared while an outline
56/// is being transformed during variation application and hinting.
57#[derive(
58    Copy, Clone, PartialEq, Eq, Default, Debug, bytemuck::AnyBitPattern, bytemuck::NoUninit,
59)]
60#[repr(transparent)]
61pub struct PointFlags(u8);
62
63impl PointFlags {
64    // Note: OFF_CURVE_QUAD is signified by the absence of both ON_CURVE
65    // and OFF_CURVE_CUBIC bits, per FreeType and TrueType convention.
66    const ON_CURVE: u8 = SimpleGlyphFlags::ON_CURVE_POINT.bits;
67    const OFF_CURVE_CUBIC: u8 = SimpleGlyphFlags::CUBIC.bits;
68    const CURVE_MASK: u8 = Self::ON_CURVE | Self::OFF_CURVE_CUBIC;
69
70    /// Creates a new on curve point flag.
71    pub const fn on_curve() -> Self {
72        Self(Self::ON_CURVE)
73    }
74
75    /// Creates a new off curve quadratic point flag.
76    pub const fn off_curve_quad() -> Self {
77        Self(0)
78    }
79
80    /// Creates a new off curve cubic point flag.
81    pub const fn off_curve_cubic() -> Self {
82        Self(Self::OFF_CURVE_CUBIC)
83    }
84
85    /// Creates a point flag from the given bits. These are truncated
86    /// to ignore markers.
87    pub const fn from_bits(bits: u8) -> Self {
88        Self(bits & Self::CURVE_MASK)
89    }
90
91    /// Returns true if this is an on curve point.
92    #[inline]
93    pub const fn is_on_curve(self) -> bool {
94        self.0 & Self::ON_CURVE != 0
95    }
96
97    /// Returns true if this is an off curve quadratic point.
98    #[inline]
99    pub const fn is_off_curve_quad(self) -> bool {
100        self.0 & Self::CURVE_MASK == 0
101    }
102
103    /// Returns true if this is an off curve cubic point.
104    #[inline]
105    pub const fn is_off_curve_cubic(self) -> bool {
106        self.0 & Self::OFF_CURVE_CUBIC != 0
107    }
108
109    pub const fn is_off_curve(self) -> bool {
110        self.is_off_curve_quad() || self.is_off_curve_cubic()
111    }
112
113    /// Flips the state of the on curve flag.
114    ///
115    /// This is used for the TrueType `FLIPPT` instruction.
116    pub fn flip_on_curve(&mut self) {
117        self.0 ^= 1;
118    }
119
120    /// Enables the on curve flag.
121    ///
122    /// This is used for the TrueType `FLIPRGON` instruction.
123    pub fn set_on_curve(&mut self) {
124        self.0 |= Self::ON_CURVE;
125    }
126
127    /// Disables the on curve flag.
128    ///
129    /// This is used for the TrueType `FLIPRGOFF` instruction.
130    pub fn clear_on_curve(&mut self) {
131        self.0 &= !Self::ON_CURVE;
132    }
133
134    /// Returns true if the given marker is set for this point.
135    pub fn has_marker(self, marker: PointMarker) -> bool {
136        self.0 & marker.0 != 0
137    }
138
139    /// Applies the given marker to this point.
140    pub fn set_marker(&mut self, marker: PointMarker) {
141        self.0 |= marker.0;
142    }
143
144    /// Clears the given marker for this point.
145    pub fn clear_marker(&mut self, marker: PointMarker) {
146        self.0 &= !marker.0
147    }
148
149    /// Returns a copy with all markers cleared.
150    pub const fn without_markers(self) -> Self {
151        Self(self.0 & Self::CURVE_MASK)
152    }
153
154    /// Returns the underlying bits.
155    pub const fn to_bits(self) -> u8 {
156        self.0
157    }
158}
159
160/// Trait for types that are usable for TrueType point coordinates.
161pub trait PointCoord:
162    Copy
163    + Default
164    // You could bytemuck with me
165    + AnyBitPattern
166    // You could compare me
167    + PartialEq
168    + PartialOrd
169    // You could do math with me
170    + Add<Output = Self>
171    + AddAssign
172    + Sub<Output = Self>
173    + Div<Output = Self>
174    + Mul<Output = Self>
175    + MulAssign {
176    fn from_fixed(x: Fixed) -> Self;
177    fn from_i32(x: i32) -> Self;
178    fn to_f32(self) -> f32;
179    fn midpoint(self, other: Self) -> Self;
180}
181
182impl<'a> SimpleGlyph<'a> {
183    /// Returns the total number of points.
184    pub fn num_points(&self) -> usize {
185        self.end_pts_of_contours()
186            .last()
187            .map(|last| last.get() as usize + 1)
188            .unwrap_or(0)
189    }
190
191    /// Returns true if the contours in the simple glyph may overlap.
192    pub fn has_overlapping_contours(&self) -> bool {
193        // Checks the first flag for the OVERLAP_SIMPLE bit.
194        // Spec says: "When used, it must be set on the first flag byte for
195        // the glyph."
196        FontData::new(self.glyph_data())
197            .read_at::<SimpleGlyphFlags>(0)
198            .map(|flag| flag.contains(SimpleGlyphFlags::OVERLAP_SIMPLE))
199            .unwrap_or_default()
200    }
201
202    /// Reads points and flags into the provided buffers.
203    ///
204    /// Drops all flag bits except on-curve. The lengths of the buffers must be
205    /// equal to the value returned by [num_points](Self::num_points).
206    ///
207    /// ## Performance
208    ///
209    /// As the name implies, this is faster than using the iterator returned by
210    /// [points](Self::points) so should be used when it is possible to
211    /// preallocate buffers.
212    pub fn read_points_fast<C: PointCoord>(
213        &self,
214        points: &mut [Point<C>],
215        flags: &mut [PointFlags],
216    ) -> Result<(), ReadError> {
217        let n_points = self.num_points();
218        if points.len() != n_points || flags.len() != n_points {
219            return Err(ReadError::InvalidArrayLen);
220        }
221        let mut cursor = FontData::new(self.glyph_data()).cursor();
222        // We'll need at most n_points flags, but fewer if there are repeats
223        let flags_data = cursor.read_array::<u8>(n_points.min(cursor.remaining_bytes()))?;
224        let mut flags_iter = flags_data.iter().copied();
225        // Keep track of the actual number of flag bytes read so that we can
226        // create a new cursor for reading coordinates
227        let mut read_flags_bytes = 0;
228        let mut i = 0;
229        while let Some(flag_bits) = flags_iter.next() {
230            read_flags_bytes += 1;
231            if SimpleGlyphFlags::from_bits_truncate(flag_bits)
232                .contains(SimpleGlyphFlags::REPEAT_FLAG)
233            {
234                let count = (flags_iter.next().ok_or(ReadError::OutOfBounds)? as usize + 1)
235                    .min(n_points - i);
236                read_flags_bytes += 1;
237                for f in &mut flags[i..i + count] {
238                    f.0 = flag_bits;
239                }
240                i += count;
241            } else {
242                flags[i].0 = flag_bits;
243                i += 1;
244            }
245            if i == n_points {
246                break;
247            }
248        }
249        let mut cursor = FontData::new(self.glyph_data()).cursor();
250        cursor.advance_by(read_flags_bytes);
251        let mut x = 0i32;
252        for (&point_flags, point) in flags.iter().zip(points.as_mut()) {
253            let mut delta = 0i32;
254            let flag = SimpleGlyphFlags::from_bits_truncate(point_flags.0);
255            if flag.contains(SimpleGlyphFlags::X_SHORT_VECTOR) {
256                delta = cursor.read::<u8>()? as i32;
257                if !flag.contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
258                    delta = -delta;
259                }
260            } else if !flag.contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
261                delta = cursor.read::<i16>()? as i32;
262            }
263            x = x.wrapping_add(delta);
264            point.x = C::from_i32(x);
265        }
266        let mut y = 0i32;
267        for (point_flags, point) in flags.iter_mut().zip(points.as_mut()) {
268            let mut delta = 0i32;
269            let flag = SimpleGlyphFlags::from_bits_truncate(point_flags.0);
270            if flag.contains(SimpleGlyphFlags::Y_SHORT_VECTOR) {
271                delta = cursor.read::<u8>()? as i32;
272                if !flag.contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
273                    delta = -delta;
274                }
275            } else if !flag.contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
276                delta = cursor.read::<i16>()? as i32;
277            }
278            y = y.wrapping_add(delta);
279            point.y = C::from_i32(y);
280            let flags_mask = if cfg!(feature = "spec_next") {
281                PointFlags::CURVE_MASK
282            } else {
283                // Drop the cubic bit if the spec_next feature is not enabled
284                PointFlags::ON_CURVE
285            };
286            point_flags.0 &= flags_mask;
287        }
288        Ok(())
289    }
290
291    /// Returns an iterator over the points in the glyph.
292    ///
293    /// ## Performance
294    ///
295    /// This is slower than [read_points_fast](Self::read_points_fast) but
296    /// provides access to the points without requiring a preallocated buffer.
297    pub fn points(&self) -> impl Iterator<Item = CurvePoint> + 'a + Clone {
298        self.points_impl()
299            .unwrap_or_else(|| PointIter::new(&[], &[], &[]))
300    }
301
302    fn points_impl(&self) -> Option<PointIter<'a>> {
303        let end_points = self.end_pts_of_contours();
304        let n_points = end_points.last()?.get().checked_add(1)?;
305        let data = self.glyph_data();
306        let lens = resolve_coords_len(data, n_points).ok()?;
307        let total_len = lens.flags + lens.x_coords + lens.y_coords;
308        if data.len() < total_len as usize {
309            return None;
310        }
311
312        let (flags, data) = data.split_at(lens.flags as usize);
313        let (x_coords, y_coords) = data.split_at(lens.x_coords as usize);
314
315        Some(PointIter::new(flags, x_coords, y_coords))
316    }
317}
318
319/// Point with an associated on-curve flag in a simple glyph.
320///
321/// This type is a simpler representation of the data in the blob.
322#[derive(Clone, Copy, Debug, PartialEq, Eq)]
323pub struct CurvePoint {
324    /// X coordinate.
325    pub x: i16,
326    /// Y coordinate.
327    pub y: i16,
328    /// True if this is an on-curve point.
329    pub on_curve: bool,
330}
331
332impl CurvePoint {
333    /// Construct a new `CurvePoint`
334    pub fn new(x: i16, y: i16, on_curve: bool) -> Self {
335        Self { x, y, on_curve }
336    }
337
338    /// Convenience method to construct an on-curve point
339    pub fn on_curve(x: i16, y: i16) -> Self {
340        Self::new(x, y, true)
341    }
342
343    /// Convenience method to construct an off-curve point
344    pub fn off_curve(x: i16, y: i16) -> Self {
345        Self::new(x, y, false)
346    }
347}
348
349#[derive(Clone)]
350struct PointIter<'a> {
351    flags: Cursor<'a>,
352    x_coords: Cursor<'a>,
353    y_coords: Cursor<'a>,
354    flag_repeats: u8,
355    cur_flags: SimpleGlyphFlags,
356    cur_x: i16,
357    cur_y: i16,
358}
359
360impl Iterator for PointIter<'_> {
361    type Item = CurvePoint;
362    fn next(&mut self) -> Option<Self::Item> {
363        self.advance_flags()?;
364        self.advance_points();
365        let is_on_curve = self.cur_flags.contains(SimpleGlyphFlags::ON_CURVE_POINT);
366        Some(CurvePoint::new(self.cur_x, self.cur_y, is_on_curve))
367    }
368}
369
370impl<'a> PointIter<'a> {
371    fn new(flags: &'a [u8], x_coords: &'a [u8], y_coords: &'a [u8]) -> Self {
372        Self {
373            flags: FontData::new(flags).cursor(),
374            x_coords: FontData::new(x_coords).cursor(),
375            y_coords: FontData::new(y_coords).cursor(),
376            flag_repeats: 0,
377            cur_flags: SimpleGlyphFlags::empty(),
378            cur_x: 0,
379            cur_y: 0,
380        }
381    }
382
383    fn advance_flags(&mut self) -> Option<()> {
384        if self.flag_repeats == 0 {
385            self.cur_flags = SimpleGlyphFlags::from_bits_truncate(self.flags.read().ok()?);
386            self.flag_repeats = self
387                .cur_flags
388                .contains(SimpleGlyphFlags::REPEAT_FLAG)
389                .then(|| self.flags.read().ok())
390                .flatten()
391                .unwrap_or(0)
392                + 1;
393        }
394        self.flag_repeats -= 1;
395        Some(())
396    }
397
398    fn advance_points(&mut self) {
399        let x_short = self.cur_flags.contains(SimpleGlyphFlags::X_SHORT_VECTOR);
400        let x_same_or_pos = self
401            .cur_flags
402            .contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR);
403        let y_short = self.cur_flags.contains(SimpleGlyphFlags::Y_SHORT_VECTOR);
404        let y_same_or_pos = self
405            .cur_flags
406            .contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR);
407
408        let delta_x = match (x_short, x_same_or_pos) {
409            (true, false) => -(self.x_coords.read::<u8>().unwrap_or(0) as i16),
410            (true, true) => self.x_coords.read::<u8>().unwrap_or(0) as i16,
411            (false, false) => self.x_coords.read::<i16>().unwrap_or(0),
412            _ => 0,
413        };
414
415        let delta_y = match (y_short, y_same_or_pos) {
416            (true, false) => -(self.y_coords.read::<u8>().unwrap_or(0) as i16),
417            (true, true) => self.y_coords.read::<u8>().unwrap_or(0) as i16,
418            (false, false) => self.y_coords.read::<i16>().unwrap_or(0),
419            _ => 0,
420        };
421
422        self.cur_x = self.cur_x.wrapping_add(delta_x);
423        self.cur_y = self.cur_y.wrapping_add(delta_y);
424    }
425}
426
427//taken from ttf_parser https://docs.rs/ttf-parser/latest/src/ttf_parser/tables/glyf.rs.html#1-677
428/// Resolves coordinate arrays length.
429///
430/// The length depends on *Simple Glyph Flags*, so we have to process them all to find it.
431fn resolve_coords_len(data: &[u8], points_total: u16) -> Result<FieldLengths, ReadError> {
432    let mut cursor = FontData::new(data).cursor();
433    let mut flags_left = u32::from(points_total);
434    //let mut repeats;
435    let mut x_coords_len = 0;
436    let mut y_coords_len = 0;
437    //let mut flags_seen = 0;
438    while flags_left > 0 {
439        let flags: SimpleGlyphFlags = cursor.read()?;
440
441        // The number of times a glyph point repeats.
442        let repeats = if flags.contains(SimpleGlyphFlags::REPEAT_FLAG) {
443            let repeats: u8 = cursor.read()?;
444            u32::from(repeats) + 1
445        } else {
446            1
447        };
448
449        if repeats > flags_left {
450            return Err(ReadError::MalformedData("repeat count too large in glyf"));
451        }
452
453        // Non-obfuscated code below.
454        // Branchless version is surprisingly faster.
455        //
456        // if flags.x_short() {
457        //     // Coordinate is 1 byte long.
458        //     x_coords_len += repeats;
459        // } else if !flags.x_is_same_or_positive_short() {
460        //     // Coordinate is 2 bytes long.
461        //     x_coords_len += repeats * 2;
462        // }
463        // if flags.y_short() {
464        //     // Coordinate is 1 byte long.
465        //     y_coords_len += repeats;
466        // } else if !flags.y_is_same_or_positive_short() {
467        //     // Coordinate is 2 bytes long.
468        //     y_coords_len += repeats * 2;
469        // }
470        let x_short = SimpleGlyphFlags::X_SHORT_VECTOR;
471        let x_long = SimpleGlyphFlags::X_SHORT_VECTOR
472            | SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR;
473        let y_short = SimpleGlyphFlags::Y_SHORT_VECTOR;
474        let y_long = SimpleGlyphFlags::Y_SHORT_VECTOR
475            | SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR;
476        x_coords_len += ((flags & x_short).bits() != 0) as u32 * repeats;
477        x_coords_len += ((flags & x_long).bits() == 0) as u32 * repeats * 2;
478
479        y_coords_len += ((flags & y_short).bits() != 0) as u32 * repeats;
480        y_coords_len += ((flags & y_long).bits() == 0) as u32 * repeats * 2;
481
482        flags_left -= repeats;
483    }
484
485    Ok(FieldLengths {
486        flags: cursor.position()? as u32,
487        x_coords: x_coords_len,
488        y_coords: y_coords_len,
489    })
490    //Some((flags_len, x_coords_len, y_coords_len))
491}
492
493struct FieldLengths {
494    flags: u32,
495    x_coords: u32,
496    y_coords: u32,
497}
498
499/// Transform for a composite component.
500#[derive(Clone, Copy, Debug, PartialEq, Eq)]
501pub struct Transform {
502    /// X scale factor.
503    pub xx: F2Dot14,
504    /// YX skew factor.
505    pub yx: F2Dot14,
506    /// XY skew factor.
507    pub xy: F2Dot14,
508    /// Y scale factor.
509    pub yy: F2Dot14,
510}
511
512impl Default for Transform {
513    fn default() -> Self {
514        Self {
515            xx: F2Dot14::from_f32(1.0),
516            yx: F2Dot14::from_f32(0.0),
517            xy: F2Dot14::from_f32(0.0),
518            yy: F2Dot14::from_f32(1.0),
519        }
520    }
521}
522
523/// A reference to another glyph. Part of [CompositeGlyph].
524#[derive(Clone, Debug, PartialEq, Eq)]
525pub struct Component {
526    /// Component flags.
527    pub flags: CompositeGlyphFlags,
528    /// Glyph identifier.
529    pub glyph: GlyphId16,
530    /// Anchor for component placement.
531    pub anchor: Anchor,
532    /// Component transformation matrix.
533    pub transform: Transform,
534}
535
536/// Anchor position for a composite component.
537#[derive(Clone, Copy, Debug, PartialEq, Eq)]
538pub enum Anchor {
539    Offset { x: i16, y: i16 },
540    Point { base: u16, component: u16 },
541}
542
543impl<'a> CompositeGlyph<'a> {
544    /// Returns an iterator over the components of the composite glyph.
545    pub fn components(&self) -> impl Iterator<Item = Component> + 'a + Clone {
546        ComponentIter {
547            cur_flags: CompositeGlyphFlags::empty(),
548            done: false,
549            cursor: FontData::new(self.component_data()).cursor(),
550        }
551    }
552
553    /// Returns an iterator that yields the glyph identifier and flags of each
554    /// component in the composite glyph.
555    pub fn component_glyphs_and_flags(
556        &self,
557    ) -> impl Iterator<Item = (GlyphId16, CompositeGlyphFlags)> + 'a + Clone {
558        ComponentGlyphIdFlagsIter {
559            cur_flags: CompositeGlyphFlags::empty(),
560            done: false,
561            cursor: FontData::new(self.component_data()).cursor(),
562        }
563    }
564
565    /// Returns the component count and TrueType interpreter instructions
566    /// in a single pass.
567    pub fn count_and_instructions(&self) -> (usize, Option<&'a [u8]>) {
568        let mut iter = ComponentGlyphIdFlagsIter {
569            cur_flags: CompositeGlyphFlags::empty(),
570            done: false,
571            cursor: FontData::new(self.component_data()).cursor(),
572        };
573        let mut count = 0;
574        while iter.by_ref().next().is_some() {
575            count += 1;
576        }
577        let instructions = if iter
578            .cur_flags
579            .contains(CompositeGlyphFlags::WE_HAVE_INSTRUCTIONS)
580        {
581            iter.cursor
582                .read::<u16>()
583                .ok()
584                .map(|len| len as usize)
585                .and_then(|len| iter.cursor.read_array(len).ok())
586        } else {
587            None
588        };
589        (count, instructions)
590    }
591
592    /// Returns the TrueType interpreter instructions.
593    pub fn instructions(&self) -> Option<&'a [u8]> {
594        self.count_and_instructions().1
595    }
596}
597
598#[derive(Clone)]
599struct ComponentIter<'a> {
600    cur_flags: CompositeGlyphFlags,
601    done: bool,
602    cursor: Cursor<'a>,
603}
604
605impl Iterator for ComponentIter<'_> {
606    type Item = Component;
607
608    fn next(&mut self) -> Option<Self::Item> {
609        if self.done {
610            return None;
611        }
612        let flags: CompositeGlyphFlags = self.cursor.read().ok()?;
613        self.cur_flags = flags;
614        let glyph = self.cursor.read::<GlyphId16>().ok()?;
615        let args_are_words = flags.contains(CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS);
616        let args_are_xy_values = flags.contains(CompositeGlyphFlags::ARGS_ARE_XY_VALUES);
617        let anchor = match (args_are_xy_values, args_are_words) {
618            (true, true) => Anchor::Offset {
619                x: self.cursor.read().ok()?,
620                y: self.cursor.read().ok()?,
621            },
622            (true, false) => Anchor::Offset {
623                x: self.cursor.read::<i8>().ok()? as _,
624                y: self.cursor.read::<i8>().ok()? as _,
625            },
626            (false, true) => Anchor::Point {
627                base: self.cursor.read().ok()?,
628                component: self.cursor.read().ok()?,
629            },
630            (false, false) => Anchor::Point {
631                base: self.cursor.read::<u8>().ok()? as _,
632                component: self.cursor.read::<u8>().ok()? as _,
633            },
634        };
635        let mut transform = Transform::default();
636        if flags.contains(CompositeGlyphFlags::WE_HAVE_A_SCALE) {
637            transform.xx = self.cursor.read().ok()?;
638            transform.yy = transform.xx;
639        } else if flags.contains(CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
640            transform.xx = self.cursor.read().ok()?;
641            transform.yy = self.cursor.read().ok()?;
642        } else if flags.contains(CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO) {
643            transform.xx = self.cursor.read().ok()?;
644            transform.yx = self.cursor.read().ok()?;
645            transform.xy = self.cursor.read().ok()?;
646            transform.yy = self.cursor.read().ok()?;
647        }
648        self.done = !flags.contains(CompositeGlyphFlags::MORE_COMPONENTS);
649
650        Some(Component {
651            flags,
652            glyph,
653            anchor,
654            transform,
655        })
656    }
657}
658
659/// Iterator that only returns glyph identifiers and flags for each component.
660///
661/// Significantly faster in cases where we're just processing the glyph
662/// tree, counting components or accessing instructions.
663#[derive(Clone)]
664struct ComponentGlyphIdFlagsIter<'a> {
665    cur_flags: CompositeGlyphFlags,
666    done: bool,
667    cursor: Cursor<'a>,
668}
669
670impl Iterator for ComponentGlyphIdFlagsIter<'_> {
671    type Item = (GlyphId16, CompositeGlyphFlags);
672
673    fn next(&mut self) -> Option<Self::Item> {
674        if self.done {
675            return None;
676        }
677        let flags: CompositeGlyphFlags = self.cursor.read().ok()?;
678        self.cur_flags = flags;
679        let glyph = self.cursor.read::<GlyphId16>().ok()?;
680        let args_are_words = flags.contains(CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS);
681        if args_are_words {
682            self.cursor.advance_by(4);
683        } else {
684            self.cursor.advance_by(2);
685        }
686        if flags.contains(CompositeGlyphFlags::WE_HAVE_A_SCALE) {
687            self.cursor.advance_by(2);
688        } else if flags.contains(CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
689            self.cursor.advance_by(4);
690        } else if flags.contains(CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO) {
691            self.cursor.advance_by(8);
692        }
693        self.done = !flags.contains(CompositeGlyphFlags::MORE_COMPONENTS);
694        Some((glyph, flags))
695    }
696}
697
698#[cfg(feature = "experimental_traverse")]
699impl<'a> SomeTable<'a> for Component {
700    fn type_name(&self) -> &str {
701        "Component"
702    }
703
704    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
705        match idx {
706            0 => Some(Field::new("flags", self.flags.bits())),
707            1 => Some(Field::new("glyph", self.glyph)),
708            2 => match self.anchor {
709                Anchor::Point { base, .. } => Some(Field::new("base", base)),
710                Anchor::Offset { x, .. } => Some(Field::new("x", x)),
711            },
712            3 => match self.anchor {
713                Anchor::Point { component, .. } => Some(Field::new("component", component)),
714                Anchor::Offset { y, .. } => Some(Field::new("y", y)),
715            },
716            _ => None,
717        }
718    }
719}
720
721impl Anchor {
722    /// Compute the flags that describe this anchor
723    pub fn compute_flags(&self) -> CompositeGlyphFlags {
724        const I8_RANGE: Range<i16> = i8::MIN as i16..i8::MAX as i16 + 1;
725        const U8_MAX: u16 = u8::MAX as u16;
726
727        let mut flags = CompositeGlyphFlags::empty();
728        match self {
729            Anchor::Offset { x, y } => {
730                flags |= CompositeGlyphFlags::ARGS_ARE_XY_VALUES;
731                if !I8_RANGE.contains(x) || !I8_RANGE.contains(y) {
732                    flags |= CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS;
733                }
734            }
735            Anchor::Point { base, component } => {
736                if base > &U8_MAX || component > &U8_MAX {
737                    flags |= CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS;
738                }
739            }
740        }
741        flags
742    }
743}
744
745impl Transform {
746    /// Compute the flags that describe this transform
747    pub fn compute_flags(&self) -> CompositeGlyphFlags {
748        if self.yx != F2Dot14::ZERO || self.xy != F2Dot14::ZERO {
749            CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO
750        } else if self.xx != self.yy {
751            CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE
752        } else if self.xx != F2Dot14::ONE {
753            CompositeGlyphFlags::WE_HAVE_A_SCALE
754        } else {
755            CompositeGlyphFlags::empty()
756        }
757    }
758}
759
760impl PointCoord for F26Dot6 {
761    fn from_fixed(x: Fixed) -> Self {
762        x.to_f26dot6()
763    }
764
765    #[inline]
766    fn from_i32(x: i32) -> Self {
767        Self::from_i32(x)
768    }
769
770    #[inline]
771    fn to_f32(self) -> f32 {
772        self.to_f32()
773    }
774
775    #[inline]
776    fn midpoint(self, other: Self) -> Self {
777        // FreeType uses integer division on 26.6 to compute midpoints.
778        // See: https://github.com/freetype/freetype/blob/de8b92dd7ec634e9e2b25ef534c54a3537555c11/src/base/ftoutln.c#L123
779        Self::from_bits(midpoint_i32(self.to_bits(), other.to_bits()))
780    }
781}
782
783impl PointCoord for Fixed {
784    fn from_fixed(x: Fixed) -> Self {
785        x
786    }
787
788    fn from_i32(x: i32) -> Self {
789        Self::from_i32(x)
790    }
791
792    fn to_f32(self) -> f32 {
793        self.to_f32()
794    }
795
796    fn midpoint(self, other: Self) -> Self {
797        Self::from_bits(midpoint_i32(self.to_bits(), other.to_bits()))
798    }
799}
800
801impl PointCoord for i32 {
802    fn from_fixed(x: Fixed) -> Self {
803        x.to_i32()
804    }
805
806    fn from_i32(x: i32) -> Self {
807        x
808    }
809
810    fn to_f32(self) -> f32 {
811        self as f32
812    }
813
814    fn midpoint(self, other: Self) -> Self {
815        midpoint_i32(self, other)
816    }
817}
818
819// Midpoint function that avoids overflow on large values.
820#[inline(always)]
821fn midpoint_i32(a: i32, b: i32) -> i32 {
822    // Original overflowing code was: (a + b) / 2
823    // Choose wrapping arithmetic here because we shouldn't ever
824    // hit this outside of fuzzing or broken fonts _and_ this is
825    // called from the outline to path conversion code which is
826    // very performance sensitive
827    a.wrapping_add(b) / 2
828}
829
830impl PointCoord for f32 {
831    fn from_fixed(x: Fixed) -> Self {
832        x.to_f32()
833    }
834
835    fn from_i32(x: i32) -> Self {
836        x as f32
837    }
838
839    fn to_f32(self) -> f32 {
840        self
841    }
842
843    fn midpoint(self, other: Self) -> Self {
844        // HarfBuzz uses a lerp here so we copy the style to
845        // preserve compatibility
846        self + 0.5 * (other - self)
847    }
848}
849
850#[cfg(test)]
851mod tests {
852    use super::*;
853    use crate::{FontRef, GlyphId, TableProvider};
854
855    #[test]
856    fn simple_glyph() {
857        let font = FontRef::new(font_test_data::COLR_GRADIENT_RECT).unwrap();
858        let loca = font.loca(None).unwrap();
859        let glyf = font.glyf().unwrap();
860        let glyph = loca.get_glyf(GlyphId::new(0), &glyf).unwrap().unwrap();
861        assert_eq!(glyph.number_of_contours(), 2);
862        let simple_glyph = if let Glyph::Simple(simple) = glyph {
863            simple
864        } else {
865            panic!("expected simple glyph");
866        };
867        assert_eq!(
868            simple_glyph
869                .end_pts_of_contours()
870                .iter()
871                .map(|x| x.get())
872                .collect::<Vec<_>>(),
873            &[3, 7]
874        );
875        assert_eq!(
876            simple_glyph
877                .points()
878                .map(|pt| (pt.x, pt.y, pt.on_curve))
879                .collect::<Vec<_>>(),
880            &[
881                (5, 0, true),
882                (5, 100, true),
883                (45, 100, true),
884                (45, 0, true),
885                (10, 5, true),
886                (40, 5, true),
887                (40, 95, true),
888                (10, 95, true),
889            ]
890        );
891    }
892
893    // Test helper to enumerate all TrueType glyphs in the given font
894    fn all_glyphs(font_data: &[u8]) -> impl Iterator<Item = Option<Glyph>> {
895        let font = FontRef::new(font_data).unwrap();
896        let loca = font.loca(None).unwrap();
897        let glyf = font.glyf().unwrap();
898        let glyph_count = font.maxp().unwrap().num_glyphs() as u32;
899        (0..glyph_count).map(move |gid| loca.get_glyf(GlyphId::new(gid), &glyf).unwrap())
900    }
901
902    #[test]
903    fn simple_glyph_overlapping_contour_flag() {
904        let gids_with_overlap: Vec<_> = all_glyphs(font_test_data::VAZIRMATN_VAR)
905            .enumerate()
906            .filter_map(|(gid, glyph)| match glyph {
907                Some(Glyph::Simple(glyph)) if glyph.has_overlapping_contours() => Some(gid),
908                _ => None,
909            })
910            .collect();
911        // Only GID 3 has the overlap bit set
912        let expected_gids_with_overlap = vec![3];
913        assert_eq!(expected_gids_with_overlap, gids_with_overlap);
914    }
915
916    #[test]
917    fn composite_glyph_overlapping_contour_flag() {
918        let gids_components_with_overlap: Vec<_> = all_glyphs(font_test_data::VAZIRMATN_VAR)
919            .enumerate()
920            .filter_map(|(gid, glyph)| match glyph {
921                Some(Glyph::Composite(glyph)) => Some((gid, glyph)),
922                _ => None,
923            })
924            .flat_map(|(gid, glyph)| {
925                glyph
926                    .components()
927                    .enumerate()
928                    .filter_map(move |(comp_ix, comp)| {
929                        comp.flags
930                            .contains(CompositeGlyphFlags::OVERLAP_COMPOUND)
931                            .then_some((gid, comp_ix))
932                    })
933            })
934            .collect();
935        // Only GID 2, component 1 has the overlap bit set
936        let expected_gids_components_with_overlap = vec![(2, 1)];
937        assert_eq!(
938            expected_gids_components_with_overlap,
939            gids_components_with_overlap
940        );
941    }
942
943    #[test]
944    fn compute_anchor_flags() {
945        let anchor = Anchor::Offset { x: -128, y: 127 };
946        assert_eq!(
947            anchor.compute_flags(),
948            CompositeGlyphFlags::ARGS_ARE_XY_VALUES
949        );
950
951        let anchor = Anchor::Offset { x: -129, y: 127 };
952        assert_eq!(
953            anchor.compute_flags(),
954            CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
955        );
956        let anchor = Anchor::Offset { x: -1, y: 128 };
957        assert_eq!(
958            anchor.compute_flags(),
959            CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
960        );
961
962        let anchor = Anchor::Point {
963            base: 255,
964            component: 20,
965        };
966        assert_eq!(anchor.compute_flags(), CompositeGlyphFlags::empty());
967
968        let anchor = Anchor::Point {
969            base: 256,
970            component: 20,
971        };
972        assert_eq!(
973            anchor.compute_flags(),
974            CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
975        )
976    }
977
978    #[test]
979    fn compute_transform_flags() {
980        fn make_xform(xx: f32, yx: f32, xy: f32, yy: f32) -> Transform {
981            Transform {
982                xx: F2Dot14::from_f32(xx),
983                yx: F2Dot14::from_f32(yx),
984                xy: F2Dot14::from_f32(xy),
985                yy: F2Dot14::from_f32(yy),
986            }
987        }
988
989        assert_eq!(
990            make_xform(1.0, 0., 0., 1.0).compute_flags(),
991            CompositeGlyphFlags::empty()
992        );
993        assert_eq!(
994            make_xform(2.0, 0., 0., 2.0).compute_flags(),
995            CompositeGlyphFlags::WE_HAVE_A_SCALE
996        );
997        assert_eq!(
998            make_xform(2.0, 0., 0., 1.0).compute_flags(),
999            CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE
1000        );
1001        assert_eq!(
1002            make_xform(2.0, 0., 1.0, 1.0).compute_flags(),
1003            CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO
1004        );
1005    }
1006
1007    #[test]
1008    fn point_flags_and_marker_bits() {
1009        let bits = [
1010            PointFlags::OFF_CURVE_CUBIC,
1011            PointFlags::ON_CURVE,
1012            PointMarker::HAS_DELTA.0,
1013            PointMarker::TOUCHED_X.0,
1014            PointMarker::TOUCHED_Y.0,
1015        ];
1016        // Ensure bits don't overlap
1017        for (i, a) in bits.iter().enumerate() {
1018            for b in &bits[i + 1..] {
1019                assert_eq!(a & b, 0);
1020            }
1021        }
1022    }
1023
1024    #[test]
1025    fn cubic_glyf() {
1026        let font = FontRef::new(font_test_data::CUBIC_GLYF).unwrap();
1027        let loca = font.loca(None).unwrap();
1028        let glyf = font.glyf().unwrap();
1029        let glyph = loca.get_glyf(GlyphId::new(2), &glyf).unwrap().unwrap();
1030        assert_eq!(glyph.number_of_contours(), 1);
1031        let simple_glyph = if let Glyph::Simple(simple) = glyph {
1032            simple
1033        } else {
1034            panic!("expected simple glyph");
1035        };
1036        assert_eq!(
1037            simple_glyph
1038                .points()
1039                .map(|pt| (pt.x, pt.y, pt.on_curve))
1040                .collect::<Vec<_>>(),
1041            &[
1042                (278, 710, true),
1043                (278, 470, true),
1044                (300, 500, false),
1045                (800, 500, false),
1046                (998, 470, true),
1047                (998, 710, true),
1048            ]
1049        );
1050    }
1051
1052    // Minimized test case from https://issues.oss-fuzz.com/issues/382732980
1053    // Add with overflow when computing midpoint of 1084092352 and 1085243712
1054    // during outline -> path conversion
1055    #[test]
1056    fn avoid_midpoint_overflow() {
1057        let a = F26Dot6::from_bits(1084092352);
1058        let b = F26Dot6::from_bits(1085243712);
1059        let expected = (a + b).to_bits() / 2;
1060        // Don't panic!
1061        let midpoint = a.midpoint(b);
1062        assert_eq!(midpoint.to_bits(), expected);
1063    }
1064}