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