1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8#[derive(Debug, Clone, Copy)]
11#[doc(hidden)]
12pub struct GposMarker {
13 feature_variations_offset_byte_start: Option<usize>,
14}
15
16impl GposMarker {
17 pub fn version_byte_range(&self) -> Range<usize> {
18 let start = 0;
19 start..start + MajorMinor::RAW_BYTE_LEN
20 }
21
22 pub fn script_list_offset_byte_range(&self) -> Range<usize> {
23 let start = self.version_byte_range().end;
24 start..start + Offset16::RAW_BYTE_LEN
25 }
26
27 pub fn feature_list_offset_byte_range(&self) -> Range<usize> {
28 let start = self.script_list_offset_byte_range().end;
29 start..start + Offset16::RAW_BYTE_LEN
30 }
31
32 pub fn lookup_list_offset_byte_range(&self) -> Range<usize> {
33 let start = self.feature_list_offset_byte_range().end;
34 start..start + Offset16::RAW_BYTE_LEN
35 }
36
37 pub fn feature_variations_offset_byte_range(&self) -> Option<Range<usize>> {
38 let start = self.feature_variations_offset_byte_start?;
39 Some(start..start + Offset32::RAW_BYTE_LEN)
40 }
41}
42
43impl MinByteRange for GposMarker {
44 fn min_byte_range(&self) -> Range<usize> {
45 0..self.lookup_list_offset_byte_range().end
46 }
47}
48
49impl TopLevelTable for Gpos<'_> {
50 const TAG: Tag = Tag::new(b"GPOS");
52}
53
54impl<'a> FontRead<'a> for Gpos<'a> {
55 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
56 let mut cursor = data.cursor();
57 let version: MajorMinor = cursor.read()?;
58 cursor.advance::<Offset16>();
59 cursor.advance::<Offset16>();
60 cursor.advance::<Offset16>();
61 let feature_variations_offset_byte_start = version
62 .compatible((1u16, 1u16))
63 .then(|| cursor.position())
64 .transpose()?;
65 version
66 .compatible((1u16, 1u16))
67 .then(|| cursor.advance::<Offset32>());
68 cursor.finish(GposMarker {
69 feature_variations_offset_byte_start,
70 })
71 }
72}
73
74pub type Gpos<'a> = TableRef<'a, GposMarker>;
77
78#[allow(clippy::needless_lifetimes)]
79impl<'a> Gpos<'a> {
80 pub fn version(&self) -> MajorMinor {
82 let range = self.shape.version_byte_range();
83 self.data.read_at(range.start).unwrap()
84 }
85
86 pub fn script_list_offset(&self) -> Offset16 {
88 let range = self.shape.script_list_offset_byte_range();
89 self.data.read_at(range.start).unwrap()
90 }
91
92 pub fn script_list(&self) -> Result<ScriptList<'a>, ReadError> {
94 let data = self.data;
95 self.script_list_offset().resolve(data)
96 }
97
98 pub fn feature_list_offset(&self) -> Offset16 {
100 let range = self.shape.feature_list_offset_byte_range();
101 self.data.read_at(range.start).unwrap()
102 }
103
104 pub fn feature_list(&self) -> Result<FeatureList<'a>, ReadError> {
106 let data = self.data;
107 self.feature_list_offset().resolve(data)
108 }
109
110 pub fn lookup_list_offset(&self) -> Offset16 {
112 let range = self.shape.lookup_list_offset_byte_range();
113 self.data.read_at(range.start).unwrap()
114 }
115
116 pub fn lookup_list(&self) -> Result<PositionLookupList<'a>, ReadError> {
118 let data = self.data;
119 self.lookup_list_offset().resolve(data)
120 }
121
122 pub fn feature_variations_offset(&self) -> Option<Nullable<Offset32>> {
123 let range = self.shape.feature_variations_offset_byte_range()?;
124 Some(self.data.read_at(range.start).unwrap())
125 }
126
127 pub fn feature_variations(&self) -> Option<Result<FeatureVariations<'a>, ReadError>> {
129 let data = self.data;
130 self.feature_variations_offset().map(|x| x.resolve(data))?
131 }
132}
133
134#[cfg(feature = "experimental_traverse")]
135impl<'a> SomeTable<'a> for Gpos<'a> {
136 fn type_name(&self) -> &str {
137 "Gpos"
138 }
139 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
140 let version = self.version();
141 match idx {
142 0usize => Some(Field::new("version", self.version())),
143 1usize => Some(Field::new(
144 "script_list_offset",
145 FieldType::offset(self.script_list_offset(), self.script_list()),
146 )),
147 2usize => Some(Field::new(
148 "feature_list_offset",
149 FieldType::offset(self.feature_list_offset(), self.feature_list()),
150 )),
151 3usize => Some(Field::new(
152 "lookup_list_offset",
153 FieldType::offset(self.lookup_list_offset(), self.lookup_list()),
154 )),
155 4usize if version.compatible((1u16, 1u16)) => Some(Field::new(
156 "feature_variations_offset",
157 FieldType::offset(
158 self.feature_variations_offset().unwrap(),
159 self.feature_variations(),
160 ),
161 )),
162 _ => None,
163 }
164 }
165}
166
167#[cfg(feature = "experimental_traverse")]
168#[allow(clippy::needless_lifetimes)]
169impl<'a> std::fmt::Debug for Gpos<'a> {
170 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171 (self as &dyn SomeTable<'a>).fmt(f)
172 }
173}
174
175pub enum PositionLookup<'a> {
177 Single(Lookup<'a, SinglePos<'a>>),
178 Pair(Lookup<'a, PairPos<'a>>),
179 Cursive(Lookup<'a, CursivePosFormat1<'a>>),
180 MarkToBase(Lookup<'a, MarkBasePosFormat1<'a>>),
181 MarkToLig(Lookup<'a, MarkLigPosFormat1<'a>>),
182 MarkToMark(Lookup<'a, MarkMarkPosFormat1<'a>>),
183 Contextual(Lookup<'a, PositionSequenceContext<'a>>),
184 ChainContextual(Lookup<'a, PositionChainContext<'a>>),
185 Extension(Lookup<'a, ExtensionSubtable<'a>>),
186}
187
188impl<'a> FontRead<'a> for PositionLookup<'a> {
189 fn read(bytes: FontData<'a>) -> Result<Self, ReadError> {
190 let untyped = Lookup::read(bytes)?;
191 match untyped.lookup_type() {
192 1 => Ok(PositionLookup::Single(untyped.into_concrete())),
193 2 => Ok(PositionLookup::Pair(untyped.into_concrete())),
194 3 => Ok(PositionLookup::Cursive(untyped.into_concrete())),
195 4 => Ok(PositionLookup::MarkToBase(untyped.into_concrete())),
196 5 => Ok(PositionLookup::MarkToLig(untyped.into_concrete())),
197 6 => Ok(PositionLookup::MarkToMark(untyped.into_concrete())),
198 7 => Ok(PositionLookup::Contextual(untyped.into_concrete())),
199 8 => Ok(PositionLookup::ChainContextual(untyped.into_concrete())),
200 9 => Ok(PositionLookup::Extension(untyped.into_concrete())),
201 other => Err(ReadError::InvalidFormat(other.into())),
202 }
203 }
204}
205
206impl<'a> PositionLookup<'a> {
207 #[allow(dead_code)]
208 pub(crate) fn of_unit_type(&self) -> Lookup<'a, ()> {
212 match self {
213 PositionLookup::Single(inner) => inner.of_unit_type(),
214 PositionLookup::Pair(inner) => inner.of_unit_type(),
215 PositionLookup::Cursive(inner) => inner.of_unit_type(),
216 PositionLookup::MarkToBase(inner) => inner.of_unit_type(),
217 PositionLookup::MarkToLig(inner) => inner.of_unit_type(),
218 PositionLookup::MarkToMark(inner) => inner.of_unit_type(),
219 PositionLookup::Contextual(inner) => inner.of_unit_type(),
220 PositionLookup::ChainContextual(inner) => inner.of_unit_type(),
221 PositionLookup::Extension(inner) => inner.of_unit_type(),
222 }
223 }
224}
225
226#[cfg(feature = "experimental_traverse")]
227impl<'a> PositionLookup<'a> {
228 fn dyn_inner(&self) -> &(dyn SomeTable<'a> + 'a) {
229 match self {
230 PositionLookup::Single(table) => table,
231 PositionLookup::Pair(table) => table,
232 PositionLookup::Cursive(table) => table,
233 PositionLookup::MarkToBase(table) => table,
234 PositionLookup::MarkToLig(table) => table,
235 PositionLookup::MarkToMark(table) => table,
236 PositionLookup::Contextual(table) => table,
237 PositionLookup::ChainContextual(table) => table,
238 PositionLookup::Extension(table) => table,
239 }
240 }
241}
242
243#[cfg(feature = "experimental_traverse")]
244impl<'a> SomeTable<'a> for PositionLookup<'a> {
245 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
246 self.dyn_inner().get_field(idx)
247 }
248 fn type_name(&self) -> &str {
249 self.dyn_inner().type_name()
250 }
251}
252
253#[cfg(feature = "experimental_traverse")]
254impl std::fmt::Debug for PositionLookup<'_> {
255 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256 self.dyn_inner().fmt(f)
257 }
258}
259
260#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
262#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
263#[repr(transparent)]
264pub struct ValueFormat {
265 bits: u16,
266}
267
268impl ValueFormat {
269 pub const X_PLACEMENT: Self = Self { bits: 0x0001 };
271
272 pub const Y_PLACEMENT: Self = Self { bits: 0x0002 };
274
275 pub const X_ADVANCE: Self = Self { bits: 0x0004 };
277
278 pub const Y_ADVANCE: Self = Self { bits: 0x0008 };
280
281 pub const X_PLACEMENT_DEVICE: Self = Self { bits: 0x0010 };
284
285 pub const Y_PLACEMENT_DEVICE: Self = Self { bits: 0x0020 };
288
289 pub const X_ADVANCE_DEVICE: Self = Self { bits: 0x0040 };
292
293 pub const Y_ADVANCE_DEVICE: Self = Self { bits: 0x0080 };
296}
297
298impl ValueFormat {
299 #[inline]
301 pub const fn empty() -> Self {
302 Self { bits: 0 }
303 }
304
305 #[inline]
307 pub const fn all() -> Self {
308 Self {
309 bits: Self::X_PLACEMENT.bits
310 | Self::Y_PLACEMENT.bits
311 | Self::X_ADVANCE.bits
312 | Self::Y_ADVANCE.bits
313 | Self::X_PLACEMENT_DEVICE.bits
314 | Self::Y_PLACEMENT_DEVICE.bits
315 | Self::X_ADVANCE_DEVICE.bits
316 | Self::Y_ADVANCE_DEVICE.bits,
317 }
318 }
319
320 #[inline]
322 pub const fn bits(&self) -> u16 {
323 self.bits
324 }
325
326 #[inline]
329 pub const fn from_bits(bits: u16) -> Option<Self> {
330 if (bits & !Self::all().bits()) == 0 {
331 Some(Self { bits })
332 } else {
333 None
334 }
335 }
336
337 #[inline]
340 pub const fn from_bits_truncate(bits: u16) -> Self {
341 Self {
342 bits: bits & Self::all().bits,
343 }
344 }
345
346 #[inline]
348 pub const fn is_empty(&self) -> bool {
349 self.bits() == Self::empty().bits()
350 }
351
352 #[inline]
354 pub const fn intersects(&self, other: Self) -> bool {
355 !(Self {
356 bits: self.bits & other.bits,
357 })
358 .is_empty()
359 }
360
361 #[inline]
363 pub const fn contains(&self, other: Self) -> bool {
364 (self.bits & other.bits) == other.bits
365 }
366
367 #[inline]
369 pub fn insert(&mut self, other: Self) {
370 self.bits |= other.bits;
371 }
372
373 #[inline]
375 pub fn remove(&mut self, other: Self) {
376 self.bits &= !other.bits;
377 }
378
379 #[inline]
381 pub fn toggle(&mut self, other: Self) {
382 self.bits ^= other.bits;
383 }
384
385 #[inline]
396 #[must_use]
397 pub const fn intersection(self, other: Self) -> Self {
398 Self {
399 bits: self.bits & other.bits,
400 }
401 }
402
403 #[inline]
414 #[must_use]
415 pub const fn union(self, other: Self) -> Self {
416 Self {
417 bits: self.bits | other.bits,
418 }
419 }
420
421 #[inline]
434 #[must_use]
435 pub const fn difference(self, other: Self) -> Self {
436 Self {
437 bits: self.bits & !other.bits,
438 }
439 }
440}
441
442impl std::ops::BitOr for ValueFormat {
443 type Output = Self;
444
445 #[inline]
447 fn bitor(self, other: ValueFormat) -> Self {
448 Self {
449 bits: self.bits | other.bits,
450 }
451 }
452}
453
454impl std::ops::BitOrAssign for ValueFormat {
455 #[inline]
457 fn bitor_assign(&mut self, other: Self) {
458 self.bits |= other.bits;
459 }
460}
461
462impl std::ops::BitXor for ValueFormat {
463 type Output = Self;
464
465 #[inline]
467 fn bitxor(self, other: Self) -> Self {
468 Self {
469 bits: self.bits ^ other.bits,
470 }
471 }
472}
473
474impl std::ops::BitXorAssign for ValueFormat {
475 #[inline]
477 fn bitxor_assign(&mut self, other: Self) {
478 self.bits ^= other.bits;
479 }
480}
481
482impl std::ops::BitAnd for ValueFormat {
483 type Output = Self;
484
485 #[inline]
487 fn bitand(self, other: Self) -> Self {
488 Self {
489 bits: self.bits & other.bits,
490 }
491 }
492}
493
494impl std::ops::BitAndAssign for ValueFormat {
495 #[inline]
497 fn bitand_assign(&mut self, other: Self) {
498 self.bits &= other.bits;
499 }
500}
501
502impl std::ops::Sub for ValueFormat {
503 type Output = Self;
504
505 #[inline]
507 fn sub(self, other: Self) -> Self {
508 Self {
509 bits: self.bits & !other.bits,
510 }
511 }
512}
513
514impl std::ops::SubAssign for ValueFormat {
515 #[inline]
517 fn sub_assign(&mut self, other: Self) {
518 self.bits &= !other.bits;
519 }
520}
521
522impl std::ops::Not for ValueFormat {
523 type Output = Self;
524
525 #[inline]
527 fn not(self) -> Self {
528 Self { bits: !self.bits } & Self::all()
529 }
530}
531
532impl std::fmt::Debug for ValueFormat {
533 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
534 let members: &[(&str, Self)] = &[
535 ("X_PLACEMENT", Self::X_PLACEMENT),
536 ("Y_PLACEMENT", Self::Y_PLACEMENT),
537 ("X_ADVANCE", Self::X_ADVANCE),
538 ("Y_ADVANCE", Self::Y_ADVANCE),
539 ("X_PLACEMENT_DEVICE", Self::X_PLACEMENT_DEVICE),
540 ("Y_PLACEMENT_DEVICE", Self::Y_PLACEMENT_DEVICE),
541 ("X_ADVANCE_DEVICE", Self::X_ADVANCE_DEVICE),
542 ("Y_ADVANCE_DEVICE", Self::Y_ADVANCE_DEVICE),
543 ];
544 let mut first = true;
545 for (name, value) in members {
546 if self.contains(*value) {
547 if !first {
548 f.write_str(" | ")?;
549 }
550 first = false;
551 f.write_str(name)?;
552 }
553 }
554 if first {
555 f.write_str("(empty)")?;
556 }
557 Ok(())
558 }
559}
560
561impl std::fmt::Binary for ValueFormat {
562 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
563 std::fmt::Binary::fmt(&self.bits, f)
564 }
565}
566
567impl std::fmt::Octal for ValueFormat {
568 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
569 std::fmt::Octal::fmt(&self.bits, f)
570 }
571}
572
573impl std::fmt::LowerHex for ValueFormat {
574 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
575 std::fmt::LowerHex::fmt(&self.bits, f)
576 }
577}
578
579impl std::fmt::UpperHex for ValueFormat {
580 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
581 std::fmt::UpperHex::fmt(&self.bits, f)
582 }
583}
584
585impl font_types::Scalar for ValueFormat {
586 type Raw = <u16 as font_types::Scalar>::Raw;
587 fn to_raw(self) -> Self::Raw {
588 self.bits().to_raw()
589 }
590 fn from_raw(raw: Self::Raw) -> Self {
591 let t = <u16>::from_raw(raw);
592 Self::from_bits_truncate(t)
593 }
594}
595
596#[cfg(feature = "experimental_traverse")]
597impl<'a> From<ValueFormat> for FieldType<'a> {
598 fn from(src: ValueFormat) -> FieldType<'a> {
599 src.bits().into()
600 }
601}
602
603#[derive(Clone)]
606pub enum AnchorTable<'a> {
607 Format1(AnchorFormat1<'a>),
608 Format2(AnchorFormat2<'a>),
609 Format3(AnchorFormat3<'a>),
610}
611
612impl<'a> AnchorTable<'a> {
613 pub fn offset_data(&self) -> FontData<'a> {
615 match self {
616 Self::Format1(item) => item.offset_data(),
617 Self::Format2(item) => item.offset_data(),
618 Self::Format3(item) => item.offset_data(),
619 }
620 }
621
622 pub fn anchor_format(&self) -> u16 {
624 match self {
625 Self::Format1(item) => item.anchor_format(),
626 Self::Format2(item) => item.anchor_format(),
627 Self::Format3(item) => item.anchor_format(),
628 }
629 }
630
631 pub fn x_coordinate(&self) -> i16 {
633 match self {
634 Self::Format1(item) => item.x_coordinate(),
635 Self::Format2(item) => item.x_coordinate(),
636 Self::Format3(item) => item.x_coordinate(),
637 }
638 }
639
640 pub fn y_coordinate(&self) -> i16 {
642 match self {
643 Self::Format1(item) => item.y_coordinate(),
644 Self::Format2(item) => item.y_coordinate(),
645 Self::Format3(item) => item.y_coordinate(),
646 }
647 }
648}
649
650impl<'a> FontRead<'a> for AnchorTable<'a> {
651 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
652 let format: u16 = data.read_at(0usize)?;
653 match format {
654 AnchorFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
655 AnchorFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
656 AnchorFormat3Marker::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
657 other => Err(ReadError::InvalidFormat(other.into())),
658 }
659 }
660}
661
662impl MinByteRange for AnchorTable<'_> {
663 fn min_byte_range(&self) -> Range<usize> {
664 match self {
665 Self::Format1(item) => item.min_byte_range(),
666 Self::Format2(item) => item.min_byte_range(),
667 Self::Format3(item) => item.min_byte_range(),
668 }
669 }
670}
671
672#[cfg(feature = "experimental_traverse")]
673impl<'a> AnchorTable<'a> {
674 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
675 match self {
676 Self::Format1(table) => table,
677 Self::Format2(table) => table,
678 Self::Format3(table) => table,
679 }
680 }
681}
682
683#[cfg(feature = "experimental_traverse")]
684impl std::fmt::Debug for AnchorTable<'_> {
685 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
686 self.dyn_inner().fmt(f)
687 }
688}
689
690#[cfg(feature = "experimental_traverse")]
691impl<'a> SomeTable<'a> for AnchorTable<'a> {
692 fn type_name(&self) -> &str {
693 self.dyn_inner().type_name()
694 }
695 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
696 self.dyn_inner().get_field(idx)
697 }
698}
699
700impl Format<u16> for AnchorFormat1Marker {
701 const FORMAT: u16 = 1;
702}
703
704#[derive(Debug, Clone, Copy)]
706#[doc(hidden)]
707pub struct AnchorFormat1Marker {}
708
709impl AnchorFormat1Marker {
710 pub fn anchor_format_byte_range(&self) -> Range<usize> {
711 let start = 0;
712 start..start + u16::RAW_BYTE_LEN
713 }
714
715 pub fn x_coordinate_byte_range(&self) -> Range<usize> {
716 let start = self.anchor_format_byte_range().end;
717 start..start + i16::RAW_BYTE_LEN
718 }
719
720 pub fn y_coordinate_byte_range(&self) -> Range<usize> {
721 let start = self.x_coordinate_byte_range().end;
722 start..start + i16::RAW_BYTE_LEN
723 }
724}
725
726impl MinByteRange for AnchorFormat1Marker {
727 fn min_byte_range(&self) -> Range<usize> {
728 0..self.y_coordinate_byte_range().end
729 }
730}
731
732impl<'a> FontRead<'a> for AnchorFormat1<'a> {
733 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
734 let mut cursor = data.cursor();
735 cursor.advance::<u16>();
736 cursor.advance::<i16>();
737 cursor.advance::<i16>();
738 cursor.finish(AnchorFormat1Marker {})
739 }
740}
741
742pub type AnchorFormat1<'a> = TableRef<'a, AnchorFormat1Marker>;
744
745#[allow(clippy::needless_lifetimes)]
746impl<'a> AnchorFormat1<'a> {
747 pub fn anchor_format(&self) -> u16 {
749 let range = self.shape.anchor_format_byte_range();
750 self.data.read_at(range.start).unwrap()
751 }
752
753 pub fn x_coordinate(&self) -> i16 {
755 let range = self.shape.x_coordinate_byte_range();
756 self.data.read_at(range.start).unwrap()
757 }
758
759 pub fn y_coordinate(&self) -> i16 {
761 let range = self.shape.y_coordinate_byte_range();
762 self.data.read_at(range.start).unwrap()
763 }
764}
765
766#[cfg(feature = "experimental_traverse")]
767impl<'a> SomeTable<'a> for AnchorFormat1<'a> {
768 fn type_name(&self) -> &str {
769 "AnchorFormat1"
770 }
771 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
772 match idx {
773 0usize => Some(Field::new("anchor_format", self.anchor_format())),
774 1usize => Some(Field::new("x_coordinate", self.x_coordinate())),
775 2usize => Some(Field::new("y_coordinate", self.y_coordinate())),
776 _ => None,
777 }
778 }
779}
780
781#[cfg(feature = "experimental_traverse")]
782#[allow(clippy::needless_lifetimes)]
783impl<'a> std::fmt::Debug for AnchorFormat1<'a> {
784 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
785 (self as &dyn SomeTable<'a>).fmt(f)
786 }
787}
788
789impl Format<u16> for AnchorFormat2Marker {
790 const FORMAT: u16 = 2;
791}
792
793#[derive(Debug, Clone, Copy)]
795#[doc(hidden)]
796pub struct AnchorFormat2Marker {}
797
798impl AnchorFormat2Marker {
799 pub fn anchor_format_byte_range(&self) -> Range<usize> {
800 let start = 0;
801 start..start + u16::RAW_BYTE_LEN
802 }
803
804 pub fn x_coordinate_byte_range(&self) -> Range<usize> {
805 let start = self.anchor_format_byte_range().end;
806 start..start + i16::RAW_BYTE_LEN
807 }
808
809 pub fn y_coordinate_byte_range(&self) -> Range<usize> {
810 let start = self.x_coordinate_byte_range().end;
811 start..start + i16::RAW_BYTE_LEN
812 }
813
814 pub fn anchor_point_byte_range(&self) -> Range<usize> {
815 let start = self.y_coordinate_byte_range().end;
816 start..start + u16::RAW_BYTE_LEN
817 }
818}
819
820impl MinByteRange for AnchorFormat2Marker {
821 fn min_byte_range(&self) -> Range<usize> {
822 0..self.anchor_point_byte_range().end
823 }
824}
825
826impl<'a> FontRead<'a> for AnchorFormat2<'a> {
827 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
828 let mut cursor = data.cursor();
829 cursor.advance::<u16>();
830 cursor.advance::<i16>();
831 cursor.advance::<i16>();
832 cursor.advance::<u16>();
833 cursor.finish(AnchorFormat2Marker {})
834 }
835}
836
837pub type AnchorFormat2<'a> = TableRef<'a, AnchorFormat2Marker>;
839
840#[allow(clippy::needless_lifetimes)]
841impl<'a> AnchorFormat2<'a> {
842 pub fn anchor_format(&self) -> u16 {
844 let range = self.shape.anchor_format_byte_range();
845 self.data.read_at(range.start).unwrap()
846 }
847
848 pub fn x_coordinate(&self) -> i16 {
850 let range = self.shape.x_coordinate_byte_range();
851 self.data.read_at(range.start).unwrap()
852 }
853
854 pub fn y_coordinate(&self) -> i16 {
856 let range = self.shape.y_coordinate_byte_range();
857 self.data.read_at(range.start).unwrap()
858 }
859
860 pub fn anchor_point(&self) -> u16 {
862 let range = self.shape.anchor_point_byte_range();
863 self.data.read_at(range.start).unwrap()
864 }
865}
866
867#[cfg(feature = "experimental_traverse")]
868impl<'a> SomeTable<'a> for AnchorFormat2<'a> {
869 fn type_name(&self) -> &str {
870 "AnchorFormat2"
871 }
872 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
873 match idx {
874 0usize => Some(Field::new("anchor_format", self.anchor_format())),
875 1usize => Some(Field::new("x_coordinate", self.x_coordinate())),
876 2usize => Some(Field::new("y_coordinate", self.y_coordinate())),
877 3usize => Some(Field::new("anchor_point", self.anchor_point())),
878 _ => None,
879 }
880 }
881}
882
883#[cfg(feature = "experimental_traverse")]
884#[allow(clippy::needless_lifetimes)]
885impl<'a> std::fmt::Debug for AnchorFormat2<'a> {
886 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
887 (self as &dyn SomeTable<'a>).fmt(f)
888 }
889}
890
891impl Format<u16> for AnchorFormat3Marker {
892 const FORMAT: u16 = 3;
893}
894
895#[derive(Debug, Clone, Copy)]
897#[doc(hidden)]
898pub struct AnchorFormat3Marker {}
899
900impl AnchorFormat3Marker {
901 pub fn anchor_format_byte_range(&self) -> Range<usize> {
902 let start = 0;
903 start..start + u16::RAW_BYTE_LEN
904 }
905
906 pub fn x_coordinate_byte_range(&self) -> Range<usize> {
907 let start = self.anchor_format_byte_range().end;
908 start..start + i16::RAW_BYTE_LEN
909 }
910
911 pub fn y_coordinate_byte_range(&self) -> Range<usize> {
912 let start = self.x_coordinate_byte_range().end;
913 start..start + i16::RAW_BYTE_LEN
914 }
915
916 pub fn x_device_offset_byte_range(&self) -> Range<usize> {
917 let start = self.y_coordinate_byte_range().end;
918 start..start + Offset16::RAW_BYTE_LEN
919 }
920
921 pub fn y_device_offset_byte_range(&self) -> Range<usize> {
922 let start = self.x_device_offset_byte_range().end;
923 start..start + Offset16::RAW_BYTE_LEN
924 }
925}
926
927impl MinByteRange for AnchorFormat3Marker {
928 fn min_byte_range(&self) -> Range<usize> {
929 0..self.y_device_offset_byte_range().end
930 }
931}
932
933impl<'a> FontRead<'a> for AnchorFormat3<'a> {
934 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
935 let mut cursor = data.cursor();
936 cursor.advance::<u16>();
937 cursor.advance::<i16>();
938 cursor.advance::<i16>();
939 cursor.advance::<Offset16>();
940 cursor.advance::<Offset16>();
941 cursor.finish(AnchorFormat3Marker {})
942 }
943}
944
945pub type AnchorFormat3<'a> = TableRef<'a, AnchorFormat3Marker>;
947
948#[allow(clippy::needless_lifetimes)]
949impl<'a> AnchorFormat3<'a> {
950 pub fn anchor_format(&self) -> u16 {
952 let range = self.shape.anchor_format_byte_range();
953 self.data.read_at(range.start).unwrap()
954 }
955
956 pub fn x_coordinate(&self) -> i16 {
958 let range = self.shape.x_coordinate_byte_range();
959 self.data.read_at(range.start).unwrap()
960 }
961
962 pub fn y_coordinate(&self) -> i16 {
964 let range = self.shape.y_coordinate_byte_range();
965 self.data.read_at(range.start).unwrap()
966 }
967
968 pub fn x_device_offset(&self) -> Nullable<Offset16> {
972 let range = self.shape.x_device_offset_byte_range();
973 self.data.read_at(range.start).unwrap()
974 }
975
976 pub fn x_device(&self) -> Option<Result<DeviceOrVariationIndex<'a>, ReadError>> {
978 let data = self.data;
979 self.x_device_offset().resolve(data)
980 }
981
982 pub fn y_device_offset(&self) -> Nullable<Offset16> {
986 let range = self.shape.y_device_offset_byte_range();
987 self.data.read_at(range.start).unwrap()
988 }
989
990 pub fn y_device(&self) -> Option<Result<DeviceOrVariationIndex<'a>, ReadError>> {
992 let data = self.data;
993 self.y_device_offset().resolve(data)
994 }
995}
996
997#[cfg(feature = "experimental_traverse")]
998impl<'a> SomeTable<'a> for AnchorFormat3<'a> {
999 fn type_name(&self) -> &str {
1000 "AnchorFormat3"
1001 }
1002 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1003 match idx {
1004 0usize => Some(Field::new("anchor_format", self.anchor_format())),
1005 1usize => Some(Field::new("x_coordinate", self.x_coordinate())),
1006 2usize => Some(Field::new("y_coordinate", self.y_coordinate())),
1007 3usize => Some(Field::new(
1008 "x_device_offset",
1009 FieldType::offset(self.x_device_offset(), self.x_device()),
1010 )),
1011 4usize => Some(Field::new(
1012 "y_device_offset",
1013 FieldType::offset(self.y_device_offset(), self.y_device()),
1014 )),
1015 _ => None,
1016 }
1017 }
1018}
1019
1020#[cfg(feature = "experimental_traverse")]
1021#[allow(clippy::needless_lifetimes)]
1022impl<'a> std::fmt::Debug for AnchorFormat3<'a> {
1023 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1024 (self as &dyn SomeTable<'a>).fmt(f)
1025 }
1026}
1027
1028#[derive(Debug, Clone, Copy)]
1030#[doc(hidden)]
1031pub struct MarkArrayMarker {
1032 mark_records_byte_len: usize,
1033}
1034
1035impl MarkArrayMarker {
1036 pub fn mark_count_byte_range(&self) -> Range<usize> {
1037 let start = 0;
1038 start..start + u16::RAW_BYTE_LEN
1039 }
1040
1041 pub fn mark_records_byte_range(&self) -> Range<usize> {
1042 let start = self.mark_count_byte_range().end;
1043 start..start + self.mark_records_byte_len
1044 }
1045}
1046
1047impl MinByteRange for MarkArrayMarker {
1048 fn min_byte_range(&self) -> Range<usize> {
1049 0..self.mark_records_byte_range().end
1050 }
1051}
1052
1053impl<'a> FontRead<'a> for MarkArray<'a> {
1054 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1055 let mut cursor = data.cursor();
1056 let mark_count: u16 = cursor.read()?;
1057 let mark_records_byte_len = (mark_count as usize)
1058 .checked_mul(MarkRecord::RAW_BYTE_LEN)
1059 .ok_or(ReadError::OutOfBounds)?;
1060 cursor.advance_by(mark_records_byte_len);
1061 cursor.finish(MarkArrayMarker {
1062 mark_records_byte_len,
1063 })
1064 }
1065}
1066
1067pub type MarkArray<'a> = TableRef<'a, MarkArrayMarker>;
1069
1070#[allow(clippy::needless_lifetimes)]
1071impl<'a> MarkArray<'a> {
1072 pub fn mark_count(&self) -> u16 {
1074 let range = self.shape.mark_count_byte_range();
1075 self.data.read_at(range.start).unwrap()
1076 }
1077
1078 pub fn mark_records(&self) -> &'a [MarkRecord] {
1081 let range = self.shape.mark_records_byte_range();
1082 self.data.read_array(range).unwrap()
1083 }
1084}
1085
1086#[cfg(feature = "experimental_traverse")]
1087impl<'a> SomeTable<'a> for MarkArray<'a> {
1088 fn type_name(&self) -> &str {
1089 "MarkArray"
1090 }
1091 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1092 match idx {
1093 0usize => Some(Field::new("mark_count", self.mark_count())),
1094 1usize => Some(Field::new(
1095 "mark_records",
1096 traversal::FieldType::array_of_records(
1097 stringify!(MarkRecord),
1098 self.mark_records(),
1099 self.offset_data(),
1100 ),
1101 )),
1102 _ => None,
1103 }
1104 }
1105}
1106
1107#[cfg(feature = "experimental_traverse")]
1108#[allow(clippy::needless_lifetimes)]
1109impl<'a> std::fmt::Debug for MarkArray<'a> {
1110 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1111 (self as &dyn SomeTable<'a>).fmt(f)
1112 }
1113}
1114
1115#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
1117#[repr(C)]
1118#[repr(packed)]
1119pub struct MarkRecord {
1120 pub mark_class: BigEndian<u16>,
1122 pub mark_anchor_offset: BigEndian<Offset16>,
1124}
1125
1126impl MarkRecord {
1127 pub fn mark_class(&self) -> u16 {
1129 self.mark_class.get()
1130 }
1131
1132 pub fn mark_anchor_offset(&self) -> Offset16 {
1134 self.mark_anchor_offset.get()
1135 }
1136
1137 pub fn mark_anchor<'a>(&self, data: FontData<'a>) -> Result<AnchorTable<'a>, ReadError> {
1142 self.mark_anchor_offset().resolve(data)
1143 }
1144}
1145
1146impl FixedSize for MarkRecord {
1147 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
1148}
1149
1150#[cfg(feature = "experimental_traverse")]
1151impl<'a> SomeRecord<'a> for MarkRecord {
1152 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1153 RecordResolver {
1154 name: "MarkRecord",
1155 get_field: Box::new(move |idx, _data| match idx {
1156 0usize => Some(Field::new("mark_class", self.mark_class())),
1157 1usize => Some(Field::new(
1158 "mark_anchor_offset",
1159 FieldType::offset(self.mark_anchor_offset(), self.mark_anchor(_data)),
1160 )),
1161 _ => None,
1162 }),
1163 data,
1164 }
1165 }
1166}
1167
1168#[derive(Clone)]
1170pub enum SinglePos<'a> {
1171 Format1(SinglePosFormat1<'a>),
1172 Format2(SinglePosFormat2<'a>),
1173}
1174
1175impl<'a> SinglePos<'a> {
1176 pub fn offset_data(&self) -> FontData<'a> {
1178 match self {
1179 Self::Format1(item) => item.offset_data(),
1180 Self::Format2(item) => item.offset_data(),
1181 }
1182 }
1183
1184 pub fn pos_format(&self) -> u16 {
1186 match self {
1187 Self::Format1(item) => item.pos_format(),
1188 Self::Format2(item) => item.pos_format(),
1189 }
1190 }
1191
1192 pub fn coverage_offset(&self) -> Offset16 {
1194 match self {
1195 Self::Format1(item) => item.coverage_offset(),
1196 Self::Format2(item) => item.coverage_offset(),
1197 }
1198 }
1199
1200 pub fn value_format(&self) -> ValueFormat {
1202 match self {
1203 Self::Format1(item) => item.value_format(),
1204 Self::Format2(item) => item.value_format(),
1205 }
1206 }
1207}
1208
1209impl<'a> FontRead<'a> for SinglePos<'a> {
1210 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1211 let format: u16 = data.read_at(0usize)?;
1212 match format {
1213 SinglePosFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1214 SinglePosFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1215 other => Err(ReadError::InvalidFormat(other.into())),
1216 }
1217 }
1218}
1219
1220impl MinByteRange for SinglePos<'_> {
1221 fn min_byte_range(&self) -> Range<usize> {
1222 match self {
1223 Self::Format1(item) => item.min_byte_range(),
1224 Self::Format2(item) => item.min_byte_range(),
1225 }
1226 }
1227}
1228
1229#[cfg(feature = "experimental_traverse")]
1230impl<'a> SinglePos<'a> {
1231 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
1232 match self {
1233 Self::Format1(table) => table,
1234 Self::Format2(table) => table,
1235 }
1236 }
1237}
1238
1239#[cfg(feature = "experimental_traverse")]
1240impl std::fmt::Debug for SinglePos<'_> {
1241 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1242 self.dyn_inner().fmt(f)
1243 }
1244}
1245
1246#[cfg(feature = "experimental_traverse")]
1247impl<'a> SomeTable<'a> for SinglePos<'a> {
1248 fn type_name(&self) -> &str {
1249 self.dyn_inner().type_name()
1250 }
1251 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1252 self.dyn_inner().get_field(idx)
1253 }
1254}
1255
1256impl Format<u16> for SinglePosFormat1Marker {
1257 const FORMAT: u16 = 1;
1258}
1259
1260#[derive(Debug, Clone, Copy)]
1262#[doc(hidden)]
1263pub struct SinglePosFormat1Marker {
1264 value_record_byte_len: usize,
1265}
1266
1267impl SinglePosFormat1Marker {
1268 pub fn pos_format_byte_range(&self) -> Range<usize> {
1269 let start = 0;
1270 start..start + u16::RAW_BYTE_LEN
1271 }
1272
1273 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1274 let start = self.pos_format_byte_range().end;
1275 start..start + Offset16::RAW_BYTE_LEN
1276 }
1277
1278 pub fn value_format_byte_range(&self) -> Range<usize> {
1279 let start = self.coverage_offset_byte_range().end;
1280 start..start + ValueFormat::RAW_BYTE_LEN
1281 }
1282
1283 pub fn value_record_byte_range(&self) -> Range<usize> {
1284 let start = self.value_format_byte_range().end;
1285 start..start + self.value_record_byte_len
1286 }
1287}
1288
1289impl MinByteRange for SinglePosFormat1Marker {
1290 fn min_byte_range(&self) -> Range<usize> {
1291 0..self.value_record_byte_range().end
1292 }
1293}
1294
1295impl<'a> FontRead<'a> for SinglePosFormat1<'a> {
1296 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1297 let mut cursor = data.cursor();
1298 cursor.advance::<u16>();
1299 cursor.advance::<Offset16>();
1300 let value_format: ValueFormat = cursor.read()?;
1301 let value_record_byte_len = <ValueRecord as ComputeSize>::compute_size(&value_format)?;
1302 cursor.advance_by(value_record_byte_len);
1303 cursor.finish(SinglePosFormat1Marker {
1304 value_record_byte_len,
1305 })
1306 }
1307}
1308
1309pub type SinglePosFormat1<'a> = TableRef<'a, SinglePosFormat1Marker>;
1311
1312#[allow(clippy::needless_lifetimes)]
1313impl<'a> SinglePosFormat1<'a> {
1314 pub fn pos_format(&self) -> u16 {
1316 let range = self.shape.pos_format_byte_range();
1317 self.data.read_at(range.start).unwrap()
1318 }
1319
1320 pub fn coverage_offset(&self) -> Offset16 {
1322 let range = self.shape.coverage_offset_byte_range();
1323 self.data.read_at(range.start).unwrap()
1324 }
1325
1326 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1328 let data = self.data;
1329 self.coverage_offset().resolve(data)
1330 }
1331
1332 pub fn value_format(&self) -> ValueFormat {
1334 let range = self.shape.value_format_byte_range();
1335 self.data.read_at(range.start).unwrap()
1336 }
1337
1338 pub fn value_record(&self) -> ValueRecord {
1341 let range = self.shape.value_record_byte_range();
1342 self.data
1343 .read_with_args(range, &self.value_format())
1344 .unwrap()
1345 }
1346}
1347
1348#[cfg(feature = "experimental_traverse")]
1349impl<'a> SomeTable<'a> for SinglePosFormat1<'a> {
1350 fn type_name(&self) -> &str {
1351 "SinglePosFormat1"
1352 }
1353 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1354 match idx {
1355 0usize => Some(Field::new("pos_format", self.pos_format())),
1356 1usize => Some(Field::new(
1357 "coverage_offset",
1358 FieldType::offset(self.coverage_offset(), self.coverage()),
1359 )),
1360 2usize => Some(Field::new("value_format", self.value_format())),
1361 3usize => Some(Field::new(
1362 "value_record",
1363 self.value_record().traversal_type(self.offset_data()),
1364 )),
1365 _ => None,
1366 }
1367 }
1368}
1369
1370#[cfg(feature = "experimental_traverse")]
1371#[allow(clippy::needless_lifetimes)]
1372impl<'a> std::fmt::Debug for SinglePosFormat1<'a> {
1373 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1374 (self as &dyn SomeTable<'a>).fmt(f)
1375 }
1376}
1377
1378impl Format<u16> for SinglePosFormat2Marker {
1379 const FORMAT: u16 = 2;
1380}
1381
1382#[derive(Debug, Clone, Copy)]
1384#[doc(hidden)]
1385pub struct SinglePosFormat2Marker {
1386 value_records_byte_len: usize,
1387}
1388
1389impl SinglePosFormat2Marker {
1390 pub fn pos_format_byte_range(&self) -> Range<usize> {
1391 let start = 0;
1392 start..start + u16::RAW_BYTE_LEN
1393 }
1394
1395 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1396 let start = self.pos_format_byte_range().end;
1397 start..start + Offset16::RAW_BYTE_LEN
1398 }
1399
1400 pub fn value_format_byte_range(&self) -> Range<usize> {
1401 let start = self.coverage_offset_byte_range().end;
1402 start..start + ValueFormat::RAW_BYTE_LEN
1403 }
1404
1405 pub fn value_count_byte_range(&self) -> Range<usize> {
1406 let start = self.value_format_byte_range().end;
1407 start..start + u16::RAW_BYTE_LEN
1408 }
1409
1410 pub fn value_records_byte_range(&self) -> Range<usize> {
1411 let start = self.value_count_byte_range().end;
1412 start..start + self.value_records_byte_len
1413 }
1414}
1415
1416impl MinByteRange for SinglePosFormat2Marker {
1417 fn min_byte_range(&self) -> Range<usize> {
1418 0..self.value_records_byte_range().end
1419 }
1420}
1421
1422impl<'a> FontRead<'a> for SinglePosFormat2<'a> {
1423 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1424 let mut cursor = data.cursor();
1425 cursor.advance::<u16>();
1426 cursor.advance::<Offset16>();
1427 let value_format: ValueFormat = cursor.read()?;
1428 let value_count: u16 = cursor.read()?;
1429 let value_records_byte_len = (value_count as usize)
1430 .checked_mul(<ValueRecord as ComputeSize>::compute_size(&value_format)?)
1431 .ok_or(ReadError::OutOfBounds)?;
1432 cursor.advance_by(value_records_byte_len);
1433 cursor.finish(SinglePosFormat2Marker {
1434 value_records_byte_len,
1435 })
1436 }
1437}
1438
1439pub type SinglePosFormat2<'a> = TableRef<'a, SinglePosFormat2Marker>;
1441
1442#[allow(clippy::needless_lifetimes)]
1443impl<'a> SinglePosFormat2<'a> {
1444 pub fn pos_format(&self) -> u16 {
1446 let range = self.shape.pos_format_byte_range();
1447 self.data.read_at(range.start).unwrap()
1448 }
1449
1450 pub fn coverage_offset(&self) -> Offset16 {
1452 let range = self.shape.coverage_offset_byte_range();
1453 self.data.read_at(range.start).unwrap()
1454 }
1455
1456 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1458 let data = self.data;
1459 self.coverage_offset().resolve(data)
1460 }
1461
1462 pub fn value_format(&self) -> ValueFormat {
1464 let range = self.shape.value_format_byte_range();
1465 self.data.read_at(range.start).unwrap()
1466 }
1467
1468 pub fn value_count(&self) -> u16 {
1471 let range = self.shape.value_count_byte_range();
1472 self.data.read_at(range.start).unwrap()
1473 }
1474
1475 pub fn value_records(&self) -> ComputedArray<'a, ValueRecord> {
1477 let range = self.shape.value_records_byte_range();
1478 self.data
1479 .read_with_args(range, &self.value_format())
1480 .unwrap()
1481 }
1482}
1483
1484#[cfg(feature = "experimental_traverse")]
1485impl<'a> SomeTable<'a> for SinglePosFormat2<'a> {
1486 fn type_name(&self) -> &str {
1487 "SinglePosFormat2"
1488 }
1489 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1490 match idx {
1491 0usize => Some(Field::new("pos_format", self.pos_format())),
1492 1usize => Some(Field::new(
1493 "coverage_offset",
1494 FieldType::offset(self.coverage_offset(), self.coverage()),
1495 )),
1496 2usize => Some(Field::new("value_format", self.value_format())),
1497 3usize => Some(Field::new("value_count", self.value_count())),
1498 4usize => Some(Field::new(
1499 "value_records",
1500 traversal::FieldType::computed_array(
1501 "ValueRecord",
1502 self.value_records(),
1503 self.offset_data(),
1504 ),
1505 )),
1506 _ => None,
1507 }
1508 }
1509}
1510
1511#[cfg(feature = "experimental_traverse")]
1512#[allow(clippy::needless_lifetimes)]
1513impl<'a> std::fmt::Debug for SinglePosFormat2<'a> {
1514 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1515 (self as &dyn SomeTable<'a>).fmt(f)
1516 }
1517}
1518
1519#[derive(Clone)]
1521pub enum PairPos<'a> {
1522 Format1(PairPosFormat1<'a>),
1523 Format2(PairPosFormat2<'a>),
1524}
1525
1526impl<'a> PairPos<'a> {
1527 pub fn offset_data(&self) -> FontData<'a> {
1529 match self {
1530 Self::Format1(item) => item.offset_data(),
1531 Self::Format2(item) => item.offset_data(),
1532 }
1533 }
1534
1535 pub fn pos_format(&self) -> u16 {
1537 match self {
1538 Self::Format1(item) => item.pos_format(),
1539 Self::Format2(item) => item.pos_format(),
1540 }
1541 }
1542
1543 pub fn coverage_offset(&self) -> Offset16 {
1545 match self {
1546 Self::Format1(item) => item.coverage_offset(),
1547 Self::Format2(item) => item.coverage_offset(),
1548 }
1549 }
1550
1551 pub fn value_format1(&self) -> ValueFormat {
1554 match self {
1555 Self::Format1(item) => item.value_format1(),
1556 Self::Format2(item) => item.value_format1(),
1557 }
1558 }
1559
1560 pub fn value_format2(&self) -> ValueFormat {
1563 match self {
1564 Self::Format1(item) => item.value_format2(),
1565 Self::Format2(item) => item.value_format2(),
1566 }
1567 }
1568}
1569
1570impl<'a> FontRead<'a> for PairPos<'a> {
1571 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1572 let format: u16 = data.read_at(0usize)?;
1573 match format {
1574 PairPosFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1575 PairPosFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1576 other => Err(ReadError::InvalidFormat(other.into())),
1577 }
1578 }
1579}
1580
1581impl MinByteRange for PairPos<'_> {
1582 fn min_byte_range(&self) -> Range<usize> {
1583 match self {
1584 Self::Format1(item) => item.min_byte_range(),
1585 Self::Format2(item) => item.min_byte_range(),
1586 }
1587 }
1588}
1589
1590#[cfg(feature = "experimental_traverse")]
1591impl<'a> PairPos<'a> {
1592 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
1593 match self {
1594 Self::Format1(table) => table,
1595 Self::Format2(table) => table,
1596 }
1597 }
1598}
1599
1600#[cfg(feature = "experimental_traverse")]
1601impl std::fmt::Debug for PairPos<'_> {
1602 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1603 self.dyn_inner().fmt(f)
1604 }
1605}
1606
1607#[cfg(feature = "experimental_traverse")]
1608impl<'a> SomeTable<'a> for PairPos<'a> {
1609 fn type_name(&self) -> &str {
1610 self.dyn_inner().type_name()
1611 }
1612 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1613 self.dyn_inner().get_field(idx)
1614 }
1615}
1616
1617impl Format<u16> for PairPosFormat1Marker {
1618 const FORMAT: u16 = 1;
1619}
1620
1621#[derive(Debug, Clone, Copy)]
1623#[doc(hidden)]
1624pub struct PairPosFormat1Marker {
1625 pair_set_offsets_byte_len: usize,
1626}
1627
1628impl PairPosFormat1Marker {
1629 pub fn pos_format_byte_range(&self) -> Range<usize> {
1630 let start = 0;
1631 start..start + u16::RAW_BYTE_LEN
1632 }
1633
1634 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1635 let start = self.pos_format_byte_range().end;
1636 start..start + Offset16::RAW_BYTE_LEN
1637 }
1638
1639 pub fn value_format1_byte_range(&self) -> Range<usize> {
1640 let start = self.coverage_offset_byte_range().end;
1641 start..start + ValueFormat::RAW_BYTE_LEN
1642 }
1643
1644 pub fn value_format2_byte_range(&self) -> Range<usize> {
1645 let start = self.value_format1_byte_range().end;
1646 start..start + ValueFormat::RAW_BYTE_LEN
1647 }
1648
1649 pub fn pair_set_count_byte_range(&self) -> Range<usize> {
1650 let start = self.value_format2_byte_range().end;
1651 start..start + u16::RAW_BYTE_LEN
1652 }
1653
1654 pub fn pair_set_offsets_byte_range(&self) -> Range<usize> {
1655 let start = self.pair_set_count_byte_range().end;
1656 start..start + self.pair_set_offsets_byte_len
1657 }
1658}
1659
1660impl MinByteRange for PairPosFormat1Marker {
1661 fn min_byte_range(&self) -> Range<usize> {
1662 0..self.pair_set_offsets_byte_range().end
1663 }
1664}
1665
1666impl<'a> FontRead<'a> for PairPosFormat1<'a> {
1667 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1668 let mut cursor = data.cursor();
1669 cursor.advance::<u16>();
1670 cursor.advance::<Offset16>();
1671 cursor.advance::<ValueFormat>();
1672 cursor.advance::<ValueFormat>();
1673 let pair_set_count: u16 = cursor.read()?;
1674 let pair_set_offsets_byte_len = (pair_set_count as usize)
1675 .checked_mul(Offset16::RAW_BYTE_LEN)
1676 .ok_or(ReadError::OutOfBounds)?;
1677 cursor.advance_by(pair_set_offsets_byte_len);
1678 cursor.finish(PairPosFormat1Marker {
1679 pair_set_offsets_byte_len,
1680 })
1681 }
1682}
1683
1684pub type PairPosFormat1<'a> = TableRef<'a, PairPosFormat1Marker>;
1686
1687#[allow(clippy::needless_lifetimes)]
1688impl<'a> PairPosFormat1<'a> {
1689 pub fn pos_format(&self) -> u16 {
1691 let range = self.shape.pos_format_byte_range();
1692 self.data.read_at(range.start).unwrap()
1693 }
1694
1695 pub fn coverage_offset(&self) -> Offset16 {
1697 let range = self.shape.coverage_offset_byte_range();
1698 self.data.read_at(range.start).unwrap()
1699 }
1700
1701 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1703 let data = self.data;
1704 self.coverage_offset().resolve(data)
1705 }
1706
1707 pub fn value_format1(&self) -> ValueFormat {
1710 let range = self.shape.value_format1_byte_range();
1711 self.data.read_at(range.start).unwrap()
1712 }
1713
1714 pub fn value_format2(&self) -> ValueFormat {
1717 let range = self.shape.value_format2_byte_range();
1718 self.data.read_at(range.start).unwrap()
1719 }
1720
1721 pub fn pair_set_count(&self) -> u16 {
1723 let range = self.shape.pair_set_count_byte_range();
1724 self.data.read_at(range.start).unwrap()
1725 }
1726
1727 pub fn pair_set_offsets(&self) -> &'a [BigEndian<Offset16>] {
1730 let range = self.shape.pair_set_offsets_byte_range();
1731 self.data.read_array(range).unwrap()
1732 }
1733
1734 pub fn pair_sets(&self) -> ArrayOfOffsets<'a, PairSet<'a>, Offset16> {
1736 let data = self.data;
1737 let offsets = self.pair_set_offsets();
1738 let args = (self.value_format1(), self.value_format2());
1739 ArrayOfOffsets::new(offsets, data, args)
1740 }
1741}
1742
1743#[cfg(feature = "experimental_traverse")]
1744impl<'a> SomeTable<'a> for PairPosFormat1<'a> {
1745 fn type_name(&self) -> &str {
1746 "PairPosFormat1"
1747 }
1748 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1749 match idx {
1750 0usize => Some(Field::new("pos_format", self.pos_format())),
1751 1usize => Some(Field::new(
1752 "coverage_offset",
1753 FieldType::offset(self.coverage_offset(), self.coverage()),
1754 )),
1755 2usize => Some(Field::new("value_format1", self.value_format1())),
1756 3usize => Some(Field::new("value_format2", self.value_format2())),
1757 4usize => Some(Field::new("pair_set_count", self.pair_set_count())),
1758 5usize => Some({
1759 let data = self.data;
1760 let args = (self.value_format1(), self.value_format2());
1761 Field::new(
1762 "pair_set_offsets",
1763 FieldType::array_of_offsets(
1764 better_type_name::<PairSet>(),
1765 self.pair_set_offsets(),
1766 move |off| {
1767 let target = off.get().resolve_with_args::<PairSet>(data, &args);
1768 FieldType::offset(off.get(), target)
1769 },
1770 ),
1771 )
1772 }),
1773 _ => None,
1774 }
1775 }
1776}
1777
1778#[cfg(feature = "experimental_traverse")]
1779#[allow(clippy::needless_lifetimes)]
1780impl<'a> std::fmt::Debug for PairPosFormat1<'a> {
1781 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1782 (self as &dyn SomeTable<'a>).fmt(f)
1783 }
1784}
1785
1786#[derive(Debug, Clone, Copy)]
1788#[doc(hidden)]
1789pub struct PairSetMarker {
1790 value_format1: ValueFormat,
1791 value_format2: ValueFormat,
1792 pair_value_records_byte_len: usize,
1793}
1794
1795impl PairSetMarker {
1796 pub fn pair_value_count_byte_range(&self) -> Range<usize> {
1797 let start = 0;
1798 start..start + u16::RAW_BYTE_LEN
1799 }
1800
1801 pub fn pair_value_records_byte_range(&self) -> Range<usize> {
1802 let start = self.pair_value_count_byte_range().end;
1803 start..start + self.pair_value_records_byte_len
1804 }
1805}
1806
1807impl MinByteRange for PairSetMarker {
1808 fn min_byte_range(&self) -> Range<usize> {
1809 0..self.pair_value_records_byte_range().end
1810 }
1811}
1812
1813impl ReadArgs for PairSet<'_> {
1814 type Args = (ValueFormat, ValueFormat);
1815}
1816
1817impl<'a> FontReadWithArgs<'a> for PairSet<'a> {
1818 fn read_with_args(
1819 data: FontData<'a>,
1820 args: &(ValueFormat, ValueFormat),
1821 ) -> Result<Self, ReadError> {
1822 let (value_format1, value_format2) = *args;
1823 let mut cursor = data.cursor();
1824 let pair_value_count: u16 = cursor.read()?;
1825 let pair_value_records_byte_len = (pair_value_count as usize)
1826 .checked_mul(<PairValueRecord as ComputeSize>::compute_size(&(
1827 value_format1,
1828 value_format2,
1829 ))?)
1830 .ok_or(ReadError::OutOfBounds)?;
1831 cursor.advance_by(pair_value_records_byte_len);
1832 cursor.finish(PairSetMarker {
1833 value_format1,
1834 value_format2,
1835 pair_value_records_byte_len,
1836 })
1837 }
1838}
1839
1840impl<'a> PairSet<'a> {
1841 pub fn read(
1846 data: FontData<'a>,
1847 value_format1: ValueFormat,
1848 value_format2: ValueFormat,
1849 ) -> Result<Self, ReadError> {
1850 let args = (value_format1, value_format2);
1851 Self::read_with_args(data, &args)
1852 }
1853}
1854
1855pub type PairSet<'a> = TableRef<'a, PairSetMarker>;
1857
1858#[allow(clippy::needless_lifetimes)]
1859impl<'a> PairSet<'a> {
1860 pub fn pair_value_count(&self) -> u16 {
1862 let range = self.shape.pair_value_count_byte_range();
1863 self.data.read_at(range.start).unwrap()
1864 }
1865
1866 pub fn pair_value_records(&self) -> ComputedArray<'a, PairValueRecord> {
1869 let range = self.shape.pair_value_records_byte_range();
1870 self.data
1871 .read_with_args(range, &(self.value_format1(), self.value_format2()))
1872 .unwrap()
1873 }
1874
1875 pub(crate) fn value_format1(&self) -> ValueFormat {
1876 self.shape.value_format1
1877 }
1878
1879 pub(crate) fn value_format2(&self) -> ValueFormat {
1880 self.shape.value_format2
1881 }
1882}
1883
1884#[cfg(feature = "experimental_traverse")]
1885impl<'a> SomeTable<'a> for PairSet<'a> {
1886 fn type_name(&self) -> &str {
1887 "PairSet"
1888 }
1889 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1890 match idx {
1891 0usize => Some(Field::new("pair_value_count", self.pair_value_count())),
1892 1usize => Some(Field::new(
1893 "pair_value_records",
1894 traversal::FieldType::computed_array(
1895 "PairValueRecord",
1896 self.pair_value_records(),
1897 self.offset_data(),
1898 ),
1899 )),
1900 _ => None,
1901 }
1902 }
1903}
1904
1905#[cfg(feature = "experimental_traverse")]
1906#[allow(clippy::needless_lifetimes)]
1907impl<'a> std::fmt::Debug for PairSet<'a> {
1908 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1909 (self as &dyn SomeTable<'a>).fmt(f)
1910 }
1911}
1912
1913#[derive(Clone, Debug)]
1915pub struct PairValueRecord {
1916 pub second_glyph: BigEndian<GlyphId16>,
1919 pub value_record1: ValueRecord,
1921 pub value_record2: ValueRecord,
1923}
1924
1925impl PairValueRecord {
1926 pub fn second_glyph(&self) -> GlyphId16 {
1929 self.second_glyph.get()
1930 }
1931
1932 pub fn value_record1(&self) -> &ValueRecord {
1934 &self.value_record1
1935 }
1936
1937 pub fn value_record2(&self) -> &ValueRecord {
1939 &self.value_record2
1940 }
1941}
1942
1943impl ReadArgs for PairValueRecord {
1944 type Args = (ValueFormat, ValueFormat);
1945}
1946
1947impl ComputeSize for PairValueRecord {
1948 #[allow(clippy::needless_question_mark)]
1949 fn compute_size(args: &(ValueFormat, ValueFormat)) -> Result<usize, ReadError> {
1950 let (value_format1, value_format2) = *args;
1951 let mut result = 0usize;
1952 result = result
1953 .checked_add(GlyphId16::RAW_BYTE_LEN)
1954 .ok_or(ReadError::OutOfBounds)?;
1955 result = result
1956 .checked_add(<ValueRecord as ComputeSize>::compute_size(&value_format1)?)
1957 .ok_or(ReadError::OutOfBounds)?;
1958 result = result
1959 .checked_add(<ValueRecord as ComputeSize>::compute_size(&value_format2)?)
1960 .ok_or(ReadError::OutOfBounds)?;
1961 Ok(result)
1962 }
1963}
1964
1965impl<'a> FontReadWithArgs<'a> for PairValueRecord {
1966 fn read_with_args(
1967 data: FontData<'a>,
1968 args: &(ValueFormat, ValueFormat),
1969 ) -> Result<Self, ReadError> {
1970 let mut cursor = data.cursor();
1971 let (value_format1, value_format2) = *args;
1972 Ok(Self {
1973 second_glyph: cursor.read_be()?,
1974 value_record1: cursor.read_with_args(&value_format1)?,
1975 value_record2: cursor.read_with_args(&value_format2)?,
1976 })
1977 }
1978}
1979
1980#[allow(clippy::needless_lifetimes)]
1981impl<'a> PairValueRecord {
1982 pub fn read(
1987 data: FontData<'a>,
1988 value_format1: ValueFormat,
1989 value_format2: ValueFormat,
1990 ) -> Result<Self, ReadError> {
1991 let args = (value_format1, value_format2);
1992 Self::read_with_args(data, &args)
1993 }
1994}
1995
1996#[cfg(feature = "experimental_traverse")]
1997impl<'a> SomeRecord<'a> for PairValueRecord {
1998 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1999 RecordResolver {
2000 name: "PairValueRecord",
2001 get_field: Box::new(move |idx, _data| match idx {
2002 0usize => Some(Field::new("second_glyph", self.second_glyph())),
2003 1usize => Some(Field::new(
2004 "value_record1",
2005 self.value_record1().traversal_type(_data),
2006 )),
2007 2usize => Some(Field::new(
2008 "value_record2",
2009 self.value_record2().traversal_type(_data),
2010 )),
2011 _ => None,
2012 }),
2013 data,
2014 }
2015 }
2016}
2017
2018impl Format<u16> for PairPosFormat2Marker {
2019 const FORMAT: u16 = 2;
2020}
2021
2022#[derive(Debug, Clone, Copy)]
2024#[doc(hidden)]
2025pub struct PairPosFormat2Marker {
2026 class1_records_byte_len: usize,
2027}
2028
2029impl PairPosFormat2Marker {
2030 pub fn pos_format_byte_range(&self) -> Range<usize> {
2031 let start = 0;
2032 start..start + u16::RAW_BYTE_LEN
2033 }
2034
2035 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2036 let start = self.pos_format_byte_range().end;
2037 start..start + Offset16::RAW_BYTE_LEN
2038 }
2039
2040 pub fn value_format1_byte_range(&self) -> Range<usize> {
2041 let start = self.coverage_offset_byte_range().end;
2042 start..start + ValueFormat::RAW_BYTE_LEN
2043 }
2044
2045 pub fn value_format2_byte_range(&self) -> Range<usize> {
2046 let start = self.value_format1_byte_range().end;
2047 start..start + ValueFormat::RAW_BYTE_LEN
2048 }
2049
2050 pub fn class_def1_offset_byte_range(&self) -> Range<usize> {
2051 let start = self.value_format2_byte_range().end;
2052 start..start + Offset16::RAW_BYTE_LEN
2053 }
2054
2055 pub fn class_def2_offset_byte_range(&self) -> Range<usize> {
2056 let start = self.class_def1_offset_byte_range().end;
2057 start..start + Offset16::RAW_BYTE_LEN
2058 }
2059
2060 pub fn class1_count_byte_range(&self) -> Range<usize> {
2061 let start = self.class_def2_offset_byte_range().end;
2062 start..start + u16::RAW_BYTE_LEN
2063 }
2064
2065 pub fn class2_count_byte_range(&self) -> Range<usize> {
2066 let start = self.class1_count_byte_range().end;
2067 start..start + u16::RAW_BYTE_LEN
2068 }
2069
2070 pub fn class1_records_byte_range(&self) -> Range<usize> {
2071 let start = self.class2_count_byte_range().end;
2072 start..start + self.class1_records_byte_len
2073 }
2074}
2075
2076impl MinByteRange for PairPosFormat2Marker {
2077 fn min_byte_range(&self) -> Range<usize> {
2078 0..self.class1_records_byte_range().end
2079 }
2080}
2081
2082impl<'a> FontRead<'a> for PairPosFormat2<'a> {
2083 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
2084 let mut cursor = data.cursor();
2085 cursor.advance::<u16>();
2086 cursor.advance::<Offset16>();
2087 let value_format1: ValueFormat = cursor.read()?;
2088 let value_format2: ValueFormat = cursor.read()?;
2089 cursor.advance::<Offset16>();
2090 cursor.advance::<Offset16>();
2091 let class1_count: u16 = cursor.read()?;
2092 let class2_count: u16 = cursor.read()?;
2093 let class1_records_byte_len = (class1_count as usize)
2094 .checked_mul(<Class1Record as ComputeSize>::compute_size(&(
2095 class2_count,
2096 value_format1,
2097 value_format2,
2098 ))?)
2099 .ok_or(ReadError::OutOfBounds)?;
2100 cursor.advance_by(class1_records_byte_len);
2101 cursor.finish(PairPosFormat2Marker {
2102 class1_records_byte_len,
2103 })
2104 }
2105}
2106
2107pub type PairPosFormat2<'a> = TableRef<'a, PairPosFormat2Marker>;
2109
2110#[allow(clippy::needless_lifetimes)]
2111impl<'a> PairPosFormat2<'a> {
2112 pub fn pos_format(&self) -> u16 {
2114 let range = self.shape.pos_format_byte_range();
2115 self.data.read_at(range.start).unwrap()
2116 }
2117
2118 pub fn coverage_offset(&self) -> Offset16 {
2120 let range = self.shape.coverage_offset_byte_range();
2121 self.data.read_at(range.start).unwrap()
2122 }
2123
2124 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2126 let data = self.data;
2127 self.coverage_offset().resolve(data)
2128 }
2129
2130 pub fn value_format1(&self) -> ValueFormat {
2133 let range = self.shape.value_format1_byte_range();
2134 self.data.read_at(range.start).unwrap()
2135 }
2136
2137 pub fn value_format2(&self) -> ValueFormat {
2140 let range = self.shape.value_format2_byte_range();
2141 self.data.read_at(range.start).unwrap()
2142 }
2143
2144 pub fn class_def1_offset(&self) -> Offset16 {
2147 let range = self.shape.class_def1_offset_byte_range();
2148 self.data.read_at(range.start).unwrap()
2149 }
2150
2151 pub fn class_def1(&self) -> Result<ClassDef<'a>, ReadError> {
2153 let data = self.data;
2154 self.class_def1_offset().resolve(data)
2155 }
2156
2157 pub fn class_def2_offset(&self) -> Offset16 {
2160 let range = self.shape.class_def2_offset_byte_range();
2161 self.data.read_at(range.start).unwrap()
2162 }
2163
2164 pub fn class_def2(&self) -> Result<ClassDef<'a>, ReadError> {
2166 let data = self.data;
2167 self.class_def2_offset().resolve(data)
2168 }
2169
2170 pub fn class1_count(&self) -> u16 {
2172 let range = self.shape.class1_count_byte_range();
2173 self.data.read_at(range.start).unwrap()
2174 }
2175
2176 pub fn class2_count(&self) -> u16 {
2178 let range = self.shape.class2_count_byte_range();
2179 self.data.read_at(range.start).unwrap()
2180 }
2181
2182 pub fn class1_records(&self) -> ComputedArray<'a, Class1Record<'a>> {
2184 let range = self.shape.class1_records_byte_range();
2185 self.data
2186 .read_with_args(
2187 range,
2188 &(
2189 self.class2_count(),
2190 self.value_format1(),
2191 self.value_format2(),
2192 ),
2193 )
2194 .unwrap()
2195 }
2196}
2197
2198#[cfg(feature = "experimental_traverse")]
2199impl<'a> SomeTable<'a> for PairPosFormat2<'a> {
2200 fn type_name(&self) -> &str {
2201 "PairPosFormat2"
2202 }
2203 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2204 match idx {
2205 0usize => Some(Field::new("pos_format", self.pos_format())),
2206 1usize => Some(Field::new(
2207 "coverage_offset",
2208 FieldType::offset(self.coverage_offset(), self.coverage()),
2209 )),
2210 2usize => Some(Field::new("value_format1", self.value_format1())),
2211 3usize => Some(Field::new("value_format2", self.value_format2())),
2212 4usize => Some(Field::new(
2213 "class_def1_offset",
2214 FieldType::offset(self.class_def1_offset(), self.class_def1()),
2215 )),
2216 5usize => Some(Field::new(
2217 "class_def2_offset",
2218 FieldType::offset(self.class_def2_offset(), self.class_def2()),
2219 )),
2220 6usize => Some(Field::new("class1_count", self.class1_count())),
2221 7usize => Some(Field::new("class2_count", self.class2_count())),
2222 8usize => Some(Field::new(
2223 "class1_records",
2224 traversal::FieldType::computed_array(
2225 "Class1Record",
2226 self.class1_records(),
2227 self.offset_data(),
2228 ),
2229 )),
2230 _ => None,
2231 }
2232 }
2233}
2234
2235#[cfg(feature = "experimental_traverse")]
2236#[allow(clippy::needless_lifetimes)]
2237impl<'a> std::fmt::Debug for PairPosFormat2<'a> {
2238 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2239 (self as &dyn SomeTable<'a>).fmt(f)
2240 }
2241}
2242
2243#[derive(Clone, Debug)]
2245pub struct Class1Record<'a> {
2246 pub class2_records: ComputedArray<'a, Class2Record>,
2248}
2249
2250impl<'a> Class1Record<'a> {
2251 pub fn class2_records(&self) -> &ComputedArray<'a, Class2Record> {
2253 &self.class2_records
2254 }
2255}
2256
2257impl ReadArgs for Class1Record<'_> {
2258 type Args = (u16, ValueFormat, ValueFormat);
2259}
2260
2261impl ComputeSize for Class1Record<'_> {
2262 #[allow(clippy::needless_question_mark)]
2263 fn compute_size(args: &(u16, ValueFormat, ValueFormat)) -> Result<usize, ReadError> {
2264 let (class2_count, value_format1, value_format2) = *args;
2265 Ok((class2_count as usize)
2266 .checked_mul(<Class2Record as ComputeSize>::compute_size(&(
2267 value_format1,
2268 value_format2,
2269 ))?)
2270 .ok_or(ReadError::OutOfBounds)?)
2271 }
2272}
2273
2274impl<'a> FontReadWithArgs<'a> for Class1Record<'a> {
2275 fn read_with_args(
2276 data: FontData<'a>,
2277 args: &(u16, ValueFormat, ValueFormat),
2278 ) -> Result<Self, ReadError> {
2279 let mut cursor = data.cursor();
2280 let (class2_count, value_format1, value_format2) = *args;
2281 Ok(Self {
2282 class2_records: cursor
2283 .read_computed_array(class2_count as usize, &(value_format1, value_format2))?,
2284 })
2285 }
2286}
2287
2288#[allow(clippy::needless_lifetimes)]
2289impl<'a> Class1Record<'a> {
2290 pub fn read(
2295 data: FontData<'a>,
2296 class2_count: u16,
2297 value_format1: ValueFormat,
2298 value_format2: ValueFormat,
2299 ) -> Result<Self, ReadError> {
2300 let args = (class2_count, value_format1, value_format2);
2301 Self::read_with_args(data, &args)
2302 }
2303}
2304
2305#[cfg(feature = "experimental_traverse")]
2306impl<'a> SomeRecord<'a> for Class1Record<'a> {
2307 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
2308 RecordResolver {
2309 name: "Class1Record",
2310 get_field: Box::new(move |idx, _data| match idx {
2311 0usize => Some(Field::new(
2312 "class2_records",
2313 traversal::FieldType::computed_array(
2314 "Class2Record",
2315 self.class2_records().clone(),
2316 FontData::new(&[]),
2317 ),
2318 )),
2319 _ => None,
2320 }),
2321 data,
2322 }
2323 }
2324}
2325
2326#[derive(Clone, Debug)]
2328pub struct Class2Record {
2329 pub value_record1: ValueRecord,
2331 pub value_record2: ValueRecord,
2333}
2334
2335impl Class2Record {
2336 pub fn value_record1(&self) -> &ValueRecord {
2338 &self.value_record1
2339 }
2340
2341 pub fn value_record2(&self) -> &ValueRecord {
2343 &self.value_record2
2344 }
2345}
2346
2347impl ReadArgs for Class2Record {
2348 type Args = (ValueFormat, ValueFormat);
2349}
2350
2351impl ComputeSize for Class2Record {
2352 #[allow(clippy::needless_question_mark)]
2353 fn compute_size(args: &(ValueFormat, ValueFormat)) -> Result<usize, ReadError> {
2354 let (value_format1, value_format2) = *args;
2355 let mut result = 0usize;
2356 result = result
2357 .checked_add(<ValueRecord as ComputeSize>::compute_size(&value_format1)?)
2358 .ok_or(ReadError::OutOfBounds)?;
2359 result = result
2360 .checked_add(<ValueRecord as ComputeSize>::compute_size(&value_format2)?)
2361 .ok_or(ReadError::OutOfBounds)?;
2362 Ok(result)
2363 }
2364}
2365
2366impl<'a> FontReadWithArgs<'a> for Class2Record {
2367 fn read_with_args(
2368 data: FontData<'a>,
2369 args: &(ValueFormat, ValueFormat),
2370 ) -> Result<Self, ReadError> {
2371 let mut cursor = data.cursor();
2372 let (value_format1, value_format2) = *args;
2373 Ok(Self {
2374 value_record1: cursor.read_with_args(&value_format1)?,
2375 value_record2: cursor.read_with_args(&value_format2)?,
2376 })
2377 }
2378}
2379
2380#[allow(clippy::needless_lifetimes)]
2381impl<'a> Class2Record {
2382 pub fn read(
2387 data: FontData<'a>,
2388 value_format1: ValueFormat,
2389 value_format2: ValueFormat,
2390 ) -> Result<Self, ReadError> {
2391 let args = (value_format1, value_format2);
2392 Self::read_with_args(data, &args)
2393 }
2394}
2395
2396#[cfg(feature = "experimental_traverse")]
2397impl<'a> SomeRecord<'a> for Class2Record {
2398 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
2399 RecordResolver {
2400 name: "Class2Record",
2401 get_field: Box::new(move |idx, _data| match idx {
2402 0usize => Some(Field::new(
2403 "value_record1",
2404 self.value_record1().traversal_type(_data),
2405 )),
2406 1usize => Some(Field::new(
2407 "value_record2",
2408 self.value_record2().traversal_type(_data),
2409 )),
2410 _ => None,
2411 }),
2412 data,
2413 }
2414 }
2415}
2416
2417impl Format<u16> for CursivePosFormat1Marker {
2418 const FORMAT: u16 = 1;
2419}
2420
2421#[derive(Debug, Clone, Copy)]
2423#[doc(hidden)]
2424pub struct CursivePosFormat1Marker {
2425 entry_exit_record_byte_len: usize,
2426}
2427
2428impl CursivePosFormat1Marker {
2429 pub fn pos_format_byte_range(&self) -> Range<usize> {
2430 let start = 0;
2431 start..start + u16::RAW_BYTE_LEN
2432 }
2433
2434 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2435 let start = self.pos_format_byte_range().end;
2436 start..start + Offset16::RAW_BYTE_LEN
2437 }
2438
2439 pub fn entry_exit_count_byte_range(&self) -> Range<usize> {
2440 let start = self.coverage_offset_byte_range().end;
2441 start..start + u16::RAW_BYTE_LEN
2442 }
2443
2444 pub fn entry_exit_record_byte_range(&self) -> Range<usize> {
2445 let start = self.entry_exit_count_byte_range().end;
2446 start..start + self.entry_exit_record_byte_len
2447 }
2448}
2449
2450impl MinByteRange for CursivePosFormat1Marker {
2451 fn min_byte_range(&self) -> Range<usize> {
2452 0..self.entry_exit_record_byte_range().end
2453 }
2454}
2455
2456impl<'a> FontRead<'a> for CursivePosFormat1<'a> {
2457 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
2458 let mut cursor = data.cursor();
2459 cursor.advance::<u16>();
2460 cursor.advance::<Offset16>();
2461 let entry_exit_count: u16 = cursor.read()?;
2462 let entry_exit_record_byte_len = (entry_exit_count as usize)
2463 .checked_mul(EntryExitRecord::RAW_BYTE_LEN)
2464 .ok_or(ReadError::OutOfBounds)?;
2465 cursor.advance_by(entry_exit_record_byte_len);
2466 cursor.finish(CursivePosFormat1Marker {
2467 entry_exit_record_byte_len,
2468 })
2469 }
2470}
2471
2472pub type CursivePosFormat1<'a> = TableRef<'a, CursivePosFormat1Marker>;
2474
2475#[allow(clippy::needless_lifetimes)]
2476impl<'a> CursivePosFormat1<'a> {
2477 pub fn pos_format(&self) -> u16 {
2479 let range = self.shape.pos_format_byte_range();
2480 self.data.read_at(range.start).unwrap()
2481 }
2482
2483 pub fn coverage_offset(&self) -> Offset16 {
2485 let range = self.shape.coverage_offset_byte_range();
2486 self.data.read_at(range.start).unwrap()
2487 }
2488
2489 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2491 let data = self.data;
2492 self.coverage_offset().resolve(data)
2493 }
2494
2495 pub fn entry_exit_count(&self) -> u16 {
2497 let range = self.shape.entry_exit_count_byte_range();
2498 self.data.read_at(range.start).unwrap()
2499 }
2500
2501 pub fn entry_exit_record(&self) -> &'a [EntryExitRecord] {
2503 let range = self.shape.entry_exit_record_byte_range();
2504 self.data.read_array(range).unwrap()
2505 }
2506}
2507
2508#[cfg(feature = "experimental_traverse")]
2509impl<'a> SomeTable<'a> for CursivePosFormat1<'a> {
2510 fn type_name(&self) -> &str {
2511 "CursivePosFormat1"
2512 }
2513 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2514 match idx {
2515 0usize => Some(Field::new("pos_format", self.pos_format())),
2516 1usize => Some(Field::new(
2517 "coverage_offset",
2518 FieldType::offset(self.coverage_offset(), self.coverage()),
2519 )),
2520 2usize => Some(Field::new("entry_exit_count", self.entry_exit_count())),
2521 3usize => Some(Field::new(
2522 "entry_exit_record",
2523 traversal::FieldType::array_of_records(
2524 stringify!(EntryExitRecord),
2525 self.entry_exit_record(),
2526 self.offset_data(),
2527 ),
2528 )),
2529 _ => None,
2530 }
2531 }
2532}
2533
2534#[cfg(feature = "experimental_traverse")]
2535#[allow(clippy::needless_lifetimes)]
2536impl<'a> std::fmt::Debug for CursivePosFormat1<'a> {
2537 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2538 (self as &dyn SomeTable<'a>).fmt(f)
2539 }
2540}
2541
2542#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
2544#[repr(C)]
2545#[repr(packed)]
2546pub struct EntryExitRecord {
2547 pub entry_anchor_offset: BigEndian<Nullable<Offset16>>,
2550 pub exit_anchor_offset: BigEndian<Nullable<Offset16>>,
2553}
2554
2555impl EntryExitRecord {
2556 pub fn entry_anchor_offset(&self) -> Nullable<Offset16> {
2559 self.entry_anchor_offset.get()
2560 }
2561
2562 pub fn entry_anchor<'a>(
2568 &self,
2569 data: FontData<'a>,
2570 ) -> Option<Result<AnchorTable<'a>, ReadError>> {
2571 self.entry_anchor_offset().resolve(data)
2572 }
2573
2574 pub fn exit_anchor_offset(&self) -> Nullable<Offset16> {
2577 self.exit_anchor_offset.get()
2578 }
2579
2580 pub fn exit_anchor<'a>(
2586 &self,
2587 data: FontData<'a>,
2588 ) -> Option<Result<AnchorTable<'a>, ReadError>> {
2589 self.exit_anchor_offset().resolve(data)
2590 }
2591}
2592
2593impl FixedSize for EntryExitRecord {
2594 const RAW_BYTE_LEN: usize = Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
2595}
2596
2597#[cfg(feature = "experimental_traverse")]
2598impl<'a> SomeRecord<'a> for EntryExitRecord {
2599 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
2600 RecordResolver {
2601 name: "EntryExitRecord",
2602 get_field: Box::new(move |idx, _data| match idx {
2603 0usize => Some(Field::new(
2604 "entry_anchor_offset",
2605 FieldType::offset(self.entry_anchor_offset(), self.entry_anchor(_data)),
2606 )),
2607 1usize => Some(Field::new(
2608 "exit_anchor_offset",
2609 FieldType::offset(self.exit_anchor_offset(), self.exit_anchor(_data)),
2610 )),
2611 _ => None,
2612 }),
2613 data,
2614 }
2615 }
2616}
2617
2618impl Format<u16> for MarkBasePosFormat1Marker {
2619 const FORMAT: u16 = 1;
2620}
2621
2622#[derive(Debug, Clone, Copy)]
2624#[doc(hidden)]
2625pub struct MarkBasePosFormat1Marker {}
2626
2627impl MarkBasePosFormat1Marker {
2628 pub fn pos_format_byte_range(&self) -> Range<usize> {
2629 let start = 0;
2630 start..start + u16::RAW_BYTE_LEN
2631 }
2632
2633 pub fn mark_coverage_offset_byte_range(&self) -> Range<usize> {
2634 let start = self.pos_format_byte_range().end;
2635 start..start + Offset16::RAW_BYTE_LEN
2636 }
2637
2638 pub fn base_coverage_offset_byte_range(&self) -> Range<usize> {
2639 let start = self.mark_coverage_offset_byte_range().end;
2640 start..start + Offset16::RAW_BYTE_LEN
2641 }
2642
2643 pub fn mark_class_count_byte_range(&self) -> Range<usize> {
2644 let start = self.base_coverage_offset_byte_range().end;
2645 start..start + u16::RAW_BYTE_LEN
2646 }
2647
2648 pub fn mark_array_offset_byte_range(&self) -> Range<usize> {
2649 let start = self.mark_class_count_byte_range().end;
2650 start..start + Offset16::RAW_BYTE_LEN
2651 }
2652
2653 pub fn base_array_offset_byte_range(&self) -> Range<usize> {
2654 let start = self.mark_array_offset_byte_range().end;
2655 start..start + Offset16::RAW_BYTE_LEN
2656 }
2657}
2658
2659impl MinByteRange for MarkBasePosFormat1Marker {
2660 fn min_byte_range(&self) -> Range<usize> {
2661 0..self.base_array_offset_byte_range().end
2662 }
2663}
2664
2665impl<'a> FontRead<'a> for MarkBasePosFormat1<'a> {
2666 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
2667 let mut cursor = data.cursor();
2668 cursor.advance::<u16>();
2669 cursor.advance::<Offset16>();
2670 cursor.advance::<Offset16>();
2671 cursor.advance::<u16>();
2672 cursor.advance::<Offset16>();
2673 cursor.advance::<Offset16>();
2674 cursor.finish(MarkBasePosFormat1Marker {})
2675 }
2676}
2677
2678pub type MarkBasePosFormat1<'a> = TableRef<'a, MarkBasePosFormat1Marker>;
2680
2681#[allow(clippy::needless_lifetimes)]
2682impl<'a> MarkBasePosFormat1<'a> {
2683 pub fn pos_format(&self) -> u16 {
2685 let range = self.shape.pos_format_byte_range();
2686 self.data.read_at(range.start).unwrap()
2687 }
2688
2689 pub fn mark_coverage_offset(&self) -> Offset16 {
2692 let range = self.shape.mark_coverage_offset_byte_range();
2693 self.data.read_at(range.start).unwrap()
2694 }
2695
2696 pub fn mark_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2698 let data = self.data;
2699 self.mark_coverage_offset().resolve(data)
2700 }
2701
2702 pub fn base_coverage_offset(&self) -> Offset16 {
2705 let range = self.shape.base_coverage_offset_byte_range();
2706 self.data.read_at(range.start).unwrap()
2707 }
2708
2709 pub fn base_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2711 let data = self.data;
2712 self.base_coverage_offset().resolve(data)
2713 }
2714
2715 pub fn mark_class_count(&self) -> u16 {
2717 let range = self.shape.mark_class_count_byte_range();
2718 self.data.read_at(range.start).unwrap()
2719 }
2720
2721 pub fn mark_array_offset(&self) -> Offset16 {
2724 let range = self.shape.mark_array_offset_byte_range();
2725 self.data.read_at(range.start).unwrap()
2726 }
2727
2728 pub fn mark_array(&self) -> Result<MarkArray<'a>, ReadError> {
2730 let data = self.data;
2731 self.mark_array_offset().resolve(data)
2732 }
2733
2734 pub fn base_array_offset(&self) -> Offset16 {
2737 let range = self.shape.base_array_offset_byte_range();
2738 self.data.read_at(range.start).unwrap()
2739 }
2740
2741 pub fn base_array(&self) -> Result<BaseArray<'a>, ReadError> {
2743 let data = self.data;
2744 let args = self.mark_class_count();
2745 self.base_array_offset().resolve_with_args(data, &args)
2746 }
2747}
2748
2749#[cfg(feature = "experimental_traverse")]
2750impl<'a> SomeTable<'a> for MarkBasePosFormat1<'a> {
2751 fn type_name(&self) -> &str {
2752 "MarkBasePosFormat1"
2753 }
2754 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2755 match idx {
2756 0usize => Some(Field::new("pos_format", self.pos_format())),
2757 1usize => Some(Field::new(
2758 "mark_coverage_offset",
2759 FieldType::offset(self.mark_coverage_offset(), self.mark_coverage()),
2760 )),
2761 2usize => Some(Field::new(
2762 "base_coverage_offset",
2763 FieldType::offset(self.base_coverage_offset(), self.base_coverage()),
2764 )),
2765 3usize => Some(Field::new("mark_class_count", self.mark_class_count())),
2766 4usize => Some(Field::new(
2767 "mark_array_offset",
2768 FieldType::offset(self.mark_array_offset(), self.mark_array()),
2769 )),
2770 5usize => Some(Field::new(
2771 "base_array_offset",
2772 FieldType::offset(self.base_array_offset(), self.base_array()),
2773 )),
2774 _ => None,
2775 }
2776 }
2777}
2778
2779#[cfg(feature = "experimental_traverse")]
2780#[allow(clippy::needless_lifetimes)]
2781impl<'a> std::fmt::Debug for MarkBasePosFormat1<'a> {
2782 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2783 (self as &dyn SomeTable<'a>).fmt(f)
2784 }
2785}
2786
2787#[derive(Debug, Clone, Copy)]
2789#[doc(hidden)]
2790pub struct BaseArrayMarker {
2791 mark_class_count: u16,
2792 base_records_byte_len: usize,
2793}
2794
2795impl BaseArrayMarker {
2796 pub fn base_count_byte_range(&self) -> Range<usize> {
2797 let start = 0;
2798 start..start + u16::RAW_BYTE_LEN
2799 }
2800
2801 pub fn base_records_byte_range(&self) -> Range<usize> {
2802 let start = self.base_count_byte_range().end;
2803 start..start + self.base_records_byte_len
2804 }
2805}
2806
2807impl MinByteRange for BaseArrayMarker {
2808 fn min_byte_range(&self) -> Range<usize> {
2809 0..self.base_records_byte_range().end
2810 }
2811}
2812
2813impl ReadArgs for BaseArray<'_> {
2814 type Args = u16;
2815}
2816
2817impl<'a> FontReadWithArgs<'a> for BaseArray<'a> {
2818 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
2819 let mark_class_count = *args;
2820 let mut cursor = data.cursor();
2821 let base_count: u16 = cursor.read()?;
2822 let base_records_byte_len = (base_count as usize)
2823 .checked_mul(<BaseRecord as ComputeSize>::compute_size(
2824 &mark_class_count,
2825 )?)
2826 .ok_or(ReadError::OutOfBounds)?;
2827 cursor.advance_by(base_records_byte_len);
2828 cursor.finish(BaseArrayMarker {
2829 mark_class_count,
2830 base_records_byte_len,
2831 })
2832 }
2833}
2834
2835impl<'a> BaseArray<'a> {
2836 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
2841 let args = mark_class_count;
2842 Self::read_with_args(data, &args)
2843 }
2844}
2845
2846pub type BaseArray<'a> = TableRef<'a, BaseArrayMarker>;
2848
2849#[allow(clippy::needless_lifetimes)]
2850impl<'a> BaseArray<'a> {
2851 pub fn base_count(&self) -> u16 {
2853 let range = self.shape.base_count_byte_range();
2854 self.data.read_at(range.start).unwrap()
2855 }
2856
2857 pub fn base_records(&self) -> ComputedArray<'a, BaseRecord<'a>> {
2859 let range = self.shape.base_records_byte_range();
2860 self.data
2861 .read_with_args(range, &self.mark_class_count())
2862 .unwrap()
2863 }
2864
2865 pub(crate) fn mark_class_count(&self) -> u16 {
2866 self.shape.mark_class_count
2867 }
2868}
2869
2870#[cfg(feature = "experimental_traverse")]
2871impl<'a> SomeTable<'a> for BaseArray<'a> {
2872 fn type_name(&self) -> &str {
2873 "BaseArray"
2874 }
2875 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2876 match idx {
2877 0usize => Some(Field::new("base_count", self.base_count())),
2878 1usize => Some(Field::new(
2879 "base_records",
2880 traversal::FieldType::computed_array(
2881 "BaseRecord",
2882 self.base_records(),
2883 self.offset_data(),
2884 ),
2885 )),
2886 _ => None,
2887 }
2888 }
2889}
2890
2891#[cfg(feature = "experimental_traverse")]
2892#[allow(clippy::needless_lifetimes)]
2893impl<'a> std::fmt::Debug for BaseArray<'a> {
2894 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2895 (self as &dyn SomeTable<'a>).fmt(f)
2896 }
2897}
2898
2899#[derive(Clone, Debug)]
2901pub struct BaseRecord<'a> {
2902 pub base_anchor_offsets: &'a [BigEndian<Nullable<Offset16>>],
2906}
2907
2908impl<'a> BaseRecord<'a> {
2909 pub fn base_anchor_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2913 self.base_anchor_offsets
2914 }
2915
2916 pub fn base_anchors(
2923 &self,
2924 data: FontData<'a>,
2925 ) -> ArrayOfNullableOffsets<'a, AnchorTable<'a>, Offset16> {
2926 let offsets = self.base_anchor_offsets();
2927 ArrayOfNullableOffsets::new(offsets, data, ())
2928 }
2929}
2930
2931impl ReadArgs for BaseRecord<'_> {
2932 type Args = u16;
2933}
2934
2935impl ComputeSize for BaseRecord<'_> {
2936 #[allow(clippy::needless_question_mark)]
2937 fn compute_size(args: &u16) -> Result<usize, ReadError> {
2938 let mark_class_count = *args;
2939 Ok((mark_class_count as usize)
2940 .checked_mul(Offset16::RAW_BYTE_LEN)
2941 .ok_or(ReadError::OutOfBounds)?)
2942 }
2943}
2944
2945impl<'a> FontReadWithArgs<'a> for BaseRecord<'a> {
2946 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
2947 let mut cursor = data.cursor();
2948 let mark_class_count = *args;
2949 Ok(Self {
2950 base_anchor_offsets: cursor.read_array(mark_class_count as usize)?,
2951 })
2952 }
2953}
2954
2955#[allow(clippy::needless_lifetimes)]
2956impl<'a> BaseRecord<'a> {
2957 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
2962 let args = mark_class_count;
2963 Self::read_with_args(data, &args)
2964 }
2965}
2966
2967#[cfg(feature = "experimental_traverse")]
2968impl<'a> SomeRecord<'a> for BaseRecord<'a> {
2969 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
2970 RecordResolver {
2971 name: "BaseRecord",
2972 get_field: Box::new(move |idx, _data| match idx {
2973 0usize => Some({
2974 Field::new(
2975 "base_anchor_offsets",
2976 FieldType::array_of_offsets(
2977 better_type_name::<AnchorTable>(),
2978 self.base_anchor_offsets(),
2979 move |off| {
2980 let target = off.get().resolve::<AnchorTable>(data);
2981 FieldType::offset(off.get(), target)
2982 },
2983 ),
2984 )
2985 }),
2986 _ => None,
2987 }),
2988 data,
2989 }
2990 }
2991}
2992
2993impl Format<u16> for MarkLigPosFormat1Marker {
2994 const FORMAT: u16 = 1;
2995}
2996
2997#[derive(Debug, Clone, Copy)]
2999#[doc(hidden)]
3000pub struct MarkLigPosFormat1Marker {}
3001
3002impl MarkLigPosFormat1Marker {
3003 pub fn pos_format_byte_range(&self) -> Range<usize> {
3004 let start = 0;
3005 start..start + u16::RAW_BYTE_LEN
3006 }
3007
3008 pub fn mark_coverage_offset_byte_range(&self) -> Range<usize> {
3009 let start = self.pos_format_byte_range().end;
3010 start..start + Offset16::RAW_BYTE_LEN
3011 }
3012
3013 pub fn ligature_coverage_offset_byte_range(&self) -> Range<usize> {
3014 let start = self.mark_coverage_offset_byte_range().end;
3015 start..start + Offset16::RAW_BYTE_LEN
3016 }
3017
3018 pub fn mark_class_count_byte_range(&self) -> Range<usize> {
3019 let start = self.ligature_coverage_offset_byte_range().end;
3020 start..start + u16::RAW_BYTE_LEN
3021 }
3022
3023 pub fn mark_array_offset_byte_range(&self) -> Range<usize> {
3024 let start = self.mark_class_count_byte_range().end;
3025 start..start + Offset16::RAW_BYTE_LEN
3026 }
3027
3028 pub fn ligature_array_offset_byte_range(&self) -> Range<usize> {
3029 let start = self.mark_array_offset_byte_range().end;
3030 start..start + Offset16::RAW_BYTE_LEN
3031 }
3032}
3033
3034impl MinByteRange for MarkLigPosFormat1Marker {
3035 fn min_byte_range(&self) -> Range<usize> {
3036 0..self.ligature_array_offset_byte_range().end
3037 }
3038}
3039
3040impl<'a> FontRead<'a> for MarkLigPosFormat1<'a> {
3041 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
3042 let mut cursor = data.cursor();
3043 cursor.advance::<u16>();
3044 cursor.advance::<Offset16>();
3045 cursor.advance::<Offset16>();
3046 cursor.advance::<u16>();
3047 cursor.advance::<Offset16>();
3048 cursor.advance::<Offset16>();
3049 cursor.finish(MarkLigPosFormat1Marker {})
3050 }
3051}
3052
3053pub type MarkLigPosFormat1<'a> = TableRef<'a, MarkLigPosFormat1Marker>;
3055
3056#[allow(clippy::needless_lifetimes)]
3057impl<'a> MarkLigPosFormat1<'a> {
3058 pub fn pos_format(&self) -> u16 {
3060 let range = self.shape.pos_format_byte_range();
3061 self.data.read_at(range.start).unwrap()
3062 }
3063
3064 pub fn mark_coverage_offset(&self) -> Offset16 {
3067 let range = self.shape.mark_coverage_offset_byte_range();
3068 self.data.read_at(range.start).unwrap()
3069 }
3070
3071 pub fn mark_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
3073 let data = self.data;
3074 self.mark_coverage_offset().resolve(data)
3075 }
3076
3077 pub fn ligature_coverage_offset(&self) -> Offset16 {
3080 let range = self.shape.ligature_coverage_offset_byte_range();
3081 self.data.read_at(range.start).unwrap()
3082 }
3083
3084 pub fn ligature_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
3086 let data = self.data;
3087 self.ligature_coverage_offset().resolve(data)
3088 }
3089
3090 pub fn mark_class_count(&self) -> u16 {
3092 let range = self.shape.mark_class_count_byte_range();
3093 self.data.read_at(range.start).unwrap()
3094 }
3095
3096 pub fn mark_array_offset(&self) -> Offset16 {
3099 let range = self.shape.mark_array_offset_byte_range();
3100 self.data.read_at(range.start).unwrap()
3101 }
3102
3103 pub fn mark_array(&self) -> Result<MarkArray<'a>, ReadError> {
3105 let data = self.data;
3106 self.mark_array_offset().resolve(data)
3107 }
3108
3109 pub fn ligature_array_offset(&self) -> Offset16 {
3112 let range = self.shape.ligature_array_offset_byte_range();
3113 self.data.read_at(range.start).unwrap()
3114 }
3115
3116 pub fn ligature_array(&self) -> Result<LigatureArray<'a>, ReadError> {
3118 let data = self.data;
3119 let args = self.mark_class_count();
3120 self.ligature_array_offset().resolve_with_args(data, &args)
3121 }
3122}
3123
3124#[cfg(feature = "experimental_traverse")]
3125impl<'a> SomeTable<'a> for MarkLigPosFormat1<'a> {
3126 fn type_name(&self) -> &str {
3127 "MarkLigPosFormat1"
3128 }
3129 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3130 match idx {
3131 0usize => Some(Field::new("pos_format", self.pos_format())),
3132 1usize => Some(Field::new(
3133 "mark_coverage_offset",
3134 FieldType::offset(self.mark_coverage_offset(), self.mark_coverage()),
3135 )),
3136 2usize => Some(Field::new(
3137 "ligature_coverage_offset",
3138 FieldType::offset(self.ligature_coverage_offset(), self.ligature_coverage()),
3139 )),
3140 3usize => Some(Field::new("mark_class_count", self.mark_class_count())),
3141 4usize => Some(Field::new(
3142 "mark_array_offset",
3143 FieldType::offset(self.mark_array_offset(), self.mark_array()),
3144 )),
3145 5usize => Some(Field::new(
3146 "ligature_array_offset",
3147 FieldType::offset(self.ligature_array_offset(), self.ligature_array()),
3148 )),
3149 _ => None,
3150 }
3151 }
3152}
3153
3154#[cfg(feature = "experimental_traverse")]
3155#[allow(clippy::needless_lifetimes)]
3156impl<'a> std::fmt::Debug for MarkLigPosFormat1<'a> {
3157 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3158 (self as &dyn SomeTable<'a>).fmt(f)
3159 }
3160}
3161
3162#[derive(Debug, Clone, Copy)]
3164#[doc(hidden)]
3165pub struct LigatureArrayMarker {
3166 mark_class_count: u16,
3167 ligature_attach_offsets_byte_len: usize,
3168}
3169
3170impl LigatureArrayMarker {
3171 pub fn ligature_count_byte_range(&self) -> Range<usize> {
3172 let start = 0;
3173 start..start + u16::RAW_BYTE_LEN
3174 }
3175
3176 pub fn ligature_attach_offsets_byte_range(&self) -> Range<usize> {
3177 let start = self.ligature_count_byte_range().end;
3178 start..start + self.ligature_attach_offsets_byte_len
3179 }
3180}
3181
3182impl MinByteRange for LigatureArrayMarker {
3183 fn min_byte_range(&self) -> Range<usize> {
3184 0..self.ligature_attach_offsets_byte_range().end
3185 }
3186}
3187
3188impl ReadArgs for LigatureArray<'_> {
3189 type Args = u16;
3190}
3191
3192impl<'a> FontReadWithArgs<'a> for LigatureArray<'a> {
3193 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
3194 let mark_class_count = *args;
3195 let mut cursor = data.cursor();
3196 let ligature_count: u16 = cursor.read()?;
3197 let ligature_attach_offsets_byte_len = (ligature_count as usize)
3198 .checked_mul(Offset16::RAW_BYTE_LEN)
3199 .ok_or(ReadError::OutOfBounds)?;
3200 cursor.advance_by(ligature_attach_offsets_byte_len);
3201 cursor.finish(LigatureArrayMarker {
3202 mark_class_count,
3203 ligature_attach_offsets_byte_len,
3204 })
3205 }
3206}
3207
3208impl<'a> LigatureArray<'a> {
3209 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
3214 let args = mark_class_count;
3215 Self::read_with_args(data, &args)
3216 }
3217}
3218
3219pub type LigatureArray<'a> = TableRef<'a, LigatureArrayMarker>;
3221
3222#[allow(clippy::needless_lifetimes)]
3223impl<'a> LigatureArray<'a> {
3224 pub fn ligature_count(&self) -> u16 {
3226 let range = self.shape.ligature_count_byte_range();
3227 self.data.read_at(range.start).unwrap()
3228 }
3229
3230 pub fn ligature_attach_offsets(&self) -> &'a [BigEndian<Offset16>] {
3234 let range = self.shape.ligature_attach_offsets_byte_range();
3235 self.data.read_array(range).unwrap()
3236 }
3237
3238 pub fn ligature_attaches(&self) -> ArrayOfOffsets<'a, LigatureAttach<'a>, Offset16> {
3240 let data = self.data;
3241 let offsets = self.ligature_attach_offsets();
3242 let args = self.mark_class_count();
3243 ArrayOfOffsets::new(offsets, data, args)
3244 }
3245
3246 pub(crate) fn mark_class_count(&self) -> u16 {
3247 self.shape.mark_class_count
3248 }
3249}
3250
3251#[cfg(feature = "experimental_traverse")]
3252impl<'a> SomeTable<'a> for LigatureArray<'a> {
3253 fn type_name(&self) -> &str {
3254 "LigatureArray"
3255 }
3256 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3257 match idx {
3258 0usize => Some(Field::new("ligature_count", self.ligature_count())),
3259 1usize => Some({
3260 let data = self.data;
3261 let args = self.mark_class_count();
3262 Field::new(
3263 "ligature_attach_offsets",
3264 FieldType::array_of_offsets(
3265 better_type_name::<LigatureAttach>(),
3266 self.ligature_attach_offsets(),
3267 move |off| {
3268 let target = off.get().resolve_with_args::<LigatureAttach>(data, &args);
3269 FieldType::offset(off.get(), target)
3270 },
3271 ),
3272 )
3273 }),
3274 _ => None,
3275 }
3276 }
3277}
3278
3279#[cfg(feature = "experimental_traverse")]
3280#[allow(clippy::needless_lifetimes)]
3281impl<'a> std::fmt::Debug for LigatureArray<'a> {
3282 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3283 (self as &dyn SomeTable<'a>).fmt(f)
3284 }
3285}
3286
3287#[derive(Debug, Clone, Copy)]
3289#[doc(hidden)]
3290pub struct LigatureAttachMarker {
3291 mark_class_count: u16,
3292 component_records_byte_len: usize,
3293}
3294
3295impl LigatureAttachMarker {
3296 pub fn component_count_byte_range(&self) -> Range<usize> {
3297 let start = 0;
3298 start..start + u16::RAW_BYTE_LEN
3299 }
3300
3301 pub fn component_records_byte_range(&self) -> Range<usize> {
3302 let start = self.component_count_byte_range().end;
3303 start..start + self.component_records_byte_len
3304 }
3305}
3306
3307impl MinByteRange for LigatureAttachMarker {
3308 fn min_byte_range(&self) -> Range<usize> {
3309 0..self.component_records_byte_range().end
3310 }
3311}
3312
3313impl ReadArgs for LigatureAttach<'_> {
3314 type Args = u16;
3315}
3316
3317impl<'a> FontReadWithArgs<'a> for LigatureAttach<'a> {
3318 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
3319 let mark_class_count = *args;
3320 let mut cursor = data.cursor();
3321 let component_count: u16 = cursor.read()?;
3322 let component_records_byte_len = (component_count as usize)
3323 .checked_mul(<ComponentRecord as ComputeSize>::compute_size(
3324 &mark_class_count,
3325 )?)
3326 .ok_or(ReadError::OutOfBounds)?;
3327 cursor.advance_by(component_records_byte_len);
3328 cursor.finish(LigatureAttachMarker {
3329 mark_class_count,
3330 component_records_byte_len,
3331 })
3332 }
3333}
3334
3335impl<'a> LigatureAttach<'a> {
3336 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
3341 let args = mark_class_count;
3342 Self::read_with_args(data, &args)
3343 }
3344}
3345
3346pub type LigatureAttach<'a> = TableRef<'a, LigatureAttachMarker>;
3348
3349#[allow(clippy::needless_lifetimes)]
3350impl<'a> LigatureAttach<'a> {
3351 pub fn component_count(&self) -> u16 {
3353 let range = self.shape.component_count_byte_range();
3354 self.data.read_at(range.start).unwrap()
3355 }
3356
3357 pub fn component_records(&self) -> ComputedArray<'a, ComponentRecord<'a>> {
3359 let range = self.shape.component_records_byte_range();
3360 self.data
3361 .read_with_args(range, &self.mark_class_count())
3362 .unwrap()
3363 }
3364
3365 pub(crate) fn mark_class_count(&self) -> u16 {
3366 self.shape.mark_class_count
3367 }
3368}
3369
3370#[cfg(feature = "experimental_traverse")]
3371impl<'a> SomeTable<'a> for LigatureAttach<'a> {
3372 fn type_name(&self) -> &str {
3373 "LigatureAttach"
3374 }
3375 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3376 match idx {
3377 0usize => Some(Field::new("component_count", self.component_count())),
3378 1usize => Some(Field::new(
3379 "component_records",
3380 traversal::FieldType::computed_array(
3381 "ComponentRecord",
3382 self.component_records(),
3383 self.offset_data(),
3384 ),
3385 )),
3386 _ => None,
3387 }
3388 }
3389}
3390
3391#[cfg(feature = "experimental_traverse")]
3392#[allow(clippy::needless_lifetimes)]
3393impl<'a> std::fmt::Debug for LigatureAttach<'a> {
3394 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3395 (self as &dyn SomeTable<'a>).fmt(f)
3396 }
3397}
3398
3399#[derive(Clone, Debug)]
3401pub struct ComponentRecord<'a> {
3402 pub ligature_anchor_offsets: &'a [BigEndian<Nullable<Offset16>>],
3406}
3407
3408impl<'a> ComponentRecord<'a> {
3409 pub fn ligature_anchor_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
3413 self.ligature_anchor_offsets
3414 }
3415
3416 pub fn ligature_anchors(
3423 &self,
3424 data: FontData<'a>,
3425 ) -> ArrayOfNullableOffsets<'a, AnchorTable<'a>, Offset16> {
3426 let offsets = self.ligature_anchor_offsets();
3427 ArrayOfNullableOffsets::new(offsets, data, ())
3428 }
3429}
3430
3431impl ReadArgs for ComponentRecord<'_> {
3432 type Args = u16;
3433}
3434
3435impl ComputeSize for ComponentRecord<'_> {
3436 #[allow(clippy::needless_question_mark)]
3437 fn compute_size(args: &u16) -> Result<usize, ReadError> {
3438 let mark_class_count = *args;
3439 Ok((mark_class_count as usize)
3440 .checked_mul(Offset16::RAW_BYTE_LEN)
3441 .ok_or(ReadError::OutOfBounds)?)
3442 }
3443}
3444
3445impl<'a> FontReadWithArgs<'a> for ComponentRecord<'a> {
3446 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
3447 let mut cursor = data.cursor();
3448 let mark_class_count = *args;
3449 Ok(Self {
3450 ligature_anchor_offsets: cursor.read_array(mark_class_count as usize)?,
3451 })
3452 }
3453}
3454
3455#[allow(clippy::needless_lifetimes)]
3456impl<'a> ComponentRecord<'a> {
3457 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
3462 let args = mark_class_count;
3463 Self::read_with_args(data, &args)
3464 }
3465}
3466
3467#[cfg(feature = "experimental_traverse")]
3468impl<'a> SomeRecord<'a> for ComponentRecord<'a> {
3469 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
3470 RecordResolver {
3471 name: "ComponentRecord",
3472 get_field: Box::new(move |idx, _data| match idx {
3473 0usize => Some({
3474 Field::new(
3475 "ligature_anchor_offsets",
3476 FieldType::array_of_offsets(
3477 better_type_name::<AnchorTable>(),
3478 self.ligature_anchor_offsets(),
3479 move |off| {
3480 let target = off.get().resolve::<AnchorTable>(data);
3481 FieldType::offset(off.get(), target)
3482 },
3483 ),
3484 )
3485 }),
3486 _ => None,
3487 }),
3488 data,
3489 }
3490 }
3491}
3492
3493impl Format<u16> for MarkMarkPosFormat1Marker {
3494 const FORMAT: u16 = 1;
3495}
3496
3497#[derive(Debug, Clone, Copy)]
3499#[doc(hidden)]
3500pub struct MarkMarkPosFormat1Marker {}
3501
3502impl MarkMarkPosFormat1Marker {
3503 pub fn pos_format_byte_range(&self) -> Range<usize> {
3504 let start = 0;
3505 start..start + u16::RAW_BYTE_LEN
3506 }
3507
3508 pub fn mark1_coverage_offset_byte_range(&self) -> Range<usize> {
3509 let start = self.pos_format_byte_range().end;
3510 start..start + Offset16::RAW_BYTE_LEN
3511 }
3512
3513 pub fn mark2_coverage_offset_byte_range(&self) -> Range<usize> {
3514 let start = self.mark1_coverage_offset_byte_range().end;
3515 start..start + Offset16::RAW_BYTE_LEN
3516 }
3517
3518 pub fn mark_class_count_byte_range(&self) -> Range<usize> {
3519 let start = self.mark2_coverage_offset_byte_range().end;
3520 start..start + u16::RAW_BYTE_LEN
3521 }
3522
3523 pub fn mark1_array_offset_byte_range(&self) -> Range<usize> {
3524 let start = self.mark_class_count_byte_range().end;
3525 start..start + Offset16::RAW_BYTE_LEN
3526 }
3527
3528 pub fn mark2_array_offset_byte_range(&self) -> Range<usize> {
3529 let start = self.mark1_array_offset_byte_range().end;
3530 start..start + Offset16::RAW_BYTE_LEN
3531 }
3532}
3533
3534impl MinByteRange for MarkMarkPosFormat1Marker {
3535 fn min_byte_range(&self) -> Range<usize> {
3536 0..self.mark2_array_offset_byte_range().end
3537 }
3538}
3539
3540impl<'a> FontRead<'a> for MarkMarkPosFormat1<'a> {
3541 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
3542 let mut cursor = data.cursor();
3543 cursor.advance::<u16>();
3544 cursor.advance::<Offset16>();
3545 cursor.advance::<Offset16>();
3546 cursor.advance::<u16>();
3547 cursor.advance::<Offset16>();
3548 cursor.advance::<Offset16>();
3549 cursor.finish(MarkMarkPosFormat1Marker {})
3550 }
3551}
3552
3553pub type MarkMarkPosFormat1<'a> = TableRef<'a, MarkMarkPosFormat1Marker>;
3555
3556#[allow(clippy::needless_lifetimes)]
3557impl<'a> MarkMarkPosFormat1<'a> {
3558 pub fn pos_format(&self) -> u16 {
3560 let range = self.shape.pos_format_byte_range();
3561 self.data.read_at(range.start).unwrap()
3562 }
3563
3564 pub fn mark1_coverage_offset(&self) -> Offset16 {
3567 let range = self.shape.mark1_coverage_offset_byte_range();
3568 self.data.read_at(range.start).unwrap()
3569 }
3570
3571 pub fn mark1_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
3573 let data = self.data;
3574 self.mark1_coverage_offset().resolve(data)
3575 }
3576
3577 pub fn mark2_coverage_offset(&self) -> Offset16 {
3580 let range = self.shape.mark2_coverage_offset_byte_range();
3581 self.data.read_at(range.start).unwrap()
3582 }
3583
3584 pub fn mark2_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
3586 let data = self.data;
3587 self.mark2_coverage_offset().resolve(data)
3588 }
3589
3590 pub fn mark_class_count(&self) -> u16 {
3592 let range = self.shape.mark_class_count_byte_range();
3593 self.data.read_at(range.start).unwrap()
3594 }
3595
3596 pub fn mark1_array_offset(&self) -> Offset16 {
3599 let range = self.shape.mark1_array_offset_byte_range();
3600 self.data.read_at(range.start).unwrap()
3601 }
3602
3603 pub fn mark1_array(&self) -> Result<MarkArray<'a>, ReadError> {
3605 let data = self.data;
3606 self.mark1_array_offset().resolve(data)
3607 }
3608
3609 pub fn mark2_array_offset(&self) -> Offset16 {
3612 let range = self.shape.mark2_array_offset_byte_range();
3613 self.data.read_at(range.start).unwrap()
3614 }
3615
3616 pub fn mark2_array(&self) -> Result<Mark2Array<'a>, ReadError> {
3618 let data = self.data;
3619 let args = self.mark_class_count();
3620 self.mark2_array_offset().resolve_with_args(data, &args)
3621 }
3622}
3623
3624#[cfg(feature = "experimental_traverse")]
3625impl<'a> SomeTable<'a> for MarkMarkPosFormat1<'a> {
3626 fn type_name(&self) -> &str {
3627 "MarkMarkPosFormat1"
3628 }
3629 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3630 match idx {
3631 0usize => Some(Field::new("pos_format", self.pos_format())),
3632 1usize => Some(Field::new(
3633 "mark1_coverage_offset",
3634 FieldType::offset(self.mark1_coverage_offset(), self.mark1_coverage()),
3635 )),
3636 2usize => Some(Field::new(
3637 "mark2_coverage_offset",
3638 FieldType::offset(self.mark2_coverage_offset(), self.mark2_coverage()),
3639 )),
3640 3usize => Some(Field::new("mark_class_count", self.mark_class_count())),
3641 4usize => Some(Field::new(
3642 "mark1_array_offset",
3643 FieldType::offset(self.mark1_array_offset(), self.mark1_array()),
3644 )),
3645 5usize => Some(Field::new(
3646 "mark2_array_offset",
3647 FieldType::offset(self.mark2_array_offset(), self.mark2_array()),
3648 )),
3649 _ => None,
3650 }
3651 }
3652}
3653
3654#[cfg(feature = "experimental_traverse")]
3655#[allow(clippy::needless_lifetimes)]
3656impl<'a> std::fmt::Debug for MarkMarkPosFormat1<'a> {
3657 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3658 (self as &dyn SomeTable<'a>).fmt(f)
3659 }
3660}
3661
3662#[derive(Debug, Clone, Copy)]
3664#[doc(hidden)]
3665pub struct Mark2ArrayMarker {
3666 mark_class_count: u16,
3667 mark2_records_byte_len: usize,
3668}
3669
3670impl Mark2ArrayMarker {
3671 pub fn mark2_count_byte_range(&self) -> Range<usize> {
3672 let start = 0;
3673 start..start + u16::RAW_BYTE_LEN
3674 }
3675
3676 pub fn mark2_records_byte_range(&self) -> Range<usize> {
3677 let start = self.mark2_count_byte_range().end;
3678 start..start + self.mark2_records_byte_len
3679 }
3680}
3681
3682impl MinByteRange for Mark2ArrayMarker {
3683 fn min_byte_range(&self) -> Range<usize> {
3684 0..self.mark2_records_byte_range().end
3685 }
3686}
3687
3688impl ReadArgs for Mark2Array<'_> {
3689 type Args = u16;
3690}
3691
3692impl<'a> FontReadWithArgs<'a> for Mark2Array<'a> {
3693 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
3694 let mark_class_count = *args;
3695 let mut cursor = data.cursor();
3696 let mark2_count: u16 = cursor.read()?;
3697 let mark2_records_byte_len = (mark2_count as usize)
3698 .checked_mul(<Mark2Record as ComputeSize>::compute_size(
3699 &mark_class_count,
3700 )?)
3701 .ok_or(ReadError::OutOfBounds)?;
3702 cursor.advance_by(mark2_records_byte_len);
3703 cursor.finish(Mark2ArrayMarker {
3704 mark_class_count,
3705 mark2_records_byte_len,
3706 })
3707 }
3708}
3709
3710impl<'a> Mark2Array<'a> {
3711 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
3716 let args = mark_class_count;
3717 Self::read_with_args(data, &args)
3718 }
3719}
3720
3721pub type Mark2Array<'a> = TableRef<'a, Mark2ArrayMarker>;
3723
3724#[allow(clippy::needless_lifetimes)]
3725impl<'a> Mark2Array<'a> {
3726 pub fn mark2_count(&self) -> u16 {
3728 let range = self.shape.mark2_count_byte_range();
3729 self.data.read_at(range.start).unwrap()
3730 }
3731
3732 pub fn mark2_records(&self) -> ComputedArray<'a, Mark2Record<'a>> {
3734 let range = self.shape.mark2_records_byte_range();
3735 self.data
3736 .read_with_args(range, &self.mark_class_count())
3737 .unwrap()
3738 }
3739
3740 pub(crate) fn mark_class_count(&self) -> u16 {
3741 self.shape.mark_class_count
3742 }
3743}
3744
3745#[cfg(feature = "experimental_traverse")]
3746impl<'a> SomeTable<'a> for Mark2Array<'a> {
3747 fn type_name(&self) -> &str {
3748 "Mark2Array"
3749 }
3750 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3751 match idx {
3752 0usize => Some(Field::new("mark2_count", self.mark2_count())),
3753 1usize => Some(Field::new(
3754 "mark2_records",
3755 traversal::FieldType::computed_array(
3756 "Mark2Record",
3757 self.mark2_records(),
3758 self.offset_data(),
3759 ),
3760 )),
3761 _ => None,
3762 }
3763 }
3764}
3765
3766#[cfg(feature = "experimental_traverse")]
3767#[allow(clippy::needless_lifetimes)]
3768impl<'a> std::fmt::Debug for Mark2Array<'a> {
3769 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3770 (self as &dyn SomeTable<'a>).fmt(f)
3771 }
3772}
3773
3774#[derive(Clone, Debug)]
3776pub struct Mark2Record<'a> {
3777 pub mark2_anchor_offsets: &'a [BigEndian<Nullable<Offset16>>],
3781}
3782
3783impl<'a> Mark2Record<'a> {
3784 pub fn mark2_anchor_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
3788 self.mark2_anchor_offsets
3789 }
3790
3791 pub fn mark2_anchors(
3798 &self,
3799 data: FontData<'a>,
3800 ) -> ArrayOfNullableOffsets<'a, AnchorTable<'a>, Offset16> {
3801 let offsets = self.mark2_anchor_offsets();
3802 ArrayOfNullableOffsets::new(offsets, data, ())
3803 }
3804}
3805
3806impl ReadArgs for Mark2Record<'_> {
3807 type Args = u16;
3808}
3809
3810impl ComputeSize for Mark2Record<'_> {
3811 #[allow(clippy::needless_question_mark)]
3812 fn compute_size(args: &u16) -> Result<usize, ReadError> {
3813 let mark_class_count = *args;
3814 Ok((mark_class_count as usize)
3815 .checked_mul(Offset16::RAW_BYTE_LEN)
3816 .ok_or(ReadError::OutOfBounds)?)
3817 }
3818}
3819
3820impl<'a> FontReadWithArgs<'a> for Mark2Record<'a> {
3821 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
3822 let mut cursor = data.cursor();
3823 let mark_class_count = *args;
3824 Ok(Self {
3825 mark2_anchor_offsets: cursor.read_array(mark_class_count as usize)?,
3826 })
3827 }
3828}
3829
3830#[allow(clippy::needless_lifetimes)]
3831impl<'a> Mark2Record<'a> {
3832 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
3837 let args = mark_class_count;
3838 Self::read_with_args(data, &args)
3839 }
3840}
3841
3842#[cfg(feature = "experimental_traverse")]
3843impl<'a> SomeRecord<'a> for Mark2Record<'a> {
3844 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
3845 RecordResolver {
3846 name: "Mark2Record",
3847 get_field: Box::new(move |idx, _data| match idx {
3848 0usize => Some({
3849 Field::new(
3850 "mark2_anchor_offsets",
3851 FieldType::array_of_offsets(
3852 better_type_name::<AnchorTable>(),
3853 self.mark2_anchor_offsets(),
3854 move |off| {
3855 let target = off.get().resolve::<AnchorTable>(data);
3856 FieldType::offset(off.get(), target)
3857 },
3858 ),
3859 )
3860 }),
3861 _ => None,
3862 }),
3863 data,
3864 }
3865 }
3866}
3867
3868impl Format<u16> for ExtensionPosFormat1Marker {
3869 const FORMAT: u16 = 1;
3870}
3871
3872#[derive(Debug)]
3874#[doc(hidden)]
3875pub struct ExtensionPosFormat1Marker<T = ()> {
3876 offset_type: std::marker::PhantomData<*const T>,
3877}
3878
3879impl<T> ExtensionPosFormat1Marker<T> {
3880 pub fn pos_format_byte_range(&self) -> Range<usize> {
3881 let start = 0;
3882 start..start + u16::RAW_BYTE_LEN
3883 }
3884
3885 pub fn extension_lookup_type_byte_range(&self) -> Range<usize> {
3886 let start = self.pos_format_byte_range().end;
3887 start..start + u16::RAW_BYTE_LEN
3888 }
3889
3890 pub fn extension_offset_byte_range(&self) -> Range<usize> {
3891 let start = self.extension_lookup_type_byte_range().end;
3892 start..start + Offset32::RAW_BYTE_LEN
3893 }
3894}
3895
3896impl MinByteRange for ExtensionPosFormat1Marker {
3897 fn min_byte_range(&self) -> Range<usize> {
3898 0..self.extension_offset_byte_range().end
3899 }
3900}
3901
3902impl<T> Clone for ExtensionPosFormat1Marker<T> {
3903 fn clone(&self) -> Self {
3904 *self
3905 }
3906}
3907
3908impl<T> Copy for ExtensionPosFormat1Marker<T> {}
3909
3910impl<'a, T> FontRead<'a> for ExtensionPosFormat1<'a, T> {
3911 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
3912 let mut cursor = data.cursor();
3913 cursor.advance::<u16>();
3914 cursor.advance::<u16>();
3915 cursor.advance::<Offset32>();
3916 cursor.finish(ExtensionPosFormat1Marker {
3917 offset_type: std::marker::PhantomData,
3918 })
3919 }
3920}
3921
3922impl<'a> ExtensionPosFormat1<'a, ()> {
3923 #[allow(dead_code)]
3924 pub(crate) fn into_concrete<T>(self) -> ExtensionPosFormat1<'a, T> {
3925 let TableRef { data, .. } = self;
3926 TableRef {
3927 shape: ExtensionPosFormat1Marker {
3928 offset_type: std::marker::PhantomData,
3929 },
3930 data,
3931 }
3932 }
3933}
3934
3935impl<'a, T> ExtensionPosFormat1<'a, T> {
3936 #[allow(dead_code)]
3937 pub(crate) fn of_unit_type(&self) -> ExtensionPosFormat1<'a, ()> {
3939 let TableRef { data, .. } = self;
3940 TableRef {
3941 shape: ExtensionPosFormat1Marker {
3942 offset_type: std::marker::PhantomData,
3943 },
3944 data: *data,
3945 }
3946 }
3947}
3948
3949pub type ExtensionPosFormat1<'a, T> = TableRef<'a, ExtensionPosFormat1Marker<T>>;
3951
3952#[allow(clippy::needless_lifetimes)]
3953impl<'a, T> ExtensionPosFormat1<'a, T> {
3954 pub fn pos_format(&self) -> u16 {
3956 let range = self.shape.pos_format_byte_range();
3957 self.data.read_at(range.start).unwrap()
3958 }
3959
3960 pub fn extension_lookup_type(&self) -> u16 {
3963 let range = self.shape.extension_lookup_type_byte_range();
3964 self.data.read_at(range.start).unwrap()
3965 }
3966
3967 pub fn extension_offset(&self) -> Offset32 {
3971 let range = self.shape.extension_offset_byte_range();
3972 self.data.read_at(range.start).unwrap()
3973 }
3974
3975 pub fn extension(&self) -> Result<T, ReadError>
3977 where
3978 T: FontRead<'a>,
3979 {
3980 let data = self.data;
3981 self.extension_offset().resolve(data)
3982 }
3983}
3984
3985#[cfg(feature = "experimental_traverse")]
3986impl<'a, T: FontRead<'a> + SomeTable<'a> + 'a> SomeTable<'a> for ExtensionPosFormat1<'a, T> {
3987 fn type_name(&self) -> &str {
3988 "ExtensionPosFormat1"
3989 }
3990 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3991 match idx {
3992 0usize => Some(Field::new("pos_format", self.pos_format())),
3993 1usize => Some(Field::new(
3994 "extension_lookup_type",
3995 self.extension_lookup_type(),
3996 )),
3997 2usize => Some(Field::new(
3998 "extension_offset",
3999 FieldType::offset(self.extension_offset(), self.extension()),
4000 )),
4001 _ => None,
4002 }
4003 }
4004}
4005
4006#[cfg(feature = "experimental_traverse")]
4007#[allow(clippy::needless_lifetimes)]
4008impl<'a, T: FontRead<'a> + SomeTable<'a> + 'a> std::fmt::Debug for ExtensionPosFormat1<'a, T> {
4009 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4010 (self as &dyn SomeTable<'a>).fmt(f)
4011 }
4012}
4013
4014pub enum ExtensionSubtable<'a> {
4016 Single(ExtensionPosFormat1<'a, SinglePos<'a>>),
4017 Pair(ExtensionPosFormat1<'a, PairPos<'a>>),
4018 Cursive(ExtensionPosFormat1<'a, CursivePosFormat1<'a>>),
4019 MarkToBase(ExtensionPosFormat1<'a, MarkBasePosFormat1<'a>>),
4020 MarkToLig(ExtensionPosFormat1<'a, MarkLigPosFormat1<'a>>),
4021 MarkToMark(ExtensionPosFormat1<'a, MarkMarkPosFormat1<'a>>),
4022 Contextual(ExtensionPosFormat1<'a, PositionSequenceContext<'a>>),
4023 ChainContextual(ExtensionPosFormat1<'a, PositionChainContext<'a>>),
4024}
4025
4026impl<'a> FontRead<'a> for ExtensionSubtable<'a> {
4027 fn read(bytes: FontData<'a>) -> Result<Self, ReadError> {
4028 let untyped = ExtensionPosFormat1::read(bytes)?;
4029 match untyped.extension_lookup_type() {
4030 1 => Ok(ExtensionSubtable::Single(untyped.into_concrete())),
4031 2 => Ok(ExtensionSubtable::Pair(untyped.into_concrete())),
4032 3 => Ok(ExtensionSubtable::Cursive(untyped.into_concrete())),
4033 4 => Ok(ExtensionSubtable::MarkToBase(untyped.into_concrete())),
4034 5 => Ok(ExtensionSubtable::MarkToLig(untyped.into_concrete())),
4035 6 => Ok(ExtensionSubtable::MarkToMark(untyped.into_concrete())),
4036 7 => Ok(ExtensionSubtable::Contextual(untyped.into_concrete())),
4037 8 => Ok(ExtensionSubtable::ChainContextual(untyped.into_concrete())),
4038 other => Err(ReadError::InvalidFormat(other.into())),
4039 }
4040 }
4041}
4042
4043impl<'a> ExtensionSubtable<'a> {
4044 #[allow(dead_code)]
4045 pub(crate) fn of_unit_type(&self) -> ExtensionPosFormat1<'a, ()> {
4049 match self {
4050 ExtensionSubtable::Single(inner) => inner.of_unit_type(),
4051 ExtensionSubtable::Pair(inner) => inner.of_unit_type(),
4052 ExtensionSubtable::Cursive(inner) => inner.of_unit_type(),
4053 ExtensionSubtable::MarkToBase(inner) => inner.of_unit_type(),
4054 ExtensionSubtable::MarkToLig(inner) => inner.of_unit_type(),
4055 ExtensionSubtable::MarkToMark(inner) => inner.of_unit_type(),
4056 ExtensionSubtable::Contextual(inner) => inner.of_unit_type(),
4057 ExtensionSubtable::ChainContextual(inner) => inner.of_unit_type(),
4058 }
4059 }
4060}
4061
4062#[cfg(feature = "experimental_traverse")]
4063impl<'a> ExtensionSubtable<'a> {
4064 fn dyn_inner(&self) -> &(dyn SomeTable<'a> + 'a) {
4065 match self {
4066 ExtensionSubtable::Single(table) => table,
4067 ExtensionSubtable::Pair(table) => table,
4068 ExtensionSubtable::Cursive(table) => table,
4069 ExtensionSubtable::MarkToBase(table) => table,
4070 ExtensionSubtable::MarkToLig(table) => table,
4071 ExtensionSubtable::MarkToMark(table) => table,
4072 ExtensionSubtable::Contextual(table) => table,
4073 ExtensionSubtable::ChainContextual(table) => table,
4074 }
4075 }
4076}
4077
4078#[cfg(feature = "experimental_traverse")]
4079impl<'a> SomeTable<'a> for ExtensionSubtable<'a> {
4080 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4081 self.dyn_inner().get_field(idx)
4082 }
4083 fn type_name(&self) -> &str {
4084 self.dyn_inner().type_name()
4085 }
4086}
4087
4088#[cfg(feature = "experimental_traverse")]
4089impl std::fmt::Debug for ExtensionSubtable<'_> {
4090 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4091 self.dyn_inner().fmt(f)
4092 }
4093}