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