Skip to main content

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        // The flag run can use two bytes per point (a flag plus its repeat
223        // count), so the encoded flags may be longer than n_points; read over
224        // all the available data and stop once every point has a flag.
225        let flags_data = cursor.read_array::<u8>(cursor.remaining_bytes())?;
226        let mut flags_iter = flags_data.iter().copied();
227        // Keep track of the actual number of flag bytes read so that we can
228        // create a new cursor for reading coordinates
229        let mut read_flags_bytes = 0;
230        let mut i = 0;
231        while let Some(flag_bits) = flags_iter.next() {
232            read_flags_bytes += 1;
233            if SimpleGlyphFlags::from_bits_truncate(flag_bits)
234                .contains(SimpleGlyphFlags::REPEAT_FLAG)
235            {
236                let count = (flags_iter.next().ok_or(ReadError::OutOfBounds)? as usize + 1)
237                    .min(n_points - i);
238                read_flags_bytes += 1;
239                for f in &mut flags[i..i + count] {
240                    f.0 = flag_bits;
241                }
242                i += count;
243            } else {
244                flags[i].0 = flag_bits;
245                i += 1;
246            }
247            if i == n_points {
248                break;
249            }
250        }
251        let mut cursor = FontData::new(self.glyph_data()).cursor();
252        cursor.advance_by(read_flags_bytes);
253        let mut x = 0i32;
254        for (&point_flags, point) in flags.iter().zip(points.as_mut()) {
255            let mut delta = 0i32;
256            let flag = SimpleGlyphFlags::from_bits_truncate(point_flags.0);
257            if flag.contains(SimpleGlyphFlags::X_SHORT_VECTOR) {
258                delta = cursor.read::<u8>()? as i32;
259                if !flag.contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
260                    delta = -delta;
261                }
262            } else if !flag.contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
263                delta = cursor.read::<i16>()? as i32;
264            }
265            x = x.wrapping_add(delta);
266            point.x = C::from_i32(x);
267        }
268        let mut y = 0i32;
269        for (point_flags, point) in flags.iter_mut().zip(points.as_mut()) {
270            let mut delta = 0i32;
271            let flag = SimpleGlyphFlags::from_bits_truncate(point_flags.0);
272            if flag.contains(SimpleGlyphFlags::Y_SHORT_VECTOR) {
273                delta = cursor.read::<u8>()? as i32;
274                if !flag.contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
275                    delta = -delta;
276                }
277            } else if !flag.contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
278                delta = cursor.read::<i16>()? as i32;
279            }
280            y = y.wrapping_add(delta);
281            point.y = C::from_i32(y);
282            let flags_mask = if cfg!(feature = "spec_next") {
283                PointFlags::CURVE_MASK
284            } else {
285                // Drop the cubic bit if the spec_next feature is not enabled
286                PointFlags::ON_CURVE
287            };
288            point_flags.0 &= flags_mask;
289        }
290        Ok(())
291    }
292
293    /// Returns an iterator over the points in the glyph.
294    ///
295    /// ## Performance
296    ///
297    /// This is slower than [read_points_fast](Self::read_points_fast) but
298    /// provides access to the points without requiring a preallocated buffer.
299    pub fn points(&self) -> impl Iterator<Item = CurvePoint> + 'a + Clone {
300        self.points_impl()
301            .unwrap_or_else(|| PointIter::new(&[], &[], &[]))
302    }
303
304    fn points_impl(&self) -> Option<PointIter<'a>> {
305        let end_points = self.end_pts_of_contours();
306        let n_points = end_points.last()?.get().checked_add(1)?;
307        let data = self.glyph_data();
308        let lens = resolve_coords_len(data, n_points).ok()?;
309        let total_len = lens.flags + lens.x_coords + lens.y_coords;
310        if data.len() < total_len as usize {
311            return None;
312        }
313
314        let (flags, data) = data.split_at(lens.flags as usize);
315        let (x_coords, y_coords) = data.split_at(lens.x_coords as usize);
316
317        Some(PointIter::new(flags, x_coords, y_coords))
318    }
319}
320
321/// Point with an associated on-curve flag in a simple glyph.
322///
323/// This type is a simpler representation of the data in the blob.
324#[derive(Clone, Copy, Debug, PartialEq, Eq)]
325pub struct CurvePoint {
326    /// X coordinate.
327    pub x: i16,
328    /// Y coordinate.
329    pub y: i16,
330    /// True if this is an on-curve point.
331    pub on_curve: bool,
332}
333
334impl CurvePoint {
335    /// Construct a new `CurvePoint`
336    pub fn new(x: i16, y: i16, on_curve: bool) -> Self {
337        Self { x, y, on_curve }
338    }
339
340    /// Convenience method to construct an on-curve point
341    pub fn on_curve(x: i16, y: i16) -> Self {
342        Self::new(x, y, true)
343    }
344
345    /// Convenience method to construct an off-curve point
346    pub fn off_curve(x: i16, y: i16) -> Self {
347        Self::new(x, y, false)
348    }
349}
350
351#[derive(Clone)]
352struct PointIter<'a> {
353    flags: Cursor<'a>,
354    x_coords: Cursor<'a>,
355    y_coords: Cursor<'a>,
356    flag_repeats: u8,
357    cur_flags: SimpleGlyphFlags,
358    cur_x: i16,
359    cur_y: i16,
360}
361
362impl Iterator for PointIter<'_> {
363    type Item = CurvePoint;
364    fn next(&mut self) -> Option<Self::Item> {
365        self.advance_flags()?;
366        self.advance_points();
367        let is_on_curve = self.cur_flags.contains(SimpleGlyphFlags::ON_CURVE_POINT);
368        Some(CurvePoint::new(self.cur_x, self.cur_y, is_on_curve))
369    }
370}
371
372impl<'a> PointIter<'a> {
373    fn new(flags: &'a [u8], x_coords: &'a [u8], y_coords: &'a [u8]) -> Self {
374        Self {
375            flags: FontData::new(flags).cursor(),
376            x_coords: FontData::new(x_coords).cursor(),
377            y_coords: FontData::new(y_coords).cursor(),
378            flag_repeats: 0,
379            cur_flags: SimpleGlyphFlags::empty(),
380            cur_x: 0,
381            cur_y: 0,
382        }
383    }
384
385    fn advance_flags(&mut self) -> Option<()> {
386        if self.flag_repeats == 0 {
387            self.cur_flags = SimpleGlyphFlags::from_bits_truncate(self.flags.read().ok()?);
388            self.flag_repeats = self
389                .cur_flags
390                .contains(SimpleGlyphFlags::REPEAT_FLAG)
391                .then(|| self.flags.read().ok())
392                .flatten()
393                .unwrap_or(0)
394                + 1;
395        }
396        self.flag_repeats -= 1;
397        Some(())
398    }
399
400    fn advance_points(&mut self) {
401        let x_short = self.cur_flags.contains(SimpleGlyphFlags::X_SHORT_VECTOR);
402        let x_same_or_pos = self
403            .cur_flags
404            .contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR);
405        let y_short = self.cur_flags.contains(SimpleGlyphFlags::Y_SHORT_VECTOR);
406        let y_same_or_pos = self
407            .cur_flags
408            .contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR);
409
410        let delta_x = match (x_short, x_same_or_pos) {
411            (true, false) => -(self.x_coords.read::<u8>().unwrap_or(0) as i16),
412            (true, true) => self.x_coords.read::<u8>().unwrap_or(0) as i16,
413            (false, false) => self.x_coords.read::<i16>().unwrap_or(0),
414            _ => 0,
415        };
416
417        let delta_y = match (y_short, y_same_or_pos) {
418            (true, false) => -(self.y_coords.read::<u8>().unwrap_or(0) as i16),
419            (true, true) => self.y_coords.read::<u8>().unwrap_or(0) as i16,
420            (false, false) => self.y_coords.read::<i16>().unwrap_or(0),
421            _ => 0,
422        };
423
424        self.cur_x = self.cur_x.wrapping_add(delta_x);
425        self.cur_y = self.cur_y.wrapping_add(delta_y);
426    }
427}
428
429//taken from ttf_parser https://docs.rs/ttf-parser/latest/src/ttf_parser/tables/glyf.rs.html#1-677
430/// Resolves coordinate arrays length.
431///
432/// The length depends on *Simple Glyph Flags*, so we have to process them all to find it.
433fn resolve_coords_len(data: &[u8], points_total: u16) -> Result<FieldLengths, ReadError> {
434    let mut cursor = FontData::new(data).cursor();
435    let mut flags_left = u32::from(points_total);
436    //let mut repeats;
437    let mut x_coords_len = 0;
438    let mut y_coords_len = 0;
439    //let mut flags_seen = 0;
440    while flags_left > 0 {
441        let flags: SimpleGlyphFlags = cursor.read()?;
442
443        // The number of times a glyph point repeats.
444        let repeats = if flags.contains(SimpleGlyphFlags::REPEAT_FLAG) {
445            let repeats: u8 = cursor.read()?;
446            u32::from(repeats) + 1
447        } else {
448            1
449        };
450
451        if repeats > flags_left {
452            return Err(ReadError::MalformedData("repeat count too large in glyf"));
453        }
454
455        // Non-obfuscated code below.
456        // Branchless version is surprisingly faster.
457        //
458        // if flags.x_short() {
459        //     // Coordinate is 1 byte long.
460        //     x_coords_len += repeats;
461        // } else if !flags.x_is_same_or_positive_short() {
462        //     // Coordinate is 2 bytes long.
463        //     x_coords_len += repeats * 2;
464        // }
465        // if flags.y_short() {
466        //     // Coordinate is 1 byte long.
467        //     y_coords_len += repeats;
468        // } else if !flags.y_is_same_or_positive_short() {
469        //     // Coordinate is 2 bytes long.
470        //     y_coords_len += repeats * 2;
471        // }
472        let x_short = SimpleGlyphFlags::X_SHORT_VECTOR;
473        let x_long = SimpleGlyphFlags::X_SHORT_VECTOR
474            | SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR;
475        let y_short = SimpleGlyphFlags::Y_SHORT_VECTOR;
476        let y_long = SimpleGlyphFlags::Y_SHORT_VECTOR
477            | SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR;
478        x_coords_len += ((flags & x_short).bits() != 0) as u32 * repeats;
479        x_coords_len += ((flags & x_long).bits() == 0) as u32 * repeats * 2;
480
481        y_coords_len += ((flags & y_short).bits() != 0) as u32 * repeats;
482        y_coords_len += ((flags & y_long).bits() == 0) as u32 * repeats * 2;
483
484        flags_left -= repeats;
485    }
486
487    Ok(FieldLengths {
488        flags: cursor.position()? as u32,
489        x_coords: x_coords_len,
490        y_coords: y_coords_len,
491    })
492    //Some((flags_len, x_coords_len, y_coords_len))
493}
494
495struct FieldLengths {
496    flags: u32,
497    x_coords: u32,
498    y_coords: u32,
499}
500
501/// Transform for a composite component.
502#[derive(Clone, Copy, Debug, PartialEq, Eq)]
503pub struct Transform {
504    /// X scale factor.
505    pub xx: F2Dot14,
506    /// YX skew factor.
507    pub yx: F2Dot14,
508    /// XY skew factor.
509    pub xy: F2Dot14,
510    /// Y scale factor.
511    pub yy: F2Dot14,
512}
513
514impl Default for Transform {
515    fn default() -> Self {
516        Self {
517            xx: F2Dot14::from_f32(1.0),
518            yx: F2Dot14::from_f32(0.0),
519            xy: F2Dot14::from_f32(0.0),
520            yy: F2Dot14::from_f32(1.0),
521        }
522    }
523}
524
525/// A reference to another glyph. Part of [CompositeGlyph].
526#[derive(Clone, Debug, PartialEq, Eq)]
527pub struct Component {
528    /// Component flags.
529    pub flags: CompositeGlyphFlags,
530    /// Glyph identifier.
531    pub glyph: GlyphId16,
532    /// Anchor for component placement.
533    pub anchor: Anchor,
534    /// Component transformation matrix.
535    pub transform: Transform,
536}
537
538/// Anchor position for a composite component.
539#[derive(Clone, Copy, Debug, PartialEq, Eq)]
540pub enum Anchor {
541    Offset { x: i16, y: i16 },
542    Point { base: u16, component: u16 },
543}
544
545impl<'a> CompositeGlyph<'a> {
546    /// Returns an iterator over the components of the composite glyph.
547    pub fn components(&self) -> impl Iterator<Item = Component> + 'a + Clone {
548        ComponentIter {
549            cur_flags: CompositeGlyphFlags::empty(),
550            done: false,
551            cursor: FontData::new(self.component_data()).cursor(),
552        }
553    }
554
555    /// Returns an iterator that yields the glyph identifier and flags of each
556    /// component in the composite glyph.
557    pub fn component_glyphs_and_flags(
558        &self,
559    ) -> impl Iterator<Item = (GlyphId16, CompositeGlyphFlags)> + 'a + Clone {
560        ComponentGlyphIdFlagsIter {
561            cur_flags: CompositeGlyphFlags::empty(),
562            done: false,
563            cursor: FontData::new(self.component_data()).cursor(),
564        }
565    }
566
567    /// Returns the component count and TrueType interpreter instructions
568    /// in a single pass.
569    pub fn count_and_instructions(&self) -> (usize, Option<&'a [u8]>) {
570        let mut iter = ComponentGlyphIdFlagsIter {
571            cur_flags: CompositeGlyphFlags::empty(),
572            done: false,
573            cursor: FontData::new(self.component_data()).cursor(),
574        };
575        let mut count = 0;
576        while iter.by_ref().next().is_some() {
577            count += 1;
578        }
579        let instructions = if iter
580            .cur_flags
581            .contains(CompositeGlyphFlags::WE_HAVE_INSTRUCTIONS)
582        {
583            iter.cursor
584                .read::<u16>()
585                .ok()
586                .map(|len| len as usize)
587                .and_then(|len| iter.cursor.read_array(len).ok())
588        } else {
589            None
590        };
591        (count, instructions)
592    }
593
594    /// Returns the TrueType interpreter instructions.
595    pub fn instructions(&self) -> Option<&'a [u8]> {
596        self.count_and_instructions().1
597    }
598}
599
600#[derive(Clone)]
601struct ComponentIter<'a> {
602    cur_flags: CompositeGlyphFlags,
603    done: bool,
604    cursor: Cursor<'a>,
605}
606
607impl Iterator for ComponentIter<'_> {
608    type Item = Component;
609
610    fn next(&mut self) -> Option<Self::Item> {
611        if self.done {
612            return None;
613        }
614        let flags: CompositeGlyphFlags = self.cursor.read().ok()?;
615        self.cur_flags = flags;
616        let glyph = self.cursor.read::<GlyphId16>().ok()?;
617        let args_are_words = flags.contains(CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS);
618        let args_are_xy_values = flags.contains(CompositeGlyphFlags::ARGS_ARE_XY_VALUES);
619        let anchor = match (args_are_xy_values, args_are_words) {
620            (true, true) => Anchor::Offset {
621                x: self.cursor.read().ok()?,
622                y: self.cursor.read().ok()?,
623            },
624            (true, false) => Anchor::Offset {
625                x: self.cursor.read::<i8>().ok()? as _,
626                y: self.cursor.read::<i8>().ok()? as _,
627            },
628            (false, true) => Anchor::Point {
629                base: self.cursor.read().ok()?,
630                component: self.cursor.read().ok()?,
631            },
632            (false, false) => Anchor::Point {
633                base: self.cursor.read::<u8>().ok()? as _,
634                component: self.cursor.read::<u8>().ok()? as _,
635            },
636        };
637        let mut transform = Transform::default();
638        if flags.contains(CompositeGlyphFlags::WE_HAVE_A_SCALE) {
639            transform.xx = self.cursor.read().ok()?;
640            transform.yy = transform.xx;
641        } else if flags.contains(CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
642            transform.xx = self.cursor.read().ok()?;
643            transform.yy = self.cursor.read().ok()?;
644        } else if flags.contains(CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO) {
645            transform.xx = self.cursor.read().ok()?;
646            transform.yx = self.cursor.read().ok()?;
647            transform.xy = self.cursor.read().ok()?;
648            transform.yy = self.cursor.read().ok()?;
649        }
650        self.done = !flags.contains(CompositeGlyphFlags::MORE_COMPONENTS);
651
652        Some(Component {
653            flags,
654            glyph,
655            anchor,
656            transform,
657        })
658    }
659}
660
661/// Iterator that only returns glyph identifiers and flags for each component.
662///
663/// Significantly faster in cases where we're just processing the glyph
664/// tree, counting components or accessing instructions.
665#[derive(Clone)]
666struct ComponentGlyphIdFlagsIter<'a> {
667    cur_flags: CompositeGlyphFlags,
668    done: bool,
669    cursor: Cursor<'a>,
670}
671
672impl Iterator for ComponentGlyphIdFlagsIter<'_> {
673    type Item = (GlyphId16, CompositeGlyphFlags);
674
675    fn next(&mut self) -> Option<Self::Item> {
676        if self.done {
677            return None;
678        }
679        let flags: CompositeGlyphFlags = self.cursor.read().ok()?;
680        self.cur_flags = flags;
681        let glyph = self.cursor.read::<GlyphId16>().ok()?;
682        let args_are_words = flags.contains(CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS);
683        if args_are_words {
684            self.cursor.advance_by(4);
685        } else {
686            self.cursor.advance_by(2);
687        }
688        if flags.contains(CompositeGlyphFlags::WE_HAVE_A_SCALE) {
689            self.cursor.advance_by(2);
690        } else if flags.contains(CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
691            self.cursor.advance_by(4);
692        } else if flags.contains(CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO) {
693            self.cursor.advance_by(8);
694        }
695        self.done = !flags.contains(CompositeGlyphFlags::MORE_COMPONENTS);
696        Some((glyph, flags))
697    }
698}
699
700#[cfg(feature = "experimental_traverse")]
701impl<'a> SomeTable<'a> for Component {
702    fn type_name(&self) -> &str {
703        "Component"
704    }
705
706    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
707        match idx {
708            0 => Some(Field::new("flags", self.flags.bits())),
709            1 => Some(Field::new("glyph", self.glyph)),
710            2 => match self.anchor {
711                Anchor::Point { base, .. } => Some(Field::new("base", base)),
712                Anchor::Offset { x, .. } => Some(Field::new("x", x)),
713            },
714            3 => match self.anchor {
715                Anchor::Point { component, .. } => Some(Field::new("component", component)),
716                Anchor::Offset { y, .. } => Some(Field::new("y", y)),
717            },
718            _ => None,
719        }
720    }
721}
722
723impl Anchor {
724    /// Compute the flags that describe this anchor
725    pub fn compute_flags(&self) -> CompositeGlyphFlags {
726        const I8_RANGE: Range<i16> = i8::MIN as i16..i8::MAX as i16 + 1;
727        const U8_MAX: u16 = u8::MAX as u16;
728
729        let mut flags = CompositeGlyphFlags::empty();
730        match self {
731            Anchor::Offset { x, y } => {
732                flags |= CompositeGlyphFlags::ARGS_ARE_XY_VALUES;
733                if !I8_RANGE.contains(x) || !I8_RANGE.contains(y) {
734                    flags |= CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS;
735                }
736            }
737            Anchor::Point { base, component } => {
738                if base > &U8_MAX || component > &U8_MAX {
739                    flags |= CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS;
740                }
741            }
742        }
743        flags
744    }
745}
746
747impl Transform {
748    /// Compute the flags that describe this transform
749    pub fn compute_flags(&self) -> CompositeGlyphFlags {
750        if self.yx != F2Dot14::ZERO || self.xy != F2Dot14::ZERO {
751            CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO
752        } else if self.xx != self.yy {
753            CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE
754        } else if self.xx != F2Dot14::ONE {
755            CompositeGlyphFlags::WE_HAVE_A_SCALE
756        } else {
757            CompositeGlyphFlags::empty()
758        }
759    }
760}
761
762impl PointCoord for F26Dot6 {
763    fn from_fixed(x: Fixed) -> Self {
764        x.to_f26dot6()
765    }
766
767    #[inline]
768    fn from_i32(x: i32) -> Self {
769        Self::from_i32(x)
770    }
771
772    #[inline]
773    fn to_f32(self) -> f32 {
774        self.to_f32()
775    }
776
777    #[inline]
778    fn midpoint(self, other: Self) -> Self {
779        // FreeType uses integer division on 26.6 to compute midpoints.
780        // See: https://github.com/freetype/freetype/blob/de8b92dd7ec634e9e2b25ef534c54a3537555c11/src/base/ftoutln.c#L123
781        Self::from_bits(midpoint_i32(self.to_bits(), other.to_bits()))
782    }
783}
784
785impl PointCoord for Fixed {
786    fn from_fixed(x: Fixed) -> Self {
787        x
788    }
789
790    fn from_i32(x: i32) -> Self {
791        Self::from_i32(x)
792    }
793
794    fn to_f32(self) -> f32 {
795        self.to_f32()
796    }
797
798    fn midpoint(self, other: Self) -> Self {
799        Self::from_bits(midpoint_i32(self.to_bits(), other.to_bits()))
800    }
801}
802
803impl PointCoord for i32 {
804    fn from_fixed(x: Fixed) -> Self {
805        x.to_i32()
806    }
807
808    fn from_i32(x: i32) -> Self {
809        x
810    }
811
812    fn to_f32(self) -> f32 {
813        self as f32
814    }
815
816    fn midpoint(self, other: Self) -> Self {
817        midpoint_i32(self, other)
818    }
819}
820
821// Midpoint function that avoids overflow on large values.
822#[inline(always)]
823fn midpoint_i32(a: i32, b: i32) -> i32 {
824    // Original overflowing code was: (a + b) / 2
825    // Choose wrapping arithmetic here because we shouldn't ever
826    // hit this outside of fuzzing or broken fonts _and_ this is
827    // called from the outline to path conversion code which is
828    // very performance sensitive
829    a.wrapping_add(b) / 2
830}
831
832impl PointCoord for f32 {
833    fn from_fixed(x: Fixed) -> Self {
834        x.to_f32()
835    }
836
837    fn from_i32(x: i32) -> Self {
838        x as f32
839    }
840
841    fn to_f32(self) -> f32 {
842        self
843    }
844
845    fn midpoint(self, other: Self) -> Self {
846        // HarfBuzz uses a lerp here so we copy the style to
847        // preserve compatibility
848        self + 0.5 * (other - self)
849    }
850}
851
852#[cfg(test)]
853mod tests {
854    use super::*;
855    use crate::{FontRef, GlyphId, TableProvider};
856
857    #[test]
858    fn simple_glyph() {
859        let font = FontRef::new(font_test_data::COLR_GRADIENT_RECT).unwrap();
860        let loca = font.loca(None).unwrap();
861        let glyf = font.glyf().unwrap();
862        let glyph = loca.get_glyf(GlyphId::new(0), &glyf).unwrap().unwrap();
863        assert_eq!(glyph.number_of_contours(), 2);
864        let simple_glyph = if let Glyph::Simple(simple) = glyph {
865            simple
866        } else {
867            panic!("expected simple glyph");
868        };
869        assert_eq!(
870            simple_glyph
871                .end_pts_of_contours()
872                .iter()
873                .map(|x| x.get())
874                .collect::<Vec<_>>(),
875            &[3, 7]
876        );
877        assert_eq!(
878            simple_glyph
879                .points()
880                .map(|pt| (pt.x, pt.y, pt.on_curve))
881                .collect::<Vec<_>>(),
882            &[
883                (5, 0, true),
884                (5, 100, true),
885                (45, 100, true),
886                (45, 0, true),
887                (10, 5, true),
888                (40, 5, true),
889                (40, 95, true),
890                (10, 95, true),
891            ]
892        );
893    }
894
895    // Test helper to enumerate all TrueType glyphs in the given font
896    fn all_glyphs(font_data: &[u8]) -> impl Iterator<Item = Option<Glyph<'_>>> {
897        let font = FontRef::new(font_data).unwrap();
898        let loca = font.loca(None).unwrap();
899        let glyf = font.glyf().unwrap();
900        let glyph_count = font.maxp().unwrap().num_glyphs() as u32;
901        (0..glyph_count).map(move |gid| loca.get_glyf(GlyphId::new(gid), &glyf).unwrap())
902    }
903
904    #[test]
905    fn simple_glyph_overlapping_contour_flag() {
906        let gids_with_overlap: Vec<_> = all_glyphs(font_test_data::VAZIRMATN_VAR)
907            .enumerate()
908            .filter_map(|(gid, glyph)| match glyph {
909                Some(Glyph::Simple(glyph)) if glyph.has_overlapping_contours() => Some(gid),
910                _ => None,
911            })
912            .collect();
913        // Only GID 3 has the overlap bit set
914        let expected_gids_with_overlap = vec![3];
915        assert_eq!(expected_gids_with_overlap, gids_with_overlap);
916    }
917
918    #[test]
919    fn composite_glyph_overlapping_contour_flag() {
920        let gids_components_with_overlap: Vec<_> = all_glyphs(font_test_data::VAZIRMATN_VAR)
921            .enumerate()
922            .filter_map(|(gid, glyph)| match glyph {
923                Some(Glyph::Composite(glyph)) => Some((gid, glyph)),
924                _ => None,
925            })
926            .flat_map(|(gid, glyph)| {
927                glyph
928                    .components()
929                    .enumerate()
930                    .filter_map(move |(comp_ix, comp)| {
931                        comp.flags
932                            .contains(CompositeGlyphFlags::OVERLAP_COMPOUND)
933                            .then_some((gid, comp_ix))
934                    })
935            })
936            .collect();
937        // Only GID 2, component 1 has the overlap bit set
938        let expected_gids_components_with_overlap = vec![(2, 1)];
939        assert_eq!(
940            expected_gids_components_with_overlap,
941            gids_components_with_overlap
942        );
943    }
944
945    #[test]
946    fn compute_anchor_flags() {
947        let anchor = Anchor::Offset { x: -128, y: 127 };
948        assert_eq!(
949            anchor.compute_flags(),
950            CompositeGlyphFlags::ARGS_ARE_XY_VALUES
951        );
952
953        let anchor = Anchor::Offset { x: -129, y: 127 };
954        assert_eq!(
955            anchor.compute_flags(),
956            CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
957        );
958        let anchor = Anchor::Offset { x: -1, y: 128 };
959        assert_eq!(
960            anchor.compute_flags(),
961            CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
962        );
963
964        let anchor = Anchor::Point {
965            base: 255,
966            component: 20,
967        };
968        assert_eq!(anchor.compute_flags(), CompositeGlyphFlags::empty());
969
970        let anchor = Anchor::Point {
971            base: 256,
972            component: 20,
973        };
974        assert_eq!(
975            anchor.compute_flags(),
976            CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
977        )
978    }
979
980    #[test]
981    fn compute_transform_flags() {
982        fn make_xform(xx: f32, yx: f32, xy: f32, yy: f32) -> Transform {
983            Transform {
984                xx: F2Dot14::from_f32(xx),
985                yx: F2Dot14::from_f32(yx),
986                xy: F2Dot14::from_f32(xy),
987                yy: F2Dot14::from_f32(yy),
988            }
989        }
990
991        assert_eq!(
992            make_xform(1.0, 0., 0., 1.0).compute_flags(),
993            CompositeGlyphFlags::empty()
994        );
995        assert_eq!(
996            make_xform(2.0, 0., 0., 2.0).compute_flags(),
997            CompositeGlyphFlags::WE_HAVE_A_SCALE
998        );
999        assert_eq!(
1000            make_xform(2.0, 0., 0., 1.0).compute_flags(),
1001            CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE
1002        );
1003        assert_eq!(
1004            make_xform(2.0, 0., 1.0, 1.0).compute_flags(),
1005            CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO
1006        );
1007    }
1008
1009    #[test]
1010    fn point_flags_and_marker_bits() {
1011        let bits = [
1012            PointFlags::OFF_CURVE_CUBIC,
1013            PointFlags::ON_CURVE,
1014            PointMarker::HAS_DELTA.0,
1015            PointMarker::TOUCHED_X.0,
1016            PointMarker::TOUCHED_Y.0,
1017        ];
1018        // Ensure bits don't overlap
1019        for (i, a) in bits.iter().enumerate() {
1020            for b in &bits[i + 1..] {
1021                assert_eq!(a & b, 0);
1022            }
1023        }
1024    }
1025
1026    #[test]
1027    fn cubic_glyf() {
1028        let font = FontRef::new(font_test_data::CUBIC_GLYF).unwrap();
1029        let loca = font.loca(None).unwrap();
1030        let glyf = font.glyf().unwrap();
1031        let glyph = loca.get_glyf(GlyphId::new(2), &glyf).unwrap().unwrap();
1032        assert_eq!(glyph.number_of_contours(), 1);
1033        let simple_glyph = if let Glyph::Simple(simple) = glyph {
1034            simple
1035        } else {
1036            panic!("expected simple glyph");
1037        };
1038        assert_eq!(
1039            simple_glyph
1040                .points()
1041                .map(|pt| (pt.x, pt.y, pt.on_curve))
1042                .collect::<Vec<_>>(),
1043            &[
1044                (278, 710, true),
1045                (278, 470, true),
1046                (300, 500, false),
1047                (800, 500, false),
1048                (998, 470, true),
1049                (998, 710, true),
1050            ]
1051        );
1052    }
1053
1054    // Minimized test case from https://issues.oss-fuzz.com/issues/382732980
1055    // Add with overflow when computing midpoint of 1084092352 and 1085243712
1056    // during outline -> path conversion
1057    #[test]
1058    fn avoid_midpoint_overflow() {
1059        let a = F26Dot6::from_bits(1084092352);
1060        let b = F26Dot6::from_bits(1085243712);
1061        let expected = (a + b).to_bits() / 2;
1062        // Don't panic!
1063        let midpoint = a.midpoint(b);
1064        assert_eq!(midpoint.to_bits(), expected);
1065    }
1066
1067    // SimpleGlyph should not panic on truncated data.
1068    //
1069    // SimpleGlyph has a variable-length array (end_pts_of_contours) followed
1070    // by a scalar field (instruction_length). The MIN_SIZE validation only
1071    // checks that the fixed-size fields fit, but doesn't account for the
1072    // array's runtime length. This causes a panic when accessing fields
1073    // that come after the array if the data is truncated.
1074    #[test]
1075    fn simple_glyph_truncated_data() {
1076        use font_test_data::bebuffer::BeBuffer;
1077
1078        // Build a SimpleGlyph with number_of_contours = 100
1079        // This means end_pts_of_contours should be 200 bytes,
1080        // pushing instruction_length to offset 210.
1081        // But we only provide 12 bytes (MIN_SIZE).
1082        let buf = BeBuffer::new()
1083            .push(100_i16) // number_of_contours = 100
1084            .push(0_i16) // x_min
1085            .push(0_i16) // y_min
1086            .push(0_i16) // x_max
1087            .push(0_i16) // y_max
1088            .push(0_u16); // would be first element of end_pts_of_contours
1089
1090        // Parsing succeeds - we have MIN_SIZE (12) bytes
1091        let glyph = SimpleGlyph::read(buf.data().into()).unwrap();
1092        assert_eq!(glyph.number_of_contours(), 100);
1093
1094        // return default value instead of panicking
1095        assert_eq!(glyph.instruction_length(), 0);
1096    }
1097
1098    // The flags run can encode up to two bytes per point (a flag plus a repeat
1099    // count). read_points_fast must agree with the points() iterator even when
1100    // the flags section is longer than the point count.
1101    #[test]
1102    fn read_points_fast_long_flags() {
1103        use font_test_data::bebuffer::BeBuffer;
1104        // 1 contour, 3 points. Each point is its own REPEAT_FLAG entry with a
1105        // repeat count of 0, so the flags section is 6 bytes for 3 points and
1106        // there are no coordinate bytes. flag 0x39 = ON_CURVE | REPEAT_FLAG |
1107        // X_IS_SAME_OR_POSITIVE | Y_IS_SAME_OR_POSITIVE.
1108        let buf = BeBuffer::new()
1109            .push(1_i16) // number_of_contours
1110            .extend([0_i16; 4]) // bounding box
1111            .push(2_u16) // end_pts_of_contours[0] => 3 points
1112            .push(0_u16) // instruction_length
1113            .extend([0x39u8, 0x00, 0x39, 0x00, 0x39, 0x00]);
1114
1115        let glyph = SimpleGlyph::read(buf.data().into()).unwrap();
1116        assert_eq!(glyph.num_points(), 3);
1117
1118        let expected: Vec<_> = glyph.points().map(|p| (p.x as i32, p.y as i32)).collect();
1119
1120        let mut points = vec![Point::default(); 3];
1121        let mut flags = vec![PointFlags::default(); 3];
1122        glyph
1123            .read_points_fast::<i32>(&mut points, &mut flags)
1124            .unwrap();
1125        let actual: Vec<_> = points.iter().map(|p| (p.x, p.y)).collect();
1126
1127        assert_eq!(actual, expected);
1128    }
1129}