1pub mod bytecode;
4pub mod outline;
5
6use bytemuck::AnyBitPattern;
7use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Sub};
8use types::{F26Dot6, Point};
9
10include!("../../generated/generated_glyf.rs");
11
12pub const PHANTOM_POINT_COUNT: usize = 4;
20
21#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
24pub struct PointMarker(u8);
25
26impl PointMarker {
27 pub const HAS_DELTA: Self = Self(0x4);
30
31 pub const TOUCHED_X: Self = Self(0x10);
34
35 pub const TOUCHED_Y: Self = Self(0x20);
38
39 pub const TOUCHED: Self = Self(Self::TOUCHED_X.0 | Self::TOUCHED_Y.0);
42
43 pub const WEAK_INTERPOLATION: Self = Self(0x2);
47
48 pub const NEAR: PointMarker = Self(0x8);
52}
53
54impl core::ops::BitOr for PointMarker {
55 type Output = Self;
56
57 fn bitor(self, rhs: Self) -> Self::Output {
58 Self(self.0 | rhs.0)
59 }
60}
61
62#[derive(
68 Copy, Clone, PartialEq, Eq, Default, Debug, bytemuck::AnyBitPattern, bytemuck::NoUninit,
69)]
70#[repr(transparent)]
71pub struct PointFlags(u8);
72
73impl PointFlags {
74 const ON_CURVE: u8 = SimpleGlyphFlags::ON_CURVE_POINT.bits;
77 const OFF_CURVE_CUBIC: u8 = SimpleGlyphFlags::CUBIC.bits;
78 const CURVE_MASK: u8 = Self::ON_CURVE | Self::OFF_CURVE_CUBIC;
79
80 pub const fn on_curve() -> Self {
82 Self(Self::ON_CURVE)
83 }
84
85 pub const fn off_curve_quad() -> Self {
87 Self(0)
88 }
89
90 pub const fn off_curve_cubic() -> Self {
92 Self(Self::OFF_CURVE_CUBIC)
93 }
94
95 pub const fn from_bits(bits: u8) -> Self {
98 Self(bits & Self::CURVE_MASK)
99 }
100
101 #[inline]
103 pub const fn is_on_curve(self) -> bool {
104 self.0 & Self::ON_CURVE != 0
105 }
106
107 #[inline]
109 pub const fn is_off_curve_quad(self) -> bool {
110 self.0 & Self::CURVE_MASK == 0
111 }
112
113 #[inline]
115 pub const fn is_off_curve_cubic(self) -> bool {
116 self.0 & Self::OFF_CURVE_CUBIC != 0
117 }
118
119 pub const fn is_off_curve(self) -> bool {
120 self.is_off_curve_quad() || self.is_off_curve_cubic()
121 }
122
123 pub fn flip_on_curve(&mut self) {
127 self.0 ^= 1;
128 }
129
130 pub fn set_on_curve(&mut self) {
134 self.0 |= Self::ON_CURVE;
135 }
136
137 pub fn clear_on_curve(&mut self) {
141 self.0 &= !Self::ON_CURVE;
142 }
143
144 pub fn has_marker(self, marker: PointMarker) -> bool {
146 self.0 & marker.0 != 0
147 }
148
149 pub fn set_marker(&mut self, marker: PointMarker) {
151 self.0 |= marker.0;
152 }
153
154 pub fn clear_marker(&mut self, marker: PointMarker) {
156 self.0 &= !marker.0
157 }
158
159 pub const fn without_markers(self) -> Self {
161 Self(self.0 & Self::CURVE_MASK)
162 }
163
164 pub const fn to_bits(self) -> u8 {
166 self.0
167 }
168}
169
170pub trait PointCoord:
172 Copy
173 + Default
174 + AnyBitPattern
176 + PartialEq
178 + PartialOrd
179 + Add<Output = Self>
181 + AddAssign
182 + Sub<Output = Self>
183 + Div<Output = Self>
184 + Mul<Output = Self>
185 + MulAssign {
186 fn from_fixed(x: Fixed) -> Self;
187 fn from_i32(x: i32) -> Self;
188 fn to_f32(self) -> f32;
189 fn midpoint(self, other: Self) -> Self;
190}
191
192impl<'a> SimpleGlyph<'a> {
193 pub fn num_points(&self) -> usize {
195 self.end_pts_of_contours()
196 .last()
197 .map(|last| last.get() as usize + 1)
198 .unwrap_or(0)
199 }
200
201 pub fn has_overlapping_contours(&self) -> bool {
203 FontData::new(self.glyph_data())
207 .read_at::<SimpleGlyphFlags>(0)
208 .map(|flag| flag.contains(SimpleGlyphFlags::OVERLAP_SIMPLE))
209 .unwrap_or_default()
210 }
211
212 pub fn read_points_fast<C: PointCoord>(
223 &self,
224 points: &mut [Point<C>],
225 flags: &mut [PointFlags],
226 ) -> Result<(), ReadError> {
227 let n_points = self.num_points();
228 if points.len() != n_points || flags.len() != n_points {
229 return Err(ReadError::InvalidArrayLen);
230 }
231 if n_points == 0 {
232 return Ok(());
233 }
234 let mut cursor = FontData::new(self.glyph_data()).cursor();
235 let flags_data = cursor.read_array::<u8>(cursor.remaining_bytes())?;
239 let mut flags_iter = flags_data.iter().copied();
240 let mut read_flags_bytes = 0;
243 let mut i = 0;
244 while let Some(flag_bits) = flags_iter.next() {
245 read_flags_bytes += 1;
246 if SimpleGlyphFlags::from_bits_truncate(flag_bits)
247 .contains(SimpleGlyphFlags::REPEAT_FLAG)
248 {
249 let count = (flags_iter.next().ok_or(ReadError::OutOfBounds)? as usize + 1)
250 .min(n_points - i);
251 read_flags_bytes += 1;
252 for f in &mut flags[i..i + count] {
253 f.0 = flag_bits;
254 }
255 i += count;
256 } else {
257 flags[i].0 = flag_bits;
258 i += 1;
259 }
260 if i == n_points {
261 break;
262 }
263 }
264 let coords = self
271 .glyph_data()
272 .get(read_flags_bytes..)
273 .ok_or(ReadError::OutOfBounds)?;
274 let mut bytes = coords.iter();
275 let mut x = 0i32;
276 for (&point_flags, point) in flags.iter().zip(points.as_mut()) {
277 let mut delta = 0i32;
278 let flag = SimpleGlyphFlags::from_bits_truncate(point_flags.0);
279 if flag.contains(SimpleGlyphFlags::X_SHORT_VECTOR) {
280 delta = *bytes.next().ok_or(ReadError::OutOfBounds)? as i32;
281 if !flag.contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
282 delta = -delta;
283 }
284 } else if !flag.contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) {
285 let hi = *bytes.next().ok_or(ReadError::OutOfBounds)?;
286 let lo = *bytes.next().ok_or(ReadError::OutOfBounds)?;
287 delta = i16::from_be_bytes([hi, lo]) as i32;
288 }
289 x = x.wrapping_add(delta);
290 point.x = C::from_i32(x);
291 }
292 let mut y = 0i32;
293 for (point_flags, point) in flags.iter_mut().zip(points.as_mut()) {
294 let mut delta = 0i32;
295 let flag = SimpleGlyphFlags::from_bits_truncate(point_flags.0);
296 if flag.contains(SimpleGlyphFlags::Y_SHORT_VECTOR) {
297 delta = *bytes.next().ok_or(ReadError::OutOfBounds)? as i32;
298 if !flag.contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
299 delta = -delta;
300 }
301 } else if !flag.contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) {
302 let hi = *bytes.next().ok_or(ReadError::OutOfBounds)?;
303 let lo = *bytes.next().ok_or(ReadError::OutOfBounds)?;
304 delta = i16::from_be_bytes([hi, lo]) as i32;
305 }
306 y = y.wrapping_add(delta);
307 point.y = C::from_i32(y);
308 let flags_mask = if cfg!(feature = "spec_next") {
309 PointFlags::CURVE_MASK
310 } else {
311 PointFlags::ON_CURVE
313 };
314 point_flags.0 &= flags_mask;
315 }
316 Ok(())
317 }
318
319 pub fn points(&self) -> impl Iterator<Item = CurvePoint> + 'a + Clone {
326 self.points_impl()
327 .unwrap_or_else(|| PointIter::new(&[], &[], &[]))
328 }
329
330 fn points_impl(&self) -> Option<PointIter<'a>> {
331 let end_points = self.end_pts_of_contours();
332 let n_points = end_points.last()?.get().checked_add(1)?;
333 let data = self.glyph_data();
334 let lens = resolve_coords_len(data, n_points).ok()?;
335 let total_len = lens.flags + lens.x_coords + lens.y_coords;
336 if data.len() < total_len as usize {
337 return None;
338 }
339
340 let (flags, data) = data.split_at(lens.flags as usize);
341 let (x_coords, y_coords) = data.split_at(lens.x_coords as usize);
342
343 Some(PointIter::new(flags, x_coords, y_coords))
344 }
345}
346
347#[derive(Clone, Copy, Debug, PartialEq, Eq)]
351pub struct CurvePoint {
352 pub x: i16,
354 pub y: i16,
356 pub on_curve: bool,
358}
359
360impl CurvePoint {
361 pub fn new(x: i16, y: i16, on_curve: bool) -> Self {
363 Self { x, y, on_curve }
364 }
365
366 pub fn on_curve(x: i16, y: i16) -> Self {
368 Self::new(x, y, true)
369 }
370
371 pub fn off_curve(x: i16, y: i16) -> Self {
373 Self::new(x, y, false)
374 }
375}
376
377#[derive(Clone)]
378struct PointIter<'a> {
379 flags: Cursor<'a>,
380 x_coords: Cursor<'a>,
381 y_coords: Cursor<'a>,
382 flag_repeats: u16,
383 cur_flags: SimpleGlyphFlags,
384 cur_x: i16,
385 cur_y: i16,
386}
387
388impl Iterator for PointIter<'_> {
389 type Item = CurvePoint;
390 fn next(&mut self) -> Option<Self::Item> {
391 self.advance_flags()?;
392 self.advance_points();
393 let is_on_curve = self.cur_flags.contains(SimpleGlyphFlags::ON_CURVE_POINT);
394 Some(CurvePoint::new(self.cur_x, self.cur_y, is_on_curve))
395 }
396}
397
398impl<'a> PointIter<'a> {
399 fn new(flags: &'a [u8], x_coords: &'a [u8], y_coords: &'a [u8]) -> Self {
400 Self {
401 flags: FontData::new(flags).cursor(),
402 x_coords: FontData::new(x_coords).cursor(),
403 y_coords: FontData::new(y_coords).cursor(),
404 flag_repeats: 0,
405 cur_flags: SimpleGlyphFlags::empty(),
406 cur_x: 0,
407 cur_y: 0,
408 }
409 }
410
411 fn advance_flags(&mut self) -> Option<()> {
412 if self.flag_repeats == 0 {
413 self.cur_flags = SimpleGlyphFlags::from_bits_truncate(self.flags.read().ok()?);
414 self.flag_repeats = self
415 .cur_flags
416 .contains(SimpleGlyphFlags::REPEAT_FLAG)
417 .then(|| self.flags.read::<u8>().ok())
418 .flatten()
419 .unwrap_or(0) as u16
420 + 1;
421 }
422 self.flag_repeats -= 1;
423 Some(())
424 }
425
426 fn advance_points(&mut self) {
427 let x_short = self.cur_flags.contains(SimpleGlyphFlags::X_SHORT_VECTOR);
428 let x_same_or_pos = self
429 .cur_flags
430 .contains(SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR);
431 let y_short = self.cur_flags.contains(SimpleGlyphFlags::Y_SHORT_VECTOR);
432 let y_same_or_pos = self
433 .cur_flags
434 .contains(SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR);
435
436 let delta_x = match (x_short, x_same_or_pos) {
437 (true, false) => -(self.x_coords.read::<u8>().unwrap_or(0) as i16),
438 (true, true) => self.x_coords.read::<u8>().unwrap_or(0) as i16,
439 (false, false) => self.x_coords.read::<i16>().unwrap_or(0),
440 _ => 0,
441 };
442
443 let delta_y = match (y_short, y_same_or_pos) {
444 (true, false) => -(self.y_coords.read::<u8>().unwrap_or(0) as i16),
445 (true, true) => self.y_coords.read::<u8>().unwrap_or(0) as i16,
446 (false, false) => self.y_coords.read::<i16>().unwrap_or(0),
447 _ => 0,
448 };
449
450 self.cur_x = self.cur_x.wrapping_add(delta_x);
451 self.cur_y = self.cur_y.wrapping_add(delta_y);
452 }
453}
454
455fn resolve_coords_len(data: &[u8], points_total: u16) -> Result<FieldLengths, ReadError> {
460 let mut cursor = FontData::new(data).cursor();
461 let mut flags_left = u32::from(points_total);
462 let mut x_coords_len = 0;
464 let mut y_coords_len = 0;
465 while flags_left > 0 {
467 let flags: SimpleGlyphFlags = cursor.read()?;
468
469 let repeats = if flags.contains(SimpleGlyphFlags::REPEAT_FLAG) {
471 let repeats: u8 = cursor.read()?;
472 u32::from(repeats) + 1
473 } else {
474 1
475 };
476
477 if repeats > flags_left {
478 return Err(ReadError::MalformedData("repeat count too large in glyf"));
479 }
480
481 let x_short = SimpleGlyphFlags::X_SHORT_VECTOR;
499 let x_long = SimpleGlyphFlags::X_SHORT_VECTOR
500 | SimpleGlyphFlags::X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR;
501 let y_short = SimpleGlyphFlags::Y_SHORT_VECTOR;
502 let y_long = SimpleGlyphFlags::Y_SHORT_VECTOR
503 | SimpleGlyphFlags::Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR;
504 x_coords_len += ((flags & x_short).bits() != 0) as u32 * repeats;
505 x_coords_len += ((flags & x_long).bits() == 0) as u32 * repeats * 2;
506
507 y_coords_len += ((flags & y_short).bits() != 0) as u32 * repeats;
508 y_coords_len += ((flags & y_long).bits() == 0) as u32 * repeats * 2;
509
510 flags_left -= repeats;
511 }
512
513 Ok(FieldLengths {
514 flags: cursor.position()? as u32,
515 x_coords: x_coords_len,
516 y_coords: y_coords_len,
517 })
518 }
520
521struct FieldLengths {
522 flags: u32,
523 x_coords: u32,
524 y_coords: u32,
525}
526
527#[derive(Clone, Copy, Debug, PartialEq, Eq)]
529pub struct Transform {
530 pub xx: F2Dot14,
532 pub yx: F2Dot14,
534 pub xy: F2Dot14,
536 pub yy: F2Dot14,
538}
539
540impl Default for Transform {
541 fn default() -> Self {
542 Self {
543 xx: F2Dot14::from_f32(1.0),
544 yx: F2Dot14::from_f32(0.0),
545 xy: F2Dot14::from_f32(0.0),
546 yy: F2Dot14::from_f32(1.0),
547 }
548 }
549}
550
551#[derive(Clone, Debug, PartialEq, Eq)]
553pub struct Component {
554 pub flags: CompositeGlyphFlags,
556 pub glyph: GlyphId16,
558 pub anchor: Anchor,
560 pub transform: Transform,
562}
563
564#[derive(Clone, Copy, Debug, PartialEq, Eq)]
566pub enum Anchor {
567 Offset { x: i16, y: i16 },
568 Point { base: u16, component: u16 },
569}
570
571impl<'a> CompositeGlyph<'a> {
572 pub fn components(&self) -> impl Iterator<Item = Component> + 'a + Clone {
574 ComponentIter {
575 cur_flags: CompositeGlyphFlags::empty(),
576 done: false,
577 cursor: FontData::new(self.component_data()).cursor(),
578 }
579 }
580
581 pub fn component_glyphs_and_flags(
584 &self,
585 ) -> impl Iterator<Item = (GlyphId16, CompositeGlyphFlags)> + 'a + Clone {
586 ComponentGlyphIdFlagsIter {
587 cur_flags: CompositeGlyphFlags::empty(),
588 done: false,
589 cursor: FontData::new(self.component_data()).cursor(),
590 }
591 }
592
593 pub fn count_and_instructions(&self) -> (usize, Option<&'a [u8]>) {
596 let mut iter = ComponentGlyphIdFlagsIter {
597 cur_flags: CompositeGlyphFlags::empty(),
598 done: false,
599 cursor: FontData::new(self.component_data()).cursor(),
600 };
601 let mut count = 0;
602 while iter.by_ref().next().is_some() {
603 count += 1;
604 }
605 let instructions = if iter
606 .cur_flags
607 .contains(CompositeGlyphFlags::WE_HAVE_INSTRUCTIONS)
608 {
609 iter.cursor
610 .read::<u16>()
611 .ok()
612 .map(|len| len as usize)
613 .and_then(|len| iter.cursor.read_array(len).ok())
614 } else {
615 None
616 };
617 (count, instructions)
618 }
619
620 pub fn instructions(&self) -> Option<&'a [u8]> {
622 self.count_and_instructions().1
623 }
624}
625
626#[derive(Clone)]
627struct ComponentIter<'a> {
628 cur_flags: CompositeGlyphFlags,
629 done: bool,
630 cursor: Cursor<'a>,
631}
632
633impl Iterator for ComponentIter<'_> {
634 type Item = Component;
635
636 fn next(&mut self) -> Option<Self::Item> {
637 if self.done {
638 return None;
639 }
640 let flags: CompositeGlyphFlags = self.cursor.read().ok()?;
641 self.cur_flags = flags;
642 let glyph = self.cursor.read::<GlyphId16>().ok()?;
643 let args_are_words = flags.contains(CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS);
644 let args_are_xy_values = flags.contains(CompositeGlyphFlags::ARGS_ARE_XY_VALUES);
645 let anchor = match (args_are_xy_values, args_are_words) {
646 (true, true) => Anchor::Offset {
647 x: self.cursor.read().ok()?,
648 y: self.cursor.read().ok()?,
649 },
650 (true, false) => Anchor::Offset {
651 x: self.cursor.read::<i8>().ok()? as _,
652 y: self.cursor.read::<i8>().ok()? as _,
653 },
654 (false, true) => Anchor::Point {
655 base: self.cursor.read().ok()?,
656 component: self.cursor.read().ok()?,
657 },
658 (false, false) => Anchor::Point {
659 base: self.cursor.read::<u8>().ok()? as _,
660 component: self.cursor.read::<u8>().ok()? as _,
661 },
662 };
663 let mut transform = Transform::default();
664 if flags.contains(CompositeGlyphFlags::WE_HAVE_A_SCALE) {
665 transform.xx = self.cursor.read().ok()?;
666 transform.yy = transform.xx;
667 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
668 transform.xx = self.cursor.read().ok()?;
669 transform.yy = self.cursor.read().ok()?;
670 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO) {
671 transform.xx = self.cursor.read().ok()?;
672 transform.yx = self.cursor.read().ok()?;
673 transform.xy = self.cursor.read().ok()?;
674 transform.yy = self.cursor.read().ok()?;
675 }
676 self.done = !flags.contains(CompositeGlyphFlags::MORE_COMPONENTS);
677
678 Some(Component {
679 flags,
680 glyph,
681 anchor,
682 transform,
683 })
684 }
685}
686
687#[derive(Clone)]
692struct ComponentGlyphIdFlagsIter<'a> {
693 cur_flags: CompositeGlyphFlags,
694 done: bool,
695 cursor: Cursor<'a>,
696}
697
698impl Iterator for ComponentGlyphIdFlagsIter<'_> {
699 type Item = (GlyphId16, CompositeGlyphFlags);
700
701 fn next(&mut self) -> Option<Self::Item> {
702 if self.done {
703 return None;
704 }
705 let flags: CompositeGlyphFlags = self.cursor.read().ok()?;
706 self.cur_flags = flags;
707 let glyph = self.cursor.read::<GlyphId16>().ok()?;
708 let args_are_words = flags.contains(CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS);
709 if args_are_words {
710 self.cursor.advance_by(4);
711 } else {
712 self.cursor.advance_by(2);
713 }
714 if flags.contains(CompositeGlyphFlags::WE_HAVE_A_SCALE) {
715 self.cursor.advance_by(2);
716 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE) {
717 self.cursor.advance_by(4);
718 } else if flags.contains(CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO) {
719 self.cursor.advance_by(8);
720 }
721 self.done = !flags.contains(CompositeGlyphFlags::MORE_COMPONENTS);
722 Some((glyph, flags))
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
866 .get(GlyphId::new(0), &glyf)
867 .and_then(|g| g.into_glyph())
868 .unwrap();
869 assert_eq!(glyph.number_of_contours(), 2);
870 let simple_glyph = if let Glyph::Simple(simple) = glyph {
871 simple
872 } else {
873 panic!("expected simple glyph");
874 };
875 assert_eq!(
876 simple_glyph
877 .end_pts_of_contours()
878 .iter()
879 .map(|x| x.get())
880 .collect::<Vec<_>>(),
881 &[3, 7]
882 );
883 assert_eq!(
884 simple_glyph
885 .points()
886 .map(|pt| (pt.x, pt.y, pt.on_curve))
887 .collect::<Vec<_>>(),
888 &[
889 (5, 0, true),
890 (5, 100, true),
891 (45, 100, true),
892 (45, 0, true),
893 (10, 5, true),
894 (40, 5, true),
895 (40, 95, true),
896 (10, 95, true),
897 ]
898 );
899 }
900
901 fn all_glyphs(font_data: &[u8]) -> impl Iterator<Item = Option<Glyph<'_>>> {
903 let font = FontRef::new(font_data).unwrap();
904 let loca = font.loca(None).unwrap();
905 let glyf = font.glyf().unwrap();
906 let glyph_count = font.maxp().unwrap().num_glyphs() as u32;
907 (0..glyph_count).map(move |gid| {
908 loca.get(GlyphId::new(gid), &glyf)
909 .and_then(|g| g.into_glyph())
910 })
911 }
912
913 #[test]
914 fn simple_glyph_overlapping_contour_flag() {
915 let gids_with_overlap: Vec<_> = all_glyphs(font_test_data::VAZIRMATN_VAR)
916 .enumerate()
917 .filter_map(|(gid, glyph)| match glyph {
918 Some(Glyph::Simple(glyph)) if glyph.has_overlapping_contours() => Some(gid),
919 _ => None,
920 })
921 .collect();
922 let expected_gids_with_overlap = vec![3];
924 assert_eq!(expected_gids_with_overlap, gids_with_overlap);
925 }
926
927 #[test]
928 fn composite_glyph_overlapping_contour_flag() {
929 let gids_components_with_overlap: Vec<_> = all_glyphs(font_test_data::VAZIRMATN_VAR)
930 .enumerate()
931 .filter_map(|(gid, glyph)| match glyph {
932 Some(Glyph::Composite(glyph)) => Some((gid, glyph)),
933 _ => None,
934 })
935 .flat_map(|(gid, glyph)| {
936 glyph
937 .components()
938 .enumerate()
939 .filter_map(move |(comp_ix, comp)| {
940 comp.flags
941 .contains(CompositeGlyphFlags::OVERLAP_COMPOUND)
942 .then_some((gid, comp_ix))
943 })
944 })
945 .collect();
946 let expected_gids_components_with_overlap = vec![(2, 1)];
948 assert_eq!(
949 expected_gids_components_with_overlap,
950 gids_components_with_overlap
951 );
952 }
953
954 #[test]
955 fn compute_anchor_flags() {
956 let anchor = Anchor::Offset { x: -128, y: 127 };
957 assert_eq!(
958 anchor.compute_flags(),
959 CompositeGlyphFlags::ARGS_ARE_XY_VALUES
960 );
961
962 let anchor = Anchor::Offset { x: -129, y: 127 };
963 assert_eq!(
964 anchor.compute_flags(),
965 CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
966 );
967 let anchor = Anchor::Offset { x: -1, y: 128 };
968 assert_eq!(
969 anchor.compute_flags(),
970 CompositeGlyphFlags::ARGS_ARE_XY_VALUES | CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
971 );
972
973 let anchor = Anchor::Point {
974 base: 255,
975 component: 20,
976 };
977 assert_eq!(anchor.compute_flags(), CompositeGlyphFlags::empty());
978
979 let anchor = Anchor::Point {
980 base: 256,
981 component: 20,
982 };
983 assert_eq!(
984 anchor.compute_flags(),
985 CompositeGlyphFlags::ARG_1_AND_2_ARE_WORDS
986 )
987 }
988
989 #[test]
990 fn compute_transform_flags() {
991 fn make_xform(xx: f32, yx: f32, xy: f32, yy: f32) -> Transform {
992 Transform {
993 xx: F2Dot14::from_f32(xx),
994 yx: F2Dot14::from_f32(yx),
995 xy: F2Dot14::from_f32(xy),
996 yy: F2Dot14::from_f32(yy),
997 }
998 }
999
1000 assert_eq!(
1001 make_xform(1.0, 0., 0., 1.0).compute_flags(),
1002 CompositeGlyphFlags::empty()
1003 );
1004 assert_eq!(
1005 make_xform(2.0, 0., 0., 2.0).compute_flags(),
1006 CompositeGlyphFlags::WE_HAVE_A_SCALE
1007 );
1008 assert_eq!(
1009 make_xform(2.0, 0., 0., 1.0).compute_flags(),
1010 CompositeGlyphFlags::WE_HAVE_AN_X_AND_Y_SCALE
1011 );
1012 assert_eq!(
1013 make_xform(2.0, 0., 1.0, 1.0).compute_flags(),
1014 CompositeGlyphFlags::WE_HAVE_A_TWO_BY_TWO
1015 );
1016 }
1017
1018 #[test]
1019 fn point_flags_and_marker_bits() {
1020 let bits = [
1021 PointFlags::OFF_CURVE_CUBIC,
1022 PointFlags::ON_CURVE,
1023 PointMarker::HAS_DELTA.0,
1024 PointMarker::TOUCHED_X.0,
1025 PointMarker::TOUCHED_Y.0,
1026 ];
1027 for (i, a) in bits.iter().enumerate() {
1029 for b in &bits[i + 1..] {
1030 assert_eq!(a & b, 0);
1031 }
1032 }
1033 }
1034
1035 #[test]
1036 fn cubic_glyf() {
1037 let font = FontRef::new(font_test_data::CUBIC_GLYF).unwrap();
1038 let loca = font.loca(None).unwrap();
1039 let glyf = font.glyf().unwrap();
1040 let glyph = loca
1041 .get(GlyphId::new(2), &glyf)
1042 .and_then(|g| g.into_glyph())
1043 .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}