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