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
11pub const PHANTOM_POINT_COUNT: usize = 4;
19
20#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
23pub struct PointMarker(u8);
24
25impl PointMarker {
26 pub const HAS_DELTA: Self = Self(0x4);
29
30 pub const TOUCHED_X: Self = Self(0x10);
33
34 pub const TOUCHED_Y: Self = Self(0x20);
37
38 pub const TOUCHED: Self = Self(Self::TOUCHED_X.0 | Self::TOUCHED_Y.0);
41
42 pub const WEAK_INTERPOLATION: Self = Self(0x2);
46
47 pub const NEAR: PointMarker = Self(0x8);
51}
52
53impl core::ops::BitOr for PointMarker {
54 type Output = Self;
55
56 fn bitor(self, rhs: Self) -> Self::Output {
57 Self(self.0 | rhs.0)
58 }
59}
60
61#[derive(
67 Copy, Clone, PartialEq, Eq, Default, Debug, bytemuck::AnyBitPattern, bytemuck::NoUninit,
68)]
69#[repr(transparent)]
70pub struct PointFlags(u8);
71
72impl PointFlags {
73 const ON_CURVE: u8 = SimpleGlyphFlags::ON_CURVE_POINT.bits;
76 const OFF_CURVE_CUBIC: u8 = SimpleGlyphFlags::CUBIC.bits;
77 const CURVE_MASK: u8 = Self::ON_CURVE | Self::OFF_CURVE_CUBIC;
78
79 pub const fn on_curve() -> Self {
81 Self(Self::ON_CURVE)
82 }
83
84 pub const fn off_curve_quad() -> Self {
86 Self(0)
87 }
88
89 pub const fn off_curve_cubic() -> Self {
91 Self(Self::OFF_CURVE_CUBIC)
92 }
93
94 pub const fn from_bits(bits: u8) -> Self {
97 Self(bits & Self::CURVE_MASK)
98 }
99
100 #[inline]
102 pub const fn is_on_curve(self) -> bool {
103 self.0 & Self::ON_CURVE != 0
104 }
105
106 #[inline]
108 pub const fn is_off_curve_quad(self) -> bool {
109 self.0 & Self::CURVE_MASK == 0
110 }
111
112 #[inline]
114 pub const fn is_off_curve_cubic(self) -> bool {
115 self.0 & Self::OFF_CURVE_CUBIC != 0
116 }
117
118 pub const fn is_off_curve(self) -> bool {
119 self.is_off_curve_quad() || self.is_off_curve_cubic()
120 }
121
122 pub fn flip_on_curve(&mut self) {
126 self.0 ^= 1;
127 }
128
129 pub fn set_on_curve(&mut self) {
133 self.0 |= Self::ON_CURVE;
134 }
135
136 pub fn clear_on_curve(&mut self) {
140 self.0 &= !Self::ON_CURVE;
141 }
142
143 pub fn has_marker(self, marker: PointMarker) -> bool {
145 self.0 & marker.0 != 0
146 }
147
148 pub fn set_marker(&mut self, marker: PointMarker) {
150 self.0 |= marker.0;
151 }
152
153 pub fn clear_marker(&mut self, marker: PointMarker) {
155 self.0 &= !marker.0
156 }
157
158 pub const fn without_markers(self) -> Self {
160 Self(self.0 & Self::CURVE_MASK)
161 }
162
163 pub const fn to_bits(self) -> u8 {
165 self.0
166 }
167}
168
169pub trait PointCoord:
171 Copy
172 + Default
173 + AnyBitPattern
175 + PartialEq
177 + PartialOrd
178 + Add<Output = Self>
180 + AddAssign
181 + Sub<Output = Self>
182 + Div<Output = Self>
183 + Mul<Output = Self>
184 + MulAssign {
185 fn from_fixed(x: Fixed) -> Self;
186 fn from_i32(x: i32) -> Self;
187 fn to_f32(self) -> f32;
188 fn midpoint(self, other: Self) -> Self;
189}
190
191impl<'a> SimpleGlyph<'a> {
192 pub fn num_points(&self) -> usize {
194 self.end_pts_of_contours()
195 .last()
196 .map(|last| last.get() as usize + 1)
197 .unwrap_or(0)
198 }
199
200 pub fn has_overlapping_contours(&self) -> bool {
202 FontData::new(self.glyph_data())
206 .read_at::<SimpleGlyphFlags>(0)
207 .map(|flag| flag.contains(SimpleGlyphFlags::OVERLAP_SIMPLE))
208 .unwrap_or_default()
209 }
210
211 pub fn read_points_fast<C: PointCoord>(
222 &self,
223 points: &mut [Point<C>],
224 flags: &mut [PointFlags],
225 ) -> Result<(), ReadError> {
226 let n_points = self.num_points();
227 if points.len() != n_points || flags.len() != n_points {
228 return Err(ReadError::InvalidArrayLen);
229 }
230 if n_points == 0 {
231 return Ok(());
232 }
233 let mut cursor = FontData::new(self.glyph_data()).cursor();
234 let flags_data = cursor.read_array::<u8>(cursor.remaining_bytes())?;
238 let mut flags_iter = flags_data.iter().copied();
239 let mut read_flags_bytes = 0;
242 let mut i = 0;
243 while let Some(flag_bits) = flags_iter.next() {
244 read_flags_bytes += 1;
245 if SimpleGlyphFlags::from_bits_truncate(flag_bits)
246 .contains(SimpleGlyphFlags::REPEAT_FLAG)
247 {
248 let count = (flags_iter.next().ok_or(ReadError::OutOfBounds)? as usize + 1)
249 .min(n_points - i);
250 read_flags_bytes += 1;
251 for f in &mut flags[i..i + count] {
252 f.0 = flag_bits;
253 }
254 i += count;
255 } else {
256 flags[i].0 = flag_bits;
257 i += 1;
258 }
259 if i == n_points {
260 break;
261 }
262 }
263 let mut cursor = FontData::new(self.glyph_data()).cursor();
264 cursor.advance_by(read_flags_bytes);
265 let mut x = 0i32;
266 for (&point_flags, point) in flags.iter().zip(points.as_mut()) {
267 let mut delta = 0i32;
268 let flag = SimpleGlyphFlags::from_bits_truncate(point_flags.0);
269 if flag.contains(SimpleGlyphFlags::X_SHORT_VECTOR) {
270 delta = cursor.read::<u8>()? as i32;
271 if !flag.contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
272 delta = -delta;
273 }
274 } else if !flag.contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
275 delta = cursor.read::<i16>()? as i32;
276 }
277 x = x.wrapping_add(delta);
278 point.x = C::from_i32(x);
279 }
280 let mut y = 0i32;
281 for (point_flags, point) in flags.iter_mut().zip(points.as_mut()) {
282 let mut delta = 0i32;
283 let flag = SimpleGlyphFlags::from_bits_truncate(point_flags.0);
284 if flag.contains(SimpleGlyphFlags::Y_SHORT_VECTOR) {
285 delta = cursor.read::<u8>()? as i32;
286 if !flag.contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
287 delta = -delta;
288 }
289 } else if !flag.contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
290 delta = cursor.read::<i16>()? as i32;
291 }
292 y = y.wrapping_add(delta);
293 point.y = C::from_i32(y);
294 let flags_mask = if cfg!(feature = "spec_next") {
295 PointFlags::CURVE_MASK
296 } else {
297 PointFlags::ON_CURVE
299 };
300 point_flags.0 &= flags_mask;
301 }
302 Ok(())
303 }
304
305 pub fn points(&self) -> impl Iterator<Item = CurvePoint> + 'a + Clone {
312 self.points_impl()
313 .unwrap_or_else(|| PointIter::new(&[], &[], &[]))
314 }
315
316 fn points_impl(&self) -> Option<PointIter<'a>> {
317 let end_points = self.end_pts_of_contours();
318 let n_points = end_points.last()?.get().checked_add(1)?;
319 let data = self.glyph_data();
320 let lens = resolve_coords_len(data, n_points).ok()?;
321 let total_len = lens.flags + lens.x_coords + lens.y_coords;
322 if data.len() < total_len as usize {
323 return None;
324 }
325
326 let (flags, data) = data.split_at(lens.flags as usize);
327 let (x_coords, y_coords) = data.split_at(lens.x_coords as usize);
328
329 Some(PointIter::new(flags, x_coords, y_coords))
330 }
331}
332
333#[derive(Clone, Copy, Debug, PartialEq, Eq)]
337pub struct CurvePoint {
338 pub x: i16,
340 pub y: i16,
342 pub on_curve: bool,
344}
345
346impl CurvePoint {
347 pub fn new(x: i16, y: i16, on_curve: bool) -> Self {
349 Self { x, y, on_curve }
350 }
351
352 pub fn on_curve(x: i16, y: i16) -> Self {
354 Self::new(x, y, true)
355 }
356
357 pub fn off_curve(x: i16, y: i16) -> Self {
359 Self::new(x, y, false)
360 }
361}
362
363#[derive(Clone)]
364struct PointIter<'a> {
365 flags: Cursor<'a>,
366 x_coords: Cursor<'a>,
367 y_coords: Cursor<'a>,
368 flag_repeats: u16,
369 cur_flags: SimpleGlyphFlags,
370 cur_x: i16,
371 cur_y: i16,
372}
373
374impl Iterator for PointIter<'_> {
375 type Item = CurvePoint;
376 fn next(&mut self) -> Option<Self::Item> {
377 self.advance_flags()?;
378 self.advance_points();
379 let is_on_curve = self.cur_flags.contains(SimpleGlyphFlags::ON_CURVE_POINT);
380 Some(CurvePoint::new(self.cur_x, self.cur_y, is_on_curve))
381 }
382}
383
384impl<'a> PointIter<'a> {
385 fn new(flags: &'a [u8], x_coords: &'a [u8], y_coords: &'a [u8]) -> Self {
386 Self {
387 flags: FontData::new(flags).cursor(),
388 x_coords: FontData::new(x_coords).cursor(),
389 y_coords: FontData::new(y_coords).cursor(),
390 flag_repeats: 0,
391 cur_flags: SimpleGlyphFlags::empty(),
392 cur_x: 0,
393 cur_y: 0,
394 }
395 }
396
397 fn advance_flags(&mut self) -> Option<()> {
398 if self.flag_repeats == 0 {
399 self.cur_flags = SimpleGlyphFlags::from_bits_truncate(self.flags.read().ok()?);
400 self.flag_repeats = self
401 .cur_flags
402 .contains(SimpleGlyphFlags::REPEAT_FLAG)
403 .then(|| self.flags.read::<u8>().ok())
404 .flatten()
405 .unwrap_or(0) as u16
406 + 1;
407 }
408 self.flag_repeats -= 1;
409 Some(())
410 }
411
412 fn advance_points(&mut self) {
413 let x_short = self.cur_flags.contains(SimpleGlyphFlags::X_SHORT_VECTOR);
414 let x_same_or_pos = self
415 .cur_flags
416 .contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR);
417 let y_short = self.cur_flags.contains(SimpleGlyphFlags::Y_SHORT_VECTOR);
418 let y_same_or_pos = self
419 .cur_flags
420 .contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR);
421
422 let delta_x = match (x_short, x_same_or_pos) {
423 (true, false) => -(self.x_coords.read::<u8>().unwrap_or(0) as i16),
424 (true, true) => self.x_coords.read::<u8>().unwrap_or(0) as i16,
425 (false, false) => self.x_coords.read::<i16>().unwrap_or(0),
426 _ => 0,
427 };
428
429 let delta_y = match (y_short, y_same_or_pos) {
430 (true, false) => -(self.y_coords.read::<u8>().unwrap_or(0) as i16),
431 (true, true) => self.y_coords.read::<u8>().unwrap_or(0) as i16,
432 (false, false) => self.y_coords.read::<i16>().unwrap_or(0),
433 _ => 0,
434 };
435
436 self.cur_x = self.cur_x.wrapping_add(delta_x);
437 self.cur_y = self.cur_y.wrapping_add(delta_y);
438 }
439}
440
441fn resolve_coords_len(data: &[u8], points_total: u16) -> Result<FieldLengths, ReadError> {
446 let mut cursor = FontData::new(data).cursor();
447 let mut flags_left = u32::from(points_total);
448 let mut x_coords_len = 0;
450 let mut y_coords_len = 0;
451 while flags_left > 0 {
453 let flags: SimpleGlyphFlags = cursor.read()?;
454
455 let repeats = if flags.contains(SimpleGlyphFlags::REPEAT_FLAG) {
457 let repeats: u8 = cursor.read()?;
458 u32::from(repeats) + 1
459 } else {
460 1
461 };
462
463 if repeats > flags_left {
464 return Err(ReadError::MalformedData("repeat count too large in glyf"));
465 }
466
467 let x_short = SimpleGlyphFlags::X_SHORT_VECTOR;
485 let x_long = SimpleGlyphFlags::X_SHORT_VECTOR
486 | SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR;
487 let y_short = SimpleGlyphFlags::Y_SHORT_VECTOR;
488 let y_long = SimpleGlyphFlags::Y_SHORT_VECTOR
489 | SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR;
490 x_coords_len += ((flags & x_short).bits() != 0) as u32 * repeats;
491 x_coords_len += ((flags & x_long).bits() == 0) as u32 * repeats * 2;
492
493 y_coords_len += ((flags & y_short).bits() != 0) as u32 * repeats;
494 y_coords_len += ((flags & y_long).bits() == 0) as u32 * repeats * 2;
495
496 flags_left -= repeats;
497 }
498
499 Ok(FieldLengths {
500 flags: cursor.position()? as u32,
501 x_coords: x_coords_len,
502 y_coords: y_coords_len,
503 })
504 }
506
507struct FieldLengths {
508 flags: u32,
509 x_coords: u32,
510 y_coords: u32,
511}
512
513#[derive(Clone, Copy, Debug, PartialEq, Eq)]
515pub struct Transform {
516 pub xx: F2Dot14,
518 pub yx: F2Dot14,
520 pub xy: F2Dot14,
522 pub yy: F2Dot14,
524}
525
526impl Default for Transform {
527 fn default() -> Self {
528 Self {
529 xx: F2Dot14::from_f32(1.0),
530 yx: F2Dot14::from_f32(0.0),
531 xy: F2Dot14::from_f32(0.0),
532 yy: F2Dot14::from_f32(1.0),
533 }
534 }
535}
536
537#[derive(Clone, Debug, PartialEq, Eq)]
539pub struct Component {
540 pub flags: CompositeGlyphFlags,
542 pub glyph: GlyphId16,
544 pub anchor: Anchor,
546 pub transform: Transform,
548}
549
550#[derive(Clone, Copy, Debug, PartialEq, Eq)]
552pub enum Anchor {
553 Offset { x: i16, y: i16 },
554 Point { base: u16, component: u16 },
555}
556
557impl<'a> CompositeGlyph<'a> {
558 pub fn components(&self) -> impl Iterator<Item = Component> + 'a + Clone {
560 ComponentIter {
561 cur_flags: CompositeGlyphFlags::empty(),
562 done: false,
563 cursor: FontData::new(self.component_data()).cursor(),
564 }
565 }
566
567 pub fn component_glyphs_and_flags(
570 &self,
571 ) -> impl Iterator<Item = (GlyphId16, CompositeGlyphFlags)> + 'a + Clone {
572 ComponentGlyphIdFlagsIter {
573 cur_flags: CompositeGlyphFlags::empty(),
574 done: false,
575 cursor: FontData::new(self.component_data()).cursor(),
576 }
577 }
578
579 pub fn count_and_instructions(&self) -> (usize, Option<&'a [u8]>) {
582 let mut iter = ComponentGlyphIdFlagsIter {
583 cur_flags: CompositeGlyphFlags::empty(),
584 done: false,
585 cursor: FontData::new(self.component_data()).cursor(),
586 };
587 let mut count = 0;
588 while iter.by_ref().next().is_some() {
589 count += 1;
590 }
591 let instructions = if iter
592 .cur_flags
593 .contains(CompositeGlyphFlags::WE_HAVE_INSTRUCTIONS)
594 {
595 iter.cursor
596 .read::<u16>()
597 .ok()
598 .map(|len| len as usize)
599 .and_then(|len| iter.cursor.read_array(len).ok())
600 } else {
601 None
602 };
603 (count, instructions)
604 }
605
606 pub fn instructions(&self) -> Option<&'a [u8]> {
608 self.count_and_instructions().1
609 }
610}
611
612#[derive(Clone)]
613struct ComponentIter<'a> {
614 cur_flags: CompositeGlyphFlags,
615 done: bool,
616 cursor: Cursor<'a>,
617}
618
619impl Iterator for ComponentIter<'_> {
620 type Item = Component;
621
622 fn next(&mut self) -> Option<Self::Item> {
623 if self.done {
624 return None;
625 }
626 let flags: CompositeGlyphFlags = self.cursor.read().ok()?;
627 self.cur_flags = flags;
628 let glyph = self.cursor.read::<GlyphId16>().ok()?;
629 let args_are_words = flags.contains(CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS);
630 let args_are_xy_values = flags.contains(CompositeGlyphFlags::ARGS_ARE_XY_VALUES);
631 let anchor = match (args_are_xy_values, args_are_words) {
632 (true, true) => Anchor::Offset {
633 x: self.cursor.read().ok()?,
634 y: self.cursor.read().ok()?,
635 },
636 (true, false) => Anchor::Offset {
637 x: self.cursor.read::<i8>().ok()? as _,
638 y: self.cursor.read::<i8>().ok()? as _,
639 },
640 (false, true) => Anchor::Point {
641 base: self.cursor.read().ok()?,
642 component: self.cursor.read().ok()?,
643 },
644 (false, false) => Anchor::Point {
645 base: self.cursor.read::<u8>().ok()? as _,
646 component: self.cursor.read::<u8>().ok()? as _,
647 },
648 };
649 let mut transform = Transform::default();
650 if flags.contains(CompositeGlyphFlags::WE_HAVE_A_SCALE) {
651 transform.xx = self.cursor.read().ok()?;
652 transform.yy = transform.xx;
653 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
654 transform.xx = self.cursor.read().ok()?;
655 transform.yy = self.cursor.read().ok()?;
656 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO) {
657 transform.xx = self.cursor.read().ok()?;
658 transform.yx = self.cursor.read().ok()?;
659 transform.xy = self.cursor.read().ok()?;
660 transform.yy = self.cursor.read().ok()?;
661 }
662 self.done = !flags.contains(CompositeGlyphFlags::MORE_COMPONENTS);
663
664 Some(Component {
665 flags,
666 glyph,
667 anchor,
668 transform,
669 })
670 }
671}
672
673#[derive(Clone)]
678struct ComponentGlyphIdFlagsIter<'a> {
679 cur_flags: CompositeGlyphFlags,
680 done: bool,
681 cursor: Cursor<'a>,
682}
683
684impl Iterator for ComponentGlyphIdFlagsIter<'_> {
685 type Item = (GlyphId16, CompositeGlyphFlags);
686
687 fn next(&mut self) -> Option<Self::Item> {
688 if self.done {
689 return None;
690 }
691 let flags: CompositeGlyphFlags = self.cursor.read().ok()?;
692 self.cur_flags = flags;
693 let glyph = self.cursor.read::<GlyphId16>().ok()?;
694 let args_are_words = flags.contains(CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS);
695 if args_are_words {
696 self.cursor.advance_by(4);
697 } else {
698 self.cursor.advance_by(2);
699 }
700 if flags.contains(CompositeGlyphFlags::WE_HAVE_A_SCALE) {
701 self.cursor.advance_by(2);
702 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
703 self.cursor.advance_by(4);
704 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO) {
705 self.cursor.advance_by(8);
706 }
707 self.done = !flags.contains(CompositeGlyphFlags::MORE_COMPONENTS);
708 Some((glyph, flags))
709 }
710}
711
712#[cfg(feature = "experimental_traverse")]
713impl<'a> SomeTable<'a> for Component {
714 fn type_name(&self) -> &str {
715 "Component"
716 }
717
718 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
719 match idx {
720 0 => Some(Field::new("flags", self.flags.bits())),
721 1 => Some(Field::new("glyph", self.glyph)),
722 2 => match self.anchor {
723 Anchor::Point { base, .. } => Some(Field::new("base", base)),
724 Anchor::Offset { x, .. } => Some(Field::new("x", x)),
725 },
726 3 => match self.anchor {
727 Anchor::Point { component, .. } => Some(Field::new("component", component)),
728 Anchor::Offset { y, .. } => Some(Field::new("y", y)),
729 },
730 _ => None,
731 }
732 }
733}
734
735impl Anchor {
736 pub fn compute_flags(&self) -> CompositeGlyphFlags {
738 const I8_RANGE: Range<i16> = i8::MIN as i16..i8::MAX as i16 + 1;
739 const U8_MAX: u16 = u8::MAX as u16;
740
741 let mut flags = CompositeGlyphFlags::empty();
742 match self {
743 Anchor::Offset { x, y } => {
744 flags |= CompositeGlyphFlags::ARGS_ARE_XY_VALUES;
745 if !I8_RANGE.contains(x) || !I8_RANGE.contains(y) {
746 flags |= CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS;
747 }
748 }
749 Anchor::Point { base, component } => {
750 if base > &U8_MAX || component > &U8_MAX {
751 flags |= CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS;
752 }
753 }
754 }
755 flags
756 }
757}
758
759impl Transform {
760 pub fn compute_flags(&self) -> CompositeGlyphFlags {
762 if self.yx != F2Dot14::ZERO || self.xy != F2Dot14::ZERO {
763 CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO
764 } else if self.xx != self.yy {
765 CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE
766 } else if self.xx != F2Dot14::ONE {
767 CompositeGlyphFlags::WE_HAVE_A_SCALE
768 } else {
769 CompositeGlyphFlags::empty()
770 }
771 }
772}
773
774impl PointCoord for F26Dot6 {
775 fn from_fixed(x: Fixed) -> Self {
776 x.to_f26dot6()
777 }
778
779 #[inline]
780 fn from_i32(x: i32) -> Self {
781 Self::from_i32(x)
782 }
783
784 #[inline]
785 fn to_f32(self) -> f32 {
786 self.to_f32()
787 }
788
789 #[inline]
790 fn midpoint(self, other: Self) -> Self {
791 Self::from_bits(midpoint_i32(self.to_bits(), other.to_bits()))
794 }
795}
796
797impl PointCoord for Fixed {
798 fn from_fixed(x: Fixed) -> Self {
799 x
800 }
801
802 fn from_i32(x: i32) -> Self {
803 Self::from_i32(x)
804 }
805
806 fn to_f32(self) -> f32 {
807 self.to_f32()
808 }
809
810 fn midpoint(self, other: Self) -> Self {
811 Self::from_bits(midpoint_i32(self.to_bits(), other.to_bits()))
812 }
813}
814
815impl PointCoord for i32 {
816 fn from_fixed(x: Fixed) -> Self {
817 x.to_i32()
818 }
819
820 fn from_i32(x: i32) -> Self {
821 x
822 }
823
824 fn to_f32(self) -> f32 {
825 self as f32
826 }
827
828 fn midpoint(self, other: Self) -> Self {
829 midpoint_i32(self, other)
830 }
831}
832
833#[inline(always)]
835fn midpoint_i32(a: i32, b: i32) -> i32 {
836 a.wrapping_add(b) / 2
842}
843
844impl PointCoord for f32 {
845 fn from_fixed(x: Fixed) -> Self {
846 x.to_f32()
847 }
848
849 fn from_i32(x: i32) -> Self {
850 x as f32
851 }
852
853 fn to_f32(self) -> f32 {
854 self
855 }
856
857 fn midpoint(self, other: Self) -> Self {
858 self + 0.5 * (other - self)
861 }
862}
863
864#[cfg(test)]
865mod tests {
866 use super::*;
867 use crate::{FontRef, GlyphId, TableProvider};
868
869 #[test]
870 fn simple_glyph() {
871 let font = FontRef::new(font_test_data::COLR_GRADIENT_RECT).unwrap();
872 let loca = font.loca(None).unwrap();
873 let glyf = font.glyf().unwrap();
874 let glyph = loca.get_glyf(GlyphId::new(0), &glyf).unwrap().unwrap();
875 assert_eq!(glyph.number_of_contours(), 2);
876 let simple_glyph = if let Glyph::Simple(simple) = glyph {
877 simple
878 } else {
879 panic!("expected simple glyph");
880 };
881 assert_eq!(
882 simple_glyph
883 .end_pts_of_contours()
884 .iter()
885 .map(|x| x.get())
886 .collect::<Vec<_>>(),
887 &[3, 7]
888 );
889 assert_eq!(
890 simple_glyph
891 .points()
892 .map(|pt| (pt.x, pt.y, pt.on_curve))
893 .collect::<Vec<_>>(),
894 &[
895 (5, 0, true),
896 (5, 100, true),
897 (45, 100, true),
898 (45, 0, true),
899 (10, 5, true),
900 (40, 5, true),
901 (40, 95, true),
902 (10, 95, true),
903 ]
904 );
905 }
906
907 fn all_glyphs(font_data: &[u8]) -> impl Iterator<Item = Option<Glyph<'_>>> {
909 let font = FontRef::new(font_data).unwrap();
910 let loca = font.loca(None).unwrap();
911 let glyf = font.glyf().unwrap();
912 let glyph_count = font.maxp().unwrap().num_glyphs() as u32;
913 (0..glyph_count).map(move |gid| loca.get_glyf(GlyphId::new(gid), &glyf).unwrap())
914 }
915
916 #[test]
917 fn simple_glyph_overlapping_contour_flag() {
918 let gids_with_overlap: Vec<_> = all_glyphs(font_test_data::VAZIRMATN_VAR)
919 .enumerate()
920 .filter_map(|(gid, glyph)| match glyph {
921 Some(Glyph::Simple(glyph)) if glyph.has_overlapping_contours() => Some(gid),
922 _ => None,
923 })
924 .collect();
925 let expected_gids_with_overlap = vec![3];
927 assert_eq!(expected_gids_with_overlap, gids_with_overlap);
928 }
929
930 #[test]
931 fn composite_glyph_overlapping_contour_flag() {
932 let gids_components_with_overlap: Vec<_> = all_glyphs(font_test_data::VAZIRMATN_VAR)
933 .enumerate()
934 .filter_map(|(gid, glyph)| match glyph {
935 Some(Glyph::Composite(glyph)) => Some((gid, glyph)),
936 _ => None,
937 })
938 .flat_map(|(gid, glyph)| {
939 glyph
940 .components()
941 .enumerate()
942 .filter_map(move |(comp_ix, comp)| {
943 comp.flags
944 .contains(CompositeGlyphFlags::OVERLAP_COMPOUND)
945 .then_some((gid, comp_ix))
946 })
947 })
948 .collect();
949 let expected_gids_components_with_overlap = vec![(2, 1)];
951 assert_eq!(
952 expected_gids_components_with_overlap,
953 gids_components_with_overlap
954 );
955 }
956
957 #[test]
958 fn compute_anchor_flags() {
959 let anchor = Anchor::Offset { x: -128, y: 127 };
960 assert_eq!(
961 anchor.compute_flags(),
962 CompositeGlyphFlags::ARGS_ARE_XY_VALUES
963 );
964
965 let anchor = Anchor::Offset { x: -129, y: 127 };
966 assert_eq!(
967 anchor.compute_flags(),
968 CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
969 );
970 let anchor = Anchor::Offset { x: -1, y: 128 };
971 assert_eq!(
972 anchor.compute_flags(),
973 CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
974 );
975
976 let anchor = Anchor::Point {
977 base: 255,
978 component: 20,
979 };
980 assert_eq!(anchor.compute_flags(), CompositeGlyphFlags::empty());
981
982 let anchor = Anchor::Point {
983 base: 256,
984 component: 20,
985 };
986 assert_eq!(
987 anchor.compute_flags(),
988 CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
989 )
990 }
991
992 #[test]
993 fn compute_transform_flags() {
994 fn make_xform(xx: f32, yx: f32, xy: f32, yy: f32) -> Transform {
995 Transform {
996 xx: F2Dot14::from_f32(xx),
997 yx: F2Dot14::from_f32(yx),
998 xy: F2Dot14::from_f32(xy),
999 yy: F2Dot14::from_f32(yy),
1000 }
1001 }
1002
1003 assert_eq!(
1004 make_xform(1.0, 0., 0., 1.0).compute_flags(),
1005 CompositeGlyphFlags::empty()
1006 );
1007 assert_eq!(
1008 make_xform(2.0, 0., 0., 2.0).compute_flags(),
1009 CompositeGlyphFlags::WE_HAVE_A_SCALE
1010 );
1011 assert_eq!(
1012 make_xform(2.0, 0., 0., 1.0).compute_flags(),
1013 CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE
1014 );
1015 assert_eq!(
1016 make_xform(2.0, 0., 1.0, 1.0).compute_flags(),
1017 CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO
1018 );
1019 }
1020
1021 #[test]
1022 fn point_flags_and_marker_bits() {
1023 let bits = [
1024 PointFlags::OFF_CURVE_CUBIC,
1025 PointFlags::ON_CURVE,
1026 PointMarker::HAS_DELTA.0,
1027 PointMarker::TOUCHED_X.0,
1028 PointMarker::TOUCHED_Y.0,
1029 ];
1030 for (i, a) in bits.iter().enumerate() {
1032 for b in &bits[i + 1..] {
1033 assert_eq!(a & b, 0);
1034 }
1035 }
1036 }
1037
1038 #[test]
1039 fn cubic_glyf() {
1040 let font = FontRef::new(font_test_data::CUBIC_GLYF).unwrap();
1041 let loca = font.loca(None).unwrap();
1042 let glyf = font.glyf().unwrap();
1043 let glyph = loca.get_glyf(GlyphId::new(2), &glyf).unwrap().unwrap();
1044 assert_eq!(glyph.number_of_contours(), 1);
1045 let simple_glyph = if let Glyph::Simple(simple) = glyph {
1046 simple
1047 } else {
1048 panic!("expected simple glyph");
1049 };
1050 assert_eq!(
1051 simple_glyph
1052 .points()
1053 .map(|pt| (pt.x, pt.y, pt.on_curve))
1054 .collect::<Vec<_>>(),
1055 &[
1056 (278, 710, true),
1057 (278, 470, true),
1058 (300, 500, false),
1059 (800, 500, false),
1060 (998, 470, true),
1061 (998, 710, true),
1062 ]
1063 );
1064 }
1065
1066 #[test]
1070 fn avoid_midpoint_overflow() {
1071 let a = F26Dot6::from_bits(1084092352);
1072 let b = F26Dot6::from_bits(1085243712);
1073 let expected = (a + b).to_bits() / 2;
1074 let midpoint = a.midpoint(b);
1076 assert_eq!(midpoint.to_bits(), expected);
1077 }
1078
1079 #[test]
1087 fn simple_glyph_truncated_data() {
1088 use font_test_data::bebuffer::BeBuffer;
1089
1090 let buf = BeBuffer::new()
1095 .push(100_i16) .push(0_i16) .push(0_i16) .push(0_i16) .push(0_i16) .push(0_u16); let glyph = SimpleGlyph::read(buf.data().into()).unwrap();
1104 assert_eq!(glyph.number_of_contours(), 100);
1105
1106 assert_eq!(glyph.instruction_length(), 0);
1108 }
1109
1110 #[test]
1114 fn read_points_fast_long_flags() {
1115 use font_test_data::bebuffer::BeBuffer;
1116 let buf = BeBuffer::new()
1121 .push(1_i16) .extend([0_i16; 4]) .push(2_u16) .push(0_u16) .extend([0x39u8, 0x00, 0x39, 0x00, 0x39, 0x00]);
1126
1127 let glyph = SimpleGlyph::read(buf.data().into()).unwrap();
1128 assert_eq!(glyph.num_points(), 3);
1129
1130 let expected: Vec<_> = glyph.points().map(|p| (p.x as i32, p.y as i32)).collect();
1131
1132 let mut points = vec![Point::default(); 3];
1133 let mut flags = vec![PointFlags::default(); 3];
1134 glyph
1135 .read_points_fast::<i32>(&mut points, &mut flags)
1136 .unwrap();
1137 let actual: Vec<_> = points.iter().map(|p| (p.x, p.y)).collect();
1138
1139 assert_eq!(actual, expected);
1140 }
1141
1142 #[test]
1143 fn point_iter_repeat_count_255_does_not_overflow() {
1144 let flags = [SimpleGlyphFlags::REPEAT_FLAG.bits(), 0xFF];
1146 let coords = [0u8; 256 * 2];
1148 let iter = PointIter::new(&flags, &coords, &coords);
1149 assert_eq!(iter.count(), 256);
1150 }
1151
1152 #[test]
1153 fn read_points_fast_does_not_panic_on_empty_glyph_with_padding() {
1154 let glyph_bytes: &[u8] = &[
1155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
1160 let glyph = SimpleGlyph::read(FontData::new(glyph_bytes)).expect("parses");
1161 assert_eq!(glyph.num_points(), 0);
1162 let mut points: Vec<Point<f32>> = vec![];
1163 let mut flags: Vec<PointFlags> = vec![];
1164 assert!(glyph.read_points_fast(&mut points, &mut flags).is_ok());
1165 }
1166}