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 coords = self
270 .glyph_data()
271 .get(read_flags_bytes..)
272 .ok_or(ReadError::OutOfBounds)?;
273 let mut bytes = coords.iter();
274 let mut x = 0i32;
275 for (&point_flags, point) in flags.iter().zip(points.as_mut()) {
276 let mut delta = 0i32;
277 let flag = SimpleGlyphFlags::from_bits_truncate(point_flags.0);
278 if flag.contains(SimpleGlyphFlags::X_SHORT_VECTOR) {
279 delta = *bytes.next().ok_or(ReadError::OutOfBounds)? as i32;
280 if !flag.contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
281 delta = -delta;
282 }
283 } else if !flag.contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
284 let hi = *bytes.next().ok_or(ReadError::OutOfBounds)?;
285 let lo = *bytes.next().ok_or(ReadError::OutOfBounds)?;
286 delta = i16::from_be_bytes([hi, lo]) as i32;
287 }
288 x = x.wrapping_add(delta);
289 point.x = C::from_i32(x);
290 }
291 let mut y = 0i32;
292 for (point_flags, point) in flags.iter_mut().zip(points.as_mut()) {
293 let mut delta = 0i32;
294 let flag = SimpleGlyphFlags::from_bits_truncate(point_flags.0);
295 if flag.contains(SimpleGlyphFlags::Y_SHORT_VECTOR) {
296 delta = *bytes.next().ok_or(ReadError::OutOfBounds)? as i32;
297 if !flag.contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
298 delta = -delta;
299 }
300 } else if !flag.contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
301 let hi = *bytes.next().ok_or(ReadError::OutOfBounds)?;
302 let lo = *bytes.next().ok_or(ReadError::OutOfBounds)?;
303 delta = i16::from_be_bytes([hi, lo]) as i32;
304 }
305 y = y.wrapping_add(delta);
306 point.y = C::from_i32(y);
307 let flags_mask = if cfg!(feature = "spec_next") {
308 PointFlags::CURVE_MASK
309 } else {
310 PointFlags::ON_CURVE
312 };
313 point_flags.0 &= flags_mask;
314 }
315 Ok(())
316 }
317
318 pub fn points(&self) -> impl Iterator<Item = CurvePoint> + 'a + Clone {
325 self.points_impl()
326 .unwrap_or_else(|| PointIter::new(&[], &[], &[]))
327 }
328
329 fn points_impl(&self) -> Option<PointIter<'a>> {
330 let end_points = self.end_pts_of_contours();
331 let n_points = end_points.last()?.get().checked_add(1)?;
332 let data = self.glyph_data();
333 let lens = resolve_coords_len(data, n_points).ok()?;
334 let total_len = lens.flags + lens.x_coords + lens.y_coords;
335 if data.len() < total_len as usize {
336 return None;
337 }
338
339 let (flags, data) = data.split_at(lens.flags as usize);
340 let (x_coords, y_coords) = data.split_at(lens.x_coords as usize);
341
342 Some(PointIter::new(flags, x_coords, y_coords))
343 }
344}
345
346#[derive(Clone, Copy, Debug, PartialEq, Eq)]
350pub struct CurvePoint {
351 pub x: i16,
353 pub y: i16,
355 pub on_curve: bool,
357}
358
359impl CurvePoint {
360 pub fn new(x: i16, y: i16, on_curve: bool) -> Self {
362 Self { x, y, on_curve }
363 }
364
365 pub fn on_curve(x: i16, y: i16) -> Self {
367 Self::new(x, y, true)
368 }
369
370 pub fn off_curve(x: i16, y: i16) -> Self {
372 Self::new(x, y, false)
373 }
374}
375
376#[derive(Clone)]
377struct PointIter<'a> {
378 flags: Cursor<'a>,
379 x_coords: Cursor<'a>,
380 y_coords: Cursor<'a>,
381 flag_repeats: u16,
382 cur_flags: SimpleGlyphFlags,
383 cur_x: i16,
384 cur_y: i16,
385}
386
387impl Iterator for PointIter<'_> {
388 type Item = CurvePoint;
389 fn next(&mut self) -> Option<Self::Item> {
390 self.advance_flags()?;
391 self.advance_points();
392 let is_on_curve = self.cur_flags.contains(SimpleGlyphFlags::ON_CURVE_POINT);
393 Some(CurvePoint::new(self.cur_x, self.cur_y, is_on_curve))
394 }
395}
396
397impl<'a> PointIter<'a> {
398 fn new(flags: &'a [u8], x_coords: &'a [u8], y_coords: &'a [u8]) -> Self {
399 Self {
400 flags: FontData::new(flags).cursor(),
401 x_coords: FontData::new(x_coords).cursor(),
402 y_coords: FontData::new(y_coords).cursor(),
403 flag_repeats: 0,
404 cur_flags: SimpleGlyphFlags::empty(),
405 cur_x: 0,
406 cur_y: 0,
407 }
408 }
409
410 fn advance_flags(&mut self) -> Option<()> {
411 if self.flag_repeats == 0 {
412 self.cur_flags = SimpleGlyphFlags::from_bits_truncate(self.flags.read().ok()?);
413 self.flag_repeats = self
414 .cur_flags
415 .contains(SimpleGlyphFlags::REPEAT_FLAG)
416 .then(|| self.flags.read::<u8>().ok())
417 .flatten()
418 .unwrap_or(0) as u16
419 + 1;
420 }
421 self.flag_repeats -= 1;
422 Some(())
423 }
424
425 fn advance_points(&mut self) {
426 let x_short = self.cur_flags.contains(SimpleGlyphFlags::X_SHORT_VECTOR);
427 let x_same_or_pos = self
428 .cur_flags
429 .contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR);
430 let y_short = self.cur_flags.contains(SimpleGlyphFlags::Y_SHORT_VECTOR);
431 let y_same_or_pos = self
432 .cur_flags
433 .contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR);
434
435 let delta_x = match (x_short, x_same_or_pos) {
436 (true, false) => -(self.x_coords.read::<u8>().unwrap_or(0) as i16),
437 (true, true) => self.x_coords.read::<u8>().unwrap_or(0) as i16,
438 (false, false) => self.x_coords.read::<i16>().unwrap_or(0),
439 _ => 0,
440 };
441
442 let delta_y = match (y_short, y_same_or_pos) {
443 (true, false) => -(self.y_coords.read::<u8>().unwrap_or(0) as i16),
444 (true, true) => self.y_coords.read::<u8>().unwrap_or(0) as i16,
445 (false, false) => self.y_coords.read::<i16>().unwrap_or(0),
446 _ => 0,
447 };
448
449 self.cur_x = self.cur_x.wrapping_add(delta_x);
450 self.cur_y = self.cur_y.wrapping_add(delta_y);
451 }
452}
453
454fn resolve_coords_len(data: &[u8], points_total: u16) -> Result<FieldLengths, ReadError> {
459 let mut cursor = FontData::new(data).cursor();
460 let mut flags_left = u32::from(points_total);
461 let mut x_coords_len = 0;
463 let mut y_coords_len = 0;
464 while flags_left > 0 {
466 let flags: SimpleGlyphFlags = cursor.read()?;
467
468 let repeats = if flags.contains(SimpleGlyphFlags::REPEAT_FLAG) {
470 let repeats: u8 = cursor.read()?;
471 u32::from(repeats) + 1
472 } else {
473 1
474 };
475
476 if repeats > flags_left {
477 return Err(ReadError::MalformedData("repeat count too large in glyf"));
478 }
479
480 let x_short = SimpleGlyphFlags::X_SHORT_VECTOR;
498 let x_long = SimpleGlyphFlags::X_SHORT_VECTOR
499 | SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR;
500 let y_short = SimpleGlyphFlags::Y_SHORT_VECTOR;
501 let y_long = SimpleGlyphFlags::Y_SHORT_VECTOR
502 | SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR;
503 x_coords_len += ((flags & x_short).bits() != 0) as u32 * repeats;
504 x_coords_len += ((flags & x_long).bits() == 0) as u32 * repeats * 2;
505
506 y_coords_len += ((flags & y_short).bits() != 0) as u32 * repeats;
507 y_coords_len += ((flags & y_long).bits() == 0) as u32 * repeats * 2;
508
509 flags_left -= repeats;
510 }
511
512 Ok(FieldLengths {
513 flags: cursor.position()? as u32,
514 x_coords: x_coords_len,
515 y_coords: y_coords_len,
516 })
517 }
519
520struct FieldLengths {
521 flags: u32,
522 x_coords: u32,
523 y_coords: u32,
524}
525
526#[derive(Clone, Copy, Debug, PartialEq, Eq)]
528pub struct Transform {
529 pub xx: F2Dot14,
531 pub yx: F2Dot14,
533 pub xy: F2Dot14,
535 pub yy: F2Dot14,
537}
538
539impl Default for Transform {
540 fn default() -> Self {
541 Self {
542 xx: F2Dot14::from_f32(1.0),
543 yx: F2Dot14::from_f32(0.0),
544 xy: F2Dot14::from_f32(0.0),
545 yy: F2Dot14::from_f32(1.0),
546 }
547 }
548}
549
550#[derive(Clone, Debug, PartialEq, Eq)]
552pub struct Component {
553 pub flags: CompositeGlyphFlags,
555 pub glyph: GlyphId16,
557 pub anchor: Anchor,
559 pub transform: Transform,
561}
562
563#[derive(Clone, Copy, Debug, PartialEq, Eq)]
565pub enum Anchor {
566 Offset { x: i16, y: i16 },
567 Point { base: u16, component: u16 },
568}
569
570impl<'a> CompositeGlyph<'a> {
571 pub fn components(&self) -> impl Iterator<Item = Component> + 'a + Clone {
573 ComponentIter {
574 cur_flags: CompositeGlyphFlags::empty(),
575 done: false,
576 cursor: FontData::new(self.component_data()).cursor(),
577 }
578 }
579
580 pub fn component_glyphs_and_flags(
583 &self,
584 ) -> impl Iterator<Item = (GlyphId16, CompositeGlyphFlags)> + 'a + Clone {
585 ComponentGlyphIdFlagsIter {
586 cur_flags: CompositeGlyphFlags::empty(),
587 done: false,
588 cursor: FontData::new(self.component_data()).cursor(),
589 }
590 }
591
592 pub fn count_and_instructions(&self) -> (usize, Option<&'a [u8]>) {
595 let mut iter = ComponentGlyphIdFlagsIter {
596 cur_flags: CompositeGlyphFlags::empty(),
597 done: false,
598 cursor: FontData::new(self.component_data()).cursor(),
599 };
600 let mut count = 0;
601 while iter.by_ref().next().is_some() {
602 count += 1;
603 }
604 let instructions = if iter
605 .cur_flags
606 .contains(CompositeGlyphFlags::WE_HAVE_INSTRUCTIONS)
607 {
608 iter.cursor
609 .read::<u16>()
610 .ok()
611 .map(|len| len as usize)
612 .and_then(|len| iter.cursor.read_array(len).ok())
613 } else {
614 None
615 };
616 (count, instructions)
617 }
618
619 pub fn instructions(&self) -> Option<&'a [u8]> {
621 self.count_and_instructions().1
622 }
623}
624
625#[derive(Clone)]
626struct ComponentIter<'a> {
627 cur_flags: CompositeGlyphFlags,
628 done: bool,
629 cursor: Cursor<'a>,
630}
631
632impl Iterator for ComponentIter<'_> {
633 type Item = Component;
634
635 fn next(&mut self) -> Option<Self::Item> {
636 if self.done {
637 return None;
638 }
639 let flags: CompositeGlyphFlags = self.cursor.read().ok()?;
640 self.cur_flags = flags;
641 let glyph = self.cursor.read::<GlyphId16>().ok()?;
642 let args_are_words = flags.contains(CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS);
643 let args_are_xy_values = flags.contains(CompositeGlyphFlags::ARGS_ARE_XY_VALUES);
644 let anchor = match (args_are_xy_values, args_are_words) {
645 (true, true) => Anchor::Offset {
646 x: self.cursor.read().ok()?,
647 y: self.cursor.read().ok()?,
648 },
649 (true, false) => Anchor::Offset {
650 x: self.cursor.read::<i8>().ok()? as _,
651 y: self.cursor.read::<i8>().ok()? as _,
652 },
653 (false, true) => Anchor::Point {
654 base: self.cursor.read().ok()?,
655 component: self.cursor.read().ok()?,
656 },
657 (false, false) => Anchor::Point {
658 base: self.cursor.read::<u8>().ok()? as _,
659 component: self.cursor.read::<u8>().ok()? as _,
660 },
661 };
662 let mut transform = Transform::default();
663 if flags.contains(CompositeGlyphFlags::WE_HAVE_A_SCALE) {
664 transform.xx = self.cursor.read().ok()?;
665 transform.yy = transform.xx;
666 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
667 transform.xx = self.cursor.read().ok()?;
668 transform.yy = self.cursor.read().ok()?;
669 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO) {
670 transform.xx = self.cursor.read().ok()?;
671 transform.yx = self.cursor.read().ok()?;
672 transform.xy = self.cursor.read().ok()?;
673 transform.yy = self.cursor.read().ok()?;
674 }
675 self.done = !flags.contains(CompositeGlyphFlags::MORE_COMPONENTS);
676
677 Some(Component {
678 flags,
679 glyph,
680 anchor,
681 transform,
682 })
683 }
684}
685
686#[derive(Clone)]
691struct ComponentGlyphIdFlagsIter<'a> {
692 cur_flags: CompositeGlyphFlags,
693 done: bool,
694 cursor: Cursor<'a>,
695}
696
697impl Iterator for ComponentGlyphIdFlagsIter<'_> {
698 type Item = (GlyphId16, CompositeGlyphFlags);
699
700 fn next(&mut self) -> Option<Self::Item> {
701 if self.done {
702 return None;
703 }
704 let flags: CompositeGlyphFlags = self.cursor.read().ok()?;
705 self.cur_flags = flags;
706 let glyph = self.cursor.read::<GlyphId16>().ok()?;
707 let args_are_words = flags.contains(CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS);
708 if args_are_words {
709 self.cursor.advance_by(4);
710 } else {
711 self.cursor.advance_by(2);
712 }
713 if flags.contains(CompositeGlyphFlags::WE_HAVE_A_SCALE) {
714 self.cursor.advance_by(2);
715 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
716 self.cursor.advance_by(4);
717 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO) {
718 self.cursor.advance_by(8);
719 }
720 self.done = !flags.contains(CompositeGlyphFlags::MORE_COMPONENTS);
721 Some((glyph, flags))
722 }
723}
724
725impl Anchor {
726 pub fn compute_flags(&self) -> CompositeGlyphFlags {
728 const I8_RANGE: Range<i16> = i8::MIN as i16..i8::MAX as i16 + 1;
729 const U8_MAX: u16 = u8::MAX as u16;
730
731 let mut flags = CompositeGlyphFlags::empty();
732 match self {
733 Anchor::Offset { x, y } => {
734 flags |= CompositeGlyphFlags::ARGS_ARE_XY_VALUES;
735 if !I8_RANGE.contains(x) || !I8_RANGE.contains(y) {
736 flags |= CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS;
737 }
738 }
739 Anchor::Point { base, component } => {
740 if base > &U8_MAX || component > &U8_MAX {
741 flags |= CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS;
742 }
743 }
744 }
745 flags
746 }
747}
748
749impl Transform {
750 pub fn compute_flags(&self) -> CompositeGlyphFlags {
752 if self.yx != F2Dot14::ZERO || self.xy != F2Dot14::ZERO {
753 CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO
754 } else if self.xx != self.yy {
755 CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE
756 } else if self.xx != F2Dot14::ONE {
757 CompositeGlyphFlags::WE_HAVE_A_SCALE
758 } else {
759 CompositeGlyphFlags::empty()
760 }
761 }
762}
763
764impl PointCoord for F26Dot6 {
765 fn from_fixed(x: Fixed) -> Self {
766 x.to_f26dot6()
767 }
768
769 #[inline]
770 fn from_i32(x: i32) -> Self {
771 Self::from_i32(x)
772 }
773
774 #[inline]
775 fn to_f32(self) -> f32 {
776 self.to_f32()
777 }
778
779 #[inline]
780 fn midpoint(self, other: Self) -> Self {
781 Self::from_bits(midpoint_i32(self.to_bits(), other.to_bits()))
784 }
785}
786
787impl PointCoord for Fixed {
788 fn from_fixed(x: Fixed) -> Self {
789 x
790 }
791
792 fn from_i32(x: i32) -> Self {
793 Self::from_i32(x)
794 }
795
796 fn to_f32(self) -> f32 {
797 self.to_f32()
798 }
799
800 fn midpoint(self, other: Self) -> Self {
801 Self::from_bits(midpoint_i32(self.to_bits(), other.to_bits()))
802 }
803}
804
805impl PointCoord for i32 {
806 fn from_fixed(x: Fixed) -> Self {
807 x.to_i32()
808 }
809
810 fn from_i32(x: i32) -> Self {
811 x
812 }
813
814 fn to_f32(self) -> f32 {
815 self as f32
816 }
817
818 fn midpoint(self, other: Self) -> Self {
819 midpoint_i32(self, other)
820 }
821}
822
823#[inline(always)]
825fn midpoint_i32(a: i32, b: i32) -> i32 {
826 a.wrapping_add(b) / 2
832}
833
834impl PointCoord for f32 {
835 fn from_fixed(x: Fixed) -> Self {
836 x.to_f32()
837 }
838
839 fn from_i32(x: i32) -> Self {
840 x as f32
841 }
842
843 fn to_f32(self) -> f32 {
844 self
845 }
846
847 fn midpoint(self, other: Self) -> Self {
848 self + 0.5 * (other - self)
851 }
852}
853
854#[cfg(test)]
855mod tests {
856 use super::*;
857 use crate::{FontRef, GlyphId, TableProvider};
858
859 #[test]
860 fn simple_glyph() {
861 let font = FontRef::new(font_test_data::COLR_GRADIENT_RECT).unwrap();
862 let loca = font.loca(None).unwrap();
863 let glyf = font.glyf().unwrap();
864 let glyph = loca
865 .get(GlyphId::new(0), &glyf)
866 .and_then(|g| g.into_glyph())
867 .unwrap();
868 assert_eq!(glyph.number_of_contours(), 2);
869 let simple_glyph = if let Glyph::Simple(simple) = glyph {
870 simple
871 } else {
872 panic!("expected simple glyph");
873 };
874 assert_eq!(
875 simple_glyph
876 .end_pts_of_contours()
877 .iter()
878 .map(|x| x.get())
879 .collect::<Vec<_>>(),
880 &[3, 7]
881 );
882 assert_eq!(
883 simple_glyph
884 .points()
885 .map(|pt| (pt.x, pt.y, pt.on_curve))
886 .collect::<Vec<_>>(),
887 &[
888 (5, 0, true),
889 (5, 100, true),
890 (45, 100, true),
891 (45, 0, true),
892 (10, 5, true),
893 (40, 5, true),
894 (40, 95, true),
895 (10, 95, true),
896 ]
897 );
898 }
899
900 fn all_glyphs(font_data: &[u8]) -> impl Iterator<Item = Option<Glyph<'_>>> {
902 let font = FontRef::new(font_data).unwrap();
903 let loca = font.loca(None).unwrap();
904 let glyf = font.glyf().unwrap();
905 let glyph_count = font.maxp().unwrap().num_glyphs() as u32;
906 (0..glyph_count).map(move |gid| {
907 loca.get(GlyphId::new(gid), &glyf)
908 .and_then(|g| g.into_glyph())
909 })
910 }
911
912 #[test]
913 fn simple_glyph_overlapping_contour_flag() {
914 let gids_with_overlap: Vec<_> = all_glyphs(font_test_data::VAZIRMATN_VAR)
915 .enumerate()
916 .filter_map(|(gid, glyph)| match glyph {
917 Some(Glyph::Simple(glyph)) if glyph.has_overlapping_contours() => Some(gid),
918 _ => None,
919 })
920 .collect();
921 let expected_gids_with_overlap = vec![3];
923 assert_eq!(expected_gids_with_overlap, gids_with_overlap);
924 }
925
926 #[test]
927 fn composite_glyph_overlapping_contour_flag() {
928 let gids_components_with_overlap: Vec<_> = all_glyphs(font_test_data::VAZIRMATN_VAR)
929 .enumerate()
930 .filter_map(|(gid, glyph)| match glyph {
931 Some(Glyph::Composite(glyph)) => Some((gid, glyph)),
932 _ => None,
933 })
934 .flat_map(|(gid, glyph)| {
935 glyph
936 .components()
937 .enumerate()
938 .filter_map(move |(comp_ix, comp)| {
939 comp.flags
940 .contains(CompositeGlyphFlags::OVERLAP_COMPOUND)
941 .then_some((gid, comp_ix))
942 })
943 })
944 .collect();
945 let expected_gids_components_with_overlap = vec![(2, 1)];
947 assert_eq!(
948 expected_gids_components_with_overlap,
949 gids_components_with_overlap
950 );
951 }
952
953 #[test]
954 fn compute_anchor_flags() {
955 let anchor = Anchor::Offset { x: -128, y: 127 };
956 assert_eq!(
957 anchor.compute_flags(),
958 CompositeGlyphFlags::ARGS_ARE_XY_VALUES
959 );
960
961 let anchor = Anchor::Offset { x: -129, y: 127 };
962 assert_eq!(
963 anchor.compute_flags(),
964 CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
965 );
966 let anchor = Anchor::Offset { x: -1, y: 128 };
967 assert_eq!(
968 anchor.compute_flags(),
969 CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
970 );
971
972 let anchor = Anchor::Point {
973 base: 255,
974 component: 20,
975 };
976 assert_eq!(anchor.compute_flags(), CompositeGlyphFlags::empty());
977
978 let anchor = Anchor::Point {
979 base: 256,
980 component: 20,
981 };
982 assert_eq!(
983 anchor.compute_flags(),
984 CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
985 )
986 }
987
988 #[test]
989 fn compute_transform_flags() {
990 fn make_xform(xx: f32, yx: f32, xy: f32, yy: f32) -> Transform {
991 Transform {
992 xx: F2Dot14::from_f32(xx),
993 yx: F2Dot14::from_f32(yx),
994 xy: F2Dot14::from_f32(xy),
995 yy: F2Dot14::from_f32(yy),
996 }
997 }
998
999 assert_eq!(
1000 make_xform(1.0, 0., 0., 1.0).compute_flags(),
1001 CompositeGlyphFlags::empty()
1002 );
1003 assert_eq!(
1004 make_xform(2.0, 0., 0., 2.0).compute_flags(),
1005 CompositeGlyphFlags::WE_HAVE_A_SCALE
1006 );
1007 assert_eq!(
1008 make_xform(2.0, 0., 0., 1.0).compute_flags(),
1009 CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE
1010 );
1011 assert_eq!(
1012 make_xform(2.0, 0., 1.0, 1.0).compute_flags(),
1013 CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO
1014 );
1015 }
1016
1017 #[test]
1018 fn point_flags_and_marker_bits() {
1019 let bits = [
1020 PointFlags::OFF_CURVE_CUBIC,
1021 PointFlags::ON_CURVE,
1022 PointMarker::HAS_DELTA.0,
1023 PointMarker::TOUCHED_X.0,
1024 PointMarker::TOUCHED_Y.0,
1025 ];
1026 for (i, a) in bits.iter().enumerate() {
1028 for b in &bits[i + 1..] {
1029 assert_eq!(a & b, 0);
1030 }
1031 }
1032 }
1033
1034 #[test]
1035 fn cubic_glyf() {
1036 let font = FontRef::new(font_test_data::CUBIC_GLYF).unwrap();
1037 let loca = font.loca(None).unwrap();
1038 let glyf = font.glyf().unwrap();
1039 let glyph = loca
1040 .get(GlyphId::new(2), &glyf)
1041 .and_then(|g| g.into_glyph())
1042 .unwrap();
1043 assert_eq!(glyph.number_of_contours(), 1);
1044 let simple_glyph = if let Glyph::Simple(simple) = glyph {
1045 simple
1046 } else {
1047 panic!("expected simple glyph");
1048 };
1049 assert_eq!(
1050 simple_glyph
1051 .points()
1052 .map(|pt| (pt.x, pt.y, pt.on_curve))
1053 .collect::<Vec<_>>(),
1054 &[
1055 (278, 710, true),
1056 (278, 470, true),
1057 (300, 500, false),
1058 (800, 500, false),
1059 (998, 470, true),
1060 (998, 710, true),
1061 ]
1062 );
1063 }
1064
1065 #[test]
1069 fn avoid_midpoint_overflow() {
1070 let a = F26Dot6::from_bits(1084092352);
1071 let b = F26Dot6::from_bits(1085243712);
1072 let expected = (a + b).to_bits() / 2;
1073 let midpoint = a.midpoint(b);
1075 assert_eq!(midpoint.to_bits(), expected);
1076 }
1077
1078 #[test]
1086 fn simple_glyph_truncated_data() {
1087 use font_test_data::bebuffer::BeBuffer;
1088
1089 let buf = BeBuffer::new()
1094 .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();
1103 assert_eq!(glyph.number_of_contours(), 100);
1104
1105 assert_eq!(glyph.instruction_length(), 0);
1107 }
1108
1109 #[test]
1113 fn read_points_fast_long_flags() {
1114 use font_test_data::bebuffer::BeBuffer;
1115 let buf = BeBuffer::new()
1120 .push(1_i16) .extend([0_i16; 4]) .push(2_u16) .push(0_u16) .extend([0x39u8, 0x00, 0x39, 0x00, 0x39, 0x00]);
1125
1126 let glyph = SimpleGlyph::read(buf.data().into()).unwrap();
1127 assert_eq!(glyph.num_points(), 3);
1128
1129 let expected: Vec<_> = glyph.points().map(|p| (p.x as i32, p.y as i32)).collect();
1130
1131 let mut points = vec![Point::default(); 3];
1132 let mut flags = vec![PointFlags::default(); 3];
1133 glyph
1134 .read_points_fast::<i32>(&mut points, &mut flags)
1135 .unwrap();
1136 let actual: Vec<_> = points.iter().map(|p| (p.x, p.y)).collect();
1137
1138 assert_eq!(actual, expected);
1139 }
1140
1141 #[test]
1142 fn point_iter_repeat_count_255_does_not_overflow() {
1143 let flags = [SimpleGlyphFlags::REPEAT_FLAG.bits(), 0xFF];
1145 let coords = [0u8; 256 * 2];
1147 let iter = PointIter::new(&flags, &coords, &coords);
1148 assert_eq!(iter.count(), 256);
1149 }
1150
1151 #[test]
1152 fn read_points_fast_does_not_panic_on_empty_glyph_with_padding() {
1153 let glyph_bytes: &[u8] = &[
1154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
1159 let glyph = SimpleGlyph::read(FontData::new(glyph_bytes)).expect("parses");
1160 assert_eq!(glyph.num_points(), 0);
1161 let mut points: Vec<Point<f32>> = vec![];
1162 let mut flags: Vec<PointFlags> = vec![];
1163 assert!(glyph.read_points_fast(&mut points, &mut flags).is_ok());
1164 }
1165}