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