1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for Gpos<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.lookup_list_offset_byte_range().end
11 }
12 fn min_table_bytes(&self) -> &'a [u8] {
13 let range = self.min_byte_range();
14 self.data.as_bytes().get(range).unwrap_or_default()
15 }
16}
17
18impl TopLevelTable for Gpos<'_> {
19 const TAG: Tag = Tag::new(b"GPOS");
21}
22
23impl ReadArgs for Gpos<'_> {
24 type Args = ();
25}
26
27impl<'a> FontRead<'a> for Gpos<'a> {
28 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
29 #[allow(clippy::absurd_extreme_comparisons)]
30 if data.len() < Self::MIN_SIZE {
31 return Err(ReadError::OutOfBounds);
32 }
33 Ok(Self { data })
34 }
35}
36
37#[derive(Clone)]
40pub struct Gpos<'a> {
41 data: FontData<'a>,
42}
43
44#[allow(clippy::needless_lifetimes)]
45impl<'a> Gpos<'a> {
46 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
47 + Offset16::RAW_BYTE_LEN
48 + Offset16::RAW_BYTE_LEN
49 + Offset16::RAW_BYTE_LEN);
50 basic_table_impls!(impl_the_methods);
51
52 pub fn version(&self) -> MajorMinor {
54 let range = self.version_byte_range();
55 self.data.read_at(range.start).ok().unwrap()
56 }
57
58 pub fn script_list_offset(&self) -> Offset16 {
60 let range = self.script_list_offset_byte_range();
61 self.data.read_at(range.start).ok().unwrap()
62 }
63
64 pub fn script_list(&self) -> Result<ScriptList<'a>, ReadError> {
66 let data = self.data;
67 self.script_list_offset().resolve(data)
68 }
69
70 pub fn feature_list_offset(&self) -> Offset16 {
72 let range = self.feature_list_offset_byte_range();
73 self.data.read_at(range.start).ok().unwrap()
74 }
75
76 pub fn feature_list(&self) -> Result<FeatureList<'a>, ReadError> {
78 let data = self.data;
79 self.feature_list_offset().resolve(data)
80 }
81
82 pub fn lookup_list_offset(&self) -> Offset16 {
84 let range = self.lookup_list_offset_byte_range();
85 self.data.read_at(range.start).ok().unwrap()
86 }
87
88 pub fn lookup_list(&self) -> Result<PositionLookupList<'a>, ReadError> {
90 let data = self.data;
91 self.lookup_list_offset().resolve(data)
92 }
93
94 pub fn feature_variations_offset(&self) -> Option<Nullable<Offset32>> {
95 let range = self.feature_variations_offset_byte_range();
96 (!range.is_empty())
97 .then(|| self.data.read_at(range.start).ok())
98 .flatten()
99 }
100
101 pub fn feature_variations(&self) -> Option<Result<FeatureVariations<'a>, ReadError>> {
103 let data = self.data;
104 self.feature_variations_offset().map(|x| x.resolve(data))?
105 }
106
107 pub fn version_byte_range(&self) -> Range<usize> {
108 let start = 0;
109 let end = start + MajorMinor::RAW_BYTE_LEN;
110 start..end
111 }
112
113 pub fn script_list_offset_byte_range(&self) -> Range<usize> {
114 let start = self.version_byte_range().end;
115 let end = start + Offset16::RAW_BYTE_LEN;
116 start..end
117 }
118
119 pub fn feature_list_offset_byte_range(&self) -> Range<usize> {
120 let start = self.script_list_offset_byte_range().end;
121 let end = start + Offset16::RAW_BYTE_LEN;
122 start..end
123 }
124
125 pub fn lookup_list_offset_byte_range(&self) -> Range<usize> {
126 let start = self.feature_list_offset_byte_range().end;
127 let end = start + Offset16::RAW_BYTE_LEN;
128 start..end
129 }
130
131 pub fn feature_variations_offset_byte_range(&self) -> Range<usize> {
132 let start = self.lookup_list_offset_byte_range().end;
133 let end = if self.version().compatible((1u16, 1u16)) {
134 start + Offset32::RAW_BYTE_LEN
135 } else {
136 start
137 };
138 start..end
139 }
140}
141
142const _: () = assert!(FontData::default_data_long_enough(Gpos::MIN_SIZE));
143
144impl Default for Gpos<'_> {
145 fn default() -> Self {
146 Self {
147 data: FontData::default_table_data(),
148 }
149 }
150}
151
152pub enum PositionLookup<'a> {
154 Single(Lookup<'a, SinglePos<'a>>),
155 Pair(Lookup<'a, PairPos<'a>>),
156 Cursive(Lookup<'a, CursivePosFormat1<'a>>),
157 MarkToBase(Lookup<'a, MarkBasePosFormat1<'a>>),
158 MarkToLig(Lookup<'a, MarkLigPosFormat1<'a>>),
159 MarkToMark(Lookup<'a, MarkMarkPosFormat1<'a>>),
160 Contextual(Lookup<'a, PositionSequenceContext<'a>>),
161 ChainContextual(Lookup<'a, PositionChainContext<'a>>),
162 Extension(Lookup<'a, ExtensionSubtable<'a>>),
163}
164
165impl Default for PositionLookup<'_> {
166 fn default() -> Self {
167 Self::Single(Default::default())
168 }
169}
170
171impl ReadArgs for PositionLookup<'_> {
172 type Args = ();
173}
174
175impl<'a> FontRead<'a> for PositionLookup<'a> {
176 fn read_with_args(bytes: FontData<'a>, _: ()) -> Result<Self, ReadError> {
177 let discriminant = Lookup::read_discriminant(bytes)?;
178 match discriminant {
179 1 => Ok(PositionLookup::Single(FontRead::read(bytes)?)),
180 2 => Ok(PositionLookup::Pair(FontRead::read(bytes)?)),
181 3 => Ok(PositionLookup::Cursive(FontRead::read(bytes)?)),
182 4 => Ok(PositionLookup::MarkToBase(FontRead::read(bytes)?)),
183 5 => Ok(PositionLookup::MarkToLig(FontRead::read(bytes)?)),
184 6 => Ok(PositionLookup::MarkToMark(FontRead::read(bytes)?)),
185 7 => Ok(PositionLookup::Contextual(FontRead::read(bytes)?)),
186 8 => Ok(PositionLookup::ChainContextual(FontRead::read(bytes)?)),
187 9 => Ok(PositionLookup::Extension(FontRead::read(bytes)?)),
188 other => Err(ReadError::InvalidFormat(other.into())),
189 }
190 }
191}
192
193impl<'a> PositionLookup<'a> {
194 #[allow(dead_code)]
195 pub(crate) fn of_unit_type(&self) -> Lookup<'a, ()> {
199 match self {
200 PositionLookup::Single(inner) => inner.of_unit_type(),
201 PositionLookup::Pair(inner) => inner.of_unit_type(),
202 PositionLookup::Cursive(inner) => inner.of_unit_type(),
203 PositionLookup::MarkToBase(inner) => inner.of_unit_type(),
204 PositionLookup::MarkToLig(inner) => inner.of_unit_type(),
205 PositionLookup::MarkToMark(inner) => inner.of_unit_type(),
206 PositionLookup::Contextual(inner) => inner.of_unit_type(),
207 PositionLookup::ChainContextual(inner) => inner.of_unit_type(),
208 PositionLookup::Extension(inner) => inner.of_unit_type(),
209 }
210 }
211}
212
213#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
215#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
216#[repr(transparent)]
217pub struct ValueFormat {
218 bits: u16,
219}
220
221impl ValueFormat {
222 pub const X_PLACEMENT: Self = Self { bits: 0x0001 };
224
225 pub const Y_PLACEMENT: Self = Self { bits: 0x0002 };
227
228 pub const X_ADVANCE: Self = Self { bits: 0x0004 };
230
231 pub const Y_ADVANCE: Self = Self { bits: 0x0008 };
233
234 pub const X_PLACEMENT_DEVICE: Self = Self { bits: 0x0010 };
237
238 pub const Y_PLACEMENT_DEVICE: Self = Self { bits: 0x0020 };
241
242 pub const X_ADVANCE_DEVICE: Self = Self { bits: 0x0040 };
245
246 pub const Y_ADVANCE_DEVICE: Self = Self { bits: 0x0080 };
249}
250
251impl ValueFormat {
252 #[inline]
254 pub const fn empty() -> Self {
255 Self { bits: 0 }
256 }
257
258 #[inline]
260 pub const fn all() -> Self {
261 Self {
262 bits: Self::X_PLACEMENT.bits
263 | Self::Y_PLACEMENT.bits
264 | Self::X_ADVANCE.bits
265 | Self::Y_ADVANCE.bits
266 | Self::X_PLACEMENT_DEVICE.bits
267 | Self::Y_PLACEMENT_DEVICE.bits
268 | Self::X_ADVANCE_DEVICE.bits
269 | Self::Y_ADVANCE_DEVICE.bits,
270 }
271 }
272
273 #[inline]
275 pub const fn bits(&self) -> u16 {
276 self.bits
277 }
278
279 #[inline]
282 pub const fn from_bits(bits: u16) -> Option<Self> {
283 if (bits & !Self::all().bits()) == 0 {
284 Some(Self { bits })
285 } else {
286 None
287 }
288 }
289
290 #[inline]
293 pub const fn from_bits_truncate(bits: u16) -> Self {
294 Self {
295 bits: bits & Self::all().bits,
296 }
297 }
298
299 #[inline]
301 pub const fn is_empty(&self) -> bool {
302 self.bits() == Self::empty().bits()
303 }
304
305 #[inline]
307 pub const fn intersects(&self, other: Self) -> bool {
308 !(Self {
309 bits: self.bits & other.bits,
310 })
311 .is_empty()
312 }
313
314 #[inline]
316 pub const fn contains(&self, other: Self) -> bool {
317 (self.bits & other.bits) == other.bits
318 }
319
320 #[inline]
322 pub fn insert(&mut self, other: Self) {
323 self.bits |= other.bits;
324 }
325
326 #[inline]
328 pub fn remove(&mut self, other: Self) {
329 self.bits &= !other.bits;
330 }
331
332 #[inline]
334 pub fn toggle(&mut self, other: Self) {
335 self.bits ^= other.bits;
336 }
337
338 #[inline]
349 #[must_use]
350 pub const fn intersection(self, other: Self) -> Self {
351 Self {
352 bits: self.bits & other.bits,
353 }
354 }
355
356 #[inline]
367 #[must_use]
368 pub const fn union(self, other: Self) -> Self {
369 Self {
370 bits: self.bits | other.bits,
371 }
372 }
373
374 #[inline]
387 #[must_use]
388 pub const fn difference(self, other: Self) -> Self {
389 Self {
390 bits: self.bits & !other.bits,
391 }
392 }
393}
394
395impl std::ops::BitOr for ValueFormat {
396 type Output = Self;
397
398 #[inline]
400 fn bitor(self, other: ValueFormat) -> Self {
401 Self {
402 bits: self.bits | other.bits,
403 }
404 }
405}
406
407impl std::ops::BitOrAssign for ValueFormat {
408 #[inline]
410 fn bitor_assign(&mut self, other: Self) {
411 self.bits |= other.bits;
412 }
413}
414
415impl std::ops::BitXor for ValueFormat {
416 type Output = Self;
417
418 #[inline]
420 fn bitxor(self, other: Self) -> Self {
421 Self {
422 bits: self.bits ^ other.bits,
423 }
424 }
425}
426
427impl std::ops::BitXorAssign for ValueFormat {
428 #[inline]
430 fn bitxor_assign(&mut self, other: Self) {
431 self.bits ^= other.bits;
432 }
433}
434
435impl std::ops::BitAnd for ValueFormat {
436 type Output = Self;
437
438 #[inline]
440 fn bitand(self, other: Self) -> Self {
441 Self {
442 bits: self.bits & other.bits,
443 }
444 }
445}
446
447impl std::ops::BitAndAssign for ValueFormat {
448 #[inline]
450 fn bitand_assign(&mut self, other: Self) {
451 self.bits &= other.bits;
452 }
453}
454
455impl std::ops::Sub for ValueFormat {
456 type Output = Self;
457
458 #[inline]
460 fn sub(self, other: Self) -> Self {
461 Self {
462 bits: self.bits & !other.bits,
463 }
464 }
465}
466
467impl std::ops::SubAssign for ValueFormat {
468 #[inline]
470 fn sub_assign(&mut self, other: Self) {
471 self.bits &= !other.bits;
472 }
473}
474
475impl std::ops::Not for ValueFormat {
476 type Output = Self;
477
478 #[inline]
480 fn not(self) -> Self {
481 Self { bits: !self.bits } & Self::all()
482 }
483}
484
485impl std::fmt::Debug for ValueFormat {
486 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
487 let members: &[(&str, Self)] = &[
488 ("X_PLACEMENT", Self::X_PLACEMENT),
489 ("Y_PLACEMENT", Self::Y_PLACEMENT),
490 ("X_ADVANCE", Self::X_ADVANCE),
491 ("Y_ADVANCE", Self::Y_ADVANCE),
492 ("X_PLACEMENT_DEVICE", Self::X_PLACEMENT_DEVICE),
493 ("Y_PLACEMENT_DEVICE", Self::Y_PLACEMENT_DEVICE),
494 ("X_ADVANCE_DEVICE", Self::X_ADVANCE_DEVICE),
495 ("Y_ADVANCE_DEVICE", Self::Y_ADVANCE_DEVICE),
496 ];
497 let mut first = true;
498 for (name, value) in members {
499 if self.contains(*value) {
500 if !first {
501 f.write_str(" | ")?;
502 }
503 first = false;
504 f.write_str(name)?;
505 }
506 }
507 if first {
508 f.write_str("(empty)")?;
509 }
510 Ok(())
511 }
512}
513
514impl std::fmt::Binary for ValueFormat {
515 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
516 std::fmt::Binary::fmt(&self.bits, f)
517 }
518}
519
520impl std::fmt::Octal for ValueFormat {
521 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
522 std::fmt::Octal::fmt(&self.bits, f)
523 }
524}
525
526impl std::fmt::LowerHex for ValueFormat {
527 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
528 std::fmt::LowerHex::fmt(&self.bits, f)
529 }
530}
531
532impl std::fmt::UpperHex for ValueFormat {
533 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
534 std::fmt::UpperHex::fmt(&self.bits, f)
535 }
536}
537
538impl font_types::Scalar for ValueFormat {
539 type Raw = <u16 as font_types::Scalar>::Raw;
540 fn to_raw(self) -> Self::Raw {
541 self.bits().to_raw()
542 }
543 fn from_raw(raw: Self::Raw) -> Self {
544 let t = <u16>::from_raw(raw);
545 Self::from_bits_truncate(t)
546 }
547}
548
549#[derive(Clone)]
552pub enum AnchorTable<'a> {
553 Format1(AnchorFormat1<'a>),
554 Format2(AnchorFormat2<'a>),
555 Format3(AnchorFormat3<'a>),
556}
557
558impl Default for AnchorTable<'_> {
559 fn default() -> Self {
560 Self::Format1(Default::default())
561 }
562}
563
564impl<'a> AnchorTable<'a> {
565 pub fn offset_data(&self) -> FontData<'a> {
567 match self {
568 Self::Format1(item) => item.offset_data(),
569 Self::Format2(item) => item.offset_data(),
570 Self::Format3(item) => item.offset_data(),
571 }
572 }
573
574 pub fn anchor_format(&self) -> u16 {
576 match self {
577 Self::Format1(item) => item.anchor_format(),
578 Self::Format2(item) => item.anchor_format(),
579 Self::Format3(item) => item.anchor_format(),
580 }
581 }
582
583 pub fn x_coordinate(&self) -> i16 {
585 match self {
586 Self::Format1(item) => item.x_coordinate(),
587 Self::Format2(item) => item.x_coordinate(),
588 Self::Format3(item) => item.x_coordinate(),
589 }
590 }
591
592 pub fn y_coordinate(&self) -> i16 {
594 match self {
595 Self::Format1(item) => item.y_coordinate(),
596 Self::Format2(item) => item.y_coordinate(),
597 Self::Format3(item) => item.y_coordinate(),
598 }
599 }
600}
601
602impl ReadArgs for AnchorTable<'_> {
603 type Args = ();
604}
605
606impl<'a> FontRead<'a> for AnchorTable<'a> {
607 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
608 let format: u16 = data.read_at(0usize)?;
609 match format {
610 AnchorFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
611 AnchorFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
612 AnchorFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
613 other => Err(ReadError::InvalidFormat(other.into())),
614 }
615 }
616}
617
618impl<'a> MinByteRange<'a> for AnchorTable<'a> {
619 fn min_byte_range(&self) -> Range<usize> {
620 match self {
621 Self::Format1(item) => item.min_byte_range(),
622 Self::Format2(item) => item.min_byte_range(),
623 Self::Format3(item) => item.min_byte_range(),
624 }
625 }
626 fn min_table_bytes(&self) -> &'a [u8] {
627 match self {
628 Self::Format1(item) => item.min_table_bytes(),
629 Self::Format2(item) => item.min_table_bytes(),
630 Self::Format3(item) => item.min_table_bytes(),
631 }
632 }
633}
634
635impl Format<u16> for AnchorFormat1<'_> {
636 const FORMAT: u16 = 1;
637}
638
639impl<'a> MinByteRange<'a> for AnchorFormat1<'a> {
640 fn min_byte_range(&self) -> Range<usize> {
641 0..self.y_coordinate_byte_range().end
642 }
643 fn min_table_bytes(&self) -> &'a [u8] {
644 let range = self.min_byte_range();
645 self.data.as_bytes().get(range).unwrap_or_default()
646 }
647}
648
649impl ReadArgs for AnchorFormat1<'_> {
650 type Args = ();
651}
652
653impl<'a> FontRead<'a> for AnchorFormat1<'a> {
654 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
655 #[allow(clippy::absurd_extreme_comparisons)]
656 if data.len() < Self::MIN_SIZE {
657 return Err(ReadError::OutOfBounds);
658 }
659 Ok(Self { data })
660 }
661}
662
663#[derive(Clone)]
665pub struct AnchorFormat1<'a> {
666 data: FontData<'a>,
667}
668
669#[allow(clippy::needless_lifetimes)]
670impl<'a> AnchorFormat1<'a> {
671 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN);
672 basic_table_impls!(impl_the_methods);
673
674 pub fn anchor_format(&self) -> u16 {
676 let range = self.anchor_format_byte_range();
677 self.data.read_at(range.start).ok().unwrap()
678 }
679
680 pub fn x_coordinate(&self) -> i16 {
682 let range = self.x_coordinate_byte_range();
683 self.data.read_at(range.start).ok().unwrap()
684 }
685
686 pub fn y_coordinate(&self) -> i16 {
688 let range = self.y_coordinate_byte_range();
689 self.data.read_at(range.start).ok().unwrap()
690 }
691
692 pub fn anchor_format_byte_range(&self) -> Range<usize> {
693 let start = 0;
694 let end = start + u16::RAW_BYTE_LEN;
695 start..end
696 }
697
698 pub fn x_coordinate_byte_range(&self) -> Range<usize> {
699 let start = self.anchor_format_byte_range().end;
700 let end = start + i16::RAW_BYTE_LEN;
701 start..end
702 }
703
704 pub fn y_coordinate_byte_range(&self) -> Range<usize> {
705 let start = self.x_coordinate_byte_range().end;
706 let end = start + i16::RAW_BYTE_LEN;
707 start..end
708 }
709}
710
711const _: () = assert!(FontData::default_data_long_enough(AnchorFormat1::MIN_SIZE));
712
713impl Default for AnchorFormat1<'_> {
714 fn default() -> Self {
715 Self {
716 data: FontData::default_format_1_u16_table_data(),
717 }
718 }
719}
720
721impl Format<u16> for AnchorFormat2<'_> {
722 const FORMAT: u16 = 2;
723}
724
725impl<'a> MinByteRange<'a> for AnchorFormat2<'a> {
726 fn min_byte_range(&self) -> Range<usize> {
727 0..self.anchor_point_byte_range().end
728 }
729 fn min_table_bytes(&self) -> &'a [u8] {
730 let range = self.min_byte_range();
731 self.data.as_bytes().get(range).unwrap_or_default()
732 }
733}
734
735impl ReadArgs for AnchorFormat2<'_> {
736 type Args = ();
737}
738
739impl<'a> FontRead<'a> for AnchorFormat2<'a> {
740 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
741 #[allow(clippy::absurd_extreme_comparisons)]
742 if data.len() < Self::MIN_SIZE {
743 return Err(ReadError::OutOfBounds);
744 }
745 Ok(Self { data })
746 }
747}
748
749#[derive(Clone)]
751pub struct AnchorFormat2<'a> {
752 data: FontData<'a>,
753}
754
755#[allow(clippy::needless_lifetimes)]
756impl<'a> AnchorFormat2<'a> {
757 pub const MIN_SIZE: usize =
758 (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
759 basic_table_impls!(impl_the_methods);
760
761 pub fn anchor_format(&self) -> u16 {
763 let range = self.anchor_format_byte_range();
764 self.data.read_at(range.start).ok().unwrap()
765 }
766
767 pub fn x_coordinate(&self) -> i16 {
769 let range = self.x_coordinate_byte_range();
770 self.data.read_at(range.start).ok().unwrap()
771 }
772
773 pub fn y_coordinate(&self) -> i16 {
775 let range = self.y_coordinate_byte_range();
776 self.data.read_at(range.start).ok().unwrap()
777 }
778
779 pub fn anchor_point(&self) -> u16 {
781 let range = self.anchor_point_byte_range();
782 self.data.read_at(range.start).ok().unwrap()
783 }
784
785 pub fn anchor_format_byte_range(&self) -> Range<usize> {
786 let start = 0;
787 let end = start + u16::RAW_BYTE_LEN;
788 start..end
789 }
790
791 pub fn x_coordinate_byte_range(&self) -> Range<usize> {
792 let start = self.anchor_format_byte_range().end;
793 let end = start + i16::RAW_BYTE_LEN;
794 start..end
795 }
796
797 pub fn y_coordinate_byte_range(&self) -> Range<usize> {
798 let start = self.x_coordinate_byte_range().end;
799 let end = start + i16::RAW_BYTE_LEN;
800 start..end
801 }
802
803 pub fn anchor_point_byte_range(&self) -> Range<usize> {
804 let start = self.y_coordinate_byte_range().end;
805 let end = start + u16::RAW_BYTE_LEN;
806 start..end
807 }
808}
809
810impl Format<u16> for AnchorFormat3<'_> {
811 const FORMAT: u16 = 3;
812}
813
814impl<'a> MinByteRange<'a> for AnchorFormat3<'a> {
815 fn min_byte_range(&self) -> Range<usize> {
816 0..self.y_device_offset_byte_range().end
817 }
818 fn min_table_bytes(&self) -> &'a [u8] {
819 let range = self.min_byte_range();
820 self.data.as_bytes().get(range).unwrap_or_default()
821 }
822}
823
824impl ReadArgs for AnchorFormat3<'_> {
825 type Args = ();
826}
827
828impl<'a> FontRead<'a> for AnchorFormat3<'a> {
829 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
830 #[allow(clippy::absurd_extreme_comparisons)]
831 if data.len() < Self::MIN_SIZE {
832 return Err(ReadError::OutOfBounds);
833 }
834 Ok(Self { data })
835 }
836}
837
838#[derive(Clone)]
840pub struct AnchorFormat3<'a> {
841 data: FontData<'a>,
842}
843
844#[allow(clippy::needless_lifetimes)]
845impl<'a> AnchorFormat3<'a> {
846 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
847 + i16::RAW_BYTE_LEN
848 + i16::RAW_BYTE_LEN
849 + Offset16::RAW_BYTE_LEN
850 + Offset16::RAW_BYTE_LEN);
851 basic_table_impls!(impl_the_methods);
852
853 pub fn anchor_format(&self) -> u16 {
855 let range = self.anchor_format_byte_range();
856 self.data.read_at(range.start).ok().unwrap()
857 }
858
859 pub fn x_coordinate(&self) -> i16 {
861 let range = self.x_coordinate_byte_range();
862 self.data.read_at(range.start).ok().unwrap()
863 }
864
865 pub fn y_coordinate(&self) -> i16 {
867 let range = self.y_coordinate_byte_range();
868 self.data.read_at(range.start).ok().unwrap()
869 }
870
871 pub fn x_device_offset(&self) -> Nullable<Offset16> {
875 let range = self.x_device_offset_byte_range();
876 self.data.read_at(range.start).ok().unwrap()
877 }
878
879 pub fn x_device(&self) -> Option<Result<DeviceOrVariationIndex<'a>, ReadError>> {
881 let data = self.data;
882 self.x_device_offset().resolve(data)
883 }
884
885 pub fn y_device_offset(&self) -> Nullable<Offset16> {
889 let range = self.y_device_offset_byte_range();
890 self.data.read_at(range.start).ok().unwrap()
891 }
892
893 pub fn y_device(&self) -> Option<Result<DeviceOrVariationIndex<'a>, ReadError>> {
895 let data = self.data;
896 self.y_device_offset().resolve(data)
897 }
898
899 pub fn anchor_format_byte_range(&self) -> Range<usize> {
900 let start = 0;
901 let end = start + u16::RAW_BYTE_LEN;
902 start..end
903 }
904
905 pub fn x_coordinate_byte_range(&self) -> Range<usize> {
906 let start = self.anchor_format_byte_range().end;
907 let end = start + i16::RAW_BYTE_LEN;
908 start..end
909 }
910
911 pub fn y_coordinate_byte_range(&self) -> Range<usize> {
912 let start = self.x_coordinate_byte_range().end;
913 let end = start + i16::RAW_BYTE_LEN;
914 start..end
915 }
916
917 pub fn x_device_offset_byte_range(&self) -> Range<usize> {
918 let start = self.y_coordinate_byte_range().end;
919 let end = start + Offset16::RAW_BYTE_LEN;
920 start..end
921 }
922
923 pub fn y_device_offset_byte_range(&self) -> Range<usize> {
924 let start = self.x_device_offset_byte_range().end;
925 let end = start + Offset16::RAW_BYTE_LEN;
926 start..end
927 }
928}
929
930impl<'a> MinByteRange<'a> for MarkArray<'a> {
931 fn min_byte_range(&self) -> Range<usize> {
932 0..self.mark_records_byte_range().end
933 }
934 fn min_table_bytes(&self) -> &'a [u8] {
935 let range = self.min_byte_range();
936 self.data.as_bytes().get(range).unwrap_or_default()
937 }
938}
939
940impl ReadArgs for MarkArray<'_> {
941 type Args = ();
942}
943
944impl<'a> FontRead<'a> for MarkArray<'a> {
945 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
946 #[allow(clippy::absurd_extreme_comparisons)]
947 if data.len() < Self::MIN_SIZE {
948 return Err(ReadError::OutOfBounds);
949 }
950 Ok(Self { data })
951 }
952}
953
954#[derive(Clone)]
956pub struct MarkArray<'a> {
957 data: FontData<'a>,
958}
959
960#[allow(clippy::needless_lifetimes)]
961impl<'a> MarkArray<'a> {
962 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
963 basic_table_impls!(impl_the_methods);
964
965 pub fn mark_count(&self) -> u16 {
967 let range = self.mark_count_byte_range();
968 self.data.read_at(range.start).ok().unwrap()
969 }
970
971 pub fn mark_records(&self) -> &'a [MarkRecord] {
974 let range = self.mark_records_byte_range();
975 self.data.read_array(range).ok().unwrap_or_default()
976 }
977
978 pub fn mark_count_byte_range(&self) -> Range<usize> {
979 let start = 0;
980 let end = start + u16::RAW_BYTE_LEN;
981 start..end
982 }
983
984 pub fn mark_records_byte_range(&self) -> Range<usize> {
985 let mark_count = self.mark_count();
986 let start = self.mark_count_byte_range().end;
987 let end =
988 start + (transforms::to_usize(mark_count)).saturating_mul(MarkRecord::RAW_BYTE_LEN);
989 start..end
990 }
991}
992
993const _: () = assert!(FontData::default_data_long_enough(MarkArray::MIN_SIZE));
994
995impl Default for MarkArray<'_> {
996 fn default() -> Self {
997 Self {
998 data: FontData::default_table_data(),
999 }
1000 }
1001}
1002
1003#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
1005#[repr(C)]
1006#[repr(packed)]
1007pub struct MarkRecord {
1008 pub mark_class: BigEndian<u16>,
1010 pub mark_anchor_offset: BigEndian<Offset16>,
1012}
1013
1014impl MarkRecord {
1015 pub fn mark_class(&self) -> u16 {
1017 self.mark_class.get()
1018 }
1019
1020 pub fn mark_anchor_offset(&self) -> Offset16 {
1022 self.mark_anchor_offset.get()
1023 }
1024
1025 pub fn mark_anchor<'a>(&self, data: FontData<'a>) -> Result<AnchorTable<'a>, ReadError> {
1030 self.mark_anchor_offset().resolve(data)
1031 }
1032}
1033
1034impl FixedSize for MarkRecord {
1035 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
1036}
1037
1038#[derive(Clone)]
1040pub enum SinglePos<'a> {
1041 Format1(SinglePosFormat1<'a>),
1042 Format2(SinglePosFormat2<'a>),
1043}
1044
1045impl Default for SinglePos<'_> {
1046 fn default() -> Self {
1047 Self::Format1(Default::default())
1048 }
1049}
1050
1051impl<'a> SinglePos<'a> {
1052 pub fn offset_data(&self) -> FontData<'a> {
1054 match self {
1055 Self::Format1(item) => item.offset_data(),
1056 Self::Format2(item) => item.offset_data(),
1057 }
1058 }
1059
1060 pub fn pos_format(&self) -> u16 {
1062 match self {
1063 Self::Format1(item) => item.pos_format(),
1064 Self::Format2(item) => item.pos_format(),
1065 }
1066 }
1067
1068 pub fn coverage_offset(&self) -> Offset16 {
1070 match self {
1071 Self::Format1(item) => item.coverage_offset(),
1072 Self::Format2(item) => item.coverage_offset(),
1073 }
1074 }
1075
1076 pub fn value_format(&self) -> ValueFormat {
1078 match self {
1079 Self::Format1(item) => item.value_format(),
1080 Self::Format2(item) => item.value_format(),
1081 }
1082 }
1083}
1084
1085impl ReadArgs for SinglePos<'_> {
1086 type Args = ();
1087}
1088
1089impl<'a> FontRead<'a> for SinglePos<'a> {
1090 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1091 let format: u16 = data.read_at(0usize)?;
1092 match format {
1093 SinglePosFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1094 SinglePosFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1095 other => Err(ReadError::InvalidFormat(other.into())),
1096 }
1097 }
1098}
1099
1100impl<'a> MinByteRange<'a> for SinglePos<'a> {
1101 fn min_byte_range(&self) -> Range<usize> {
1102 match self {
1103 Self::Format1(item) => item.min_byte_range(),
1104 Self::Format2(item) => item.min_byte_range(),
1105 }
1106 }
1107 fn min_table_bytes(&self) -> &'a [u8] {
1108 match self {
1109 Self::Format1(item) => item.min_table_bytes(),
1110 Self::Format2(item) => item.min_table_bytes(),
1111 }
1112 }
1113}
1114
1115impl Format<u16> for SinglePosFormat1<'_> {
1116 const FORMAT: u16 = 1;
1117}
1118
1119impl<'a> MinByteRange<'a> for SinglePosFormat1<'a> {
1120 fn min_byte_range(&self) -> Range<usize> {
1121 0..self.value_record_byte_range().end
1122 }
1123 fn min_table_bytes(&self) -> &'a [u8] {
1124 let range = self.min_byte_range();
1125 self.data.as_bytes().get(range).unwrap_or_default()
1126 }
1127}
1128
1129impl ReadArgs for SinglePosFormat1<'_> {
1130 type Args = ();
1131}
1132
1133impl<'a> FontRead<'a> for SinglePosFormat1<'a> {
1134 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1135 #[allow(clippy::absurd_extreme_comparisons)]
1136 if data.len() < Self::MIN_SIZE {
1137 return Err(ReadError::OutOfBounds);
1138 }
1139 Ok(Self { data })
1140 }
1141}
1142
1143#[derive(Clone)]
1145pub struct SinglePosFormat1<'a> {
1146 data: FontData<'a>,
1147}
1148
1149#[allow(clippy::needless_lifetimes)]
1150impl<'a> SinglePosFormat1<'a> {
1151 pub const MIN_SIZE: usize =
1152 (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + ValueFormat::RAW_BYTE_LEN);
1153 basic_table_impls!(impl_the_methods);
1154
1155 pub fn pos_format(&self) -> u16 {
1157 let range = self.pos_format_byte_range();
1158 self.data.read_at(range.start).ok().unwrap()
1159 }
1160
1161 pub fn coverage_offset(&self) -> Offset16 {
1163 let range = self.coverage_offset_byte_range();
1164 self.data.read_at(range.start).ok().unwrap()
1165 }
1166
1167 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1169 let data = self.data;
1170 self.coverage_offset().resolve(data)
1171 }
1172
1173 pub fn value_format(&self) -> ValueFormat {
1175 let range = self.value_format_byte_range();
1176 self.data.read_at(range.start).ok().unwrap()
1177 }
1178
1179 pub fn value_record(&self) -> ValueRecord<'a> {
1182 let range = self.value_record_byte_range();
1183 ValueRecord::read_at(self.data, range.start, self.value_format()).unwrap_or_default()
1184 }
1185
1186 pub fn pos_format_byte_range(&self) -> Range<usize> {
1187 let start = 0;
1188 let end = start + u16::RAW_BYTE_LEN;
1189 start..end
1190 }
1191
1192 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1193 let start = self.pos_format_byte_range().end;
1194 let end = start + Offset16::RAW_BYTE_LEN;
1195 start..end
1196 }
1197
1198 pub fn value_format_byte_range(&self) -> Range<usize> {
1199 let start = self.coverage_offset_byte_range().end;
1200 let end = start + ValueFormat::RAW_BYTE_LEN;
1201 start..end
1202 }
1203
1204 pub fn value_record_byte_range(&self) -> Range<usize> {
1205 let start = self.value_format_byte_range().end;
1206 let end =
1207 start + <ValueRecord as ComputeSize>::compute_size(self.value_format()).unwrap_or(0);
1208 start..end
1209 }
1210}
1211
1212const _: () = assert!(FontData::default_data_long_enough(
1213 SinglePosFormat1::MIN_SIZE
1214));
1215
1216impl Default for SinglePosFormat1<'_> {
1217 fn default() -> Self {
1218 Self {
1219 data: FontData::default_format_1_u16_table_data(),
1220 }
1221 }
1222}
1223
1224impl Format<u16> for SinglePosFormat2<'_> {
1225 const FORMAT: u16 = 2;
1226}
1227
1228impl<'a> MinByteRange<'a> for SinglePosFormat2<'a> {
1229 fn min_byte_range(&self) -> Range<usize> {
1230 0..self.value_records_byte_range().end
1231 }
1232 fn min_table_bytes(&self) -> &'a [u8] {
1233 let range = self.min_byte_range();
1234 self.data.as_bytes().get(range).unwrap_or_default()
1235 }
1236}
1237
1238impl ReadArgs for SinglePosFormat2<'_> {
1239 type Args = ();
1240}
1241
1242impl<'a> FontRead<'a> for SinglePosFormat2<'a> {
1243 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1244 #[allow(clippy::absurd_extreme_comparisons)]
1245 if data.len() < Self::MIN_SIZE {
1246 return Err(ReadError::OutOfBounds);
1247 }
1248 Ok(Self { data })
1249 }
1250}
1251
1252#[derive(Clone)]
1254pub struct SinglePosFormat2<'a> {
1255 data: FontData<'a>,
1256}
1257
1258#[allow(clippy::needless_lifetimes)]
1259impl<'a> SinglePosFormat2<'a> {
1260 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1261 + Offset16::RAW_BYTE_LEN
1262 + ValueFormat::RAW_BYTE_LEN
1263 + u16::RAW_BYTE_LEN);
1264 basic_table_impls!(impl_the_methods);
1265
1266 pub fn pos_format(&self) -> u16 {
1268 let range = self.pos_format_byte_range();
1269 self.data.read_at(range.start).ok().unwrap()
1270 }
1271
1272 pub fn coverage_offset(&self) -> Offset16 {
1274 let range = self.coverage_offset_byte_range();
1275 self.data.read_at(range.start).ok().unwrap()
1276 }
1277
1278 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1280 let data = self.data;
1281 self.coverage_offset().resolve(data)
1282 }
1283
1284 pub fn value_format(&self) -> ValueFormat {
1286 let range = self.value_format_byte_range();
1287 self.data.read_at(range.start).ok().unwrap()
1288 }
1289
1290 pub fn value_count(&self) -> u16 {
1293 let range = self.value_count_byte_range();
1294 self.data.read_at(range.start).ok().unwrap()
1295 }
1296
1297 pub fn value_records(&self) -> ComputedArray<'a, ValueRecord<'a>> {
1299 let range = self.value_records_byte_range();
1300 ComputedArray::new(self.data, range, self.value_format()).unwrap_or_default()
1301 }
1302
1303 pub fn pos_format_byte_range(&self) -> Range<usize> {
1304 let start = 0;
1305 let end = start + u16::RAW_BYTE_LEN;
1306 start..end
1307 }
1308
1309 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1310 let start = self.pos_format_byte_range().end;
1311 let end = start + Offset16::RAW_BYTE_LEN;
1312 start..end
1313 }
1314
1315 pub fn value_format_byte_range(&self) -> Range<usize> {
1316 let start = self.coverage_offset_byte_range().end;
1317 let end = start + ValueFormat::RAW_BYTE_LEN;
1318 start..end
1319 }
1320
1321 pub fn value_count_byte_range(&self) -> Range<usize> {
1322 let start = self.value_format_byte_range().end;
1323 let end = start + u16::RAW_BYTE_LEN;
1324 start..end
1325 }
1326
1327 pub fn value_records_byte_range(&self) -> Range<usize> {
1328 let value_count = self.value_count();
1329 let start = self.value_count_byte_range().end;
1330 let end = start
1331 + (transforms::to_usize(value_count)).saturating_mul(
1332 <ValueRecord as ComputeSize>::compute_size(self.value_format()).unwrap_or(0),
1333 );
1334 start..end
1335 }
1336}
1337
1338#[derive(Clone)]
1340pub enum PairPos<'a> {
1341 Format1(PairPosFormat1<'a>),
1342 Format2(PairPosFormat2<'a>),
1343}
1344
1345impl Default for PairPos<'_> {
1346 fn default() -> Self {
1347 Self::Format1(Default::default())
1348 }
1349}
1350
1351impl<'a> PairPos<'a> {
1352 pub fn offset_data(&self) -> FontData<'a> {
1354 match self {
1355 Self::Format1(item) => item.offset_data(),
1356 Self::Format2(item) => item.offset_data(),
1357 }
1358 }
1359
1360 pub fn pos_format(&self) -> u16 {
1362 match self {
1363 Self::Format1(item) => item.pos_format(),
1364 Self::Format2(item) => item.pos_format(),
1365 }
1366 }
1367
1368 pub fn coverage_offset(&self) -> Offset16 {
1370 match self {
1371 Self::Format1(item) => item.coverage_offset(),
1372 Self::Format2(item) => item.coverage_offset(),
1373 }
1374 }
1375
1376 pub fn value_format1(&self) -> ValueFormat {
1379 match self {
1380 Self::Format1(item) => item.value_format1(),
1381 Self::Format2(item) => item.value_format1(),
1382 }
1383 }
1384
1385 pub fn value_format2(&self) -> ValueFormat {
1388 match self {
1389 Self::Format1(item) => item.value_format2(),
1390 Self::Format2(item) => item.value_format2(),
1391 }
1392 }
1393}
1394
1395impl ReadArgs for PairPos<'_> {
1396 type Args = ();
1397}
1398
1399impl<'a> FontRead<'a> for PairPos<'a> {
1400 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1401 let format: u16 = data.read_at(0usize)?;
1402 match format {
1403 PairPosFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1404 PairPosFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1405 other => Err(ReadError::InvalidFormat(other.into())),
1406 }
1407 }
1408}
1409
1410impl<'a> MinByteRange<'a> for PairPos<'a> {
1411 fn min_byte_range(&self) -> Range<usize> {
1412 match self {
1413 Self::Format1(item) => item.min_byte_range(),
1414 Self::Format2(item) => item.min_byte_range(),
1415 }
1416 }
1417 fn min_table_bytes(&self) -> &'a [u8] {
1418 match self {
1419 Self::Format1(item) => item.min_table_bytes(),
1420 Self::Format2(item) => item.min_table_bytes(),
1421 }
1422 }
1423}
1424
1425impl Format<u16> for PairPosFormat1<'_> {
1426 const FORMAT: u16 = 1;
1427}
1428
1429impl<'a> MinByteRange<'a> for PairPosFormat1<'a> {
1430 fn min_byte_range(&self) -> Range<usize> {
1431 0..self.pair_set_offsets_byte_range().end
1432 }
1433 fn min_table_bytes(&self) -> &'a [u8] {
1434 let range = self.min_byte_range();
1435 self.data.as_bytes().get(range).unwrap_or_default()
1436 }
1437}
1438
1439impl ReadArgs for PairPosFormat1<'_> {
1440 type Args = ();
1441}
1442
1443impl<'a> FontRead<'a> for PairPosFormat1<'a> {
1444 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1445 #[allow(clippy::absurd_extreme_comparisons)]
1446 if data.len() < Self::MIN_SIZE {
1447 return Err(ReadError::OutOfBounds);
1448 }
1449 Ok(Self { data })
1450 }
1451}
1452
1453#[derive(Clone)]
1455pub struct PairPosFormat1<'a> {
1456 data: FontData<'a>,
1457}
1458
1459#[allow(clippy::needless_lifetimes)]
1460impl<'a> PairPosFormat1<'a> {
1461 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1462 + Offset16::RAW_BYTE_LEN
1463 + ValueFormat::RAW_BYTE_LEN
1464 + ValueFormat::RAW_BYTE_LEN
1465 + u16::RAW_BYTE_LEN);
1466 basic_table_impls!(impl_the_methods);
1467
1468 pub fn pos_format(&self) -> u16 {
1470 let range = self.pos_format_byte_range();
1471 self.data.read_at(range.start).ok().unwrap()
1472 }
1473
1474 pub fn coverage_offset(&self) -> Offset16 {
1476 let range = self.coverage_offset_byte_range();
1477 self.data.read_at(range.start).ok().unwrap()
1478 }
1479
1480 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1482 let data = self.data;
1483 self.coverage_offset().resolve(data)
1484 }
1485
1486 pub fn value_format1(&self) -> ValueFormat {
1489 let range = self.value_format1_byte_range();
1490 self.data.read_at(range.start).ok().unwrap()
1491 }
1492
1493 pub fn value_format2(&self) -> ValueFormat {
1496 let range = self.value_format2_byte_range();
1497 self.data.read_at(range.start).ok().unwrap()
1498 }
1499
1500 pub fn pair_set_count(&self) -> u16 {
1502 let range = self.pair_set_count_byte_range();
1503 self.data.read_at(range.start).ok().unwrap()
1504 }
1505
1506 pub fn pair_set_offsets(&self) -> &'a [BigEndian<Offset16>] {
1509 let range = self.pair_set_offsets_byte_range();
1510 self.data.read_array(range).ok().unwrap_or_default()
1511 }
1512
1513 pub fn pair_sets(&self) -> ArrayOfOffsets<'a, PairSet<'a>, Offset16> {
1515 let data = self.data;
1516 let offsets = self.pair_set_offsets();
1517 let args = (self.value_format1(), self.value_format2());
1518 ArrayOfOffsets::new(offsets, data, args)
1519 }
1520
1521 pub fn pos_format_byte_range(&self) -> Range<usize> {
1522 let start = 0;
1523 let end = start + u16::RAW_BYTE_LEN;
1524 start..end
1525 }
1526
1527 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1528 let start = self.pos_format_byte_range().end;
1529 let end = start + Offset16::RAW_BYTE_LEN;
1530 start..end
1531 }
1532
1533 pub fn value_format1_byte_range(&self) -> Range<usize> {
1534 let start = self.coverage_offset_byte_range().end;
1535 let end = start + ValueFormat::RAW_BYTE_LEN;
1536 start..end
1537 }
1538
1539 pub fn value_format2_byte_range(&self) -> Range<usize> {
1540 let start = self.value_format1_byte_range().end;
1541 let end = start + ValueFormat::RAW_BYTE_LEN;
1542 start..end
1543 }
1544
1545 pub fn pair_set_count_byte_range(&self) -> Range<usize> {
1546 let start = self.value_format2_byte_range().end;
1547 let end = start + u16::RAW_BYTE_LEN;
1548 start..end
1549 }
1550
1551 pub fn pair_set_offsets_byte_range(&self) -> Range<usize> {
1552 let pair_set_count = self.pair_set_count();
1553 let start = self.pair_set_count_byte_range().end;
1554 let end =
1555 start + (transforms::to_usize(pair_set_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1556 start..end
1557 }
1558}
1559
1560const _: () = assert!(FontData::default_data_long_enough(PairPosFormat1::MIN_SIZE));
1561
1562impl Default for PairPosFormat1<'_> {
1563 fn default() -> Self {
1564 Self {
1565 data: FontData::default_format_1_u16_table_data(),
1566 }
1567 }
1568}
1569
1570impl<'a> MinByteRange<'a> for PairSet<'a> {
1571 fn min_byte_range(&self) -> Range<usize> {
1572 0..self.pair_value_records_byte_range().end
1573 }
1574 fn min_table_bytes(&self) -> &'a [u8] {
1575 let range = self.min_byte_range();
1576 self.data.as_bytes().get(range).unwrap_or_default()
1577 }
1578}
1579
1580impl ReadArgs for PairSet<'_> {
1581 type Args = (ValueFormat, ValueFormat);
1582}
1583
1584impl<'a> FontRead<'a> for PairSet<'a> {
1585 fn read_with_args(
1586 data: FontData<'a>,
1587 args: (ValueFormat, ValueFormat),
1588 ) -> Result<Self, ReadError> {
1589 let (value_format1, value_format2) = args;
1590
1591 #[allow(clippy::absurd_extreme_comparisons)]
1592 if data.len() < Self::MIN_SIZE {
1593 return Err(ReadError::OutOfBounds);
1594 }
1595 Ok(Self {
1596 data,
1597 value_format1,
1598 value_format2,
1599 })
1600 }
1601}
1602
1603impl<'a> PairSet<'a> {
1604 pub fn read(
1609 data: FontData<'a>,
1610 value_format1: ValueFormat,
1611 value_format2: ValueFormat,
1612 ) -> Result<Self, ReadError> {
1613 let args = (value_format1, value_format2);
1614 Self::read_with_args(data, args)
1615 }
1616}
1617
1618#[derive(Clone)]
1620pub struct PairSet<'a> {
1621 data: FontData<'a>,
1622 value_format1: ValueFormat,
1623 value_format2: ValueFormat,
1624}
1625
1626#[allow(clippy::needless_lifetimes)]
1627impl<'a> PairSet<'a> {
1628 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
1629 basic_table_impls!(impl_the_methods);
1630
1631 pub fn pair_value_count(&self) -> u16 {
1633 let range = self.pair_value_count_byte_range();
1634 self.data.read_at(range.start).ok().unwrap()
1635 }
1636
1637 pub fn pair_value_records(&self) -> ComputedArray<'a, PairValueRecord<'a>> {
1640 let range = self.pair_value_records_byte_range();
1641 ComputedArray::new(
1642 self.data,
1643 range,
1644 (self.value_format1(), self.value_format2()),
1645 )
1646 .unwrap_or_default()
1647 }
1648
1649 pub(crate) fn value_format1(&self) -> ValueFormat {
1650 self.value_format1
1651 }
1652
1653 pub(crate) fn value_format2(&self) -> ValueFormat {
1654 self.value_format2
1655 }
1656
1657 pub fn pair_value_count_byte_range(&self) -> Range<usize> {
1658 let start = 0;
1659 let end = start + u16::RAW_BYTE_LEN;
1660 start..end
1661 }
1662
1663 pub fn pair_value_records_byte_range(&self) -> Range<usize> {
1664 let pair_value_count = self.pair_value_count();
1665 let start = self.pair_value_count_byte_range().end;
1666 let end = start
1667 + (transforms::to_usize(pair_value_count)).saturating_mul(
1668 <PairValueRecord as ComputeSize>::compute_size((
1669 self.value_format1(),
1670 self.value_format2(),
1671 ))
1672 .unwrap_or(0),
1673 );
1674 start..end
1675 }
1676}
1677
1678const _: () = assert!(FontData::default_data_long_enough(PairSet::MIN_SIZE));
1679
1680impl Default for PairSet<'_> {
1681 fn default() -> Self {
1682 Self {
1683 data: FontData::default_table_data(),
1684 value_format1: Default::default(),
1685 value_format2: Default::default(),
1686 }
1687 }
1688}
1689
1690#[derive(Clone, Debug)]
1692pub struct PairValueRecord<'a> {
1693 pub second_glyph: BigEndian<GlyphId16>,
1696 pub value_record1: ValueRecord<'a>,
1698 pub value_record2: ValueRecord<'a>,
1700}
1701
1702impl<'a> PairValueRecord<'a> {
1703 pub fn second_glyph(&self) -> GlyphId16 {
1706 self.second_glyph.get()
1707 }
1708
1709 pub fn value_record1(&self) -> &ValueRecord<'a> {
1711 &self.value_record1
1712 }
1713
1714 pub fn value_record2(&self) -> &ValueRecord<'a> {
1716 &self.value_record2
1717 }
1718}
1719
1720impl ReadArgs for PairValueRecord<'_> {
1721 type Args = (ValueFormat, ValueFormat);
1722}
1723
1724impl ComputeSize for PairValueRecord<'_> {
1725 #[allow(clippy::needless_question_mark)]
1726 fn compute_size(args: (ValueFormat, ValueFormat)) -> Result<usize, ReadError> {
1727 let (value_format1, value_format2) = args;
1728 let mut result = 0usize;
1729 result = result
1730 .checked_add(GlyphId16::RAW_BYTE_LEN)
1731 .ok_or(ReadError::OutOfBounds)?;
1732 result = result
1733 .checked_add(<ValueRecord as ComputeSize>::compute_size(value_format1).unwrap_or(0))
1734 .ok_or(ReadError::OutOfBounds)?;
1735 result = result
1736 .checked_add(<ValueRecord as ComputeSize>::compute_size(value_format2).unwrap_or(0))
1737 .ok_or(ReadError::OutOfBounds)?;
1738 Ok(result)
1739 }
1740}
1741
1742impl<'a> FontReadAt<'a> for PairValueRecord<'a> {
1743 fn read_at(
1744 data: FontData<'a>,
1745 offset: usize,
1746 args: (ValueFormat, ValueFormat),
1747 ) -> Result<Self, ReadError> {
1748 let mut cursor = data.cursor();
1749 cursor.advance_by(offset);
1750 let (value_format1, value_format2) = args;
1751 Ok(Self {
1752 second_glyph: cursor.read_be()?,
1753 value_record1: cursor.read_at_with_args(value_format1)?,
1754 value_record2: cursor.read_at_with_args(value_format2)?,
1755 })
1756 }
1757}
1758
1759#[allow(clippy::needless_lifetimes)]
1760impl<'a> PairValueRecord<'a> {
1761 pub fn read(
1766 data: FontData<'a>,
1767 offset: usize,
1768 value_format1: ValueFormat,
1769 value_format2: ValueFormat,
1770 ) -> Result<Self, ReadError> {
1771 let args = (value_format1, value_format2);
1772 Self::read_at(data, offset, args)
1773 }
1774}
1775
1776impl Format<u16> for PairPosFormat2<'_> {
1777 const FORMAT: u16 = 2;
1778}
1779
1780impl<'a> MinByteRange<'a> for PairPosFormat2<'a> {
1781 fn min_byte_range(&self) -> Range<usize> {
1782 0..self.class1_records_byte_range().end
1783 }
1784 fn min_table_bytes(&self) -> &'a [u8] {
1785 let range = self.min_byte_range();
1786 self.data.as_bytes().get(range).unwrap_or_default()
1787 }
1788}
1789
1790impl ReadArgs for PairPosFormat2<'_> {
1791 type Args = ();
1792}
1793
1794impl<'a> FontRead<'a> for PairPosFormat2<'a> {
1795 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1796 #[allow(clippy::absurd_extreme_comparisons)]
1797 if data.len() < Self::MIN_SIZE {
1798 return Err(ReadError::OutOfBounds);
1799 }
1800 Ok(Self { data })
1801 }
1802}
1803
1804#[derive(Clone)]
1806pub struct PairPosFormat2<'a> {
1807 data: FontData<'a>,
1808}
1809
1810#[allow(clippy::needless_lifetimes)]
1811impl<'a> PairPosFormat2<'a> {
1812 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1813 + Offset16::RAW_BYTE_LEN
1814 + ValueFormat::RAW_BYTE_LEN
1815 + ValueFormat::RAW_BYTE_LEN
1816 + Offset16::RAW_BYTE_LEN
1817 + Offset16::RAW_BYTE_LEN
1818 + u16::RAW_BYTE_LEN
1819 + u16::RAW_BYTE_LEN);
1820 basic_table_impls!(impl_the_methods);
1821
1822 pub fn pos_format(&self) -> u16 {
1824 let range = self.pos_format_byte_range();
1825 self.data.read_at(range.start).ok().unwrap()
1826 }
1827
1828 pub fn coverage_offset(&self) -> Offset16 {
1830 let range = self.coverage_offset_byte_range();
1831 self.data.read_at(range.start).ok().unwrap()
1832 }
1833
1834 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1836 let data = self.data;
1837 self.coverage_offset().resolve(data)
1838 }
1839
1840 pub fn value_format1(&self) -> ValueFormat {
1843 let range = self.value_format1_byte_range();
1844 self.data.read_at(range.start).ok().unwrap()
1845 }
1846
1847 pub fn value_format2(&self) -> ValueFormat {
1850 let range = self.value_format2_byte_range();
1851 self.data.read_at(range.start).ok().unwrap()
1852 }
1853
1854 pub fn class_def1_offset(&self) -> Offset16 {
1857 let range = self.class_def1_offset_byte_range();
1858 self.data.read_at(range.start).ok().unwrap()
1859 }
1860
1861 pub fn class_def1(&self) -> Result<ClassDef<'a>, ReadError> {
1863 let data = self.data;
1864 self.class_def1_offset().resolve(data)
1865 }
1866
1867 pub fn class_def2_offset(&self) -> Offset16 {
1870 let range = self.class_def2_offset_byte_range();
1871 self.data.read_at(range.start).ok().unwrap()
1872 }
1873
1874 pub fn class_def2(&self) -> Result<ClassDef<'a>, ReadError> {
1876 let data = self.data;
1877 self.class_def2_offset().resolve(data)
1878 }
1879
1880 pub fn class1_count(&self) -> u16 {
1882 let range = self.class1_count_byte_range();
1883 self.data.read_at(range.start).ok().unwrap()
1884 }
1885
1886 pub fn class2_count(&self) -> u16 {
1888 let range = self.class2_count_byte_range();
1889 self.data.read_at(range.start).ok().unwrap()
1890 }
1891
1892 pub fn class1_records(&self) -> ComputedArray<'a, Class1Record<'a>> {
1894 let range = self.class1_records_byte_range();
1895 ComputedArray::new(
1896 self.data,
1897 range,
1898 (
1899 self.class2_count(),
1900 self.value_format1(),
1901 self.value_format2(),
1902 ),
1903 )
1904 .unwrap_or_default()
1905 }
1906
1907 pub fn pos_format_byte_range(&self) -> Range<usize> {
1908 let start = 0;
1909 let end = start + u16::RAW_BYTE_LEN;
1910 start..end
1911 }
1912
1913 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1914 let start = self.pos_format_byte_range().end;
1915 let end = start + Offset16::RAW_BYTE_LEN;
1916 start..end
1917 }
1918
1919 pub fn value_format1_byte_range(&self) -> Range<usize> {
1920 let start = self.coverage_offset_byte_range().end;
1921 let end = start + ValueFormat::RAW_BYTE_LEN;
1922 start..end
1923 }
1924
1925 pub fn value_format2_byte_range(&self) -> Range<usize> {
1926 let start = self.value_format1_byte_range().end;
1927 let end = start + ValueFormat::RAW_BYTE_LEN;
1928 start..end
1929 }
1930
1931 pub fn class_def1_offset_byte_range(&self) -> Range<usize> {
1932 let start = self.value_format2_byte_range().end;
1933 let end = start + Offset16::RAW_BYTE_LEN;
1934 start..end
1935 }
1936
1937 pub fn class_def2_offset_byte_range(&self) -> Range<usize> {
1938 let start = self.class_def1_offset_byte_range().end;
1939 let end = start + Offset16::RAW_BYTE_LEN;
1940 start..end
1941 }
1942
1943 pub fn class1_count_byte_range(&self) -> Range<usize> {
1944 let start = self.class_def2_offset_byte_range().end;
1945 let end = start + u16::RAW_BYTE_LEN;
1946 start..end
1947 }
1948
1949 pub fn class2_count_byte_range(&self) -> Range<usize> {
1950 let start = self.class1_count_byte_range().end;
1951 let end = start + u16::RAW_BYTE_LEN;
1952 start..end
1953 }
1954
1955 pub fn class1_records_byte_range(&self) -> Range<usize> {
1956 let class1_count = self.class1_count();
1957 let start = self.class2_count_byte_range().end;
1958 let end = start
1959 + (transforms::to_usize(class1_count)).saturating_mul(
1960 <Class1Record as ComputeSize>::compute_size((
1961 self.class2_count(),
1962 self.value_format1(),
1963 self.value_format2(),
1964 ))
1965 .unwrap_or(0),
1966 );
1967 start..end
1968 }
1969}
1970
1971#[derive(Clone, Debug)]
1973pub struct Class1Record<'a> {
1974 pub class2_records: ComputedArray<'a, Class2Record<'a>>,
1976}
1977
1978impl<'a> Class1Record<'a> {
1979 pub fn class2_records(&self) -> &ComputedArray<'a, Class2Record<'a>> {
1981 &self.class2_records
1982 }
1983}
1984
1985impl ReadArgs for Class1Record<'_> {
1986 type Args = (u16, ValueFormat, ValueFormat);
1987}
1988
1989impl ComputeSize for Class1Record<'_> {
1990 #[allow(clippy::needless_question_mark)]
1991 fn compute_size(args: (u16, ValueFormat, ValueFormat)) -> Result<usize, ReadError> {
1992 let (class2_count, value_format1, value_format2) = args;
1993 Ok((transforms::to_usize(class2_count)).saturating_mul(
1994 <Class2Record as ComputeSize>::compute_size((value_format1, value_format2))
1995 .unwrap_or(0),
1996 ))
1997 }
1998}
1999
2000impl<'a> FontReadAt<'a> for Class1Record<'a> {
2001 fn read_at(
2002 data: FontData<'a>,
2003 offset: usize,
2004 args: (u16, ValueFormat, ValueFormat),
2005 ) -> Result<Self, ReadError> {
2006 let mut cursor = data.cursor();
2007 cursor.advance_by(offset);
2008 let (class2_count, value_format1, value_format2) = args;
2009 Ok(Self {
2010 class2_records: cursor.read_computed_array(
2011 transforms::to_usize(class2_count),
2012 (value_format1, value_format2),
2013 )?,
2014 })
2015 }
2016}
2017
2018#[allow(clippy::needless_lifetimes)]
2019impl<'a> Class1Record<'a> {
2020 pub fn read(
2025 data: FontData<'a>,
2026 offset: usize,
2027 class2_count: u16,
2028 value_format1: ValueFormat,
2029 value_format2: ValueFormat,
2030 ) -> Result<Self, ReadError> {
2031 let args = (class2_count, value_format1, value_format2);
2032 Self::read_at(data, offset, args)
2033 }
2034}
2035
2036#[derive(Clone, Debug)]
2038pub struct Class2Record<'a> {
2039 pub value_record1: ValueRecord<'a>,
2041 pub value_record2: ValueRecord<'a>,
2043}
2044
2045impl<'a> Class2Record<'a> {
2046 pub fn value_record1(&self) -> &ValueRecord<'a> {
2048 &self.value_record1
2049 }
2050
2051 pub fn value_record2(&self) -> &ValueRecord<'a> {
2053 &self.value_record2
2054 }
2055}
2056
2057impl ReadArgs for Class2Record<'_> {
2058 type Args = (ValueFormat, ValueFormat);
2059}
2060
2061impl ComputeSize for Class2Record<'_> {
2062 #[allow(clippy::needless_question_mark)]
2063 fn compute_size(args: (ValueFormat, ValueFormat)) -> Result<usize, ReadError> {
2064 let (value_format1, value_format2) = args;
2065 let mut result = 0usize;
2066 result = result
2067 .checked_add(<ValueRecord as ComputeSize>::compute_size(value_format1).unwrap_or(0))
2068 .ok_or(ReadError::OutOfBounds)?;
2069 result = result
2070 .checked_add(<ValueRecord as ComputeSize>::compute_size(value_format2).unwrap_or(0))
2071 .ok_or(ReadError::OutOfBounds)?;
2072 Ok(result)
2073 }
2074}
2075
2076impl<'a> FontReadAt<'a> for Class2Record<'a> {
2077 fn read_at(
2078 data: FontData<'a>,
2079 offset: usize,
2080 args: (ValueFormat, ValueFormat),
2081 ) -> Result<Self, ReadError> {
2082 let mut cursor = data.cursor();
2083 cursor.advance_by(offset);
2084 let (value_format1, value_format2) = args;
2085 Ok(Self {
2086 value_record1: cursor.read_at_with_args(value_format1)?,
2087 value_record2: cursor.read_at_with_args(value_format2)?,
2088 })
2089 }
2090}
2091
2092#[allow(clippy::needless_lifetimes)]
2093impl<'a> Class2Record<'a> {
2094 pub fn read(
2099 data: FontData<'a>,
2100 offset: usize,
2101 value_format1: ValueFormat,
2102 value_format2: ValueFormat,
2103 ) -> Result<Self, ReadError> {
2104 let args = (value_format1, value_format2);
2105 Self::read_at(data, offset, args)
2106 }
2107}
2108
2109impl Format<u16> for CursivePosFormat1<'_> {
2110 const FORMAT: u16 = 1;
2111}
2112
2113impl<'a> MinByteRange<'a> for CursivePosFormat1<'a> {
2114 fn min_byte_range(&self) -> Range<usize> {
2115 0..self.entry_exit_record_byte_range().end
2116 }
2117 fn min_table_bytes(&self) -> &'a [u8] {
2118 let range = self.min_byte_range();
2119 self.data.as_bytes().get(range).unwrap_or_default()
2120 }
2121}
2122
2123impl ReadArgs for CursivePosFormat1<'_> {
2124 type Args = ();
2125}
2126
2127impl<'a> FontRead<'a> for CursivePosFormat1<'a> {
2128 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2129 #[allow(clippy::absurd_extreme_comparisons)]
2130 if data.len() < Self::MIN_SIZE {
2131 return Err(ReadError::OutOfBounds);
2132 }
2133 Ok(Self { data })
2134 }
2135}
2136
2137#[derive(Clone)]
2139pub struct CursivePosFormat1<'a> {
2140 data: FontData<'a>,
2141}
2142
2143#[allow(clippy::needless_lifetimes)]
2144impl<'a> CursivePosFormat1<'a> {
2145 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2146 basic_table_impls!(impl_the_methods);
2147
2148 pub fn pos_format(&self) -> u16 {
2150 let range = self.pos_format_byte_range();
2151 self.data.read_at(range.start).ok().unwrap()
2152 }
2153
2154 pub fn coverage_offset(&self) -> Offset16 {
2156 let range = self.coverage_offset_byte_range();
2157 self.data.read_at(range.start).ok().unwrap()
2158 }
2159
2160 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2162 let data = self.data;
2163 self.coverage_offset().resolve(data)
2164 }
2165
2166 pub fn entry_exit_count(&self) -> u16 {
2168 let range = self.entry_exit_count_byte_range();
2169 self.data.read_at(range.start).ok().unwrap()
2170 }
2171
2172 pub fn entry_exit_record(&self) -> &'a [EntryExitRecord] {
2174 let range = self.entry_exit_record_byte_range();
2175 self.data.read_array(range).ok().unwrap_or_default()
2176 }
2177
2178 pub fn pos_format_byte_range(&self) -> Range<usize> {
2179 let start = 0;
2180 let end = start + u16::RAW_BYTE_LEN;
2181 start..end
2182 }
2183
2184 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2185 let start = self.pos_format_byte_range().end;
2186 let end = start + Offset16::RAW_BYTE_LEN;
2187 start..end
2188 }
2189
2190 pub fn entry_exit_count_byte_range(&self) -> Range<usize> {
2191 let start = self.coverage_offset_byte_range().end;
2192 let end = start + u16::RAW_BYTE_LEN;
2193 start..end
2194 }
2195
2196 pub fn entry_exit_record_byte_range(&self) -> Range<usize> {
2197 let entry_exit_count = self.entry_exit_count();
2198 let start = self.entry_exit_count_byte_range().end;
2199 let end = start
2200 + (transforms::to_usize(entry_exit_count))
2201 .saturating_mul(EntryExitRecord::RAW_BYTE_LEN);
2202 start..end
2203 }
2204}
2205
2206const _: () = assert!(FontData::default_data_long_enough(
2207 CursivePosFormat1::MIN_SIZE
2208));
2209
2210impl Default for CursivePosFormat1<'_> {
2211 fn default() -> Self {
2212 Self {
2213 data: FontData::default_format_1_u16_table_data(),
2214 }
2215 }
2216}
2217
2218#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
2220#[repr(C)]
2221#[repr(packed)]
2222pub struct EntryExitRecord {
2223 pub entry_anchor_offset: BigEndian<Nullable<Offset16>>,
2226 pub exit_anchor_offset: BigEndian<Nullable<Offset16>>,
2229}
2230
2231impl EntryExitRecord {
2232 pub fn entry_anchor_offset(&self) -> Nullable<Offset16> {
2235 self.entry_anchor_offset.get()
2236 }
2237
2238 pub fn entry_anchor<'a>(
2244 &self,
2245 data: FontData<'a>,
2246 ) -> Option<Result<AnchorTable<'a>, ReadError>> {
2247 self.entry_anchor_offset().resolve(data)
2248 }
2249
2250 pub fn exit_anchor_offset(&self) -> Nullable<Offset16> {
2253 self.exit_anchor_offset.get()
2254 }
2255
2256 pub fn exit_anchor<'a>(
2262 &self,
2263 data: FontData<'a>,
2264 ) -> Option<Result<AnchorTable<'a>, ReadError>> {
2265 self.exit_anchor_offset().resolve(data)
2266 }
2267}
2268
2269impl FixedSize for EntryExitRecord {
2270 const RAW_BYTE_LEN: usize = Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
2271}
2272
2273impl Format<u16> for MarkBasePosFormat1<'_> {
2274 const FORMAT: u16 = 1;
2275}
2276
2277impl<'a> MinByteRange<'a> for MarkBasePosFormat1<'a> {
2278 fn min_byte_range(&self) -> Range<usize> {
2279 0..self.base_array_offset_byte_range().end
2280 }
2281 fn min_table_bytes(&self) -> &'a [u8] {
2282 let range = self.min_byte_range();
2283 self.data.as_bytes().get(range).unwrap_or_default()
2284 }
2285}
2286
2287impl ReadArgs for MarkBasePosFormat1<'_> {
2288 type Args = ();
2289}
2290
2291impl<'a> FontRead<'a> for MarkBasePosFormat1<'a> {
2292 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2293 #[allow(clippy::absurd_extreme_comparisons)]
2294 if data.len() < Self::MIN_SIZE {
2295 return Err(ReadError::OutOfBounds);
2296 }
2297 Ok(Self { data })
2298 }
2299}
2300
2301#[derive(Clone)]
2303pub struct MarkBasePosFormat1<'a> {
2304 data: FontData<'a>,
2305}
2306
2307#[allow(clippy::needless_lifetimes)]
2308impl<'a> MarkBasePosFormat1<'a> {
2309 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
2310 + Offset16::RAW_BYTE_LEN
2311 + Offset16::RAW_BYTE_LEN
2312 + u16::RAW_BYTE_LEN
2313 + Offset16::RAW_BYTE_LEN
2314 + Offset16::RAW_BYTE_LEN);
2315 basic_table_impls!(impl_the_methods);
2316
2317 pub fn pos_format(&self) -> u16 {
2319 let range = self.pos_format_byte_range();
2320 self.data.read_at(range.start).ok().unwrap()
2321 }
2322
2323 pub fn mark_coverage_offset(&self) -> Offset16 {
2326 let range = self.mark_coverage_offset_byte_range();
2327 self.data.read_at(range.start).ok().unwrap()
2328 }
2329
2330 pub fn mark_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2332 let data = self.data;
2333 self.mark_coverage_offset().resolve(data)
2334 }
2335
2336 pub fn base_coverage_offset(&self) -> Offset16 {
2339 let range = self.base_coverage_offset_byte_range();
2340 self.data.read_at(range.start).ok().unwrap()
2341 }
2342
2343 pub fn base_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2345 let data = self.data;
2346 self.base_coverage_offset().resolve(data)
2347 }
2348
2349 pub fn mark_class_count(&self) -> u16 {
2351 let range = self.mark_class_count_byte_range();
2352 self.data.read_at(range.start).ok().unwrap()
2353 }
2354
2355 pub fn mark_array_offset(&self) -> Offset16 {
2358 let range = self.mark_array_offset_byte_range();
2359 self.data.read_at(range.start).ok().unwrap()
2360 }
2361
2362 pub fn mark_array(&self) -> Result<MarkArray<'a>, ReadError> {
2364 let data = self.data;
2365 self.mark_array_offset().resolve(data)
2366 }
2367
2368 pub fn base_array_offset(&self) -> Offset16 {
2371 let range = self.base_array_offset_byte_range();
2372 self.data.read_at(range.start).ok().unwrap()
2373 }
2374
2375 pub fn base_array(&self) -> Result<BaseArray<'a>, ReadError> {
2377 let data = self.data;
2378 let args = self.mark_class_count();
2379 self.base_array_offset().resolve_with_args(data, args)
2380 }
2381
2382 pub fn pos_format_byte_range(&self) -> Range<usize> {
2383 let start = 0;
2384 let end = start + u16::RAW_BYTE_LEN;
2385 start..end
2386 }
2387
2388 pub fn mark_coverage_offset_byte_range(&self) -> Range<usize> {
2389 let start = self.pos_format_byte_range().end;
2390 let end = start + Offset16::RAW_BYTE_LEN;
2391 start..end
2392 }
2393
2394 pub fn base_coverage_offset_byte_range(&self) -> Range<usize> {
2395 let start = self.mark_coverage_offset_byte_range().end;
2396 let end = start + Offset16::RAW_BYTE_LEN;
2397 start..end
2398 }
2399
2400 pub fn mark_class_count_byte_range(&self) -> Range<usize> {
2401 let start = self.base_coverage_offset_byte_range().end;
2402 let end = start + u16::RAW_BYTE_LEN;
2403 start..end
2404 }
2405
2406 pub fn mark_array_offset_byte_range(&self) -> Range<usize> {
2407 let start = self.mark_class_count_byte_range().end;
2408 let end = start + Offset16::RAW_BYTE_LEN;
2409 start..end
2410 }
2411
2412 pub fn base_array_offset_byte_range(&self) -> Range<usize> {
2413 let start = self.mark_array_offset_byte_range().end;
2414 let end = start + Offset16::RAW_BYTE_LEN;
2415 start..end
2416 }
2417}
2418
2419const _: () = assert!(FontData::default_data_long_enough(
2420 MarkBasePosFormat1::MIN_SIZE
2421));
2422
2423impl Default for MarkBasePosFormat1<'_> {
2424 fn default() -> Self {
2425 Self {
2426 data: FontData::default_format_1_u16_table_data(),
2427 }
2428 }
2429}
2430
2431impl<'a> MinByteRange<'a> for BaseArray<'a> {
2432 fn min_byte_range(&self) -> Range<usize> {
2433 0..self.base_records_byte_range().end
2434 }
2435 fn min_table_bytes(&self) -> &'a [u8] {
2436 let range = self.min_byte_range();
2437 self.data.as_bytes().get(range).unwrap_or_default()
2438 }
2439}
2440
2441impl ReadArgs for BaseArray<'_> {
2442 type Args = u16;
2443}
2444
2445impl<'a> FontRead<'a> for BaseArray<'a> {
2446 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
2447 let mark_class_count = args;
2448
2449 #[allow(clippy::absurd_extreme_comparisons)]
2450 if data.len() < Self::MIN_SIZE {
2451 return Err(ReadError::OutOfBounds);
2452 }
2453 Ok(Self {
2454 data,
2455 mark_class_count,
2456 })
2457 }
2458}
2459
2460impl<'a> BaseArray<'a> {
2461 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
2466 let args = mark_class_count;
2467 Self::read_with_args(data, args)
2468 }
2469}
2470
2471#[derive(Clone)]
2473pub struct BaseArray<'a> {
2474 data: FontData<'a>,
2475 mark_class_count: u16,
2476}
2477
2478#[allow(clippy::needless_lifetimes)]
2479impl<'a> BaseArray<'a> {
2480 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
2481 basic_table_impls!(impl_the_methods);
2482
2483 pub fn base_count(&self) -> u16 {
2485 let range = self.base_count_byte_range();
2486 self.data.read_at(range.start).ok().unwrap()
2487 }
2488
2489 pub fn base_records(&self) -> ComputedArray<'a, BaseRecord<'a>> {
2491 let range = self.base_records_byte_range();
2492 ComputedArray::new(self.data, range, self.mark_class_count()).unwrap_or_default()
2493 }
2494
2495 pub(crate) fn mark_class_count(&self) -> u16 {
2496 self.mark_class_count
2497 }
2498
2499 pub fn base_count_byte_range(&self) -> Range<usize> {
2500 let start = 0;
2501 let end = start + u16::RAW_BYTE_LEN;
2502 start..end
2503 }
2504
2505 pub fn base_records_byte_range(&self) -> Range<usize> {
2506 let base_count = self.base_count();
2507 let start = self.base_count_byte_range().end;
2508 let end = start
2509 + (transforms::to_usize(base_count)).saturating_mul(
2510 <BaseRecord as ComputeSize>::compute_size(self.mark_class_count()).unwrap_or(0),
2511 );
2512 start..end
2513 }
2514}
2515
2516const _: () = assert!(FontData::default_data_long_enough(BaseArray::MIN_SIZE));
2517
2518impl Default for BaseArray<'_> {
2519 fn default() -> Self {
2520 Self {
2521 data: FontData::default_table_data(),
2522 mark_class_count: Default::default(),
2523 }
2524 }
2525}
2526
2527#[derive(Clone, Debug)]
2529pub struct BaseRecord<'a> {
2530 pub base_anchor_offsets: &'a [BigEndian<Nullable<Offset16>>],
2534}
2535
2536impl<'a> BaseRecord<'a> {
2537 pub fn base_anchor_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2541 self.base_anchor_offsets
2542 }
2543
2544 pub fn base_anchors(
2551 &self,
2552 data: FontData<'a>,
2553 ) -> ArrayOfNullableOffsets<'a, AnchorTable<'a>, Offset16> {
2554 let offsets = self.base_anchor_offsets();
2555 ArrayOfNullableOffsets::new(offsets, data, ())
2556 }
2557}
2558
2559impl ReadArgs for BaseRecord<'_> {
2560 type Args = u16;
2561}
2562
2563impl ComputeSize for BaseRecord<'_> {
2564 #[allow(clippy::needless_question_mark)]
2565 fn compute_size(args: u16) -> Result<usize, ReadError> {
2566 let mark_class_count = args;
2567 Ok((transforms::to_usize(mark_class_count)).saturating_mul(Offset16::RAW_BYTE_LEN))
2568 }
2569}
2570
2571impl<'a> FontRead<'a> for BaseRecord<'a> {
2572 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
2573 let mut cursor = data.cursor();
2574 let mark_class_count = args;
2575 Ok(Self {
2576 base_anchor_offsets: cursor.read_array(transforms::to_usize(mark_class_count))?,
2577 })
2578 }
2579}
2580
2581crate::impl_font_read_at!(BaseRecord<'a>);
2582
2583#[allow(clippy::needless_lifetimes)]
2584impl<'a> BaseRecord<'a> {
2585 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
2590 let args = mark_class_count;
2591 Self::read_with_args(data, args)
2592 }
2593}
2594
2595impl Format<u16> for MarkLigPosFormat1<'_> {
2596 const FORMAT: u16 = 1;
2597}
2598
2599impl<'a> MinByteRange<'a> for MarkLigPosFormat1<'a> {
2600 fn min_byte_range(&self) -> Range<usize> {
2601 0..self.ligature_array_offset_byte_range().end
2602 }
2603 fn min_table_bytes(&self) -> &'a [u8] {
2604 let range = self.min_byte_range();
2605 self.data.as_bytes().get(range).unwrap_or_default()
2606 }
2607}
2608
2609impl ReadArgs for MarkLigPosFormat1<'_> {
2610 type Args = ();
2611}
2612
2613impl<'a> FontRead<'a> for MarkLigPosFormat1<'a> {
2614 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2615 #[allow(clippy::absurd_extreme_comparisons)]
2616 if data.len() < Self::MIN_SIZE {
2617 return Err(ReadError::OutOfBounds);
2618 }
2619 Ok(Self { data })
2620 }
2621}
2622
2623#[derive(Clone)]
2625pub struct MarkLigPosFormat1<'a> {
2626 data: FontData<'a>,
2627}
2628
2629#[allow(clippy::needless_lifetimes)]
2630impl<'a> MarkLigPosFormat1<'a> {
2631 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
2632 + Offset16::RAW_BYTE_LEN
2633 + Offset16::RAW_BYTE_LEN
2634 + u16::RAW_BYTE_LEN
2635 + Offset16::RAW_BYTE_LEN
2636 + Offset16::RAW_BYTE_LEN);
2637 basic_table_impls!(impl_the_methods);
2638
2639 pub fn pos_format(&self) -> u16 {
2641 let range = self.pos_format_byte_range();
2642 self.data.read_at(range.start).ok().unwrap()
2643 }
2644
2645 pub fn mark_coverage_offset(&self) -> Offset16 {
2648 let range = self.mark_coverage_offset_byte_range();
2649 self.data.read_at(range.start).ok().unwrap()
2650 }
2651
2652 pub fn mark_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2654 let data = self.data;
2655 self.mark_coverage_offset().resolve(data)
2656 }
2657
2658 pub fn ligature_coverage_offset(&self) -> Offset16 {
2661 let range = self.ligature_coverage_offset_byte_range();
2662 self.data.read_at(range.start).ok().unwrap()
2663 }
2664
2665 pub fn ligature_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2667 let data = self.data;
2668 self.ligature_coverage_offset().resolve(data)
2669 }
2670
2671 pub fn mark_class_count(&self) -> u16 {
2673 let range = self.mark_class_count_byte_range();
2674 self.data.read_at(range.start).ok().unwrap()
2675 }
2676
2677 pub fn mark_array_offset(&self) -> Offset16 {
2680 let range = self.mark_array_offset_byte_range();
2681 self.data.read_at(range.start).ok().unwrap()
2682 }
2683
2684 pub fn mark_array(&self) -> Result<MarkArray<'a>, ReadError> {
2686 let data = self.data;
2687 self.mark_array_offset().resolve(data)
2688 }
2689
2690 pub fn ligature_array_offset(&self) -> Offset16 {
2693 let range = self.ligature_array_offset_byte_range();
2694 self.data.read_at(range.start).ok().unwrap()
2695 }
2696
2697 pub fn ligature_array(&self) -> Result<LigatureArray<'a>, ReadError> {
2699 let data = self.data;
2700 let args = self.mark_class_count();
2701 self.ligature_array_offset().resolve_with_args(data, args)
2702 }
2703
2704 pub fn pos_format_byte_range(&self) -> Range<usize> {
2705 let start = 0;
2706 let end = start + u16::RAW_BYTE_LEN;
2707 start..end
2708 }
2709
2710 pub fn mark_coverage_offset_byte_range(&self) -> Range<usize> {
2711 let start = self.pos_format_byte_range().end;
2712 let end = start + Offset16::RAW_BYTE_LEN;
2713 start..end
2714 }
2715
2716 pub fn ligature_coverage_offset_byte_range(&self) -> Range<usize> {
2717 let start = self.mark_coverage_offset_byte_range().end;
2718 let end = start + Offset16::RAW_BYTE_LEN;
2719 start..end
2720 }
2721
2722 pub fn mark_class_count_byte_range(&self) -> Range<usize> {
2723 let start = self.ligature_coverage_offset_byte_range().end;
2724 let end = start + u16::RAW_BYTE_LEN;
2725 start..end
2726 }
2727
2728 pub fn mark_array_offset_byte_range(&self) -> Range<usize> {
2729 let start = self.mark_class_count_byte_range().end;
2730 let end = start + Offset16::RAW_BYTE_LEN;
2731 start..end
2732 }
2733
2734 pub fn ligature_array_offset_byte_range(&self) -> Range<usize> {
2735 let start = self.mark_array_offset_byte_range().end;
2736 let end = start + Offset16::RAW_BYTE_LEN;
2737 start..end
2738 }
2739}
2740
2741const _: () = assert!(FontData::default_data_long_enough(
2742 MarkLigPosFormat1::MIN_SIZE
2743));
2744
2745impl Default for MarkLigPosFormat1<'_> {
2746 fn default() -> Self {
2747 Self {
2748 data: FontData::default_format_1_u16_table_data(),
2749 }
2750 }
2751}
2752
2753impl<'a> MinByteRange<'a> for LigatureArray<'a> {
2754 fn min_byte_range(&self) -> Range<usize> {
2755 0..self.ligature_attach_offsets_byte_range().end
2756 }
2757 fn min_table_bytes(&self) -> &'a [u8] {
2758 let range = self.min_byte_range();
2759 self.data.as_bytes().get(range).unwrap_or_default()
2760 }
2761}
2762
2763impl ReadArgs for LigatureArray<'_> {
2764 type Args = u16;
2765}
2766
2767impl<'a> FontRead<'a> for LigatureArray<'a> {
2768 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
2769 let mark_class_count = args;
2770
2771 #[allow(clippy::absurd_extreme_comparisons)]
2772 if data.len() < Self::MIN_SIZE {
2773 return Err(ReadError::OutOfBounds);
2774 }
2775 Ok(Self {
2776 data,
2777 mark_class_count,
2778 })
2779 }
2780}
2781
2782impl<'a> LigatureArray<'a> {
2783 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
2788 let args = mark_class_count;
2789 Self::read_with_args(data, args)
2790 }
2791}
2792
2793#[derive(Clone)]
2795pub struct LigatureArray<'a> {
2796 data: FontData<'a>,
2797 mark_class_count: u16,
2798}
2799
2800#[allow(clippy::needless_lifetimes)]
2801impl<'a> LigatureArray<'a> {
2802 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
2803 basic_table_impls!(impl_the_methods);
2804
2805 pub fn ligature_count(&self) -> u16 {
2807 let range = self.ligature_count_byte_range();
2808 self.data.read_at(range.start).ok().unwrap()
2809 }
2810
2811 pub fn ligature_attach_offsets(&self) -> &'a [BigEndian<Offset16>] {
2815 let range = self.ligature_attach_offsets_byte_range();
2816 self.data.read_array(range).ok().unwrap_or_default()
2817 }
2818
2819 pub fn ligature_attaches(&self) -> ArrayOfOffsets<'a, LigatureAttach<'a>, Offset16> {
2821 let data = self.data;
2822 let offsets = self.ligature_attach_offsets();
2823 let args = self.mark_class_count();
2824 ArrayOfOffsets::new(offsets, data, args)
2825 }
2826
2827 pub(crate) fn mark_class_count(&self) -> u16 {
2828 self.mark_class_count
2829 }
2830
2831 pub fn ligature_count_byte_range(&self) -> Range<usize> {
2832 let start = 0;
2833 let end = start + u16::RAW_BYTE_LEN;
2834 start..end
2835 }
2836
2837 pub fn ligature_attach_offsets_byte_range(&self) -> Range<usize> {
2838 let ligature_count = self.ligature_count();
2839 let start = self.ligature_count_byte_range().end;
2840 let end =
2841 start + (transforms::to_usize(ligature_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
2842 start..end
2843 }
2844}
2845
2846const _: () = assert!(FontData::default_data_long_enough(LigatureArray::MIN_SIZE));
2847
2848impl Default for LigatureArray<'_> {
2849 fn default() -> Self {
2850 Self {
2851 data: FontData::default_table_data(),
2852 mark_class_count: Default::default(),
2853 }
2854 }
2855}
2856
2857impl<'a> MinByteRange<'a> for LigatureAttach<'a> {
2858 fn min_byte_range(&self) -> Range<usize> {
2859 0..self.component_records_byte_range().end
2860 }
2861 fn min_table_bytes(&self) -> &'a [u8] {
2862 let range = self.min_byte_range();
2863 self.data.as_bytes().get(range).unwrap_or_default()
2864 }
2865}
2866
2867impl ReadArgs for LigatureAttach<'_> {
2868 type Args = u16;
2869}
2870
2871impl<'a> FontRead<'a> for LigatureAttach<'a> {
2872 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
2873 let mark_class_count = args;
2874
2875 #[allow(clippy::absurd_extreme_comparisons)]
2876 if data.len() < Self::MIN_SIZE {
2877 return Err(ReadError::OutOfBounds);
2878 }
2879 Ok(Self {
2880 data,
2881 mark_class_count,
2882 })
2883 }
2884}
2885
2886impl<'a> LigatureAttach<'a> {
2887 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
2892 let args = mark_class_count;
2893 Self::read_with_args(data, args)
2894 }
2895}
2896
2897#[derive(Clone)]
2899pub struct LigatureAttach<'a> {
2900 data: FontData<'a>,
2901 mark_class_count: u16,
2902}
2903
2904#[allow(clippy::needless_lifetimes)]
2905impl<'a> LigatureAttach<'a> {
2906 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
2907 basic_table_impls!(impl_the_methods);
2908
2909 pub fn component_count(&self) -> u16 {
2911 let range = self.component_count_byte_range();
2912 self.data.read_at(range.start).ok().unwrap()
2913 }
2914
2915 pub fn component_records(&self) -> ComputedArray<'a, ComponentRecord<'a>> {
2917 let range = self.component_records_byte_range();
2918 ComputedArray::new(self.data, range, self.mark_class_count()).unwrap_or_default()
2919 }
2920
2921 pub(crate) fn mark_class_count(&self) -> u16 {
2922 self.mark_class_count
2923 }
2924
2925 pub fn component_count_byte_range(&self) -> Range<usize> {
2926 let start = 0;
2927 let end = start + u16::RAW_BYTE_LEN;
2928 start..end
2929 }
2930
2931 pub fn component_records_byte_range(&self) -> Range<usize> {
2932 let component_count = self.component_count();
2933 let start = self.component_count_byte_range().end;
2934 let end = start
2935 + (transforms::to_usize(component_count)).saturating_mul(
2936 <ComponentRecord as ComputeSize>::compute_size(self.mark_class_count())
2937 .unwrap_or(0),
2938 );
2939 start..end
2940 }
2941}
2942
2943const _: () = assert!(FontData::default_data_long_enough(LigatureAttach::MIN_SIZE));
2944
2945impl Default for LigatureAttach<'_> {
2946 fn default() -> Self {
2947 Self {
2948 data: FontData::default_table_data(),
2949 mark_class_count: Default::default(),
2950 }
2951 }
2952}
2953
2954#[derive(Clone, Debug)]
2956pub struct ComponentRecord<'a> {
2957 pub ligature_anchor_offsets: &'a [BigEndian<Nullable<Offset16>>],
2961}
2962
2963impl<'a> ComponentRecord<'a> {
2964 pub fn ligature_anchor_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2968 self.ligature_anchor_offsets
2969 }
2970
2971 pub fn ligature_anchors(
2978 &self,
2979 data: FontData<'a>,
2980 ) -> ArrayOfNullableOffsets<'a, AnchorTable<'a>, Offset16> {
2981 let offsets = self.ligature_anchor_offsets();
2982 ArrayOfNullableOffsets::new(offsets, data, ())
2983 }
2984}
2985
2986impl ReadArgs for ComponentRecord<'_> {
2987 type Args = u16;
2988}
2989
2990impl ComputeSize for ComponentRecord<'_> {
2991 #[allow(clippy::needless_question_mark)]
2992 fn compute_size(args: u16) -> Result<usize, ReadError> {
2993 let mark_class_count = args;
2994 Ok((transforms::to_usize(mark_class_count)).saturating_mul(Offset16::RAW_BYTE_LEN))
2995 }
2996}
2997
2998impl<'a> FontRead<'a> for ComponentRecord<'a> {
2999 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
3000 let mut cursor = data.cursor();
3001 let mark_class_count = args;
3002 Ok(Self {
3003 ligature_anchor_offsets: cursor.read_array(transforms::to_usize(mark_class_count))?,
3004 })
3005 }
3006}
3007
3008crate::impl_font_read_at!(ComponentRecord<'a>);
3009
3010#[allow(clippy::needless_lifetimes)]
3011impl<'a> ComponentRecord<'a> {
3012 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
3017 let args = mark_class_count;
3018 Self::read_with_args(data, args)
3019 }
3020}
3021
3022impl Format<u16> for MarkMarkPosFormat1<'_> {
3023 const FORMAT: u16 = 1;
3024}
3025
3026impl<'a> MinByteRange<'a> for MarkMarkPosFormat1<'a> {
3027 fn min_byte_range(&self) -> Range<usize> {
3028 0..self.mark2_array_offset_byte_range().end
3029 }
3030 fn min_table_bytes(&self) -> &'a [u8] {
3031 let range = self.min_byte_range();
3032 self.data.as_bytes().get(range).unwrap_or_default()
3033 }
3034}
3035
3036impl ReadArgs for MarkMarkPosFormat1<'_> {
3037 type Args = ();
3038}
3039
3040impl<'a> FontRead<'a> for MarkMarkPosFormat1<'a> {
3041 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3042 #[allow(clippy::absurd_extreme_comparisons)]
3043 if data.len() < Self::MIN_SIZE {
3044 return Err(ReadError::OutOfBounds);
3045 }
3046 Ok(Self { data })
3047 }
3048}
3049
3050#[derive(Clone)]
3052pub struct MarkMarkPosFormat1<'a> {
3053 data: FontData<'a>,
3054}
3055
3056#[allow(clippy::needless_lifetimes)]
3057impl<'a> MarkMarkPosFormat1<'a> {
3058 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
3059 + Offset16::RAW_BYTE_LEN
3060 + Offset16::RAW_BYTE_LEN
3061 + u16::RAW_BYTE_LEN
3062 + Offset16::RAW_BYTE_LEN
3063 + Offset16::RAW_BYTE_LEN);
3064 basic_table_impls!(impl_the_methods);
3065
3066 pub fn pos_format(&self) -> u16 {
3068 let range = self.pos_format_byte_range();
3069 self.data.read_at(range.start).ok().unwrap()
3070 }
3071
3072 pub fn mark1_coverage_offset(&self) -> Offset16 {
3075 let range = self.mark1_coverage_offset_byte_range();
3076 self.data.read_at(range.start).ok().unwrap()
3077 }
3078
3079 pub fn mark1_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
3081 let data = self.data;
3082 self.mark1_coverage_offset().resolve(data)
3083 }
3084
3085 pub fn mark2_coverage_offset(&self) -> Offset16 {
3088 let range = self.mark2_coverage_offset_byte_range();
3089 self.data.read_at(range.start).ok().unwrap()
3090 }
3091
3092 pub fn mark2_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
3094 let data = self.data;
3095 self.mark2_coverage_offset().resolve(data)
3096 }
3097
3098 pub fn mark_class_count(&self) -> u16 {
3100 let range = self.mark_class_count_byte_range();
3101 self.data.read_at(range.start).ok().unwrap()
3102 }
3103
3104 pub fn mark1_array_offset(&self) -> Offset16 {
3107 let range = self.mark1_array_offset_byte_range();
3108 self.data.read_at(range.start).ok().unwrap()
3109 }
3110
3111 pub fn mark1_array(&self) -> Result<MarkArray<'a>, ReadError> {
3113 let data = self.data;
3114 self.mark1_array_offset().resolve(data)
3115 }
3116
3117 pub fn mark2_array_offset(&self) -> Offset16 {
3120 let range = self.mark2_array_offset_byte_range();
3121 self.data.read_at(range.start).ok().unwrap()
3122 }
3123
3124 pub fn mark2_array(&self) -> Result<Mark2Array<'a>, ReadError> {
3126 let data = self.data;
3127 let args = self.mark_class_count();
3128 self.mark2_array_offset().resolve_with_args(data, args)
3129 }
3130
3131 pub fn pos_format_byte_range(&self) -> Range<usize> {
3132 let start = 0;
3133 let end = start + u16::RAW_BYTE_LEN;
3134 start..end
3135 }
3136
3137 pub fn mark1_coverage_offset_byte_range(&self) -> Range<usize> {
3138 let start = self.pos_format_byte_range().end;
3139 let end = start + Offset16::RAW_BYTE_LEN;
3140 start..end
3141 }
3142
3143 pub fn mark2_coverage_offset_byte_range(&self) -> Range<usize> {
3144 let start = self.mark1_coverage_offset_byte_range().end;
3145 let end = start + Offset16::RAW_BYTE_LEN;
3146 start..end
3147 }
3148
3149 pub fn mark_class_count_byte_range(&self) -> Range<usize> {
3150 let start = self.mark2_coverage_offset_byte_range().end;
3151 let end = start + u16::RAW_BYTE_LEN;
3152 start..end
3153 }
3154
3155 pub fn mark1_array_offset_byte_range(&self) -> Range<usize> {
3156 let start = self.mark_class_count_byte_range().end;
3157 let end = start + Offset16::RAW_BYTE_LEN;
3158 start..end
3159 }
3160
3161 pub fn mark2_array_offset_byte_range(&self) -> Range<usize> {
3162 let start = self.mark1_array_offset_byte_range().end;
3163 let end = start + Offset16::RAW_BYTE_LEN;
3164 start..end
3165 }
3166}
3167
3168const _: () = assert!(FontData::default_data_long_enough(
3169 MarkMarkPosFormat1::MIN_SIZE
3170));
3171
3172impl Default for MarkMarkPosFormat1<'_> {
3173 fn default() -> Self {
3174 Self {
3175 data: FontData::default_format_1_u16_table_data(),
3176 }
3177 }
3178}
3179
3180impl<'a> MinByteRange<'a> for Mark2Array<'a> {
3181 fn min_byte_range(&self) -> Range<usize> {
3182 0..self.mark2_records_byte_range().end
3183 }
3184 fn min_table_bytes(&self) -> &'a [u8] {
3185 let range = self.min_byte_range();
3186 self.data.as_bytes().get(range).unwrap_or_default()
3187 }
3188}
3189
3190impl ReadArgs for Mark2Array<'_> {
3191 type Args = u16;
3192}
3193
3194impl<'a> FontRead<'a> for Mark2Array<'a> {
3195 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
3196 let mark_class_count = args;
3197
3198 #[allow(clippy::absurd_extreme_comparisons)]
3199 if data.len() < Self::MIN_SIZE {
3200 return Err(ReadError::OutOfBounds);
3201 }
3202 Ok(Self {
3203 data,
3204 mark_class_count,
3205 })
3206 }
3207}
3208
3209impl<'a> Mark2Array<'a> {
3210 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
3215 let args = mark_class_count;
3216 Self::read_with_args(data, args)
3217 }
3218}
3219
3220#[derive(Clone)]
3222pub struct Mark2Array<'a> {
3223 data: FontData<'a>,
3224 mark_class_count: u16,
3225}
3226
3227#[allow(clippy::needless_lifetimes)]
3228impl<'a> Mark2Array<'a> {
3229 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
3230 basic_table_impls!(impl_the_methods);
3231
3232 pub fn mark2_count(&self) -> u16 {
3234 let range = self.mark2_count_byte_range();
3235 self.data.read_at(range.start).ok().unwrap()
3236 }
3237
3238 pub fn mark2_records(&self) -> ComputedArray<'a, Mark2Record<'a>> {
3240 let range = self.mark2_records_byte_range();
3241 ComputedArray::new(self.data, range, self.mark_class_count()).unwrap_or_default()
3242 }
3243
3244 pub(crate) fn mark_class_count(&self) -> u16 {
3245 self.mark_class_count
3246 }
3247
3248 pub fn mark2_count_byte_range(&self) -> Range<usize> {
3249 let start = 0;
3250 let end = start + u16::RAW_BYTE_LEN;
3251 start..end
3252 }
3253
3254 pub fn mark2_records_byte_range(&self) -> Range<usize> {
3255 let mark2_count = self.mark2_count();
3256 let start = self.mark2_count_byte_range().end;
3257 let end = start
3258 + (transforms::to_usize(mark2_count)).saturating_mul(
3259 <Mark2Record as ComputeSize>::compute_size(self.mark_class_count()).unwrap_or(0),
3260 );
3261 start..end
3262 }
3263}
3264
3265const _: () = assert!(FontData::default_data_long_enough(Mark2Array::MIN_SIZE));
3266
3267impl Default for Mark2Array<'_> {
3268 fn default() -> Self {
3269 Self {
3270 data: FontData::default_table_data(),
3271 mark_class_count: Default::default(),
3272 }
3273 }
3274}
3275
3276#[derive(Clone, Debug)]
3278pub struct Mark2Record<'a> {
3279 pub mark2_anchor_offsets: &'a [BigEndian<Nullable<Offset16>>],
3283}
3284
3285impl<'a> Mark2Record<'a> {
3286 pub fn mark2_anchor_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
3290 self.mark2_anchor_offsets
3291 }
3292
3293 pub fn mark2_anchors(
3300 &self,
3301 data: FontData<'a>,
3302 ) -> ArrayOfNullableOffsets<'a, AnchorTable<'a>, Offset16> {
3303 let offsets = self.mark2_anchor_offsets();
3304 ArrayOfNullableOffsets::new(offsets, data, ())
3305 }
3306}
3307
3308impl ReadArgs for Mark2Record<'_> {
3309 type Args = u16;
3310}
3311
3312impl ComputeSize for Mark2Record<'_> {
3313 #[allow(clippy::needless_question_mark)]
3314 fn compute_size(args: u16) -> Result<usize, ReadError> {
3315 let mark_class_count = args;
3316 Ok((transforms::to_usize(mark_class_count)).saturating_mul(Offset16::RAW_BYTE_LEN))
3317 }
3318}
3319
3320impl<'a> FontRead<'a> for Mark2Record<'a> {
3321 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
3322 let mut cursor = data.cursor();
3323 let mark_class_count = args;
3324 Ok(Self {
3325 mark2_anchor_offsets: cursor.read_array(transforms::to_usize(mark_class_count))?,
3326 })
3327 }
3328}
3329
3330crate::impl_font_read_at!(Mark2Record<'a>);
3331
3332#[allow(clippy::needless_lifetimes)]
3333impl<'a> Mark2Record<'a> {
3334 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
3339 let args = mark_class_count;
3340 Self::read_with_args(data, args)
3341 }
3342}
3343
3344impl Format<u16> for ExtensionPosFormat1<'_> {
3345 const FORMAT: u16 = 1;
3346}
3347
3348impl Discriminant for ExtensionPosFormat1<'_, ()> {
3349 fn read_discriminant(data: FontData<'_>) -> Result<u16, ReadError> {
3350 data.read_at(u16::RAW_BYTE_LEN)
3351 }
3352}
3353
3354impl<'a, T> MinByteRange<'a> for ExtensionPosFormat1<'a, T> {
3355 fn min_byte_range(&self) -> Range<usize> {
3356 0..self.extension_offset_byte_range().end
3357 }
3358 fn min_table_bytes(&self) -> &'a [u8] {
3359 let range = self.min_byte_range();
3360 self.data.as_bytes().get(range).unwrap_or_default()
3361 }
3362}
3363
3364impl<T> ReadArgs for ExtensionPosFormat1<'_, T> {
3365 type Args = ();
3366}
3367
3368impl<'a, T> FontRead<'a> for ExtensionPosFormat1<'a, T> {
3369 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3370 #[allow(clippy::absurd_extreme_comparisons)]
3371 if data.len() < Self::MIN_SIZE {
3372 return Err(ReadError::OutOfBounds);
3373 }
3374 Ok(Self {
3375 data,
3376 offset_type: std::marker::PhantomData,
3377 })
3378 }
3379}
3380
3381impl<'a, T> ExtensionPosFormat1<'a, T> {
3382 #[allow(dead_code)]
3383 pub(crate) fn of_unit_type(&self) -> ExtensionPosFormat1<'a, ()> {
3385 ExtensionPosFormat1 {
3386 data: self.data,
3387 offset_type: std::marker::PhantomData,
3388 }
3389 }
3390}
3391
3392#[derive(Clone)]
3394pub struct ExtensionPosFormat1<'a, T = ()> {
3395 data: FontData<'a>,
3396 offset_type: std::marker::PhantomData<*const T>,
3397}
3398
3399#[allow(clippy::needless_lifetimes)]
3400impl<'a, T> ExtensionPosFormat1<'a, T> {
3401 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN);
3402 basic_table_impls!(impl_the_methods);
3403
3404 pub fn pos_format(&self) -> u16 {
3406 let range = self.pos_format_byte_range();
3407 self.data.read_at(range.start).ok().unwrap()
3408 }
3409
3410 pub fn extension_lookup_type(&self) -> u16 {
3413 let range = self.extension_lookup_type_byte_range();
3414 self.data.read_at(range.start).ok().unwrap()
3415 }
3416
3417 pub fn extension_offset(&self) -> Offset32 {
3421 let range = self.extension_offset_byte_range();
3422 self.data.read_at(range.start).ok().unwrap()
3423 }
3424
3425 pub fn extension(&self) -> Result<T, ReadError>
3427 where
3428 T: FontRead<'a, Args = ()>,
3429 {
3430 let data = self.data;
3431 self.extension_offset().resolve(data)
3432 }
3433
3434 pub fn pos_format_byte_range(&self) -> Range<usize> {
3435 let start = 0;
3436 let end = start + u16::RAW_BYTE_LEN;
3437 start..end
3438 }
3439
3440 pub fn extension_lookup_type_byte_range(&self) -> Range<usize> {
3441 let start = self.pos_format_byte_range().end;
3442 let end = start + u16::RAW_BYTE_LEN;
3443 start..end
3444 }
3445
3446 pub fn extension_offset_byte_range(&self) -> Range<usize> {
3447 let start = self.extension_lookup_type_byte_range().end;
3448 let end = start + Offset32::RAW_BYTE_LEN;
3449 start..end
3450 }
3451}
3452
3453const _: () = assert!(FontData::default_data_long_enough(
3454 ExtensionPosFormat1::<()>::MIN_SIZE
3455));
3456
3457impl<T> Default for ExtensionPosFormat1<'_, T> {
3458 fn default() -> Self {
3459 Self {
3460 data: FontData::default_format_1_u16_table_data(),
3461 offset_type: std::marker::PhantomData,
3462 }
3463 }
3464}
3465
3466pub enum ExtensionSubtable<'a> {
3468 Single(ExtensionPosFormat1<'a, SinglePos<'a>>),
3469 Pair(ExtensionPosFormat1<'a, PairPos<'a>>),
3470 Cursive(ExtensionPosFormat1<'a, CursivePosFormat1<'a>>),
3471 MarkToBase(ExtensionPosFormat1<'a, MarkBasePosFormat1<'a>>),
3472 MarkToLig(ExtensionPosFormat1<'a, MarkLigPosFormat1<'a>>),
3473 MarkToMark(ExtensionPosFormat1<'a, MarkMarkPosFormat1<'a>>),
3474 Contextual(ExtensionPosFormat1<'a, PositionSequenceContext<'a>>),
3475 ChainContextual(ExtensionPosFormat1<'a, PositionChainContext<'a>>),
3476}
3477
3478impl Default for ExtensionSubtable<'_> {
3479 fn default() -> Self {
3480 Self::Single(Default::default())
3481 }
3482}
3483
3484impl ReadArgs for ExtensionSubtable<'_> {
3485 type Args = ();
3486}
3487
3488impl<'a> FontRead<'a> for ExtensionSubtable<'a> {
3489 fn read_with_args(bytes: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3490 let discriminant = ExtensionPosFormat1::read_discriminant(bytes)?;
3491 match discriminant {
3492 1 => Ok(ExtensionSubtable::Single(FontRead::read(bytes)?)),
3493 2 => Ok(ExtensionSubtable::Pair(FontRead::read(bytes)?)),
3494 3 => Ok(ExtensionSubtable::Cursive(FontRead::read(bytes)?)),
3495 4 => Ok(ExtensionSubtable::MarkToBase(FontRead::read(bytes)?)),
3496 5 => Ok(ExtensionSubtable::MarkToLig(FontRead::read(bytes)?)),
3497 6 => Ok(ExtensionSubtable::MarkToMark(FontRead::read(bytes)?)),
3498 7 => Ok(ExtensionSubtable::Contextual(FontRead::read(bytes)?)),
3499 8 => Ok(ExtensionSubtable::ChainContextual(FontRead::read(bytes)?)),
3500 other => Err(ReadError::InvalidFormat(other.into())),
3501 }
3502 }
3503}
3504
3505impl<'a> ExtensionSubtable<'a> {
3506 #[allow(dead_code)]
3507 pub(crate) fn of_unit_type(&self) -> ExtensionPosFormat1<'a, ()> {
3511 match self {
3512 ExtensionSubtable::Single(inner) => inner.of_unit_type(),
3513 ExtensionSubtable::Pair(inner) => inner.of_unit_type(),
3514 ExtensionSubtable::Cursive(inner) => inner.of_unit_type(),
3515 ExtensionSubtable::MarkToBase(inner) => inner.of_unit_type(),
3516 ExtensionSubtable::MarkToLig(inner) => inner.of_unit_type(),
3517 ExtensionSubtable::MarkToMark(inner) => inner.of_unit_type(),
3518 ExtensionSubtable::Contextual(inner) => inner.of_unit_type(),
3519 ExtensionSubtable::ChainContextual(inner) => inner.of_unit_type(),
3520 }
3521 }
3522}