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(fontcull_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(fontcull_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<_> =
919 all_glyphs(fontcull_font_test_data::VAZIRMATN_VAR)
920 .enumerate()
921 .filter_map(|(gid, glyph)| match glyph {
922 Some(Glyph::Composite(glyph)) => Some((gid, glyph)),
923 _ => None,
924 })
925 .flat_map(|(gid, glyph)| {
926 glyph
927 .components()
928 .enumerate()
929 .filter_map(move |(comp_ix, comp)| {
930 comp.flags
931 .contains(CompositeGlyphFlags::OVERLAP_COMPOUND)
932 .then_some((gid, comp_ix))
933 })
934 })
935 .collect();
936 let expected_gids_components_with_overlap = vec![(2, 1)];
938 assert_eq!(
939 expected_gids_components_with_overlap,
940 gids_components_with_overlap
941 );
942 }
943
944 #[test]
945 fn compute_anchor_flags() {
946 let anchor = Anchor::Offset { x: -128, y: 127 };
947 assert_eq!(
948 anchor.compute_flags(),
949 CompositeGlyphFlags::ARGS_ARE_XY_VALUES
950 );
951
952 let anchor = Anchor::Offset { x: -129, y: 127 };
953 assert_eq!(
954 anchor.compute_flags(),
955 CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
956 );
957 let anchor = Anchor::Offset { x: -1, y: 128 };
958 assert_eq!(
959 anchor.compute_flags(),
960 CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
961 );
962
963 let anchor = Anchor::Point {
964 base: 255,
965 component: 20,
966 };
967 assert_eq!(anchor.compute_flags(), CompositeGlyphFlags::empty());
968
969 let anchor = Anchor::Point {
970 base: 256,
971 component: 20,
972 };
973 assert_eq!(
974 anchor.compute_flags(),
975 CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
976 )
977 }
978
979 #[test]
980 fn compute_transform_flags() {
981 fn make_xform(xx: f32, yx: f32, xy: f32, yy: f32) -> Transform {
982 Transform {
983 xx: F2Dot14::from_f32(xx),
984 yx: F2Dot14::from_f32(yx),
985 xy: F2Dot14::from_f32(xy),
986 yy: F2Dot14::from_f32(yy),
987 }
988 }
989
990 assert_eq!(
991 make_xform(1.0, 0., 0., 1.0).compute_flags(),
992 CompositeGlyphFlags::empty()
993 );
994 assert_eq!(
995 make_xform(2.0, 0., 0., 2.0).compute_flags(),
996 CompositeGlyphFlags::WE_HAVE_A_SCALE
997 );
998 assert_eq!(
999 make_xform(2.0, 0., 0., 1.0).compute_flags(),
1000 CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE
1001 );
1002 assert_eq!(
1003 make_xform(2.0, 0., 1.0, 1.0).compute_flags(),
1004 CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO
1005 );
1006 }
1007
1008 #[test]
1009 fn point_flags_and_marker_bits() {
1010 let bits = [
1011 PointFlags::OFF_CURVE_CUBIC,
1012 PointFlags::ON_CURVE,
1013 PointMarker::HAS_DELTA.0,
1014 PointMarker::TOUCHED_X.0,
1015 PointMarker::TOUCHED_Y.0,
1016 ];
1017 for (i, a) in bits.iter().enumerate() {
1019 for b in &bits[i + 1..] {
1020 assert_eq!(a & b, 0);
1021 }
1022 }
1023 }
1024
1025 #[test]
1026 fn cubic_glyf() {
1027 let font = FontRef::new(fontcull_font_test_data::CUBIC_GLYF).unwrap();
1028 let loca = font.loca(None).unwrap();
1029 let glyf = font.glyf().unwrap();
1030 let glyph = loca.get_glyf(GlyphId::new(2), &glyf).unwrap().unwrap();
1031 assert_eq!(glyph.number_of_contours(), 1);
1032 let simple_glyph = if let Glyph::Simple(simple) = glyph {
1033 simple
1034 } else {
1035 panic!("expected simple glyph");
1036 };
1037 assert_eq!(
1038 simple_glyph
1039 .points()
1040 .map(|pt| (pt.x, pt.y, pt.on_curve))
1041 .collect::<Vec<_>>(),
1042 &[
1043 (278, 710, true),
1044 (278, 470, true),
1045 (300, 500, false),
1046 (800, 500, false),
1047 (998, 470, true),
1048 (998, 710, true),
1049 ]
1050 );
1051 }
1052
1053 #[test]
1057 fn avoid_midpoint_overflow() {
1058 let a = F26Dot6::from_bits(1084092352);
1059 let b = F26Dot6::from_bits(1085243712);
1060 let expected = (a + b).to_bits() / 2;
1061 let midpoint = a.midpoint(b);
1063 assert_eq!(midpoint.to_bits(), expected);
1064 }
1065}