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 flags_data = cursor.read_array::<u8>(n_points.min(cursor.remaining_bytes()))?;
224 let mut flags_iter = flags_data.iter().copied();
225 let mut read_flags_bytes = 0;
228 let mut i = 0;
229 while let Some(flag_bits) = flags_iter.next() {
230 read_flags_bytes += 1;
231 if SimpleGlyphFlags::from_bits_truncate(flag_bits)
232 .contains(SimpleGlyphFlags::REPEAT_FLAG)
233 {
234 let count = (flags_iter.next().ok_or(ReadError::OutOfBounds)? as usize + 1)
235 .min(n_points - i);
236 read_flags_bytes += 1;
237 for f in &mut flags[i..i + count] {
238 f.0 = flag_bits;
239 }
240 i += count;
241 } else {
242 flags[i].0 = flag_bits;
243 i += 1;
244 }
245 if i == n_points {
246 break;
247 }
248 }
249 let mut cursor = FontData::new(self.glyph_data()).cursor();
250 cursor.advance_by(read_flags_bytes);
251 let mut x = 0i32;
252 for (&point_flags, point) in flags.iter().zip(points.as_mut()) {
253 let mut delta = 0i32;
254 let flag = SimpleGlyphFlags::from_bits_truncate(point_flags.0);
255 if flag.contains(SimpleGlyphFlags::X_SHORT_VECTOR) {
256 delta = cursor.read::<u8>()? as i32;
257 if !flag.contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
258 delta = -delta;
259 }
260 } else if !flag.contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
261 delta = cursor.read::<i16>()? as i32;
262 }
263 x = x.wrapping_add(delta);
264 point.x = C::from_i32(x);
265 }
266 let mut y = 0i32;
267 for (point_flags, point) in flags.iter_mut().zip(points.as_mut()) {
268 let mut delta = 0i32;
269 let flag = SimpleGlyphFlags::from_bits_truncate(point_flags.0);
270 if flag.contains(SimpleGlyphFlags::Y_SHORT_VECTOR) {
271 delta = cursor.read::<u8>()? as i32;
272 if !flag.contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
273 delta = -delta;
274 }
275 } else if !flag.contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
276 delta = cursor.read::<i16>()? as i32;
277 }
278 y = y.wrapping_add(delta);
279 point.y = C::from_i32(y);
280 let flags_mask = if cfg!(feature = "spec_next") {
281 PointFlags::CURVE_MASK
282 } else {
283 PointFlags::ON_CURVE
285 };
286 point_flags.0 &= flags_mask;
287 }
288 Ok(())
289 }
290
291 pub fn points(&self) -> impl Iterator<Item = CurvePoint> + 'a + Clone {
298 self.points_impl()
299 .unwrap_or_else(|| PointIter::new(&[], &[], &[]))
300 }
301
302 fn points_impl(&self) -> Option<PointIter<'a>> {
303 let end_points = self.end_pts_of_contours();
304 let n_points = end_points.last()?.get().checked_add(1)?;
305 let data = self.glyph_data();
306 let lens = resolve_coords_len(data, n_points).ok()?;
307 let total_len = lens.flags + lens.x_coords + lens.y_coords;
308 if data.len() < total_len as usize {
309 return None;
310 }
311
312 let (flags, data) = data.split_at(lens.flags as usize);
313 let (x_coords, y_coords) = data.split_at(lens.x_coords as usize);
314
315 Some(PointIter::new(flags, x_coords, y_coords))
316 }
317}
318
319#[derive(Clone, Copy, Debug, PartialEq, Eq)]
323pub struct CurvePoint {
324 pub x: i16,
326 pub y: i16,
328 pub on_curve: bool,
330}
331
332impl CurvePoint {
333 pub fn new(x: i16, y: i16, on_curve: bool) -> Self {
335 Self { x, y, on_curve }
336 }
337
338 pub fn on_curve(x: i16, y: i16) -> Self {
340 Self::new(x, y, true)
341 }
342
343 pub fn off_curve(x: i16, y: i16) -> Self {
345 Self::new(x, y, false)
346 }
347}
348
349#[derive(Clone)]
350struct PointIter<'a> {
351 flags: Cursor<'a>,
352 x_coords: Cursor<'a>,
353 y_coords: Cursor<'a>,
354 flag_repeats: u8,
355 cur_flags: SimpleGlyphFlags,
356 cur_x: i16,
357 cur_y: i16,
358}
359
360impl Iterator for PointIter<'_> {
361 type Item = CurvePoint;
362 fn next(&mut self) -> Option<Self::Item> {
363 self.advance_flags()?;
364 self.advance_points();
365 let is_on_curve = self.cur_flags.contains(SimpleGlyphFlags::ON_CURVE_POINT);
366 Some(CurvePoint::new(self.cur_x, self.cur_y, is_on_curve))
367 }
368}
369
370impl<'a> PointIter<'a> {
371 fn new(flags: &'a [u8], x_coords: &'a [u8], y_coords: &'a [u8]) -> Self {
372 Self {
373 flags: FontData::new(flags).cursor(),
374 x_coords: FontData::new(x_coords).cursor(),
375 y_coords: FontData::new(y_coords).cursor(),
376 flag_repeats: 0,
377 cur_flags: SimpleGlyphFlags::empty(),
378 cur_x: 0,
379 cur_y: 0,
380 }
381 }
382
383 fn advance_flags(&mut self) -> Option<()> {
384 if self.flag_repeats == 0 {
385 self.cur_flags = SimpleGlyphFlags::from_bits_truncate(self.flags.read().ok()?);
386 self.flag_repeats = self
387 .cur_flags
388 .contains(SimpleGlyphFlags::REPEAT_FLAG)
389 .then(|| self.flags.read().ok())
390 .flatten()
391 .unwrap_or(0)
392 + 1;
393 }
394 self.flag_repeats -= 1;
395 Some(())
396 }
397
398 fn advance_points(&mut self) {
399 let x_short = self.cur_flags.contains(SimpleGlyphFlags::X_SHORT_VECTOR);
400 let x_same_or_pos = self
401 .cur_flags
402 .contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR);
403 let y_short = self.cur_flags.contains(SimpleGlyphFlags::Y_SHORT_VECTOR);
404 let y_same_or_pos = self
405 .cur_flags
406 .contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR);
407
408 let delta_x = match (x_short, x_same_or_pos) {
409 (true, false) => -(self.x_coords.read::<u8>().unwrap_or(0) as i16),
410 (true, true) => self.x_coords.read::<u8>().unwrap_or(0) as i16,
411 (false, false) => self.x_coords.read::<i16>().unwrap_or(0),
412 _ => 0,
413 };
414
415 let delta_y = match (y_short, y_same_or_pos) {
416 (true, false) => -(self.y_coords.read::<u8>().unwrap_or(0) as i16),
417 (true, true) => self.y_coords.read::<u8>().unwrap_or(0) as i16,
418 (false, false) => self.y_coords.read::<i16>().unwrap_or(0),
419 _ => 0,
420 };
421
422 self.cur_x = self.cur_x.wrapping_add(delta_x);
423 self.cur_y = self.cur_y.wrapping_add(delta_y);
424 }
425}
426
427fn resolve_coords_len(data: &[u8], points_total: u16) -> Result<FieldLengths, ReadError> {
432 let mut cursor = FontData::new(data).cursor();
433 let mut flags_left = u32::from(points_total);
434 let mut x_coords_len = 0;
436 let mut y_coords_len = 0;
437 while flags_left > 0 {
439 let flags: SimpleGlyphFlags = cursor.read()?;
440
441 let repeats = if flags.contains(SimpleGlyphFlags::REPEAT_FLAG) {
443 let repeats: u8 = cursor.read()?;
444 u32::from(repeats) + 1
445 } else {
446 1
447 };
448
449 if repeats > flags_left {
450 return Err(ReadError::MalformedData("repeat count too large in glyf"));
451 }
452
453 let x_short = SimpleGlyphFlags::X_SHORT_VECTOR;
471 let x_long = SimpleGlyphFlags::X_SHORT_VECTOR
472 | SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR;
473 let y_short = SimpleGlyphFlags::Y_SHORT_VECTOR;
474 let y_long = SimpleGlyphFlags::Y_SHORT_VECTOR
475 | SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR;
476 x_coords_len += ((flags & x_short).bits() != 0) as u32 * repeats;
477 x_coords_len += ((flags & x_long).bits() == 0) as u32 * repeats * 2;
478
479 y_coords_len += ((flags & y_short).bits() != 0) as u32 * repeats;
480 y_coords_len += ((flags & y_long).bits() == 0) as u32 * repeats * 2;
481
482 flags_left -= repeats;
483 }
484
485 Ok(FieldLengths {
486 flags: cursor.position()? as u32,
487 x_coords: x_coords_len,
488 y_coords: y_coords_len,
489 })
490 }
492
493struct FieldLengths {
494 flags: u32,
495 x_coords: u32,
496 y_coords: u32,
497}
498
499#[derive(Clone, Copy, Debug, PartialEq, Eq)]
501pub struct Transform {
502 pub xx: F2Dot14,
504 pub yx: F2Dot14,
506 pub xy: F2Dot14,
508 pub yy: F2Dot14,
510}
511
512impl Default for Transform {
513 fn default() -> Self {
514 Self {
515 xx: F2Dot14::from_f32(1.0),
516 yx: F2Dot14::from_f32(0.0),
517 xy: F2Dot14::from_f32(0.0),
518 yy: F2Dot14::from_f32(1.0),
519 }
520 }
521}
522
523#[derive(Clone, Debug, PartialEq, Eq)]
525pub struct Component {
526 pub flags: CompositeGlyphFlags,
528 pub glyph: GlyphId16,
530 pub anchor: Anchor,
532 pub transform: Transform,
534}
535
536#[derive(Clone, Copy, Debug, PartialEq, Eq)]
538pub enum Anchor {
539 Offset { x: i16, y: i16 },
540 Point { base: u16, component: u16 },
541}
542
543impl<'a> CompositeGlyph<'a> {
544 pub fn components(&self) -> impl Iterator<Item = Component> + 'a + Clone {
546 ComponentIter {
547 cur_flags: CompositeGlyphFlags::empty(),
548 done: false,
549 cursor: FontData::new(self.component_data()).cursor(),
550 }
551 }
552
553 pub fn component_glyphs_and_flags(
556 &self,
557 ) -> impl Iterator<Item = (GlyphId16, CompositeGlyphFlags)> + 'a + Clone {
558 ComponentGlyphIdFlagsIter {
559 cur_flags: CompositeGlyphFlags::empty(),
560 done: false,
561 cursor: FontData::new(self.component_data()).cursor(),
562 }
563 }
564
565 pub fn count_and_instructions(&self) -> (usize, Option<&'a [u8]>) {
568 let mut iter = ComponentGlyphIdFlagsIter {
569 cur_flags: CompositeGlyphFlags::empty(),
570 done: false,
571 cursor: FontData::new(self.component_data()).cursor(),
572 };
573 let mut count = 0;
574 while iter.by_ref().next().is_some() {
575 count += 1;
576 }
577 let instructions = if iter
578 .cur_flags
579 .contains(CompositeGlyphFlags::WE_HAVE_INSTRUCTIONS)
580 {
581 iter.cursor
582 .read::<u16>()
583 .ok()
584 .map(|len| len as usize)
585 .and_then(|len| iter.cursor.read_array(len).ok())
586 } else {
587 None
588 };
589 (count, instructions)
590 }
591
592 pub fn instructions(&self) -> Option<&'a [u8]> {
594 self.count_and_instructions().1
595 }
596}
597
598#[derive(Clone)]
599struct ComponentIter<'a> {
600 cur_flags: CompositeGlyphFlags,
601 done: bool,
602 cursor: Cursor<'a>,
603}
604
605impl Iterator for ComponentIter<'_> {
606 type Item = Component;
607
608 fn next(&mut self) -> Option<Self::Item> {
609 if self.done {
610 return None;
611 }
612 let flags: CompositeGlyphFlags = self.cursor.read().ok()?;
613 self.cur_flags = flags;
614 let glyph = self.cursor.read::<GlyphId16>().ok()?;
615 let args_are_words = flags.contains(CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS);
616 let args_are_xy_values = flags.contains(CompositeGlyphFlags::ARGS_ARE_XY_VALUES);
617 let anchor = match (args_are_xy_values, args_are_words) {
618 (true, true) => Anchor::Offset {
619 x: self.cursor.read().ok()?,
620 y: self.cursor.read().ok()?,
621 },
622 (true, false) => Anchor::Offset {
623 x: self.cursor.read::<i8>().ok()? as _,
624 y: self.cursor.read::<i8>().ok()? as _,
625 },
626 (false, true) => Anchor::Point {
627 base: self.cursor.read().ok()?,
628 component: self.cursor.read().ok()?,
629 },
630 (false, false) => Anchor::Point {
631 base: self.cursor.read::<u8>().ok()? as _,
632 component: self.cursor.read::<u8>().ok()? as _,
633 },
634 };
635 let mut transform = Transform::default();
636 if flags.contains(CompositeGlyphFlags::WE_HAVE_A_SCALE) {
637 transform.xx = self.cursor.read().ok()?;
638 transform.yy = transform.xx;
639 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
640 transform.xx = self.cursor.read().ok()?;
641 transform.yy = self.cursor.read().ok()?;
642 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO) {
643 transform.xx = self.cursor.read().ok()?;
644 transform.yx = self.cursor.read().ok()?;
645 transform.xy = self.cursor.read().ok()?;
646 transform.yy = self.cursor.read().ok()?;
647 }
648 self.done = !flags.contains(CompositeGlyphFlags::MORE_COMPONENTS);
649
650 Some(Component {
651 flags,
652 glyph,
653 anchor,
654 transform,
655 })
656 }
657}
658
659#[derive(Clone)]
664struct ComponentGlyphIdFlagsIter<'a> {
665 cur_flags: CompositeGlyphFlags,
666 done: bool,
667 cursor: Cursor<'a>,
668}
669
670impl Iterator for ComponentGlyphIdFlagsIter<'_> {
671 type Item = (GlyphId16, CompositeGlyphFlags);
672
673 fn next(&mut self) -> Option<Self::Item> {
674 if self.done {
675 return None;
676 }
677 let flags: CompositeGlyphFlags = self.cursor.read().ok()?;
678 self.cur_flags = flags;
679 let glyph = self.cursor.read::<GlyphId16>().ok()?;
680 let args_are_words = flags.contains(CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS);
681 if args_are_words {
682 self.cursor.advance_by(4);
683 } else {
684 self.cursor.advance_by(2);
685 }
686 if flags.contains(CompositeGlyphFlags::WE_HAVE_A_SCALE) {
687 self.cursor.advance_by(2);
688 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
689 self.cursor.advance_by(4);
690 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO) {
691 self.cursor.advance_by(8);
692 }
693 self.done = !flags.contains(CompositeGlyphFlags::MORE_COMPONENTS);
694 Some((glyph, flags))
695 }
696}
697
698#[cfg(feature = "experimental_traverse")]
699impl<'a> SomeTable<'a> for Component {
700 fn type_name(&self) -> &str {
701 "Component"
702 }
703
704 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
705 match idx {
706 0 => Some(Field::new("flags", self.flags.bits())),
707 1 => Some(Field::new("glyph", self.glyph)),
708 2 => match self.anchor {
709 Anchor::Point { base, .. } => Some(Field::new("base", base)),
710 Anchor::Offset { x, .. } => Some(Field::new("x", x)),
711 },
712 3 => match self.anchor {
713 Anchor::Point { component, .. } => Some(Field::new("component", component)),
714 Anchor::Offset { y, .. } => Some(Field::new("y", y)),
715 },
716 _ => None,
717 }
718 }
719}
720
721impl Anchor {
722 pub fn compute_flags(&self) -> CompositeGlyphFlags {
724 const I8_RANGE: Range<i16> = i8::MIN as i16..i8::MAX as i16 + 1;
725 const U8_MAX: u16 = u8::MAX as u16;
726
727 let mut flags = CompositeGlyphFlags::empty();
728 match self {
729 Anchor::Offset { x, y } => {
730 flags |= CompositeGlyphFlags::ARGS_ARE_XY_VALUES;
731 if !I8_RANGE.contains(x) || !I8_RANGE.contains(y) {
732 flags |= CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS;
733 }
734 }
735 Anchor::Point { base, component } => {
736 if base > &U8_MAX || component > &U8_MAX {
737 flags |= CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS;
738 }
739 }
740 }
741 flags
742 }
743}
744
745impl Transform {
746 pub fn compute_flags(&self) -> CompositeGlyphFlags {
748 if self.yx != F2Dot14::ZERO || self.xy != F2Dot14::ZERO {
749 CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO
750 } else if self.xx != self.yy {
751 CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE
752 } else if self.xx != F2Dot14::ONE {
753 CompositeGlyphFlags::WE_HAVE_A_SCALE
754 } else {
755 CompositeGlyphFlags::empty()
756 }
757 }
758}
759
760impl PointCoord for F26Dot6 {
761 fn from_fixed(x: Fixed) -> Self {
762 x.to_f26dot6()
763 }
764
765 #[inline]
766 fn from_i32(x: i32) -> Self {
767 Self::from_i32(x)
768 }
769
770 #[inline]
771 fn to_f32(self) -> f32 {
772 self.to_f32()
773 }
774
775 #[inline]
776 fn midpoint(self, other: Self) -> Self {
777 Self::from_bits(midpoint_i32(self.to_bits(), other.to_bits()))
780 }
781}
782
783impl PointCoord for Fixed {
784 fn from_fixed(x: Fixed) -> Self {
785 x
786 }
787
788 fn from_i32(x: i32) -> Self {
789 Self::from_i32(x)
790 }
791
792 fn to_f32(self) -> f32 {
793 self.to_f32()
794 }
795
796 fn midpoint(self, other: Self) -> Self {
797 Self::from_bits(midpoint_i32(self.to_bits(), other.to_bits()))
798 }
799}
800
801impl PointCoord for i32 {
802 fn from_fixed(x: Fixed) -> Self {
803 x.to_i32()
804 }
805
806 fn from_i32(x: i32) -> Self {
807 x
808 }
809
810 fn to_f32(self) -> f32 {
811 self as f32
812 }
813
814 fn midpoint(self, other: Self) -> Self {
815 midpoint_i32(self, other)
816 }
817}
818
819#[inline(always)]
821fn midpoint_i32(a: i32, b: i32) -> i32 {
822 a.wrapping_add(b) / 2
828}
829
830impl PointCoord for f32 {
831 fn from_fixed(x: Fixed) -> Self {
832 x.to_f32()
833 }
834
835 fn from_i32(x: i32) -> Self {
836 x as f32
837 }
838
839 fn to_f32(self) -> f32 {
840 self
841 }
842
843 fn midpoint(self, other: Self) -> Self {
844 self + 0.5 * (other - self)
847 }
848}
849
850#[cfg(test)]
851mod tests {
852 use super::*;
853 use crate::{FontRef, GlyphId, TableProvider};
854
855 #[test]
856 fn simple_glyph() {
857 let font = FontRef::new(font_test_data::COLR_GRADIENT_RECT).unwrap();
858 let loca = font.loca(None).unwrap();
859 let glyf = font.glyf().unwrap();
860 let glyph = loca.get_glyf(GlyphId::new(0), &glyf).unwrap().unwrap();
861 assert_eq!(glyph.number_of_contours(), 2);
862 let simple_glyph = if let Glyph::Simple(simple) = glyph {
863 simple
864 } else {
865 panic!("expected simple glyph");
866 };
867 assert_eq!(
868 simple_glyph
869 .end_pts_of_contours()
870 .iter()
871 .map(|x| x.get())
872 .collect::<Vec<_>>(),
873 &[3, 7]
874 );
875 assert_eq!(
876 simple_glyph
877 .points()
878 .map(|pt| (pt.x, pt.y, pt.on_curve))
879 .collect::<Vec<_>>(),
880 &[
881 (5, 0, true),
882 (5, 100, true),
883 (45, 100, true),
884 (45, 0, true),
885 (10, 5, true),
886 (40, 5, true),
887 (40, 95, true),
888 (10, 95, true),
889 ]
890 );
891 }
892
893 fn all_glyphs(font_data: &[u8]) -> impl Iterator<Item = Option<Glyph>> {
895 let font = FontRef::new(font_data).unwrap();
896 let loca = font.loca(None).unwrap();
897 let glyf = font.glyf().unwrap();
898 let glyph_count = font.maxp().unwrap().num_glyphs() as u32;
899 (0..glyph_count).map(move |gid| loca.get_glyf(GlyphId::new(gid), &glyf).unwrap())
900 }
901
902 #[test]
903 fn simple_glyph_overlapping_contour_flag() {
904 let gids_with_overlap: Vec<_> = all_glyphs(font_test_data::VAZIRMATN_VAR)
905 .enumerate()
906 .filter_map(|(gid, glyph)| match glyph {
907 Some(Glyph::Simple(glyph)) if glyph.has_overlapping_contours() => Some(gid),
908 _ => None,
909 })
910 .collect();
911 let expected_gids_with_overlap = vec![3];
913 assert_eq!(expected_gids_with_overlap, gids_with_overlap);
914 }
915
916 #[test]
917 fn composite_glyph_overlapping_contour_flag() {
918 let gids_components_with_overlap: Vec<_> = all_glyphs(font_test_data::VAZIRMATN_VAR)
919 .enumerate()
920 .filter_map(|(gid, glyph)| match glyph {
921 Some(Glyph::Composite(glyph)) => Some((gid, glyph)),
922 _ => None,
923 })
924 .flat_map(|(gid, glyph)| {
925 glyph
926 .components()
927 .enumerate()
928 .filter_map(move |(comp_ix, comp)| {
929 comp.flags
930 .contains(CompositeGlyphFlags::OVERLAP_COMPOUND)
931 .then_some((gid, comp_ix))
932 })
933 })
934 .collect();
935 let expected_gids_components_with_overlap = vec![(2, 1)];
937 assert_eq!(
938 expected_gids_components_with_overlap,
939 gids_components_with_overlap
940 );
941 }
942
943 #[test]
944 fn compute_anchor_flags() {
945 let anchor = Anchor::Offset { x: -128, y: 127 };
946 assert_eq!(
947 anchor.compute_flags(),
948 CompositeGlyphFlags::ARGS_ARE_XY_VALUES
949 );
950
951 let anchor = Anchor::Offset { x: -129, y: 127 };
952 assert_eq!(
953 anchor.compute_flags(),
954 CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
955 );
956 let anchor = Anchor::Offset { x: -1, y: 128 };
957 assert_eq!(
958 anchor.compute_flags(),
959 CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
960 );
961
962 let anchor = Anchor::Point {
963 base: 255,
964 component: 20,
965 };
966 assert_eq!(anchor.compute_flags(), CompositeGlyphFlags::empty());
967
968 let anchor = Anchor::Point {
969 base: 256,
970 component: 20,
971 };
972 assert_eq!(
973 anchor.compute_flags(),
974 CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
975 )
976 }
977
978 #[test]
979 fn compute_transform_flags() {
980 fn make_xform(xx: f32, yx: f32, xy: f32, yy: f32) -> Transform {
981 Transform {
982 xx: F2Dot14::from_f32(xx),
983 yx: F2Dot14::from_f32(yx),
984 xy: F2Dot14::from_f32(xy),
985 yy: F2Dot14::from_f32(yy),
986 }
987 }
988
989 assert_eq!(
990 make_xform(1.0, 0., 0., 1.0).compute_flags(),
991 CompositeGlyphFlags::empty()
992 );
993 assert_eq!(
994 make_xform(2.0, 0., 0., 2.0).compute_flags(),
995 CompositeGlyphFlags::WE_HAVE_A_SCALE
996 );
997 assert_eq!(
998 make_xform(2.0, 0., 0., 1.0).compute_flags(),
999 CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE
1000 );
1001 assert_eq!(
1002 make_xform(2.0, 0., 1.0, 1.0).compute_flags(),
1003 CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO
1004 );
1005 }
1006
1007 #[test]
1008 fn point_flags_and_marker_bits() {
1009 let bits = [
1010 PointFlags::OFF_CURVE_CUBIC,
1011 PointFlags::ON_CURVE,
1012 PointMarker::HAS_DELTA.0,
1013 PointMarker::TOUCHED_X.0,
1014 PointMarker::TOUCHED_Y.0,
1015 ];
1016 for (i, a) in bits.iter().enumerate() {
1018 for b in &bits[i + 1..] {
1019 assert_eq!(a & b, 0);
1020 }
1021 }
1022 }
1023
1024 #[test]
1025 fn cubic_glyf() {
1026 let font = FontRef::new(font_test_data::CUBIC_GLYF).unwrap();
1027 let loca = font.loca(None).unwrap();
1028 let glyf = font.glyf().unwrap();
1029 let glyph = loca.get_glyf(GlyphId::new(2), &glyf).unwrap().unwrap();
1030 assert_eq!(glyph.number_of_contours(), 1);
1031 let simple_glyph = if let Glyph::Simple(simple) = glyph {
1032 simple
1033 } else {
1034 panic!("expected simple glyph");
1035 };
1036 assert_eq!(
1037 simple_glyph
1038 .points()
1039 .map(|pt| (pt.x, pt.y, pt.on_curve))
1040 .collect::<Vec<_>>(),
1041 &[
1042 (278, 710, true),
1043 (278, 470, true),
1044 (300, 500, false),
1045 (800, 500, false),
1046 (998, 470, true),
1047 (998, 710, true),
1048 ]
1049 );
1050 }
1051
1052 #[test]
1056 fn avoid_midpoint_overflow() {
1057 let a = F26Dot6::from_bits(1084092352);
1058 let b = F26Dot6::from_bits(1085243712);
1059 let expected = (a + b).to_bits() / 2;
1060 let midpoint = a.midpoint(b);
1062 assert_eq!(midpoint.to_bits(), expected);
1063 }
1064}