1pub 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#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
14pub struct PointMarker(u8);
15
16impl PointMarker {
17 pub const HAS_DELTA: Self = Self(0x4);
20
21 pub const TOUCHED_X: Self = Self(0x10);
24
25 pub const TOUCHED_Y: Self = Self(0x20);
28
29 pub const TOUCHED: Self = Self(Self::TOUCHED_X.0 | Self::TOUCHED_Y.0);
32
33 pub const WEAK_INTERPOLATION: Self = Self(0x2);
37
38 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#[derive(
58 Copy, Clone, PartialEq, Eq, Default, Debug, bytemuck::AnyBitPattern, bytemuck::NoUninit,
59)]
60#[repr(transparent)]
61pub struct PointFlags(u8);
62
63impl PointFlags {
64 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 pub const fn on_curve() -> Self {
72 Self(Self::ON_CURVE)
73 }
74
75 pub const fn off_curve_quad() -> Self {
77 Self(0)
78 }
79
80 pub const fn off_curve_cubic() -> Self {
82 Self(Self::OFF_CURVE_CUBIC)
83 }
84
85 pub const fn from_bits(bits: u8) -> Self {
88 Self(bits & Self::CURVE_MASK)
89 }
90
91 #[inline]
93 pub const fn is_on_curve(self) -> bool {
94 self.0 & Self::ON_CURVE != 0
95 }
96
97 #[inline]
99 pub const fn is_off_curve_quad(self) -> bool {
100 self.0 & Self::CURVE_MASK == 0
101 }
102
103 #[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 pub fn flip_on_curve(&mut self) {
117 self.0 ^= 1;
118 }
119
120 pub fn set_on_curve(&mut self) {
124 self.0 |= Self::ON_CURVE;
125 }
126
127 pub fn clear_on_curve(&mut self) {
131 self.0 &= !Self::ON_CURVE;
132 }
133
134 pub fn has_marker(self, marker: PointMarker) -> bool {
136 self.0 & marker.0 != 0
137 }
138
139 pub fn set_marker(&mut self, marker: PointMarker) {
141 self.0 |= marker.0;
142 }
143
144 pub fn clear_marker(&mut self, marker: PointMarker) {
146 self.0 &= !marker.0
147 }
148
149 pub const fn without_markers(self) -> Self {
151 Self(self.0 & Self::CURVE_MASK)
152 }
153
154 pub const fn to_bits(self) -> u8 {
156 self.0
157 }
158}
159
160pub trait PointCoord:
162 Copy
163 + Default
164 + AnyBitPattern
166 + PartialEq
168 + PartialOrd
169 + 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 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 pub fn has_overlapping_contours(&self) -> bool {
193 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 pub fn read_points_fast<C: PointCoord>(
213 &self,
214 points: &mut [Point<C>],
215 flags: &mut [PointFlags],
216 ) -> Result<(), ReadError> {
217 let n_points = self.num_points();
218 if points.len() != n_points || flags.len() != n_points {
219 return Err(ReadError::InvalidArrayLen);
220 }
221 let mut cursor = FontData::new(self.glyph_data()).cursor();
222 let mut i = 0;
223 while i < n_points {
224 let flag = cursor.read::<SimpleGlyphFlags>()?;
225 let flag_bits = flag.bits();
226 if flag.contains(SimpleGlyphFlags::REPEAT_FLAG) {
227 let count = (cursor.read::<u8>()? as usize + 1).min(n_points - i);
228 for f in &mut flags[i..i + count] {
229 f.0 = flag_bits;
230 }
231 i += count;
232 } else {
233 flags[i].0 = flag_bits;
234 i += 1;
235 }
236 }
237 let mut x = 0i32;
238 for (&point_flags, point) in flags.iter().zip(points.as_mut()) {
239 let mut delta = 0i32;
240 let flag = SimpleGlyphFlags::from_bits_truncate(point_flags.0);
241 if flag.contains(SimpleGlyphFlags::X_SHORT_VECTOR) {
242 delta = cursor.read::<u8>()? as i32;
243 if !flag.contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
244 delta = -delta;
245 }
246 } else if !flag.contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
247 delta = cursor.read::<i16>()? as i32;
248 }
249 x = x.wrapping_add(delta);
250 point.x = C::from_i32(x);
251 }
252 let mut y = 0i32;
253 for (point_flags, point) in flags.iter_mut().zip(points.as_mut()) {
254 let mut delta = 0i32;
255 let flag = SimpleGlyphFlags::from_bits_truncate(point_flags.0);
256 if flag.contains(SimpleGlyphFlags::Y_SHORT_VECTOR) {
257 delta = cursor.read::<u8>()? as i32;
258 if !flag.contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
259 delta = -delta;
260 }
261 } else if !flag.contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
262 delta = cursor.read::<i16>()? as i32;
263 }
264 y = y.wrapping_add(delta);
265 point.y = C::from_i32(y);
266 let flags_mask = if cfg!(feature = "spec_next") {
267 PointFlags::CURVE_MASK
268 } else {
269 PointFlags::ON_CURVE
271 };
272 point_flags.0 &= flags_mask;
273 }
274 Ok(())
275 }
276
277 pub fn points(&self) -> impl Iterator<Item = CurvePoint> + 'a + Clone {
284 self.points_impl()
285 .unwrap_or_else(|| PointIter::new(&[], &[], &[]))
286 }
287
288 fn points_impl(&self) -> Option<PointIter<'a>> {
289 let end_points = self.end_pts_of_contours();
290 let n_points = end_points.last()?.get().checked_add(1)?;
291 let data = self.glyph_data();
292 let lens = resolve_coords_len(data, n_points).ok()?;
293 let total_len = lens.flags + lens.x_coords + lens.y_coords;
294 if data.len() < total_len as usize {
295 return None;
296 }
297
298 let (flags, data) = data.split_at(lens.flags as usize);
299 let (x_coords, y_coords) = data.split_at(lens.x_coords as usize);
300
301 Some(PointIter::new(flags, x_coords, y_coords))
302 }
303}
304
305#[derive(Clone, Copy, Debug, PartialEq, Eq)]
309pub struct CurvePoint {
310 pub x: i16,
312 pub y: i16,
314 pub on_curve: bool,
316}
317
318impl CurvePoint {
319 pub fn new(x: i16, y: i16, on_curve: bool) -> Self {
321 Self { x, y, on_curve }
322 }
323
324 pub fn on_curve(x: i16, y: i16) -> Self {
326 Self::new(x, y, true)
327 }
328
329 pub fn off_curve(x: i16, y: i16) -> Self {
331 Self::new(x, y, false)
332 }
333}
334
335#[derive(Clone)]
336struct PointIter<'a> {
337 flags: Cursor<'a>,
338 x_coords: Cursor<'a>,
339 y_coords: Cursor<'a>,
340 flag_repeats: u8,
341 cur_flags: SimpleGlyphFlags,
342 cur_x: i16,
343 cur_y: i16,
344}
345
346impl Iterator for PointIter<'_> {
347 type Item = CurvePoint;
348 fn next(&mut self) -> Option<Self::Item> {
349 self.advance_flags()?;
350 self.advance_points();
351 let is_on_curve = self.cur_flags.contains(SimpleGlyphFlags::ON_CURVE_POINT);
352 Some(CurvePoint::new(self.cur_x, self.cur_y, is_on_curve))
353 }
354}
355
356impl<'a> PointIter<'a> {
357 fn new(flags: &'a [u8], x_coords: &'a [u8], y_coords: &'a [u8]) -> Self {
358 Self {
359 flags: FontData::new(flags).cursor(),
360 x_coords: FontData::new(x_coords).cursor(),
361 y_coords: FontData::new(y_coords).cursor(),
362 flag_repeats: 0,
363 cur_flags: SimpleGlyphFlags::empty(),
364 cur_x: 0,
365 cur_y: 0,
366 }
367 }
368
369 fn advance_flags(&mut self) -> Option<()> {
370 if self.flag_repeats == 0 {
371 self.cur_flags = SimpleGlyphFlags::from_bits_truncate(self.flags.read().ok()?);
372 self.flag_repeats = self
373 .cur_flags
374 .contains(SimpleGlyphFlags::REPEAT_FLAG)
375 .then(|| self.flags.read().ok())
376 .flatten()
377 .unwrap_or(0)
378 + 1;
379 }
380 self.flag_repeats -= 1;
381 Some(())
382 }
383
384 fn advance_points(&mut self) {
385 let x_short = self.cur_flags.contains(SimpleGlyphFlags::X_SHORT_VECTOR);
386 let x_same_or_pos = self
387 .cur_flags
388 .contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR);
389 let y_short = self.cur_flags.contains(SimpleGlyphFlags::Y_SHORT_VECTOR);
390 let y_same_or_pos = self
391 .cur_flags
392 .contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR);
393
394 let delta_x = match (x_short, x_same_or_pos) {
395 (true, false) => -(self.x_coords.read::<u8>().unwrap_or(0) as i16),
396 (true, true) => self.x_coords.read::<u8>().unwrap_or(0) as i16,
397 (false, false) => self.x_coords.read::<i16>().unwrap_or(0),
398 _ => 0,
399 };
400
401 let delta_y = match (y_short, y_same_or_pos) {
402 (true, false) => -(self.y_coords.read::<u8>().unwrap_or(0) as i16),
403 (true, true) => self.y_coords.read::<u8>().unwrap_or(0) as i16,
404 (false, false) => self.y_coords.read::<i16>().unwrap_or(0),
405 _ => 0,
406 };
407
408 self.cur_x = self.cur_x.wrapping_add(delta_x);
409 self.cur_y = self.cur_y.wrapping_add(delta_y);
410 }
411}
412
413fn resolve_coords_len(data: &[u8], points_total: u16) -> Result<FieldLengths, ReadError> {
418 let mut cursor = FontData::new(data).cursor();
419 let mut flags_left = u32::from(points_total);
420 let mut x_coords_len = 0;
422 let mut y_coords_len = 0;
423 while flags_left > 0 {
425 let flags: SimpleGlyphFlags = cursor.read()?;
426
427 let repeats = if flags.contains(SimpleGlyphFlags::REPEAT_FLAG) {
429 let repeats: u8 = cursor.read()?;
430 u32::from(repeats) + 1
431 } else {
432 1
433 };
434
435 if repeats > flags_left {
436 return Err(ReadError::MalformedData("repeat count too large in glyf"));
437 }
438
439 let x_short = SimpleGlyphFlags::X_SHORT_VECTOR;
457 let x_long = SimpleGlyphFlags::X_SHORT_VECTOR
458 | SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR;
459 let y_short = SimpleGlyphFlags::Y_SHORT_VECTOR;
460 let y_long = SimpleGlyphFlags::Y_SHORT_VECTOR
461 | SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR;
462 x_coords_len += ((flags & x_short).bits() != 0) as u32 * repeats;
463 x_coords_len += ((flags & x_long).bits() == 0) as u32 * repeats * 2;
464
465 y_coords_len += ((flags & y_short).bits() != 0) as u32 * repeats;
466 y_coords_len += ((flags & y_long).bits() == 0) as u32 * repeats * 2;
467
468 flags_left -= repeats;
469 }
470
471 Ok(FieldLengths {
472 flags: cursor.position()? as u32,
473 x_coords: x_coords_len,
474 y_coords: y_coords_len,
475 })
476 }
478
479struct FieldLengths {
480 flags: u32,
481 x_coords: u32,
482 y_coords: u32,
483}
484
485#[derive(Clone, Copy, Debug, PartialEq, Eq)]
487pub struct Transform {
488 pub xx: F2Dot14,
490 pub yx: F2Dot14,
492 pub xy: F2Dot14,
494 pub yy: F2Dot14,
496}
497
498impl Default for Transform {
499 fn default() -> Self {
500 Self {
501 xx: F2Dot14::from_f32(1.0),
502 yx: F2Dot14::from_f32(0.0),
503 xy: F2Dot14::from_f32(0.0),
504 yy: F2Dot14::from_f32(1.0),
505 }
506 }
507}
508
509#[derive(Clone, Debug, PartialEq, Eq)]
511pub struct Component {
512 pub flags: CompositeGlyphFlags,
514 pub glyph: GlyphId16,
516 pub anchor: Anchor,
518 pub transform: Transform,
520}
521
522#[derive(Clone, Copy, Debug, PartialEq, Eq)]
524pub enum Anchor {
525 Offset { x: i16, y: i16 },
526 Point { base: u16, component: u16 },
527}
528
529impl<'a> CompositeGlyph<'a> {
530 pub fn components(&self) -> impl Iterator<Item = Component> + 'a + Clone {
532 ComponentIter {
533 cur_flags: CompositeGlyphFlags::empty(),
534 done: false,
535 cursor: FontData::new(self.component_data()).cursor(),
536 }
537 }
538
539 pub fn component_glyphs_and_flags(
542 &self,
543 ) -> impl Iterator<Item = (GlyphId16, CompositeGlyphFlags)> + 'a + Clone {
544 ComponentGlyphIdFlagsIter {
545 cur_flags: CompositeGlyphFlags::empty(),
546 done: false,
547 cursor: FontData::new(self.component_data()).cursor(),
548 }
549 }
550
551 pub fn count_and_instructions(&self) -> (usize, Option<&'a [u8]>) {
554 let mut iter = ComponentGlyphIdFlagsIter {
555 cur_flags: CompositeGlyphFlags::empty(),
556 done: false,
557 cursor: FontData::new(self.component_data()).cursor(),
558 };
559 let mut count = 0;
560 while iter.by_ref().next().is_some() {
561 count += 1;
562 }
563 let instructions = if iter
564 .cur_flags
565 .contains(CompositeGlyphFlags::WE_HAVE_INSTRUCTIONS)
566 {
567 iter.cursor
568 .read::<u16>()
569 .ok()
570 .map(|len| len as usize)
571 .and_then(|len| iter.cursor.read_array(len).ok())
572 } else {
573 None
574 };
575 (count, instructions)
576 }
577
578 pub fn instructions(&self) -> Option<&'a [u8]> {
580 self.count_and_instructions().1
581 }
582}
583
584#[derive(Clone)]
585struct ComponentIter<'a> {
586 cur_flags: CompositeGlyphFlags,
587 done: bool,
588 cursor: Cursor<'a>,
589}
590
591impl Iterator for ComponentIter<'_> {
592 type Item = Component;
593
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::<GlyphId16>().ok()?;
601 let args_are_words = flags.contains(CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS);
602 let args_are_xy_values = flags.contains(CompositeGlyphFlags::ARGS_ARE_XY_VALUES);
603 let anchor = match (args_are_xy_values, args_are_words) {
604 (true, true) => Anchor::Offset {
605 x: self.cursor.read().ok()?,
606 y: self.cursor.read().ok()?,
607 },
608 (true, false) => Anchor::Offset {
609 x: self.cursor.read::<i8>().ok()? as _,
610 y: self.cursor.read::<i8>().ok()? as _,
611 },
612 (false, true) => Anchor::Point {
613 base: self.cursor.read().ok()?,
614 component: self.cursor.read().ok()?,
615 },
616 (false, false) => Anchor::Point {
617 base: self.cursor.read::<u8>().ok()? as _,
618 component: self.cursor.read::<u8>().ok()? as _,
619 },
620 };
621 let mut transform = Transform::default();
622 if flags.contains(CompositeGlyphFlags::WE_HAVE_A_SCALE) {
623 transform.xx = self.cursor.read().ok()?;
624 transform.yy = transform.xx;
625 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
626 transform.xx = self.cursor.read().ok()?;
627 transform.yy = self.cursor.read().ok()?;
628 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO) {
629 transform.xx = self.cursor.read().ok()?;
630 transform.yx = self.cursor.read().ok()?;
631 transform.xy = self.cursor.read().ok()?;
632 transform.yy = self.cursor.read().ok()?;
633 }
634 self.done = !flags.contains(CompositeGlyphFlags::MORE_COMPONENTS);
635
636 Some(Component {
637 flags,
638 glyph,
639 anchor,
640 transform,
641 })
642 }
643}
644
645#[derive(Clone)]
650struct ComponentGlyphIdFlagsIter<'a> {
651 cur_flags: CompositeGlyphFlags,
652 done: bool,
653 cursor: Cursor<'a>,
654}
655
656impl Iterator for ComponentGlyphIdFlagsIter<'_> {
657 type Item = (GlyphId16, CompositeGlyphFlags);
658
659 fn next(&mut self) -> Option<Self::Item> {
660 if self.done {
661 return None;
662 }
663 let flags: CompositeGlyphFlags = self.cursor.read().ok()?;
664 self.cur_flags = flags;
665 let glyph = self.cursor.read::<GlyphId16>().ok()?;
666 let args_are_words = flags.contains(CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS);
667 if args_are_words {
668 self.cursor.advance_by(4);
669 } else {
670 self.cursor.advance_by(2);
671 }
672 if flags.contains(CompositeGlyphFlags::WE_HAVE_A_SCALE) {
673 self.cursor.advance_by(2);
674 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
675 self.cursor.advance_by(4);
676 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO) {
677 self.cursor.advance_by(8);
678 }
679 self.done = !flags.contains(CompositeGlyphFlags::MORE_COMPONENTS);
680 Some((glyph, flags))
681 }
682}
683
684#[cfg(feature = "experimental_traverse")]
685impl<'a> SomeTable<'a> for Component {
686 fn type_name(&self) -> &str {
687 "Component"
688 }
689
690 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
691 match idx {
692 0 => Some(Field::new("flags", self.flags.bits())),
693 1 => Some(Field::new("glyph", self.glyph)),
694 2 => match self.anchor {
695 Anchor::Point { base, .. } => Some(Field::new("base", base)),
696 Anchor::Offset { x, .. } => Some(Field::new("x", x)),
697 },
698 3 => match self.anchor {
699 Anchor::Point { component, .. } => Some(Field::new("component", component)),
700 Anchor::Offset { y, .. } => Some(Field::new("y", y)),
701 },
702 _ => None,
703 }
704 }
705}
706
707impl Anchor {
708 pub fn compute_flags(&self) -> CompositeGlyphFlags {
710 const I8_RANGE: Range<i16> = i8::MIN as i16..i8::MAX as i16 + 1;
711 const U8_MAX: u16 = u8::MAX as u16;
712
713 let mut flags = CompositeGlyphFlags::empty();
714 match self {
715 Anchor::Offset { x, y } => {
716 flags |= CompositeGlyphFlags::ARGS_ARE_XY_VALUES;
717 if !I8_RANGE.contains(x) || !I8_RANGE.contains(y) {
718 flags |= CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS;
719 }
720 }
721 Anchor::Point { base, component } => {
722 if base > &U8_MAX || component > &U8_MAX {
723 flags |= CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS;
724 }
725 }
726 }
727 flags
728 }
729}
730
731impl Transform {
732 pub fn compute_flags(&self) -> CompositeGlyphFlags {
734 if self.yx != F2Dot14::ZERO || self.xy != F2Dot14::ZERO {
735 CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO
736 } else if self.xx != self.yy {
737 CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE
738 } else if self.xx != F2Dot14::ONE {
739 CompositeGlyphFlags::WE_HAVE_A_SCALE
740 } else {
741 CompositeGlyphFlags::empty()
742 }
743 }
744}
745
746impl PointCoord for F26Dot6 {
747 fn from_fixed(x: Fixed) -> Self {
748 x.to_f26dot6()
749 }
750
751 #[inline]
752 fn from_i32(x: i32) -> Self {
753 Self::from_i32(x)
754 }
755
756 #[inline]
757 fn to_f32(self) -> f32 {
758 self.to_f32()
759 }
760
761 #[inline]
762 fn midpoint(self, other: Self) -> Self {
763 Self::from_bits(midpoint_i32(self.to_bits(), other.to_bits()))
766 }
767}
768
769impl PointCoord for Fixed {
770 fn from_fixed(x: Fixed) -> Self {
771 x
772 }
773
774 fn from_i32(x: i32) -> Self {
775 Self::from_i32(x)
776 }
777
778 fn to_f32(self) -> f32 {
779 self.to_f32()
780 }
781
782 fn midpoint(self, other: Self) -> Self {
783 Self::from_bits(midpoint_i32(self.to_bits(), other.to_bits()))
784 }
785}
786
787impl PointCoord for i32 {
788 fn from_fixed(x: Fixed) -> Self {
789 x.to_i32()
790 }
791
792 fn from_i32(x: i32) -> Self {
793 x
794 }
795
796 fn to_f32(self) -> f32 {
797 self as f32
798 }
799
800 fn midpoint(self, other: Self) -> Self {
801 midpoint_i32(self, other)
802 }
803}
804
805#[inline(always)]
807fn midpoint_i32(a: i32, b: i32) -> i32 {
808 a.wrapping_add(b) / 2
814}
815
816impl PointCoord for f32 {
817 fn from_fixed(x: Fixed) -> Self {
818 x.to_f32()
819 }
820
821 fn from_i32(x: i32) -> Self {
822 x as f32
823 }
824
825 fn to_f32(self) -> f32 {
826 self
827 }
828
829 fn midpoint(self, other: Self) -> Self {
830 self + 0.5 * (other - self)
833 }
834}
835
836#[cfg(test)]
837mod tests {
838 use super::*;
839 use crate::{FontRef, GlyphId, TableProvider};
840
841 #[test]
842 fn simple_glyph() {
843 let font = FontRef::new(font_test_data::COLR_GRADIENT_RECT).unwrap();
844 let loca = font.loca(None).unwrap();
845 let glyf = font.glyf().unwrap();
846 let glyph = loca.get_glyf(GlyphId::new(0), &glyf).unwrap().unwrap();
847 assert_eq!(glyph.number_of_contours(), 2);
848 let simple_glyph = if let Glyph::Simple(simple) = glyph {
849 simple
850 } else {
851 panic!("expected simple glyph");
852 };
853 assert_eq!(
854 simple_glyph
855 .end_pts_of_contours()
856 .iter()
857 .map(|x| x.get())
858 .collect::<Vec<_>>(),
859 &[3, 7]
860 );
861 assert_eq!(
862 simple_glyph
863 .points()
864 .map(|pt| (pt.x, pt.y, pt.on_curve))
865 .collect::<Vec<_>>(),
866 &[
867 (5, 0, true),
868 (5, 100, true),
869 (45, 100, true),
870 (45, 0, true),
871 (10, 5, true),
872 (40, 5, true),
873 (40, 95, true),
874 (10, 95, true),
875 ]
876 );
877 }
878
879 fn all_glyphs(font_data: &[u8]) -> impl Iterator<Item = Option<Glyph>> {
881 let font = FontRef::new(font_data).unwrap();
882 let loca = font.loca(None).unwrap();
883 let glyf = font.glyf().unwrap();
884 let glyph_count = font.maxp().unwrap().num_glyphs() as u32;
885 (0..glyph_count).map(move |gid| loca.get_glyf(GlyphId::new(gid), &glyf).unwrap())
886 }
887
888 #[test]
889 fn simple_glyph_overlapping_contour_flag() {
890 let gids_with_overlap: Vec<_> = all_glyphs(font_test_data::VAZIRMATN_VAR)
891 .enumerate()
892 .filter_map(|(gid, glyph)| match glyph {
893 Some(Glyph::Simple(glyph)) if glyph.has_overlapping_contours() => Some(gid),
894 _ => None,
895 })
896 .collect();
897 let expected_gids_with_overlap = vec![3];
899 assert_eq!(expected_gids_with_overlap, gids_with_overlap);
900 }
901
902 #[test]
903 fn composite_glyph_overlapping_contour_flag() {
904 let gids_components_with_overlap: Vec<_> = all_glyphs(font_test_data::VAZIRMATN_VAR)
905 .enumerate()
906 .filter_map(|(gid, glyph)| match glyph {
907 Some(Glyph::Composite(glyph)) => Some((gid, glyph)),
908 _ => None,
909 })
910 .flat_map(|(gid, glyph)| {
911 glyph
912 .components()
913 .enumerate()
914 .filter_map(move |(comp_ix, comp)| {
915 comp.flags
916 .contains(CompositeGlyphFlags::OVERLAP_COMPOUND)
917 .then_some((gid, comp_ix))
918 })
919 })
920 .collect();
921 let expected_gids_components_with_overlap = vec![(2, 1)];
923 assert_eq!(
924 expected_gids_components_with_overlap,
925 gids_components_with_overlap
926 );
927 }
928
929 #[test]
930 fn compute_anchor_flags() {
931 let anchor = Anchor::Offset { x: -128, y: 127 };
932 assert_eq!(
933 anchor.compute_flags(),
934 CompositeGlyphFlags::ARGS_ARE_XY_VALUES
935 );
936
937 let anchor = Anchor::Offset { x: -129, y: 127 };
938 assert_eq!(
939 anchor.compute_flags(),
940 CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
941 );
942 let anchor = Anchor::Offset { x: -1, y: 128 };
943 assert_eq!(
944 anchor.compute_flags(),
945 CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
946 );
947
948 let anchor = Anchor::Point {
949 base: 255,
950 component: 20,
951 };
952 assert_eq!(anchor.compute_flags(), CompositeGlyphFlags::empty());
953
954 let anchor = Anchor::Point {
955 base: 256,
956 component: 20,
957 };
958 assert_eq!(
959 anchor.compute_flags(),
960 CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
961 )
962 }
963
964 #[test]
965 fn compute_transform_flags() {
966 fn make_xform(xx: f32, yx: f32, xy: f32, yy: f32) -> Transform {
967 Transform {
968 xx: F2Dot14::from_f32(xx),
969 yx: F2Dot14::from_f32(yx),
970 xy: F2Dot14::from_f32(xy),
971 yy: F2Dot14::from_f32(yy),
972 }
973 }
974
975 assert_eq!(
976 make_xform(1.0, 0., 0., 1.0).compute_flags(),
977 CompositeGlyphFlags::empty()
978 );
979 assert_eq!(
980 make_xform(2.0, 0., 0., 2.0).compute_flags(),
981 CompositeGlyphFlags::WE_HAVE_A_SCALE
982 );
983 assert_eq!(
984 make_xform(2.0, 0., 0., 1.0).compute_flags(),
985 CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE
986 );
987 assert_eq!(
988 make_xform(2.0, 0., 1.0, 1.0).compute_flags(),
989 CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO
990 );
991 }
992
993 #[test]
994 fn point_flags_and_marker_bits() {
995 let bits = [
996 PointFlags::OFF_CURVE_CUBIC,
997 PointFlags::ON_CURVE,
998 PointMarker::HAS_DELTA.0,
999 PointMarker::TOUCHED_X.0,
1000 PointMarker::TOUCHED_Y.0,
1001 ];
1002 for (i, a) in bits.iter().enumerate() {
1004 for b in &bits[i + 1..] {
1005 assert_eq!(a & b, 0);
1006 }
1007 }
1008 }
1009
1010 #[test]
1011 fn cubic_glyf() {
1012 let font = FontRef::new(font_test_data::CUBIC_GLYF).unwrap();
1013 let loca = font.loca(None).unwrap();
1014 let glyf = font.glyf().unwrap();
1015 let glyph = loca.get_glyf(GlyphId::new(2), &glyf).unwrap().unwrap();
1016 assert_eq!(glyph.number_of_contours(), 1);
1017 let simple_glyph = if let Glyph::Simple(simple) = glyph {
1018 simple
1019 } else {
1020 panic!("expected simple glyph");
1021 };
1022 assert_eq!(
1023 simple_glyph
1024 .points()
1025 .map(|pt| (pt.x, pt.y, pt.on_curve))
1026 .collect::<Vec<_>>(),
1027 &[
1028 (278, 710, true),
1029 (278, 470, true),
1030 (300, 500, false),
1031 (800, 500, false),
1032 (998, 470, true),
1033 (998, 710, true),
1034 ]
1035 );
1036 }
1037
1038 #[test]
1042 fn avoid_midpoint_overflow() {
1043 let a = F26Dot6::from_bits(1084092352);
1044 let b = F26Dot6::from_bits(1085243712);
1045 let expected = (a + b).to_bits() / 2;
1046 let midpoint = a.midpoint(b);
1048 assert_eq!(midpoint.to_bits(), expected);
1049 }
1050}