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