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.offset_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 let Some(data) = TableDataRef::new(data.as_bytes()) else {
34 return Err(ReadError::OutOfBounds);
35 };
36 Ok(Self { data })
37 }
38}
39
40#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
42#[repr(C, packed)]
43#[doc(hidden)]
44pub struct GposFixedHeader {
45 pub version: BigEndian<MajorMinor>,
46 pub script_list_offset: BigEndian<Offset16>,
47 pub feature_list_offset: BigEndian<Offset16>,
48 pub lookup_list_offset: BigEndian<Offset16>,
49}
50
51#[allow(clippy::absurd_extreme_comparisons)]
52const _: () = assert!(std::mem::size_of::<GposFixedHeader>() <= Gpos::MIN_SIZE);
53
54#[derive(Clone)]
57pub struct Gpos<'a> {
58 data: TableDataRef<'a, GposFixedHeader>,
59}
60
61#[allow(clippy::needless_lifetimes)]
62impl<'a> Gpos<'a> {
63 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
64 + Offset16::RAW_BYTE_LEN
65 + Offset16::RAW_BYTE_LEN
66 + Offset16::RAW_BYTE_LEN);
67 basic_table_impls!(impl_the_methods);
68
69 pub fn version(&self) -> MajorMinor {
71 self.data.header().version.get()
72 }
73
74 pub fn script_list_offset(&self) -> Offset16 {
76 self.data.header().script_list_offset.get()
77 }
78
79 pub fn script_list(&self) -> Result<ScriptList<'a>, ReadError> {
81 let data = self.offset_data();
82 self.script_list_offset().resolve(data)
83 }
84
85 pub fn feature_list_offset(&self) -> Offset16 {
87 self.data.header().feature_list_offset.get()
88 }
89
90 pub fn feature_list(&self) -> Result<FeatureList<'a>, ReadError> {
92 let data = self.offset_data();
93 self.feature_list_offset().resolve(data)
94 }
95
96 pub fn lookup_list_offset(&self) -> Offset16 {
98 self.data.header().lookup_list_offset.get()
99 }
100
101 pub fn lookup_list(&self) -> Result<PositionLookupList<'a>, ReadError> {
103 let data = self.offset_data();
104 self.lookup_list_offset().resolve(data)
105 }
106
107 pub fn feature_variations_offset(&self) -> Option<Nullable<Offset32>> {
108 let range = self.feature_variations_offset_byte_range();
109 (!range.is_empty())
110 .then(|| self.offset_data().read_at(range.start).ok())
111 .flatten()
112 }
113
114 pub fn feature_variations(&self) -> Option<Result<FeatureVariations<'a>, ReadError>> {
116 let data = self.offset_data();
117 self.feature_variations_offset().map(|x| x.resolve(data))?
118 }
119
120 pub fn version_byte_range(&self) -> Range<usize> {
121 let start = 0;
122 let end = start + MajorMinor::RAW_BYTE_LEN;
123 start..end
124 }
125
126 pub fn script_list_offset_byte_range(&self) -> Range<usize> {
127 let start = self.version_byte_range().end;
128 let end = start + Offset16::RAW_BYTE_LEN;
129 start..end
130 }
131
132 pub fn feature_list_offset_byte_range(&self) -> Range<usize> {
133 let start = self.script_list_offset_byte_range().end;
134 let end = start + Offset16::RAW_BYTE_LEN;
135 start..end
136 }
137
138 pub fn lookup_list_offset_byte_range(&self) -> Range<usize> {
139 let start = self.feature_list_offset_byte_range().end;
140 let end = start + Offset16::RAW_BYTE_LEN;
141 start..end
142 }
143
144 pub fn feature_variations_offset_byte_range(&self) -> Range<usize> {
145 let start = self.lookup_list_offset_byte_range().end;
146 let end = if self.version().compatible((1u16, 1u16)) {
147 start + Offset32::RAW_BYTE_LEN
148 } else {
149 start
150 };
151 start..end
152 }
153}
154
155const _: () = assert!(FontData::default_data_long_enough(Gpos::MIN_SIZE));
156
157impl Default for Gpos<'_> {
158 fn default() -> Self {
159 Self {
160 data: TableDataRef::new(FontData::default_table_data().as_bytes())
161 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
162 }
163 }
164}
165
166pub enum PositionLookup<'a> {
168 Single(Lookup<'a, SinglePos<'a>>),
169 Pair(Lookup<'a, PairPos<'a>>),
170 Cursive(Lookup<'a, CursivePosFormat1<'a>>),
171 MarkToBase(Lookup<'a, MarkBasePosFormat1<'a>>),
172 MarkToLig(Lookup<'a, MarkLigPosFormat1<'a>>),
173 MarkToMark(Lookup<'a, MarkMarkPosFormat1<'a>>),
174 Contextual(Lookup<'a, PositionSequenceContext<'a>>),
175 ChainContextual(Lookup<'a, PositionChainContext<'a>>),
176 Extension(Lookup<'a, ExtensionSubtable<'a>>),
177}
178
179impl Default for PositionLookup<'_> {
180 fn default() -> Self {
181 Self::Single(Default::default())
182 }
183}
184
185impl ReadArgs for PositionLookup<'_> {
186 type Args = ();
187}
188
189impl<'a> FontRead<'a> for PositionLookup<'a> {
190 fn read_with_args(bytes: FontData<'a>, _: ()) -> Result<Self, ReadError> {
191 let discriminant = Lookup::read_discriminant(bytes)?;
192 match discriminant {
193 1 => Ok(PositionLookup::Single(FontRead::read(bytes)?)),
194 2 => Ok(PositionLookup::Pair(FontRead::read(bytes)?)),
195 3 => Ok(PositionLookup::Cursive(FontRead::read(bytes)?)),
196 4 => Ok(PositionLookup::MarkToBase(FontRead::read(bytes)?)),
197 5 => Ok(PositionLookup::MarkToLig(FontRead::read(bytes)?)),
198 6 => Ok(PositionLookup::MarkToMark(FontRead::read(bytes)?)),
199 7 => Ok(PositionLookup::Contextual(FontRead::read(bytes)?)),
200 8 => Ok(PositionLookup::ChainContextual(FontRead::read(bytes)?)),
201 9 => Ok(PositionLookup::Extension(FontRead::read(bytes)?)),
202 other => Err(ReadError::InvalidFormat(other.into())),
203 }
204 }
205}
206
207impl<'a> PositionLookup<'a> {
208 #[allow(dead_code)]
209 pub(crate) fn of_unit_type(&self) -> Lookup<'a, ()> {
213 match self {
214 PositionLookup::Single(inner) => inner.of_unit_type(),
215 PositionLookup::Pair(inner) => inner.of_unit_type(),
216 PositionLookup::Cursive(inner) => inner.of_unit_type(),
217 PositionLookup::MarkToBase(inner) => inner.of_unit_type(),
218 PositionLookup::MarkToLig(inner) => inner.of_unit_type(),
219 PositionLookup::MarkToMark(inner) => inner.of_unit_type(),
220 PositionLookup::Contextual(inner) => inner.of_unit_type(),
221 PositionLookup::ChainContextual(inner) => inner.of_unit_type(),
222 PositionLookup::Extension(inner) => inner.of_unit_type(),
223 }
224 }
225}
226
227#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
229#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
230#[repr(transparent)]
231pub struct ValueFormat {
232 bits: u16,
233}
234
235impl ValueFormat {
236 pub const X_PLACEMENT: Self = Self { bits: 0x0001 };
238
239 pub const Y_PLACEMENT: Self = Self { bits: 0x0002 };
241
242 pub const X_ADVANCE: Self = Self { bits: 0x0004 };
244
245 pub const Y_ADVANCE: Self = Self { bits: 0x0008 };
247
248 pub const X_PLACEMENT_DEVICE: Self = Self { bits: 0x0010 };
251
252 pub const Y_PLACEMENT_DEVICE: Self = Self { bits: 0x0020 };
255
256 pub const X_ADVANCE_DEVICE: Self = Self { bits: 0x0040 };
259
260 pub const Y_ADVANCE_DEVICE: Self = Self { bits: 0x0080 };
263}
264
265impl ValueFormat {
266 #[inline]
268 pub const fn empty() -> Self {
269 Self { bits: 0 }
270 }
271
272 #[inline]
274 pub const fn all() -> Self {
275 Self {
276 bits: Self::X_PLACEMENT.bits
277 | Self::Y_PLACEMENT.bits
278 | Self::X_ADVANCE.bits
279 | Self::Y_ADVANCE.bits
280 | Self::X_PLACEMENT_DEVICE.bits
281 | Self::Y_PLACEMENT_DEVICE.bits
282 | Self::X_ADVANCE_DEVICE.bits
283 | Self::Y_ADVANCE_DEVICE.bits,
284 }
285 }
286
287 #[inline]
289 pub const fn bits(&self) -> u16 {
290 self.bits
291 }
292
293 #[inline]
296 pub const fn from_bits(bits: u16) -> Option<Self> {
297 if (bits & !Self::all().bits()) == 0 {
298 Some(Self { bits })
299 } else {
300 None
301 }
302 }
303
304 #[inline]
307 pub const fn from_bits_truncate(bits: u16) -> Self {
308 Self {
309 bits: bits & Self::all().bits,
310 }
311 }
312
313 #[inline]
315 pub const fn is_empty(&self) -> bool {
316 self.bits() == Self::empty().bits()
317 }
318
319 #[inline]
321 pub const fn intersects(&self, other: Self) -> bool {
322 !(Self {
323 bits: self.bits & other.bits,
324 })
325 .is_empty()
326 }
327
328 #[inline]
330 pub const fn contains(&self, other: Self) -> bool {
331 (self.bits & other.bits) == other.bits
332 }
333
334 #[inline]
336 pub fn insert(&mut self, other: Self) {
337 self.bits |= other.bits;
338 }
339
340 #[inline]
342 pub fn remove(&mut self, other: Self) {
343 self.bits &= !other.bits;
344 }
345
346 #[inline]
348 pub fn toggle(&mut self, other: Self) {
349 self.bits ^= other.bits;
350 }
351
352 #[inline]
363 #[must_use]
364 pub const fn intersection(self, other: Self) -> Self {
365 Self {
366 bits: self.bits & other.bits,
367 }
368 }
369
370 #[inline]
381 #[must_use]
382 pub const fn union(self, other: Self) -> Self {
383 Self {
384 bits: self.bits | other.bits,
385 }
386 }
387
388 #[inline]
401 #[must_use]
402 pub const fn difference(self, other: Self) -> Self {
403 Self {
404 bits: self.bits & !other.bits,
405 }
406 }
407}
408
409impl std::ops::BitOr for ValueFormat {
410 type Output = Self;
411
412 #[inline]
414 fn bitor(self, other: ValueFormat) -> Self {
415 Self {
416 bits: self.bits | other.bits,
417 }
418 }
419}
420
421impl std::ops::BitOrAssign for ValueFormat {
422 #[inline]
424 fn bitor_assign(&mut self, other: Self) {
425 self.bits |= other.bits;
426 }
427}
428
429impl std::ops::BitXor for ValueFormat {
430 type Output = Self;
431
432 #[inline]
434 fn bitxor(self, other: Self) -> Self {
435 Self {
436 bits: self.bits ^ other.bits,
437 }
438 }
439}
440
441impl std::ops::BitXorAssign for ValueFormat {
442 #[inline]
444 fn bitxor_assign(&mut self, other: Self) {
445 self.bits ^= other.bits;
446 }
447}
448
449impl std::ops::BitAnd for ValueFormat {
450 type Output = Self;
451
452 #[inline]
454 fn bitand(self, other: Self) -> Self {
455 Self {
456 bits: self.bits & other.bits,
457 }
458 }
459}
460
461impl std::ops::BitAndAssign for ValueFormat {
462 #[inline]
464 fn bitand_assign(&mut self, other: Self) {
465 self.bits &= other.bits;
466 }
467}
468
469impl std::ops::Sub for ValueFormat {
470 type Output = Self;
471
472 #[inline]
474 fn sub(self, other: Self) -> Self {
475 Self {
476 bits: self.bits & !other.bits,
477 }
478 }
479}
480
481impl std::ops::SubAssign for ValueFormat {
482 #[inline]
484 fn sub_assign(&mut self, other: Self) {
485 self.bits &= !other.bits;
486 }
487}
488
489impl std::ops::Not for ValueFormat {
490 type Output = Self;
491
492 #[inline]
494 fn not(self) -> Self {
495 Self { bits: !self.bits } & Self::all()
496 }
497}
498
499impl std::fmt::Debug for ValueFormat {
500 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
501 let members: &[(&str, Self)] = &[
502 ("X_PLACEMENT", Self::X_PLACEMENT),
503 ("Y_PLACEMENT", Self::Y_PLACEMENT),
504 ("X_ADVANCE", Self::X_ADVANCE),
505 ("Y_ADVANCE", Self::Y_ADVANCE),
506 ("X_PLACEMENT_DEVICE", Self::X_PLACEMENT_DEVICE),
507 ("Y_PLACEMENT_DEVICE", Self::Y_PLACEMENT_DEVICE),
508 ("X_ADVANCE_DEVICE", Self::X_ADVANCE_DEVICE),
509 ("Y_ADVANCE_DEVICE", Self::Y_ADVANCE_DEVICE),
510 ];
511 let mut first = true;
512 for (name, value) in members {
513 if self.contains(*value) {
514 if !first {
515 f.write_str(" | ")?;
516 }
517 first = false;
518 f.write_str(name)?;
519 }
520 }
521 if first {
522 f.write_str("(empty)")?;
523 }
524 Ok(())
525 }
526}
527
528impl std::fmt::Binary for ValueFormat {
529 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
530 std::fmt::Binary::fmt(&self.bits, f)
531 }
532}
533
534impl std::fmt::Octal for ValueFormat {
535 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
536 std::fmt::Octal::fmt(&self.bits, f)
537 }
538}
539
540impl std::fmt::LowerHex for ValueFormat {
541 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
542 std::fmt::LowerHex::fmt(&self.bits, f)
543 }
544}
545
546impl std::fmt::UpperHex for ValueFormat {
547 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
548 std::fmt::UpperHex::fmt(&self.bits, f)
549 }
550}
551
552impl font_types::Scalar for ValueFormat {
553 type Raw = <u16 as font_types::Scalar>::Raw;
554 fn to_raw(self) -> Self::Raw {
555 self.bits().to_raw()
556 }
557 fn from_raw(raw: Self::Raw) -> Self {
558 let t = <u16>::from_raw(raw);
559 Self::from_bits_truncate(t)
560 }
561}
562
563#[derive(Clone)]
566pub enum AnchorTable<'a> {
567 Format1(AnchorFormat1<'a>),
568 Format2(AnchorFormat2<'a>),
569 Format3(AnchorFormat3<'a>),
570}
571
572impl Default for AnchorTable<'_> {
573 fn default() -> Self {
574 Self::Format1(Default::default())
575 }
576}
577
578impl<'a> AnchorTable<'a> {
579 pub fn offset_data(&self) -> FontData<'a> {
581 match self {
582 Self::Format1(item) => item.offset_data(),
583 Self::Format2(item) => item.offset_data(),
584 Self::Format3(item) => item.offset_data(),
585 }
586 }
587
588 pub fn anchor_format(&self) -> u16 {
590 match self {
591 Self::Format1(item) => item.anchor_format(),
592 Self::Format2(item) => item.anchor_format(),
593 Self::Format3(item) => item.anchor_format(),
594 }
595 }
596
597 pub fn x_coordinate(&self) -> i16 {
599 match self {
600 Self::Format1(item) => item.x_coordinate(),
601 Self::Format2(item) => item.x_coordinate(),
602 Self::Format3(item) => item.x_coordinate(),
603 }
604 }
605
606 pub fn y_coordinate(&self) -> i16 {
608 match self {
609 Self::Format1(item) => item.y_coordinate(),
610 Self::Format2(item) => item.y_coordinate(),
611 Self::Format3(item) => item.y_coordinate(),
612 }
613 }
614}
615
616impl ReadArgs for AnchorTable<'_> {
617 type Args = ();
618}
619
620impl<'a> FontRead<'a> for AnchorTable<'a> {
621 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
622 let format: u16 = data.read_at(0usize)?;
623 match format {
624 AnchorFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
625 AnchorFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
626 AnchorFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
627 other => Err(ReadError::InvalidFormat(other.into())),
628 }
629 }
630}
631
632impl<'a> MinByteRange<'a> for AnchorTable<'a> {
633 fn min_byte_range(&self) -> Range<usize> {
634 match self {
635 Self::Format1(item) => item.min_byte_range(),
636 Self::Format2(item) => item.min_byte_range(),
637 Self::Format3(item) => item.min_byte_range(),
638 }
639 }
640 fn min_table_bytes(&self) -> &'a [u8] {
641 match self {
642 Self::Format1(item) => item.min_table_bytes(),
643 Self::Format2(item) => item.min_table_bytes(),
644 Self::Format3(item) => item.min_table_bytes(),
645 }
646 }
647}
648
649impl Format<u16> for AnchorFormat1<'_> {
650 const FORMAT: u16 = 1;
651}
652
653impl<'a> MinByteRange<'a> for AnchorFormat1<'a> {
654 fn min_byte_range(&self) -> Range<usize> {
655 0..self.y_coordinate_byte_range().end
656 }
657 fn min_table_bytes(&self) -> &'a [u8] {
658 let range = self.min_byte_range();
659 self.offset_data().as_bytes().get(range).unwrap_or_default()
660 }
661}
662
663impl ReadArgs for AnchorFormat1<'_> {
664 type Args = ();
665}
666
667impl<'a> FontRead<'a> for AnchorFormat1<'a> {
668 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
669 #[allow(clippy::absurd_extreme_comparisons)]
670 if data.len() < Self::MIN_SIZE {
671 return Err(ReadError::OutOfBounds);
672 }
673 let Some(data) = TableDataRef::new(data.as_bytes()) else {
674 return Err(ReadError::OutOfBounds);
675 };
676 Ok(Self { data })
677 }
678}
679
680#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
682#[repr(C, packed)]
683#[doc(hidden)]
684pub struct AnchorFormat1FixedHeader {
685 pub anchor_format: BigEndian<u16>,
686 pub x_coordinate: BigEndian<i16>,
687 pub y_coordinate: BigEndian<i16>,
688}
689
690#[allow(clippy::absurd_extreme_comparisons)]
691const _: () = assert!(std::mem::size_of::<AnchorFormat1FixedHeader>() <= AnchorFormat1::MIN_SIZE);
692
693#[derive(Clone)]
695pub struct AnchorFormat1<'a> {
696 data: TableDataRef<'a, AnchorFormat1FixedHeader>,
697}
698
699#[allow(clippy::needless_lifetimes)]
700impl<'a> AnchorFormat1<'a> {
701 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN);
702 basic_table_impls!(impl_the_methods);
703
704 pub fn anchor_format(&self) -> u16 {
706 self.data.header().anchor_format.get()
707 }
708
709 pub fn x_coordinate(&self) -> i16 {
711 self.data.header().x_coordinate.get()
712 }
713
714 pub fn y_coordinate(&self) -> i16 {
716 self.data.header().y_coordinate.get()
717 }
718
719 pub fn anchor_format_byte_range(&self) -> Range<usize> {
720 let start = 0;
721 let end = start + u16::RAW_BYTE_LEN;
722 start..end
723 }
724
725 pub fn x_coordinate_byte_range(&self) -> Range<usize> {
726 let start = self.anchor_format_byte_range().end;
727 let end = start + i16::RAW_BYTE_LEN;
728 start..end
729 }
730
731 pub fn y_coordinate_byte_range(&self) -> Range<usize> {
732 let start = self.x_coordinate_byte_range().end;
733 let end = start + i16::RAW_BYTE_LEN;
734 start..end
735 }
736}
737
738const _: () = assert!(FontData::default_data_long_enough(AnchorFormat1::MIN_SIZE));
739
740impl Default for AnchorFormat1<'_> {
741 fn default() -> Self {
742 Self {
743 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
744 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
745 }
746 }
747}
748
749impl Format<u16> for AnchorFormat2<'_> {
750 const FORMAT: u16 = 2;
751}
752
753impl<'a> MinByteRange<'a> for AnchorFormat2<'a> {
754 fn min_byte_range(&self) -> Range<usize> {
755 0..self.anchor_point_byte_range().end
756 }
757 fn min_table_bytes(&self) -> &'a [u8] {
758 let range = self.min_byte_range();
759 self.offset_data().as_bytes().get(range).unwrap_or_default()
760 }
761}
762
763impl ReadArgs for AnchorFormat2<'_> {
764 type Args = ();
765}
766
767impl<'a> FontRead<'a> for AnchorFormat2<'a> {
768 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
769 #[allow(clippy::absurd_extreme_comparisons)]
770 if data.len() < Self::MIN_SIZE {
771 return Err(ReadError::OutOfBounds);
772 }
773 let Some(data) = TableDataRef::new(data.as_bytes()) else {
774 return Err(ReadError::OutOfBounds);
775 };
776 Ok(Self { data })
777 }
778}
779
780#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
782#[repr(C, packed)]
783#[doc(hidden)]
784pub struct AnchorFormat2FixedHeader {
785 pub anchor_format: BigEndian<u16>,
786 pub x_coordinate: BigEndian<i16>,
787 pub y_coordinate: BigEndian<i16>,
788 pub anchor_point: BigEndian<u16>,
789}
790
791#[allow(clippy::absurd_extreme_comparisons)]
792const _: () = assert!(std::mem::size_of::<AnchorFormat2FixedHeader>() <= AnchorFormat2::MIN_SIZE);
793
794#[derive(Clone)]
796pub struct AnchorFormat2<'a> {
797 data: TableDataRef<'a, AnchorFormat2FixedHeader>,
798}
799
800#[allow(clippy::needless_lifetimes)]
801impl<'a> AnchorFormat2<'a> {
802 pub const MIN_SIZE: usize =
803 (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
804 basic_table_impls!(impl_the_methods);
805
806 pub fn anchor_format(&self) -> u16 {
808 self.data.header().anchor_format.get()
809 }
810
811 pub fn x_coordinate(&self) -> i16 {
813 self.data.header().x_coordinate.get()
814 }
815
816 pub fn y_coordinate(&self) -> i16 {
818 self.data.header().y_coordinate.get()
819 }
820
821 pub fn anchor_point(&self) -> u16 {
823 self.data.header().anchor_point.get()
824 }
825
826 pub fn anchor_format_byte_range(&self) -> Range<usize> {
827 let start = 0;
828 let end = start + u16::RAW_BYTE_LEN;
829 start..end
830 }
831
832 pub fn x_coordinate_byte_range(&self) -> Range<usize> {
833 let start = self.anchor_format_byte_range().end;
834 let end = start + i16::RAW_BYTE_LEN;
835 start..end
836 }
837
838 pub fn y_coordinate_byte_range(&self) -> Range<usize> {
839 let start = self.x_coordinate_byte_range().end;
840 let end = start + i16::RAW_BYTE_LEN;
841 start..end
842 }
843
844 pub fn anchor_point_byte_range(&self) -> Range<usize> {
845 let start = self.y_coordinate_byte_range().end;
846 let end = start + u16::RAW_BYTE_LEN;
847 start..end
848 }
849}
850
851impl Format<u16> for AnchorFormat3<'_> {
852 const FORMAT: u16 = 3;
853}
854
855impl<'a> MinByteRange<'a> for AnchorFormat3<'a> {
856 fn min_byte_range(&self) -> Range<usize> {
857 0..self.y_device_offset_byte_range().end
858 }
859 fn min_table_bytes(&self) -> &'a [u8] {
860 let range = self.min_byte_range();
861 self.offset_data().as_bytes().get(range).unwrap_or_default()
862 }
863}
864
865impl ReadArgs for AnchorFormat3<'_> {
866 type Args = ();
867}
868
869impl<'a> FontRead<'a> for AnchorFormat3<'a> {
870 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
871 #[allow(clippy::absurd_extreme_comparisons)]
872 if data.len() < Self::MIN_SIZE {
873 return Err(ReadError::OutOfBounds);
874 }
875 let Some(data) = TableDataRef::new(data.as_bytes()) else {
876 return Err(ReadError::OutOfBounds);
877 };
878 Ok(Self { data })
879 }
880}
881
882#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
884#[repr(C, packed)]
885#[doc(hidden)]
886pub struct AnchorFormat3FixedHeader {
887 pub anchor_format: BigEndian<u16>,
888 pub x_coordinate: BigEndian<i16>,
889 pub y_coordinate: BigEndian<i16>,
890 pub x_device_offset: BigEndian<Nullable<Offset16>>,
891 pub y_device_offset: BigEndian<Nullable<Offset16>>,
892}
893
894#[allow(clippy::absurd_extreme_comparisons)]
895const _: () = assert!(std::mem::size_of::<AnchorFormat3FixedHeader>() <= AnchorFormat3::MIN_SIZE);
896
897#[derive(Clone)]
899pub struct AnchorFormat3<'a> {
900 data: TableDataRef<'a, AnchorFormat3FixedHeader>,
901}
902
903#[allow(clippy::needless_lifetimes)]
904impl<'a> AnchorFormat3<'a> {
905 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
906 + i16::RAW_BYTE_LEN
907 + i16::RAW_BYTE_LEN
908 + Offset16::RAW_BYTE_LEN
909 + Offset16::RAW_BYTE_LEN);
910 basic_table_impls!(impl_the_methods);
911
912 pub fn anchor_format(&self) -> u16 {
914 self.data.header().anchor_format.get()
915 }
916
917 pub fn x_coordinate(&self) -> i16 {
919 self.data.header().x_coordinate.get()
920 }
921
922 pub fn y_coordinate(&self) -> i16 {
924 self.data.header().y_coordinate.get()
925 }
926
927 pub fn x_device_offset(&self) -> Nullable<Offset16> {
931 self.data.header().x_device_offset.get()
932 }
933
934 pub fn x_device(&self) -> Option<Result<DeviceOrVariationIndex<'a>, ReadError>> {
936 let data = self.offset_data();
937 self.x_device_offset().resolve(data)
938 }
939
940 pub fn y_device_offset(&self) -> Nullable<Offset16> {
944 self.data.header().y_device_offset.get()
945 }
946
947 pub fn y_device(&self) -> Option<Result<DeviceOrVariationIndex<'a>, ReadError>> {
949 let data = self.offset_data();
950 self.y_device_offset().resolve(data)
951 }
952
953 pub fn anchor_format_byte_range(&self) -> Range<usize> {
954 let start = 0;
955 let end = start + u16::RAW_BYTE_LEN;
956 start..end
957 }
958
959 pub fn x_coordinate_byte_range(&self) -> Range<usize> {
960 let start = self.anchor_format_byte_range().end;
961 let end = start + i16::RAW_BYTE_LEN;
962 start..end
963 }
964
965 pub fn y_coordinate_byte_range(&self) -> Range<usize> {
966 let start = self.x_coordinate_byte_range().end;
967 let end = start + i16::RAW_BYTE_LEN;
968 start..end
969 }
970
971 pub fn x_device_offset_byte_range(&self) -> Range<usize> {
972 let start = self.y_coordinate_byte_range().end;
973 let end = start + Offset16::RAW_BYTE_LEN;
974 start..end
975 }
976
977 pub fn y_device_offset_byte_range(&self) -> Range<usize> {
978 let start = self.x_device_offset_byte_range().end;
979 let end = start + Offset16::RAW_BYTE_LEN;
980 start..end
981 }
982}
983
984impl<'a> MinByteRange<'a> for MarkArray<'a> {
985 fn min_byte_range(&self) -> Range<usize> {
986 0..self.mark_records_byte_range().end
987 }
988 fn min_table_bytes(&self) -> &'a [u8] {
989 let range = self.min_byte_range();
990 self.offset_data().as_bytes().get(range).unwrap_or_default()
991 }
992}
993
994impl ReadArgs for MarkArray<'_> {
995 type Args = ();
996}
997
998impl<'a> FontRead<'a> for MarkArray<'a> {
999 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1000 #[allow(clippy::absurd_extreme_comparisons)]
1001 if data.len() < Self::MIN_SIZE {
1002 return Err(ReadError::OutOfBounds);
1003 }
1004 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1005 return Err(ReadError::OutOfBounds);
1006 };
1007 Ok(Self { data })
1008 }
1009}
1010
1011#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1013#[repr(C, packed)]
1014#[doc(hidden)]
1015pub struct MarkArrayFixedHeader {
1016 pub mark_count: BigEndian<u16>,
1017}
1018
1019#[allow(clippy::absurd_extreme_comparisons)]
1020const _: () = assert!(std::mem::size_of::<MarkArrayFixedHeader>() <= MarkArray::MIN_SIZE);
1021
1022#[derive(Clone)]
1024pub struct MarkArray<'a> {
1025 data: TableDataRef<'a, MarkArrayFixedHeader>,
1026}
1027
1028#[allow(clippy::needless_lifetimes)]
1029impl<'a> MarkArray<'a> {
1030 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
1031 basic_table_impls!(impl_the_methods);
1032
1033 pub fn mark_count(&self) -> u16 {
1035 self.data.header().mark_count.get()
1036 }
1037
1038 pub fn mark_records(&self) -> &'a [MarkRecord] {
1041 let range = self.mark_records_byte_range();
1042 self.offset_data()
1043 .read_array(range)
1044 .ok()
1045 .unwrap_or_default()
1046 }
1047
1048 pub fn mark_count_byte_range(&self) -> Range<usize> {
1049 let start = 0;
1050 let end = start + u16::RAW_BYTE_LEN;
1051 start..end
1052 }
1053
1054 pub fn mark_records_byte_range(&self) -> Range<usize> {
1055 let mark_count = self.mark_count();
1056 let start = self.mark_count_byte_range().end;
1057 let end =
1058 start + (transforms::to_usize(mark_count)).saturating_mul(MarkRecord::RAW_BYTE_LEN);
1059 start..end
1060 }
1061}
1062
1063const _: () = assert!(FontData::default_data_long_enough(MarkArray::MIN_SIZE));
1064
1065impl Default for MarkArray<'_> {
1066 fn default() -> Self {
1067 Self {
1068 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1069 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1070 }
1071 }
1072}
1073
1074#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
1076#[repr(C)]
1077#[repr(packed)]
1078pub struct MarkRecord {
1079 pub mark_class: BigEndian<u16>,
1081 pub mark_anchor_offset: BigEndian<Offset16>,
1083}
1084
1085impl MarkRecord {
1086 pub fn mark_class(&self) -> u16 {
1088 self.mark_class.get()
1089 }
1090
1091 pub fn mark_anchor_offset(&self) -> Offset16 {
1093 self.mark_anchor_offset.get()
1094 }
1095
1096 pub fn mark_anchor<'a>(&self, data: FontData<'a>) -> Result<AnchorTable<'a>, ReadError> {
1101 self.mark_anchor_offset().resolve(data)
1102 }
1103}
1104
1105impl FixedSize for MarkRecord {
1106 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
1107}
1108
1109#[derive(Clone)]
1111pub enum SinglePos<'a> {
1112 Format1(SinglePosFormat1<'a>),
1113 Format2(SinglePosFormat2<'a>),
1114}
1115
1116impl Default for SinglePos<'_> {
1117 fn default() -> Self {
1118 Self::Format1(Default::default())
1119 }
1120}
1121
1122impl<'a> SinglePos<'a> {
1123 pub fn offset_data(&self) -> FontData<'a> {
1125 match self {
1126 Self::Format1(item) => item.offset_data(),
1127 Self::Format2(item) => item.offset_data(),
1128 }
1129 }
1130
1131 pub fn pos_format(&self) -> u16 {
1133 match self {
1134 Self::Format1(item) => item.pos_format(),
1135 Self::Format2(item) => item.pos_format(),
1136 }
1137 }
1138
1139 pub fn coverage_offset(&self) -> Offset16 {
1141 match self {
1142 Self::Format1(item) => item.coverage_offset(),
1143 Self::Format2(item) => item.coverage_offset(),
1144 }
1145 }
1146
1147 pub fn value_format(&self) -> ValueFormat {
1149 match self {
1150 Self::Format1(item) => item.value_format(),
1151 Self::Format2(item) => item.value_format(),
1152 }
1153 }
1154}
1155
1156impl ReadArgs for SinglePos<'_> {
1157 type Args = ();
1158}
1159
1160impl<'a> FontRead<'a> for SinglePos<'a> {
1161 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1162 let format: u16 = data.read_at(0usize)?;
1163 match format {
1164 SinglePosFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1165 SinglePosFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1166 other => Err(ReadError::InvalidFormat(other.into())),
1167 }
1168 }
1169}
1170
1171impl<'a> MinByteRange<'a> for SinglePos<'a> {
1172 fn min_byte_range(&self) -> Range<usize> {
1173 match self {
1174 Self::Format1(item) => item.min_byte_range(),
1175 Self::Format2(item) => item.min_byte_range(),
1176 }
1177 }
1178 fn min_table_bytes(&self) -> &'a [u8] {
1179 match self {
1180 Self::Format1(item) => item.min_table_bytes(),
1181 Self::Format2(item) => item.min_table_bytes(),
1182 }
1183 }
1184}
1185
1186impl Format<u16> for SinglePosFormat1<'_> {
1187 const FORMAT: u16 = 1;
1188}
1189
1190impl<'a> MinByteRange<'a> for SinglePosFormat1<'a> {
1191 fn min_byte_range(&self) -> Range<usize> {
1192 0..self.value_record_byte_range().end
1193 }
1194 fn min_table_bytes(&self) -> &'a [u8] {
1195 let range = self.min_byte_range();
1196 self.offset_data().as_bytes().get(range).unwrap_or_default()
1197 }
1198}
1199
1200impl ReadArgs for SinglePosFormat1<'_> {
1201 type Args = ();
1202}
1203
1204impl<'a> FontRead<'a> for SinglePosFormat1<'a> {
1205 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1206 #[allow(clippy::absurd_extreme_comparisons)]
1207 if data.len() < Self::MIN_SIZE {
1208 return Err(ReadError::OutOfBounds);
1209 }
1210 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1211 return Err(ReadError::OutOfBounds);
1212 };
1213 Ok(Self { data })
1214 }
1215}
1216
1217#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1219#[repr(C, packed)]
1220#[doc(hidden)]
1221pub struct SinglePosFormat1FixedHeader {
1222 pub pos_format: BigEndian<u16>,
1223 pub coverage_offset: BigEndian<Offset16>,
1224 pub value_format: BigEndian<ValueFormat>,
1225}
1226
1227#[allow(clippy::absurd_extreme_comparisons)]
1228const _: () =
1229 assert!(std::mem::size_of::<SinglePosFormat1FixedHeader>() <= SinglePosFormat1::MIN_SIZE);
1230
1231#[derive(Clone)]
1233pub struct SinglePosFormat1<'a> {
1234 data: TableDataRef<'a, SinglePosFormat1FixedHeader>,
1235}
1236
1237#[allow(clippy::needless_lifetimes)]
1238impl<'a> SinglePosFormat1<'a> {
1239 pub const MIN_SIZE: usize =
1240 (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + ValueFormat::RAW_BYTE_LEN);
1241 basic_table_impls!(impl_the_methods);
1242
1243 pub fn pos_format(&self) -> u16 {
1245 self.data.header().pos_format.get()
1246 }
1247
1248 pub fn coverage_offset(&self) -> Offset16 {
1250 self.data.header().coverage_offset.get()
1251 }
1252
1253 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1255 let data = self.offset_data();
1256 self.coverage_offset().resolve(data)
1257 }
1258
1259 pub fn value_format(&self) -> ValueFormat {
1261 self.data.header().value_format.get()
1262 }
1263
1264 pub fn value_record(&self) -> ValueRecord<'a> {
1267 let range = self.value_record_byte_range();
1268 ValueRecord::read_at(self.offset_data(), range.start, self.value_format())
1269 .unwrap_or_default()
1270 }
1271
1272 pub fn pos_format_byte_range(&self) -> Range<usize> {
1273 let start = 0;
1274 let end = start + u16::RAW_BYTE_LEN;
1275 start..end
1276 }
1277
1278 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1279 let start = self.pos_format_byte_range().end;
1280 let end = start + Offset16::RAW_BYTE_LEN;
1281 start..end
1282 }
1283
1284 pub fn value_format_byte_range(&self) -> Range<usize> {
1285 let start = self.coverage_offset_byte_range().end;
1286 let end = start + ValueFormat::RAW_BYTE_LEN;
1287 start..end
1288 }
1289
1290 pub fn value_record_byte_range(&self) -> Range<usize> {
1291 let start = self.value_format_byte_range().end;
1292 let end =
1293 start + <ValueRecord as ComputeSize>::compute_size(self.value_format()).unwrap_or(0);
1294 start..end
1295 }
1296}
1297
1298const _: () = assert!(FontData::default_data_long_enough(
1299 SinglePosFormat1::MIN_SIZE
1300));
1301
1302impl Default for SinglePosFormat1<'_> {
1303 fn default() -> Self {
1304 Self {
1305 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
1306 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1307 }
1308 }
1309}
1310
1311impl Format<u16> for SinglePosFormat2<'_> {
1312 const FORMAT: u16 = 2;
1313}
1314
1315impl<'a> MinByteRange<'a> for SinglePosFormat2<'a> {
1316 fn min_byte_range(&self) -> Range<usize> {
1317 0..self.value_records_byte_range().end
1318 }
1319 fn min_table_bytes(&self) -> &'a [u8] {
1320 let range = self.min_byte_range();
1321 self.offset_data().as_bytes().get(range).unwrap_or_default()
1322 }
1323}
1324
1325impl ReadArgs for SinglePosFormat2<'_> {
1326 type Args = ();
1327}
1328
1329impl<'a> FontRead<'a> for SinglePosFormat2<'a> {
1330 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1331 #[allow(clippy::absurd_extreme_comparisons)]
1332 if data.len() < Self::MIN_SIZE {
1333 return Err(ReadError::OutOfBounds);
1334 }
1335 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1336 return Err(ReadError::OutOfBounds);
1337 };
1338 Ok(Self { data })
1339 }
1340}
1341
1342#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1344#[repr(C, packed)]
1345#[doc(hidden)]
1346pub struct SinglePosFormat2FixedHeader {
1347 pub pos_format: BigEndian<u16>,
1348 pub coverage_offset: BigEndian<Offset16>,
1349 pub value_format: BigEndian<ValueFormat>,
1350 pub value_count: BigEndian<u16>,
1351}
1352
1353#[allow(clippy::absurd_extreme_comparisons)]
1354const _: () =
1355 assert!(std::mem::size_of::<SinglePosFormat2FixedHeader>() <= SinglePosFormat2::MIN_SIZE);
1356
1357#[derive(Clone)]
1359pub struct SinglePosFormat2<'a> {
1360 data: TableDataRef<'a, SinglePosFormat2FixedHeader>,
1361}
1362
1363#[allow(clippy::needless_lifetimes)]
1364impl<'a> SinglePosFormat2<'a> {
1365 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1366 + Offset16::RAW_BYTE_LEN
1367 + ValueFormat::RAW_BYTE_LEN
1368 + u16::RAW_BYTE_LEN);
1369 basic_table_impls!(impl_the_methods);
1370
1371 pub fn pos_format(&self) -> u16 {
1373 self.data.header().pos_format.get()
1374 }
1375
1376 pub fn coverage_offset(&self) -> Offset16 {
1378 self.data.header().coverage_offset.get()
1379 }
1380
1381 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1383 let data = self.offset_data();
1384 self.coverage_offset().resolve(data)
1385 }
1386
1387 pub fn value_format(&self) -> ValueFormat {
1389 self.data.header().value_format.get()
1390 }
1391
1392 pub fn value_count(&self) -> u16 {
1395 self.data.header().value_count.get()
1396 }
1397
1398 pub fn value_records(&self) -> ComputedArray<'a, ValueRecord<'a>> {
1400 let range = self.value_records_byte_range();
1401 ComputedArray::new(self.offset_data(), range, self.value_format()).unwrap_or_default()
1402 }
1403
1404 pub fn pos_format_byte_range(&self) -> Range<usize> {
1405 let start = 0;
1406 let end = start + u16::RAW_BYTE_LEN;
1407 start..end
1408 }
1409
1410 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1411 let start = self.pos_format_byte_range().end;
1412 let end = start + Offset16::RAW_BYTE_LEN;
1413 start..end
1414 }
1415
1416 pub fn value_format_byte_range(&self) -> Range<usize> {
1417 let start = self.coverage_offset_byte_range().end;
1418 let end = start + ValueFormat::RAW_BYTE_LEN;
1419 start..end
1420 }
1421
1422 pub fn value_count_byte_range(&self) -> Range<usize> {
1423 let start = self.value_format_byte_range().end;
1424 let end = start + u16::RAW_BYTE_LEN;
1425 start..end
1426 }
1427
1428 pub fn value_records_byte_range(&self) -> Range<usize> {
1429 let value_count = self.value_count();
1430 let start = self.value_count_byte_range().end;
1431 let end = start
1432 + (transforms::to_usize(value_count)).saturating_mul(
1433 <ValueRecord as ComputeSize>::compute_size(self.value_format()).unwrap_or(0),
1434 );
1435 start..end
1436 }
1437}
1438
1439#[derive(Clone)]
1441pub enum PairPos<'a> {
1442 Format1(PairPosFormat1<'a>),
1443 Format2(PairPosFormat2<'a>),
1444}
1445
1446impl Default for PairPos<'_> {
1447 fn default() -> Self {
1448 Self::Format1(Default::default())
1449 }
1450}
1451
1452impl<'a> PairPos<'a> {
1453 pub fn offset_data(&self) -> FontData<'a> {
1455 match self {
1456 Self::Format1(item) => item.offset_data(),
1457 Self::Format2(item) => item.offset_data(),
1458 }
1459 }
1460
1461 pub fn pos_format(&self) -> u16 {
1463 match self {
1464 Self::Format1(item) => item.pos_format(),
1465 Self::Format2(item) => item.pos_format(),
1466 }
1467 }
1468
1469 pub fn coverage_offset(&self) -> Offset16 {
1471 match self {
1472 Self::Format1(item) => item.coverage_offset(),
1473 Self::Format2(item) => item.coverage_offset(),
1474 }
1475 }
1476
1477 pub fn value_format1(&self) -> ValueFormat {
1480 match self {
1481 Self::Format1(item) => item.value_format1(),
1482 Self::Format2(item) => item.value_format1(),
1483 }
1484 }
1485
1486 pub fn value_format2(&self) -> ValueFormat {
1489 match self {
1490 Self::Format1(item) => item.value_format2(),
1491 Self::Format2(item) => item.value_format2(),
1492 }
1493 }
1494}
1495
1496impl ReadArgs for PairPos<'_> {
1497 type Args = ();
1498}
1499
1500impl<'a> FontRead<'a> for PairPos<'a> {
1501 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1502 let format: u16 = data.read_at(0usize)?;
1503 match format {
1504 PairPosFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1505 PairPosFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1506 other => Err(ReadError::InvalidFormat(other.into())),
1507 }
1508 }
1509}
1510
1511impl<'a> MinByteRange<'a> for PairPos<'a> {
1512 fn min_byte_range(&self) -> Range<usize> {
1513 match self {
1514 Self::Format1(item) => item.min_byte_range(),
1515 Self::Format2(item) => item.min_byte_range(),
1516 }
1517 }
1518 fn min_table_bytes(&self) -> &'a [u8] {
1519 match self {
1520 Self::Format1(item) => item.min_table_bytes(),
1521 Self::Format2(item) => item.min_table_bytes(),
1522 }
1523 }
1524}
1525
1526impl Format<u16> for PairPosFormat1<'_> {
1527 const FORMAT: u16 = 1;
1528}
1529
1530impl<'a> MinByteRange<'a> for PairPosFormat1<'a> {
1531 fn min_byte_range(&self) -> Range<usize> {
1532 0..self.pair_set_offsets_byte_range().end
1533 }
1534 fn min_table_bytes(&self) -> &'a [u8] {
1535 let range = self.min_byte_range();
1536 self.offset_data().as_bytes().get(range).unwrap_or_default()
1537 }
1538}
1539
1540impl ReadArgs for PairPosFormat1<'_> {
1541 type Args = ();
1542}
1543
1544impl<'a> FontRead<'a> for PairPosFormat1<'a> {
1545 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1546 #[allow(clippy::absurd_extreme_comparisons)]
1547 if data.len() < Self::MIN_SIZE {
1548 return Err(ReadError::OutOfBounds);
1549 }
1550 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1551 return Err(ReadError::OutOfBounds);
1552 };
1553 Ok(Self { data })
1554 }
1555}
1556
1557#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1559#[repr(C, packed)]
1560#[doc(hidden)]
1561pub struct PairPosFormat1FixedHeader {
1562 pub pos_format: BigEndian<u16>,
1563 pub coverage_offset: BigEndian<Offset16>,
1564 pub value_format1: BigEndian<ValueFormat>,
1565 pub value_format2: BigEndian<ValueFormat>,
1566 pub pair_set_count: BigEndian<u16>,
1567}
1568
1569#[allow(clippy::absurd_extreme_comparisons)]
1570const _: () = assert!(std::mem::size_of::<PairPosFormat1FixedHeader>() <= PairPosFormat1::MIN_SIZE);
1571
1572#[derive(Clone)]
1574pub struct PairPosFormat1<'a> {
1575 data: TableDataRef<'a, PairPosFormat1FixedHeader>,
1576}
1577
1578#[allow(clippy::needless_lifetimes)]
1579impl<'a> PairPosFormat1<'a> {
1580 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1581 + Offset16::RAW_BYTE_LEN
1582 + ValueFormat::RAW_BYTE_LEN
1583 + ValueFormat::RAW_BYTE_LEN
1584 + u16::RAW_BYTE_LEN);
1585 basic_table_impls!(impl_the_methods);
1586
1587 pub fn pos_format(&self) -> u16 {
1589 self.data.header().pos_format.get()
1590 }
1591
1592 pub fn coverage_offset(&self) -> Offset16 {
1594 self.data.header().coverage_offset.get()
1595 }
1596
1597 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1599 let data = self.offset_data();
1600 self.coverage_offset().resolve(data)
1601 }
1602
1603 pub fn value_format1(&self) -> ValueFormat {
1606 self.data.header().value_format1.get()
1607 }
1608
1609 pub fn value_format2(&self) -> ValueFormat {
1612 self.data.header().value_format2.get()
1613 }
1614
1615 pub fn pair_set_count(&self) -> u16 {
1617 self.data.header().pair_set_count.get()
1618 }
1619
1620 pub fn pair_set_offsets(&self) -> &'a [BigEndian<Offset16>] {
1623 let range = self.pair_set_offsets_byte_range();
1624 self.offset_data()
1625 .read_array(range)
1626 .ok()
1627 .unwrap_or_default()
1628 }
1629
1630 pub fn pair_sets(&self) -> ArrayOfOffsets<'a, PairSet<'a>, Offset16> {
1632 let data = self.offset_data();
1633 let offsets = self.pair_set_offsets();
1634 let args = (self.value_format1(), self.value_format2());
1635 ArrayOfOffsets::new(offsets, data, args)
1636 }
1637
1638 pub fn pos_format_byte_range(&self) -> Range<usize> {
1639 let start = 0;
1640 let end = start + u16::RAW_BYTE_LEN;
1641 start..end
1642 }
1643
1644 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1645 let start = self.pos_format_byte_range().end;
1646 let end = start + Offset16::RAW_BYTE_LEN;
1647 start..end
1648 }
1649
1650 pub fn value_format1_byte_range(&self) -> Range<usize> {
1651 let start = self.coverage_offset_byte_range().end;
1652 let end = start + ValueFormat::RAW_BYTE_LEN;
1653 start..end
1654 }
1655
1656 pub fn value_format2_byte_range(&self) -> Range<usize> {
1657 let start = self.value_format1_byte_range().end;
1658 let end = start + ValueFormat::RAW_BYTE_LEN;
1659 start..end
1660 }
1661
1662 pub fn pair_set_count_byte_range(&self) -> Range<usize> {
1663 let start = self.value_format2_byte_range().end;
1664 let end = start + u16::RAW_BYTE_LEN;
1665 start..end
1666 }
1667
1668 pub fn pair_set_offsets_byte_range(&self) -> Range<usize> {
1669 let pair_set_count = self.pair_set_count();
1670 let start = self.pair_set_count_byte_range().end;
1671 let end =
1672 start + (transforms::to_usize(pair_set_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1673 start..end
1674 }
1675}
1676
1677const _: () = assert!(FontData::default_data_long_enough(PairPosFormat1::MIN_SIZE));
1678
1679impl Default for PairPosFormat1<'_> {
1680 fn default() -> Self {
1681 Self {
1682 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
1683 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1684 }
1685 }
1686}
1687
1688impl<'a> MinByteRange<'a> for PairSet<'a> {
1689 fn min_byte_range(&self) -> Range<usize> {
1690 0..self.pair_value_records_byte_range().end
1691 }
1692 fn min_table_bytes(&self) -> &'a [u8] {
1693 let range = self.min_byte_range();
1694 self.offset_data().as_bytes().get(range).unwrap_or_default()
1695 }
1696}
1697
1698impl ReadArgs for PairSet<'_> {
1699 type Args = (ValueFormat, ValueFormat);
1700}
1701
1702impl<'a> FontRead<'a> for PairSet<'a> {
1703 fn read_with_args(
1704 data: FontData<'a>,
1705 args: (ValueFormat, ValueFormat),
1706 ) -> Result<Self, ReadError> {
1707 let (value_format1, value_format2) = args;
1708
1709 #[allow(clippy::absurd_extreme_comparisons)]
1710 if data.len() < Self::MIN_SIZE {
1711 return Err(ReadError::OutOfBounds);
1712 }
1713 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1714 return Err(ReadError::OutOfBounds);
1715 };
1716 Ok(Self {
1717 data,
1718 value_format1,
1719 value_format2,
1720 })
1721 }
1722}
1723
1724impl<'a> PairSet<'a> {
1725 pub fn read(
1730 data: FontData<'a>,
1731 value_format1: ValueFormat,
1732 value_format2: ValueFormat,
1733 ) -> Result<Self, ReadError> {
1734 let args = (value_format1, value_format2);
1735 Self::read_with_args(data, args)
1736 }
1737}
1738
1739#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1741#[repr(C, packed)]
1742#[doc(hidden)]
1743pub struct PairSetFixedHeader {
1744 pub pair_value_count: BigEndian<u16>,
1745}
1746
1747#[allow(clippy::absurd_extreme_comparisons)]
1748const _: () = assert!(std::mem::size_of::<PairSetFixedHeader>() <= PairSet::MIN_SIZE);
1749
1750#[derive(Clone)]
1752pub struct PairSet<'a> {
1753 data: TableDataRef<'a, PairSetFixedHeader>,
1754 value_format1: ValueFormat,
1755 value_format2: ValueFormat,
1756}
1757
1758#[allow(clippy::needless_lifetimes)]
1759impl<'a> PairSet<'a> {
1760 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
1761 basic_table_impls!(impl_the_methods);
1762
1763 pub fn pair_value_count(&self) -> u16 {
1765 self.data.header().pair_value_count.get()
1766 }
1767
1768 pub fn pair_value_records(&self) -> ComputedArray<'a, PairValueRecord<'a>> {
1771 let range = self.pair_value_records_byte_range();
1772 ComputedArray::new(
1773 self.offset_data(),
1774 range,
1775 (self.value_format1(), self.value_format2()),
1776 )
1777 .unwrap_or_default()
1778 }
1779
1780 pub(crate) fn value_format1(&self) -> ValueFormat {
1781 self.value_format1
1782 }
1783
1784 pub(crate) fn value_format2(&self) -> ValueFormat {
1785 self.value_format2
1786 }
1787
1788 pub fn pair_value_count_byte_range(&self) -> Range<usize> {
1789 let start = 0;
1790 let end = start + u16::RAW_BYTE_LEN;
1791 start..end
1792 }
1793
1794 pub fn pair_value_records_byte_range(&self) -> Range<usize> {
1795 let pair_value_count = self.pair_value_count();
1796 let start = self.pair_value_count_byte_range().end;
1797 let end = start
1798 + (transforms::to_usize(pair_value_count)).saturating_mul(
1799 <PairValueRecord as ComputeSize>::compute_size((
1800 self.value_format1(),
1801 self.value_format2(),
1802 ))
1803 .unwrap_or(0),
1804 );
1805 start..end
1806 }
1807}
1808
1809const _: () = assert!(FontData::default_data_long_enough(PairSet::MIN_SIZE));
1810
1811impl Default for PairSet<'_> {
1812 fn default() -> Self {
1813 Self {
1814 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1815 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1816 value_format1: Default::default(),
1817 value_format2: Default::default(),
1818 }
1819 }
1820}
1821
1822#[derive(Clone, Debug)]
1824pub struct PairValueRecord<'a> {
1825 pub second_glyph: BigEndian<GlyphId16>,
1828 pub value_record1: ValueRecord<'a>,
1830 pub value_record2: ValueRecord<'a>,
1832}
1833
1834impl<'a> PairValueRecord<'a> {
1835 pub fn second_glyph(&self) -> GlyphId16 {
1838 self.second_glyph.get()
1839 }
1840
1841 pub fn value_record1(&self) -> &ValueRecord<'a> {
1843 &self.value_record1
1844 }
1845
1846 pub fn value_record2(&self) -> &ValueRecord<'a> {
1848 &self.value_record2
1849 }
1850}
1851
1852impl ReadArgs for PairValueRecord<'_> {
1853 type Args = (ValueFormat, ValueFormat);
1854}
1855
1856impl ComputeSize for PairValueRecord<'_> {
1857 #[allow(clippy::needless_question_mark)]
1858 fn compute_size(args: (ValueFormat, ValueFormat)) -> Result<usize, ReadError> {
1859 let (value_format1, value_format2) = args;
1860 let mut result = 0usize;
1861 result = result
1862 .checked_add(GlyphId16::RAW_BYTE_LEN)
1863 .ok_or(ReadError::OutOfBounds)?;
1864 result = result
1865 .checked_add(<ValueRecord as ComputeSize>::compute_size(value_format1).unwrap_or(0))
1866 .ok_or(ReadError::OutOfBounds)?;
1867 result = result
1868 .checked_add(<ValueRecord as ComputeSize>::compute_size(value_format2).unwrap_or(0))
1869 .ok_or(ReadError::OutOfBounds)?;
1870 Ok(result)
1871 }
1872}
1873
1874impl<'a> FontReadAt<'a> for PairValueRecord<'a> {
1875 fn read_at(
1876 data: FontData<'a>,
1877 offset: usize,
1878 args: (ValueFormat, ValueFormat),
1879 ) -> Result<Self, ReadError> {
1880 let mut cursor = data.cursor();
1881 cursor.advance_by(offset);
1882 let (value_format1, value_format2) = args;
1883 Ok(Self {
1884 second_glyph: cursor.read_be()?,
1885 value_record1: cursor.read_at_with_args(value_format1)?,
1886 value_record2: cursor.read_at_with_args(value_format2)?,
1887 })
1888 }
1889}
1890
1891#[allow(clippy::needless_lifetimes)]
1892impl<'a> PairValueRecord<'a> {
1893 pub fn read(
1898 data: FontData<'a>,
1899 offset: usize,
1900 value_format1: ValueFormat,
1901 value_format2: ValueFormat,
1902 ) -> Result<Self, ReadError> {
1903 let args = (value_format1, value_format2);
1904 Self::read_at(data, offset, args)
1905 }
1906}
1907
1908impl Format<u16> for PairPosFormat2<'_> {
1909 const FORMAT: u16 = 2;
1910}
1911
1912impl<'a> MinByteRange<'a> for PairPosFormat2<'a> {
1913 fn min_byte_range(&self) -> Range<usize> {
1914 0..self.class1_records_byte_range().end
1915 }
1916 fn min_table_bytes(&self) -> &'a [u8] {
1917 let range = self.min_byte_range();
1918 self.offset_data().as_bytes().get(range).unwrap_or_default()
1919 }
1920}
1921
1922impl ReadArgs for PairPosFormat2<'_> {
1923 type Args = ();
1924}
1925
1926impl<'a> FontRead<'a> for PairPosFormat2<'a> {
1927 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1928 #[allow(clippy::absurd_extreme_comparisons)]
1929 if data.len() < Self::MIN_SIZE {
1930 return Err(ReadError::OutOfBounds);
1931 }
1932 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1933 return Err(ReadError::OutOfBounds);
1934 };
1935 Ok(Self { data })
1936 }
1937}
1938
1939#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1941#[repr(C, packed)]
1942#[doc(hidden)]
1943pub struct PairPosFormat2FixedHeader {
1944 pub pos_format: BigEndian<u16>,
1945 pub coverage_offset: BigEndian<Offset16>,
1946 pub value_format1: BigEndian<ValueFormat>,
1947 pub value_format2: BigEndian<ValueFormat>,
1948 pub class_def1_offset: BigEndian<Offset16>,
1949 pub class_def2_offset: BigEndian<Offset16>,
1950 pub class1_count: BigEndian<u16>,
1951 pub class2_count: BigEndian<u16>,
1952}
1953
1954#[allow(clippy::absurd_extreme_comparisons)]
1955const _: () = assert!(std::mem::size_of::<PairPosFormat2FixedHeader>() <= PairPosFormat2::MIN_SIZE);
1956
1957#[derive(Clone)]
1959pub struct PairPosFormat2<'a> {
1960 data: TableDataRef<'a, PairPosFormat2FixedHeader>,
1961}
1962
1963#[allow(clippy::needless_lifetimes)]
1964impl<'a> PairPosFormat2<'a> {
1965 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1966 + Offset16::RAW_BYTE_LEN
1967 + ValueFormat::RAW_BYTE_LEN
1968 + ValueFormat::RAW_BYTE_LEN
1969 + Offset16::RAW_BYTE_LEN
1970 + Offset16::RAW_BYTE_LEN
1971 + u16::RAW_BYTE_LEN
1972 + u16::RAW_BYTE_LEN);
1973 basic_table_impls!(impl_the_methods);
1974
1975 pub fn pos_format(&self) -> u16 {
1977 self.data.header().pos_format.get()
1978 }
1979
1980 pub fn coverage_offset(&self) -> Offset16 {
1982 self.data.header().coverage_offset.get()
1983 }
1984
1985 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1987 let data = self.offset_data();
1988 self.coverage_offset().resolve(data)
1989 }
1990
1991 pub fn value_format1(&self) -> ValueFormat {
1994 self.data.header().value_format1.get()
1995 }
1996
1997 pub fn value_format2(&self) -> ValueFormat {
2000 self.data.header().value_format2.get()
2001 }
2002
2003 pub fn class_def1_offset(&self) -> Offset16 {
2006 self.data.header().class_def1_offset.get()
2007 }
2008
2009 pub fn class_def1(&self) -> Result<ClassDef<'a>, ReadError> {
2011 let data = self.offset_data();
2012 self.class_def1_offset().resolve(data)
2013 }
2014
2015 pub fn class_def2_offset(&self) -> Offset16 {
2018 self.data.header().class_def2_offset.get()
2019 }
2020
2021 pub fn class_def2(&self) -> Result<ClassDef<'a>, ReadError> {
2023 let data = self.offset_data();
2024 self.class_def2_offset().resolve(data)
2025 }
2026
2027 pub fn class1_count(&self) -> u16 {
2029 self.data.header().class1_count.get()
2030 }
2031
2032 pub fn class2_count(&self) -> u16 {
2034 self.data.header().class2_count.get()
2035 }
2036
2037 pub fn class1_records(&self) -> ComputedArray<'a, Class1Record<'a>> {
2039 let range = self.class1_records_byte_range();
2040 ComputedArray::new(
2041 self.offset_data(),
2042 range,
2043 (
2044 self.class2_count(),
2045 self.value_format1(),
2046 self.value_format2(),
2047 ),
2048 )
2049 .unwrap_or_default()
2050 }
2051
2052 pub fn pos_format_byte_range(&self) -> Range<usize> {
2053 let start = 0;
2054 let end = start + u16::RAW_BYTE_LEN;
2055 start..end
2056 }
2057
2058 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2059 let start = self.pos_format_byte_range().end;
2060 let end = start + Offset16::RAW_BYTE_LEN;
2061 start..end
2062 }
2063
2064 pub fn value_format1_byte_range(&self) -> Range<usize> {
2065 let start = self.coverage_offset_byte_range().end;
2066 let end = start + ValueFormat::RAW_BYTE_LEN;
2067 start..end
2068 }
2069
2070 pub fn value_format2_byte_range(&self) -> Range<usize> {
2071 let start = self.value_format1_byte_range().end;
2072 let end = start + ValueFormat::RAW_BYTE_LEN;
2073 start..end
2074 }
2075
2076 pub fn class_def1_offset_byte_range(&self) -> Range<usize> {
2077 let start = self.value_format2_byte_range().end;
2078 let end = start + Offset16::RAW_BYTE_LEN;
2079 start..end
2080 }
2081
2082 pub fn class_def2_offset_byte_range(&self) -> Range<usize> {
2083 let start = self.class_def1_offset_byte_range().end;
2084 let end = start + Offset16::RAW_BYTE_LEN;
2085 start..end
2086 }
2087
2088 pub fn class1_count_byte_range(&self) -> Range<usize> {
2089 let start = self.class_def2_offset_byte_range().end;
2090 let end = start + u16::RAW_BYTE_LEN;
2091 start..end
2092 }
2093
2094 pub fn class2_count_byte_range(&self) -> Range<usize> {
2095 let start = self.class1_count_byte_range().end;
2096 let end = start + u16::RAW_BYTE_LEN;
2097 start..end
2098 }
2099
2100 pub fn class1_records_byte_range(&self) -> Range<usize> {
2101 let class1_count = self.class1_count();
2102 let start = self.class2_count_byte_range().end;
2103 let end = start
2104 + (transforms::to_usize(class1_count)).saturating_mul(
2105 <Class1Record as ComputeSize>::compute_size((
2106 self.class2_count(),
2107 self.value_format1(),
2108 self.value_format2(),
2109 ))
2110 .unwrap_or(0),
2111 );
2112 start..end
2113 }
2114}
2115
2116#[derive(Clone, Debug)]
2118pub struct Class1Record<'a> {
2119 pub class2_records: ComputedArray<'a, Class2Record<'a>>,
2121}
2122
2123impl<'a> Class1Record<'a> {
2124 pub fn class2_records(&self) -> &ComputedArray<'a, Class2Record<'a>> {
2126 &self.class2_records
2127 }
2128}
2129
2130impl ReadArgs for Class1Record<'_> {
2131 type Args = (u16, ValueFormat, ValueFormat);
2132}
2133
2134impl ComputeSize for Class1Record<'_> {
2135 #[allow(clippy::needless_question_mark)]
2136 fn compute_size(args: (u16, ValueFormat, ValueFormat)) -> Result<usize, ReadError> {
2137 let (class2_count, value_format1, value_format2) = args;
2138 Ok((transforms::to_usize(class2_count)).saturating_mul(
2139 <Class2Record as ComputeSize>::compute_size((value_format1, value_format2))
2140 .unwrap_or(0),
2141 ))
2142 }
2143}
2144
2145impl<'a> FontReadAt<'a> for Class1Record<'a> {
2146 fn read_at(
2147 data: FontData<'a>,
2148 offset: usize,
2149 args: (u16, ValueFormat, ValueFormat),
2150 ) -> Result<Self, ReadError> {
2151 let mut cursor = data.cursor();
2152 cursor.advance_by(offset);
2153 let (class2_count, value_format1, value_format2) = args;
2154 Ok(Self {
2155 class2_records: cursor.read_computed_array(
2156 transforms::to_usize(class2_count),
2157 (value_format1, value_format2),
2158 )?,
2159 })
2160 }
2161}
2162
2163#[allow(clippy::needless_lifetimes)]
2164impl<'a> Class1Record<'a> {
2165 pub fn read(
2170 data: FontData<'a>,
2171 offset: usize,
2172 class2_count: u16,
2173 value_format1: ValueFormat,
2174 value_format2: ValueFormat,
2175 ) -> Result<Self, ReadError> {
2176 let args = (class2_count, value_format1, value_format2);
2177 Self::read_at(data, offset, args)
2178 }
2179}
2180
2181#[derive(Clone, Debug)]
2183pub struct Class2Record<'a> {
2184 pub value_record1: ValueRecord<'a>,
2186 pub value_record2: ValueRecord<'a>,
2188}
2189
2190impl<'a> Class2Record<'a> {
2191 pub fn value_record1(&self) -> &ValueRecord<'a> {
2193 &self.value_record1
2194 }
2195
2196 pub fn value_record2(&self) -> &ValueRecord<'a> {
2198 &self.value_record2
2199 }
2200}
2201
2202impl ReadArgs for Class2Record<'_> {
2203 type Args = (ValueFormat, ValueFormat);
2204}
2205
2206impl ComputeSize for Class2Record<'_> {
2207 #[allow(clippy::needless_question_mark)]
2208 fn compute_size(args: (ValueFormat, ValueFormat)) -> Result<usize, ReadError> {
2209 let (value_format1, value_format2) = args;
2210 let mut result = 0usize;
2211 result = result
2212 .checked_add(<ValueRecord as ComputeSize>::compute_size(value_format1).unwrap_or(0))
2213 .ok_or(ReadError::OutOfBounds)?;
2214 result = result
2215 .checked_add(<ValueRecord as ComputeSize>::compute_size(value_format2).unwrap_or(0))
2216 .ok_or(ReadError::OutOfBounds)?;
2217 Ok(result)
2218 }
2219}
2220
2221impl<'a> FontReadAt<'a> for Class2Record<'a> {
2222 fn read_at(
2223 data: FontData<'a>,
2224 offset: usize,
2225 args: (ValueFormat, ValueFormat),
2226 ) -> Result<Self, ReadError> {
2227 let mut cursor = data.cursor();
2228 cursor.advance_by(offset);
2229 let (value_format1, value_format2) = args;
2230 Ok(Self {
2231 value_record1: cursor.read_at_with_args(value_format1)?,
2232 value_record2: cursor.read_at_with_args(value_format2)?,
2233 })
2234 }
2235}
2236
2237#[allow(clippy::needless_lifetimes)]
2238impl<'a> Class2Record<'a> {
2239 pub fn read(
2244 data: FontData<'a>,
2245 offset: usize,
2246 value_format1: ValueFormat,
2247 value_format2: ValueFormat,
2248 ) -> Result<Self, ReadError> {
2249 let args = (value_format1, value_format2);
2250 Self::read_at(data, offset, args)
2251 }
2252}
2253
2254impl Format<u16> for CursivePosFormat1<'_> {
2255 const FORMAT: u16 = 1;
2256}
2257
2258impl<'a> MinByteRange<'a> for CursivePosFormat1<'a> {
2259 fn min_byte_range(&self) -> Range<usize> {
2260 0..self.entry_exit_record_byte_range().end
2261 }
2262 fn min_table_bytes(&self) -> &'a [u8] {
2263 let range = self.min_byte_range();
2264 self.offset_data().as_bytes().get(range).unwrap_or_default()
2265 }
2266}
2267
2268impl ReadArgs for CursivePosFormat1<'_> {
2269 type Args = ();
2270}
2271
2272impl<'a> FontRead<'a> for CursivePosFormat1<'a> {
2273 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2274 #[allow(clippy::absurd_extreme_comparisons)]
2275 if data.len() < Self::MIN_SIZE {
2276 return Err(ReadError::OutOfBounds);
2277 }
2278 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2279 return Err(ReadError::OutOfBounds);
2280 };
2281 Ok(Self { data })
2282 }
2283}
2284
2285#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2287#[repr(C, packed)]
2288#[doc(hidden)]
2289pub struct CursivePosFormat1FixedHeader {
2290 pub pos_format: BigEndian<u16>,
2291 pub coverage_offset: BigEndian<Offset16>,
2292 pub entry_exit_count: BigEndian<u16>,
2293}
2294
2295#[allow(clippy::absurd_extreme_comparisons)]
2296const _: () =
2297 assert!(std::mem::size_of::<CursivePosFormat1FixedHeader>() <= CursivePosFormat1::MIN_SIZE);
2298
2299#[derive(Clone)]
2301pub struct CursivePosFormat1<'a> {
2302 data: TableDataRef<'a, CursivePosFormat1FixedHeader>,
2303}
2304
2305#[allow(clippy::needless_lifetimes)]
2306impl<'a> CursivePosFormat1<'a> {
2307 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2308 basic_table_impls!(impl_the_methods);
2309
2310 pub fn pos_format(&self) -> u16 {
2312 self.data.header().pos_format.get()
2313 }
2314
2315 pub fn coverage_offset(&self) -> Offset16 {
2317 self.data.header().coverage_offset.get()
2318 }
2319
2320 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2322 let data = self.offset_data();
2323 self.coverage_offset().resolve(data)
2324 }
2325
2326 pub fn entry_exit_count(&self) -> u16 {
2328 self.data.header().entry_exit_count.get()
2329 }
2330
2331 pub fn entry_exit_record(&self) -> &'a [EntryExitRecord] {
2333 let range = self.entry_exit_record_byte_range();
2334 self.offset_data()
2335 .read_array(range)
2336 .ok()
2337 .unwrap_or_default()
2338 }
2339
2340 pub fn pos_format_byte_range(&self) -> Range<usize> {
2341 let start = 0;
2342 let end = start + u16::RAW_BYTE_LEN;
2343 start..end
2344 }
2345
2346 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2347 let start = self.pos_format_byte_range().end;
2348 let end = start + Offset16::RAW_BYTE_LEN;
2349 start..end
2350 }
2351
2352 pub fn entry_exit_count_byte_range(&self) -> Range<usize> {
2353 let start = self.coverage_offset_byte_range().end;
2354 let end = start + u16::RAW_BYTE_LEN;
2355 start..end
2356 }
2357
2358 pub fn entry_exit_record_byte_range(&self) -> Range<usize> {
2359 let entry_exit_count = self.entry_exit_count();
2360 let start = self.entry_exit_count_byte_range().end;
2361 let end = start
2362 + (transforms::to_usize(entry_exit_count))
2363 .saturating_mul(EntryExitRecord::RAW_BYTE_LEN);
2364 start..end
2365 }
2366}
2367
2368const _: () = assert!(FontData::default_data_long_enough(
2369 CursivePosFormat1::MIN_SIZE
2370));
2371
2372impl Default for CursivePosFormat1<'_> {
2373 fn default() -> Self {
2374 Self {
2375 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
2376 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2377 }
2378 }
2379}
2380
2381#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
2383#[repr(C)]
2384#[repr(packed)]
2385pub struct EntryExitRecord {
2386 pub entry_anchor_offset: BigEndian<Nullable<Offset16>>,
2389 pub exit_anchor_offset: BigEndian<Nullable<Offset16>>,
2392}
2393
2394impl EntryExitRecord {
2395 pub fn entry_anchor_offset(&self) -> Nullable<Offset16> {
2398 self.entry_anchor_offset.get()
2399 }
2400
2401 pub fn entry_anchor<'a>(
2407 &self,
2408 data: FontData<'a>,
2409 ) -> Option<Result<AnchorTable<'a>, ReadError>> {
2410 self.entry_anchor_offset().resolve(data)
2411 }
2412
2413 pub fn exit_anchor_offset(&self) -> Nullable<Offset16> {
2416 self.exit_anchor_offset.get()
2417 }
2418
2419 pub fn exit_anchor<'a>(
2425 &self,
2426 data: FontData<'a>,
2427 ) -> Option<Result<AnchorTable<'a>, ReadError>> {
2428 self.exit_anchor_offset().resolve(data)
2429 }
2430}
2431
2432impl FixedSize for EntryExitRecord {
2433 const RAW_BYTE_LEN: usize = Offset16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
2434}
2435
2436impl Format<u16> for MarkBasePosFormat1<'_> {
2437 const FORMAT: u16 = 1;
2438}
2439
2440impl<'a> MinByteRange<'a> for MarkBasePosFormat1<'a> {
2441 fn min_byte_range(&self) -> Range<usize> {
2442 0..self.base_array_offset_byte_range().end
2443 }
2444 fn min_table_bytes(&self) -> &'a [u8] {
2445 let range = self.min_byte_range();
2446 self.offset_data().as_bytes().get(range).unwrap_or_default()
2447 }
2448}
2449
2450impl ReadArgs for MarkBasePosFormat1<'_> {
2451 type Args = ();
2452}
2453
2454impl<'a> FontRead<'a> for MarkBasePosFormat1<'a> {
2455 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2456 #[allow(clippy::absurd_extreme_comparisons)]
2457 if data.len() < Self::MIN_SIZE {
2458 return Err(ReadError::OutOfBounds);
2459 }
2460 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2461 return Err(ReadError::OutOfBounds);
2462 };
2463 Ok(Self { data })
2464 }
2465}
2466
2467#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2469#[repr(C, packed)]
2470#[doc(hidden)]
2471pub struct MarkBasePosFormat1FixedHeader {
2472 pub pos_format: BigEndian<u16>,
2473 pub mark_coverage_offset: BigEndian<Offset16>,
2474 pub base_coverage_offset: BigEndian<Offset16>,
2475 pub mark_class_count: BigEndian<u16>,
2476 pub mark_array_offset: BigEndian<Offset16>,
2477 pub base_array_offset: BigEndian<Offset16>,
2478}
2479
2480#[allow(clippy::absurd_extreme_comparisons)]
2481const _: () =
2482 assert!(std::mem::size_of::<MarkBasePosFormat1FixedHeader>() <= MarkBasePosFormat1::MIN_SIZE);
2483
2484#[derive(Clone)]
2486pub struct MarkBasePosFormat1<'a> {
2487 data: TableDataRef<'a, MarkBasePosFormat1FixedHeader>,
2488}
2489
2490#[allow(clippy::needless_lifetimes)]
2491impl<'a> MarkBasePosFormat1<'a> {
2492 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
2493 + Offset16::RAW_BYTE_LEN
2494 + Offset16::RAW_BYTE_LEN
2495 + u16::RAW_BYTE_LEN
2496 + Offset16::RAW_BYTE_LEN
2497 + Offset16::RAW_BYTE_LEN);
2498 basic_table_impls!(impl_the_methods);
2499
2500 pub fn pos_format(&self) -> u16 {
2502 self.data.header().pos_format.get()
2503 }
2504
2505 pub fn mark_coverage_offset(&self) -> Offset16 {
2508 self.data.header().mark_coverage_offset.get()
2509 }
2510
2511 pub fn mark_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2513 let data = self.offset_data();
2514 self.mark_coverage_offset().resolve(data)
2515 }
2516
2517 pub fn base_coverage_offset(&self) -> Offset16 {
2520 self.data.header().base_coverage_offset.get()
2521 }
2522
2523 pub fn base_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2525 let data = self.offset_data();
2526 self.base_coverage_offset().resolve(data)
2527 }
2528
2529 pub fn mark_class_count(&self) -> u16 {
2531 self.data.header().mark_class_count.get()
2532 }
2533
2534 pub fn mark_array_offset(&self) -> Offset16 {
2537 self.data.header().mark_array_offset.get()
2538 }
2539
2540 pub fn mark_array(&self) -> Result<MarkArray<'a>, ReadError> {
2542 let data = self.offset_data();
2543 self.mark_array_offset().resolve(data)
2544 }
2545
2546 pub fn base_array_offset(&self) -> Offset16 {
2549 self.data.header().base_array_offset.get()
2550 }
2551
2552 pub fn base_array(&self) -> Result<BaseArray<'a>, ReadError> {
2554 let data = self.offset_data();
2555 let args = self.mark_class_count();
2556 self.base_array_offset().resolve_with_args(data, args)
2557 }
2558
2559 pub fn pos_format_byte_range(&self) -> Range<usize> {
2560 let start = 0;
2561 let end = start + u16::RAW_BYTE_LEN;
2562 start..end
2563 }
2564
2565 pub fn mark_coverage_offset_byte_range(&self) -> Range<usize> {
2566 let start = self.pos_format_byte_range().end;
2567 let end = start + Offset16::RAW_BYTE_LEN;
2568 start..end
2569 }
2570
2571 pub fn base_coverage_offset_byte_range(&self) -> Range<usize> {
2572 let start = self.mark_coverage_offset_byte_range().end;
2573 let end = start + Offset16::RAW_BYTE_LEN;
2574 start..end
2575 }
2576
2577 pub fn mark_class_count_byte_range(&self) -> Range<usize> {
2578 let start = self.base_coverage_offset_byte_range().end;
2579 let end = start + u16::RAW_BYTE_LEN;
2580 start..end
2581 }
2582
2583 pub fn mark_array_offset_byte_range(&self) -> Range<usize> {
2584 let start = self.mark_class_count_byte_range().end;
2585 let end = start + Offset16::RAW_BYTE_LEN;
2586 start..end
2587 }
2588
2589 pub fn base_array_offset_byte_range(&self) -> Range<usize> {
2590 let start = self.mark_array_offset_byte_range().end;
2591 let end = start + Offset16::RAW_BYTE_LEN;
2592 start..end
2593 }
2594}
2595
2596const _: () = assert!(FontData::default_data_long_enough(
2597 MarkBasePosFormat1::MIN_SIZE
2598));
2599
2600impl Default for MarkBasePosFormat1<'_> {
2601 fn default() -> Self {
2602 Self {
2603 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
2604 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2605 }
2606 }
2607}
2608
2609impl<'a> MinByteRange<'a> for BaseArray<'a> {
2610 fn min_byte_range(&self) -> Range<usize> {
2611 0..self.base_records_byte_range().end
2612 }
2613 fn min_table_bytes(&self) -> &'a [u8] {
2614 let range = self.min_byte_range();
2615 self.offset_data().as_bytes().get(range).unwrap_or_default()
2616 }
2617}
2618
2619impl ReadArgs for BaseArray<'_> {
2620 type Args = u16;
2621}
2622
2623impl<'a> FontRead<'a> for BaseArray<'a> {
2624 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
2625 let mark_class_count = args;
2626
2627 #[allow(clippy::absurd_extreme_comparisons)]
2628 if data.len() < Self::MIN_SIZE {
2629 return Err(ReadError::OutOfBounds);
2630 }
2631 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2632 return Err(ReadError::OutOfBounds);
2633 };
2634 Ok(Self {
2635 data,
2636 mark_class_count,
2637 })
2638 }
2639}
2640
2641impl<'a> BaseArray<'a> {
2642 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
2647 let args = mark_class_count;
2648 Self::read_with_args(data, args)
2649 }
2650}
2651
2652#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2654#[repr(C, packed)]
2655#[doc(hidden)]
2656pub struct BaseArrayFixedHeader {
2657 pub base_count: BigEndian<u16>,
2658}
2659
2660#[allow(clippy::absurd_extreme_comparisons)]
2661const _: () = assert!(std::mem::size_of::<BaseArrayFixedHeader>() <= BaseArray::MIN_SIZE);
2662
2663#[derive(Clone)]
2665pub struct BaseArray<'a> {
2666 data: TableDataRef<'a, BaseArrayFixedHeader>,
2667 mark_class_count: u16,
2668}
2669
2670#[allow(clippy::needless_lifetimes)]
2671impl<'a> BaseArray<'a> {
2672 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
2673 basic_table_impls!(impl_the_methods);
2674
2675 pub fn base_count(&self) -> u16 {
2677 self.data.header().base_count.get()
2678 }
2679
2680 pub fn base_records(&self) -> ComputedArray<'a, BaseRecord<'a>> {
2682 let range = self.base_records_byte_range();
2683 ComputedArray::new(self.offset_data(), range, self.mark_class_count()).unwrap_or_default()
2684 }
2685
2686 pub(crate) fn mark_class_count(&self) -> u16 {
2687 self.mark_class_count
2688 }
2689
2690 pub fn base_count_byte_range(&self) -> Range<usize> {
2691 let start = 0;
2692 let end = start + u16::RAW_BYTE_LEN;
2693 start..end
2694 }
2695
2696 pub fn base_records_byte_range(&self) -> Range<usize> {
2697 let base_count = self.base_count();
2698 let start = self.base_count_byte_range().end;
2699 let end = start
2700 + (transforms::to_usize(base_count)).saturating_mul(
2701 <BaseRecord as ComputeSize>::compute_size(self.mark_class_count()).unwrap_or(0),
2702 );
2703 start..end
2704 }
2705}
2706
2707const _: () = assert!(FontData::default_data_long_enough(BaseArray::MIN_SIZE));
2708
2709impl Default for BaseArray<'_> {
2710 fn default() -> Self {
2711 Self {
2712 data: TableDataRef::new(FontData::default_table_data().as_bytes())
2713 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2714 mark_class_count: Default::default(),
2715 }
2716 }
2717}
2718
2719#[derive(Clone, Debug)]
2721pub struct BaseRecord<'a> {
2722 pub base_anchor_offsets: &'a [BigEndian<Nullable<Offset16>>],
2726}
2727
2728impl<'a> BaseRecord<'a> {
2729 pub fn base_anchor_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2733 self.base_anchor_offsets
2734 }
2735
2736 pub fn base_anchors(
2743 &self,
2744 data: FontData<'a>,
2745 ) -> ArrayOfNullableOffsets<'a, AnchorTable<'a>, Offset16> {
2746 let offsets = self.base_anchor_offsets();
2747 ArrayOfNullableOffsets::new(offsets, data, ())
2748 }
2749}
2750
2751impl ReadArgs for BaseRecord<'_> {
2752 type Args = u16;
2753}
2754
2755impl ComputeSize for BaseRecord<'_> {
2756 #[allow(clippy::needless_question_mark)]
2757 fn compute_size(args: u16) -> Result<usize, ReadError> {
2758 let mark_class_count = args;
2759 Ok((transforms::to_usize(mark_class_count)).saturating_mul(Offset16::RAW_BYTE_LEN))
2760 }
2761}
2762
2763impl<'a> FontRead<'a> for BaseRecord<'a> {
2764 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
2765 let mut cursor = data.cursor();
2766 let mark_class_count = args;
2767 Ok(Self {
2768 base_anchor_offsets: cursor.read_array(transforms::to_usize(mark_class_count))?,
2769 })
2770 }
2771}
2772
2773crate::impl_font_read_at!(BaseRecord<'a>);
2774
2775#[allow(clippy::needless_lifetimes)]
2776impl<'a> BaseRecord<'a> {
2777 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
2782 let args = mark_class_count;
2783 Self::read_with_args(data, args)
2784 }
2785}
2786
2787impl Format<u16> for MarkLigPosFormat1<'_> {
2788 const FORMAT: u16 = 1;
2789}
2790
2791impl<'a> MinByteRange<'a> for MarkLigPosFormat1<'a> {
2792 fn min_byte_range(&self) -> Range<usize> {
2793 0..self.ligature_array_offset_byte_range().end
2794 }
2795 fn min_table_bytes(&self) -> &'a [u8] {
2796 let range = self.min_byte_range();
2797 self.offset_data().as_bytes().get(range).unwrap_or_default()
2798 }
2799}
2800
2801impl ReadArgs for MarkLigPosFormat1<'_> {
2802 type Args = ();
2803}
2804
2805impl<'a> FontRead<'a> for MarkLigPosFormat1<'a> {
2806 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2807 #[allow(clippy::absurd_extreme_comparisons)]
2808 if data.len() < Self::MIN_SIZE {
2809 return Err(ReadError::OutOfBounds);
2810 }
2811 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2812 return Err(ReadError::OutOfBounds);
2813 };
2814 Ok(Self { data })
2815 }
2816}
2817
2818#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2820#[repr(C, packed)]
2821#[doc(hidden)]
2822pub struct MarkLigPosFormat1FixedHeader {
2823 pub pos_format: BigEndian<u16>,
2824 pub mark_coverage_offset: BigEndian<Offset16>,
2825 pub ligature_coverage_offset: BigEndian<Offset16>,
2826 pub mark_class_count: BigEndian<u16>,
2827 pub mark_array_offset: BigEndian<Offset16>,
2828 pub ligature_array_offset: BigEndian<Offset16>,
2829}
2830
2831#[allow(clippy::absurd_extreme_comparisons)]
2832const _: () =
2833 assert!(std::mem::size_of::<MarkLigPosFormat1FixedHeader>() <= MarkLigPosFormat1::MIN_SIZE);
2834
2835#[derive(Clone)]
2837pub struct MarkLigPosFormat1<'a> {
2838 data: TableDataRef<'a, MarkLigPosFormat1FixedHeader>,
2839}
2840
2841#[allow(clippy::needless_lifetimes)]
2842impl<'a> MarkLigPosFormat1<'a> {
2843 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
2844 + Offset16::RAW_BYTE_LEN
2845 + Offset16::RAW_BYTE_LEN
2846 + u16::RAW_BYTE_LEN
2847 + Offset16::RAW_BYTE_LEN
2848 + Offset16::RAW_BYTE_LEN);
2849 basic_table_impls!(impl_the_methods);
2850
2851 pub fn pos_format(&self) -> u16 {
2853 self.data.header().pos_format.get()
2854 }
2855
2856 pub fn mark_coverage_offset(&self) -> Offset16 {
2859 self.data.header().mark_coverage_offset.get()
2860 }
2861
2862 pub fn mark_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2864 let data = self.offset_data();
2865 self.mark_coverage_offset().resolve(data)
2866 }
2867
2868 pub fn ligature_coverage_offset(&self) -> Offset16 {
2871 self.data.header().ligature_coverage_offset.get()
2872 }
2873
2874 pub fn ligature_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2876 let data = self.offset_data();
2877 self.ligature_coverage_offset().resolve(data)
2878 }
2879
2880 pub fn mark_class_count(&self) -> u16 {
2882 self.data.header().mark_class_count.get()
2883 }
2884
2885 pub fn mark_array_offset(&self) -> Offset16 {
2888 self.data.header().mark_array_offset.get()
2889 }
2890
2891 pub fn mark_array(&self) -> Result<MarkArray<'a>, ReadError> {
2893 let data = self.offset_data();
2894 self.mark_array_offset().resolve(data)
2895 }
2896
2897 pub fn ligature_array_offset(&self) -> Offset16 {
2900 self.data.header().ligature_array_offset.get()
2901 }
2902
2903 pub fn ligature_array(&self) -> Result<LigatureArray<'a>, ReadError> {
2905 let data = self.offset_data();
2906 let args = self.mark_class_count();
2907 self.ligature_array_offset().resolve_with_args(data, args)
2908 }
2909
2910 pub fn pos_format_byte_range(&self) -> Range<usize> {
2911 let start = 0;
2912 let end = start + u16::RAW_BYTE_LEN;
2913 start..end
2914 }
2915
2916 pub fn mark_coverage_offset_byte_range(&self) -> Range<usize> {
2917 let start = self.pos_format_byte_range().end;
2918 let end = start + Offset16::RAW_BYTE_LEN;
2919 start..end
2920 }
2921
2922 pub fn ligature_coverage_offset_byte_range(&self) -> Range<usize> {
2923 let start = self.mark_coverage_offset_byte_range().end;
2924 let end = start + Offset16::RAW_BYTE_LEN;
2925 start..end
2926 }
2927
2928 pub fn mark_class_count_byte_range(&self) -> Range<usize> {
2929 let start = self.ligature_coverage_offset_byte_range().end;
2930 let end = start + u16::RAW_BYTE_LEN;
2931 start..end
2932 }
2933
2934 pub fn mark_array_offset_byte_range(&self) -> Range<usize> {
2935 let start = self.mark_class_count_byte_range().end;
2936 let end = start + Offset16::RAW_BYTE_LEN;
2937 start..end
2938 }
2939
2940 pub fn ligature_array_offset_byte_range(&self) -> Range<usize> {
2941 let start = self.mark_array_offset_byte_range().end;
2942 let end = start + Offset16::RAW_BYTE_LEN;
2943 start..end
2944 }
2945}
2946
2947const _: () = assert!(FontData::default_data_long_enough(
2948 MarkLigPosFormat1::MIN_SIZE
2949));
2950
2951impl Default for MarkLigPosFormat1<'_> {
2952 fn default() -> Self {
2953 Self {
2954 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
2955 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2956 }
2957 }
2958}
2959
2960impl<'a> MinByteRange<'a> for LigatureArray<'a> {
2961 fn min_byte_range(&self) -> Range<usize> {
2962 0..self.ligature_attach_offsets_byte_range().end
2963 }
2964 fn min_table_bytes(&self) -> &'a [u8] {
2965 let range = self.min_byte_range();
2966 self.offset_data().as_bytes().get(range).unwrap_or_default()
2967 }
2968}
2969
2970impl ReadArgs for LigatureArray<'_> {
2971 type Args = u16;
2972}
2973
2974impl<'a> FontRead<'a> for LigatureArray<'a> {
2975 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
2976 let mark_class_count = args;
2977
2978 #[allow(clippy::absurd_extreme_comparisons)]
2979 if data.len() < Self::MIN_SIZE {
2980 return Err(ReadError::OutOfBounds);
2981 }
2982 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2983 return Err(ReadError::OutOfBounds);
2984 };
2985 Ok(Self {
2986 data,
2987 mark_class_count,
2988 })
2989 }
2990}
2991
2992impl<'a> LigatureArray<'a> {
2993 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
2998 let args = mark_class_count;
2999 Self::read_with_args(data, args)
3000 }
3001}
3002
3003#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3005#[repr(C, packed)]
3006#[doc(hidden)]
3007pub struct LigatureArrayFixedHeader {
3008 pub ligature_count: BigEndian<u16>,
3009}
3010
3011#[allow(clippy::absurd_extreme_comparisons)]
3012const _: () = assert!(std::mem::size_of::<LigatureArrayFixedHeader>() <= LigatureArray::MIN_SIZE);
3013
3014#[derive(Clone)]
3016pub struct LigatureArray<'a> {
3017 data: TableDataRef<'a, LigatureArrayFixedHeader>,
3018 mark_class_count: u16,
3019}
3020
3021#[allow(clippy::needless_lifetimes)]
3022impl<'a> LigatureArray<'a> {
3023 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
3024 basic_table_impls!(impl_the_methods);
3025
3026 pub fn ligature_count(&self) -> u16 {
3028 self.data.header().ligature_count.get()
3029 }
3030
3031 pub fn ligature_attach_offsets(&self) -> &'a [BigEndian<Offset16>] {
3035 let range = self.ligature_attach_offsets_byte_range();
3036 self.offset_data()
3037 .read_array(range)
3038 .ok()
3039 .unwrap_or_default()
3040 }
3041
3042 pub fn ligature_attaches(&self) -> ArrayOfOffsets<'a, LigatureAttach<'a>, Offset16> {
3044 let data = self.offset_data();
3045 let offsets = self.ligature_attach_offsets();
3046 let args = self.mark_class_count();
3047 ArrayOfOffsets::new(offsets, data, args)
3048 }
3049
3050 pub(crate) fn mark_class_count(&self) -> u16 {
3051 self.mark_class_count
3052 }
3053
3054 pub fn ligature_count_byte_range(&self) -> Range<usize> {
3055 let start = 0;
3056 let end = start + u16::RAW_BYTE_LEN;
3057 start..end
3058 }
3059
3060 pub fn ligature_attach_offsets_byte_range(&self) -> Range<usize> {
3061 let ligature_count = self.ligature_count();
3062 let start = self.ligature_count_byte_range().end;
3063 let end =
3064 start + (transforms::to_usize(ligature_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
3065 start..end
3066 }
3067}
3068
3069const _: () = assert!(FontData::default_data_long_enough(LigatureArray::MIN_SIZE));
3070
3071impl Default for LigatureArray<'_> {
3072 fn default() -> Self {
3073 Self {
3074 data: TableDataRef::new(FontData::default_table_data().as_bytes())
3075 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
3076 mark_class_count: Default::default(),
3077 }
3078 }
3079}
3080
3081impl<'a> MinByteRange<'a> for LigatureAttach<'a> {
3082 fn min_byte_range(&self) -> Range<usize> {
3083 0..self.component_records_byte_range().end
3084 }
3085 fn min_table_bytes(&self) -> &'a [u8] {
3086 let range = self.min_byte_range();
3087 self.offset_data().as_bytes().get(range).unwrap_or_default()
3088 }
3089}
3090
3091impl ReadArgs for LigatureAttach<'_> {
3092 type Args = u16;
3093}
3094
3095impl<'a> FontRead<'a> for LigatureAttach<'a> {
3096 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
3097 let mark_class_count = args;
3098
3099 #[allow(clippy::absurd_extreme_comparisons)]
3100 if data.len() < Self::MIN_SIZE {
3101 return Err(ReadError::OutOfBounds);
3102 }
3103 let Some(data) = TableDataRef::new(data.as_bytes()) else {
3104 return Err(ReadError::OutOfBounds);
3105 };
3106 Ok(Self {
3107 data,
3108 mark_class_count,
3109 })
3110 }
3111}
3112
3113impl<'a> LigatureAttach<'a> {
3114 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
3119 let args = mark_class_count;
3120 Self::read_with_args(data, args)
3121 }
3122}
3123
3124#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3126#[repr(C, packed)]
3127#[doc(hidden)]
3128pub struct LigatureAttachFixedHeader {
3129 pub component_count: BigEndian<u16>,
3130}
3131
3132#[allow(clippy::absurd_extreme_comparisons)]
3133const _: () = assert!(std::mem::size_of::<LigatureAttachFixedHeader>() <= LigatureAttach::MIN_SIZE);
3134
3135#[derive(Clone)]
3137pub struct LigatureAttach<'a> {
3138 data: TableDataRef<'a, LigatureAttachFixedHeader>,
3139 mark_class_count: u16,
3140}
3141
3142#[allow(clippy::needless_lifetimes)]
3143impl<'a> LigatureAttach<'a> {
3144 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
3145 basic_table_impls!(impl_the_methods);
3146
3147 pub fn component_count(&self) -> u16 {
3149 self.data.header().component_count.get()
3150 }
3151
3152 pub fn component_records(&self) -> ComputedArray<'a, ComponentRecord<'a>> {
3154 let range = self.component_records_byte_range();
3155 ComputedArray::new(self.offset_data(), range, self.mark_class_count()).unwrap_or_default()
3156 }
3157
3158 pub(crate) fn mark_class_count(&self) -> u16 {
3159 self.mark_class_count
3160 }
3161
3162 pub fn component_count_byte_range(&self) -> Range<usize> {
3163 let start = 0;
3164 let end = start + u16::RAW_BYTE_LEN;
3165 start..end
3166 }
3167
3168 pub fn component_records_byte_range(&self) -> Range<usize> {
3169 let component_count = self.component_count();
3170 let start = self.component_count_byte_range().end;
3171 let end = start
3172 + (transforms::to_usize(component_count)).saturating_mul(
3173 <ComponentRecord as ComputeSize>::compute_size(self.mark_class_count())
3174 .unwrap_or(0),
3175 );
3176 start..end
3177 }
3178}
3179
3180const _: () = assert!(FontData::default_data_long_enough(LigatureAttach::MIN_SIZE));
3181
3182impl Default for LigatureAttach<'_> {
3183 fn default() -> Self {
3184 Self {
3185 data: TableDataRef::new(FontData::default_table_data().as_bytes())
3186 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
3187 mark_class_count: Default::default(),
3188 }
3189 }
3190}
3191
3192#[derive(Clone, Debug)]
3194pub struct ComponentRecord<'a> {
3195 pub ligature_anchor_offsets: &'a [BigEndian<Nullable<Offset16>>],
3199}
3200
3201impl<'a> ComponentRecord<'a> {
3202 pub fn ligature_anchor_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
3206 self.ligature_anchor_offsets
3207 }
3208
3209 pub fn ligature_anchors(
3216 &self,
3217 data: FontData<'a>,
3218 ) -> ArrayOfNullableOffsets<'a, AnchorTable<'a>, Offset16> {
3219 let offsets = self.ligature_anchor_offsets();
3220 ArrayOfNullableOffsets::new(offsets, data, ())
3221 }
3222}
3223
3224impl ReadArgs for ComponentRecord<'_> {
3225 type Args = u16;
3226}
3227
3228impl ComputeSize for ComponentRecord<'_> {
3229 #[allow(clippy::needless_question_mark)]
3230 fn compute_size(args: u16) -> Result<usize, ReadError> {
3231 let mark_class_count = args;
3232 Ok((transforms::to_usize(mark_class_count)).saturating_mul(Offset16::RAW_BYTE_LEN))
3233 }
3234}
3235
3236impl<'a> FontRead<'a> for ComponentRecord<'a> {
3237 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
3238 let mut cursor = data.cursor();
3239 let mark_class_count = args;
3240 Ok(Self {
3241 ligature_anchor_offsets: cursor.read_array(transforms::to_usize(mark_class_count))?,
3242 })
3243 }
3244}
3245
3246crate::impl_font_read_at!(ComponentRecord<'a>);
3247
3248#[allow(clippy::needless_lifetimes)]
3249impl<'a> ComponentRecord<'a> {
3250 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
3255 let args = mark_class_count;
3256 Self::read_with_args(data, args)
3257 }
3258}
3259
3260impl Format<u16> for MarkMarkPosFormat1<'_> {
3261 const FORMAT: u16 = 1;
3262}
3263
3264impl<'a> MinByteRange<'a> for MarkMarkPosFormat1<'a> {
3265 fn min_byte_range(&self) -> Range<usize> {
3266 0..self.mark2_array_offset_byte_range().end
3267 }
3268 fn min_table_bytes(&self) -> &'a [u8] {
3269 let range = self.min_byte_range();
3270 self.offset_data().as_bytes().get(range).unwrap_or_default()
3271 }
3272}
3273
3274impl ReadArgs for MarkMarkPosFormat1<'_> {
3275 type Args = ();
3276}
3277
3278impl<'a> FontRead<'a> for MarkMarkPosFormat1<'a> {
3279 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3280 #[allow(clippy::absurd_extreme_comparisons)]
3281 if data.len() < Self::MIN_SIZE {
3282 return Err(ReadError::OutOfBounds);
3283 }
3284 let Some(data) = TableDataRef::new(data.as_bytes()) else {
3285 return Err(ReadError::OutOfBounds);
3286 };
3287 Ok(Self { data })
3288 }
3289}
3290
3291#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3293#[repr(C, packed)]
3294#[doc(hidden)]
3295pub struct MarkMarkPosFormat1FixedHeader {
3296 pub pos_format: BigEndian<u16>,
3297 pub mark1_coverage_offset: BigEndian<Offset16>,
3298 pub mark2_coverage_offset: BigEndian<Offset16>,
3299 pub mark_class_count: BigEndian<u16>,
3300 pub mark1_array_offset: BigEndian<Offset16>,
3301 pub mark2_array_offset: BigEndian<Offset16>,
3302}
3303
3304#[allow(clippy::absurd_extreme_comparisons)]
3305const _: () =
3306 assert!(std::mem::size_of::<MarkMarkPosFormat1FixedHeader>() <= MarkMarkPosFormat1::MIN_SIZE);
3307
3308#[derive(Clone)]
3310pub struct MarkMarkPosFormat1<'a> {
3311 data: TableDataRef<'a, MarkMarkPosFormat1FixedHeader>,
3312}
3313
3314#[allow(clippy::needless_lifetimes)]
3315impl<'a> MarkMarkPosFormat1<'a> {
3316 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
3317 + Offset16::RAW_BYTE_LEN
3318 + Offset16::RAW_BYTE_LEN
3319 + u16::RAW_BYTE_LEN
3320 + Offset16::RAW_BYTE_LEN
3321 + Offset16::RAW_BYTE_LEN);
3322 basic_table_impls!(impl_the_methods);
3323
3324 pub fn pos_format(&self) -> u16 {
3326 self.data.header().pos_format.get()
3327 }
3328
3329 pub fn mark1_coverage_offset(&self) -> Offset16 {
3332 self.data.header().mark1_coverage_offset.get()
3333 }
3334
3335 pub fn mark1_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
3337 let data = self.offset_data();
3338 self.mark1_coverage_offset().resolve(data)
3339 }
3340
3341 pub fn mark2_coverage_offset(&self) -> Offset16 {
3344 self.data.header().mark2_coverage_offset.get()
3345 }
3346
3347 pub fn mark2_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
3349 let data = self.offset_data();
3350 self.mark2_coverage_offset().resolve(data)
3351 }
3352
3353 pub fn mark_class_count(&self) -> u16 {
3355 self.data.header().mark_class_count.get()
3356 }
3357
3358 pub fn mark1_array_offset(&self) -> Offset16 {
3361 self.data.header().mark1_array_offset.get()
3362 }
3363
3364 pub fn mark1_array(&self) -> Result<MarkArray<'a>, ReadError> {
3366 let data = self.offset_data();
3367 self.mark1_array_offset().resolve(data)
3368 }
3369
3370 pub fn mark2_array_offset(&self) -> Offset16 {
3373 self.data.header().mark2_array_offset.get()
3374 }
3375
3376 pub fn mark2_array(&self) -> Result<Mark2Array<'a>, ReadError> {
3378 let data = self.offset_data();
3379 let args = self.mark_class_count();
3380 self.mark2_array_offset().resolve_with_args(data, args)
3381 }
3382
3383 pub fn pos_format_byte_range(&self) -> Range<usize> {
3384 let start = 0;
3385 let end = start + u16::RAW_BYTE_LEN;
3386 start..end
3387 }
3388
3389 pub fn mark1_coverage_offset_byte_range(&self) -> Range<usize> {
3390 let start = self.pos_format_byte_range().end;
3391 let end = start + Offset16::RAW_BYTE_LEN;
3392 start..end
3393 }
3394
3395 pub fn mark2_coverage_offset_byte_range(&self) -> Range<usize> {
3396 let start = self.mark1_coverage_offset_byte_range().end;
3397 let end = start + Offset16::RAW_BYTE_LEN;
3398 start..end
3399 }
3400
3401 pub fn mark_class_count_byte_range(&self) -> Range<usize> {
3402 let start = self.mark2_coverage_offset_byte_range().end;
3403 let end = start + u16::RAW_BYTE_LEN;
3404 start..end
3405 }
3406
3407 pub fn mark1_array_offset_byte_range(&self) -> Range<usize> {
3408 let start = self.mark_class_count_byte_range().end;
3409 let end = start + Offset16::RAW_BYTE_LEN;
3410 start..end
3411 }
3412
3413 pub fn mark2_array_offset_byte_range(&self) -> Range<usize> {
3414 let start = self.mark1_array_offset_byte_range().end;
3415 let end = start + Offset16::RAW_BYTE_LEN;
3416 start..end
3417 }
3418}
3419
3420const _: () = assert!(FontData::default_data_long_enough(
3421 MarkMarkPosFormat1::MIN_SIZE
3422));
3423
3424impl Default for MarkMarkPosFormat1<'_> {
3425 fn default() -> Self {
3426 Self {
3427 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
3428 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
3429 }
3430 }
3431}
3432
3433impl<'a> MinByteRange<'a> for Mark2Array<'a> {
3434 fn min_byte_range(&self) -> Range<usize> {
3435 0..self.mark2_records_byte_range().end
3436 }
3437 fn min_table_bytes(&self) -> &'a [u8] {
3438 let range = self.min_byte_range();
3439 self.offset_data().as_bytes().get(range).unwrap_or_default()
3440 }
3441}
3442
3443impl ReadArgs for Mark2Array<'_> {
3444 type Args = u16;
3445}
3446
3447impl<'a> FontRead<'a> for Mark2Array<'a> {
3448 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
3449 let mark_class_count = args;
3450
3451 #[allow(clippy::absurd_extreme_comparisons)]
3452 if data.len() < Self::MIN_SIZE {
3453 return Err(ReadError::OutOfBounds);
3454 }
3455 let Some(data) = TableDataRef::new(data.as_bytes()) else {
3456 return Err(ReadError::OutOfBounds);
3457 };
3458 Ok(Self {
3459 data,
3460 mark_class_count,
3461 })
3462 }
3463}
3464
3465impl<'a> Mark2Array<'a> {
3466 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
3471 let args = mark_class_count;
3472 Self::read_with_args(data, args)
3473 }
3474}
3475
3476#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3478#[repr(C, packed)]
3479#[doc(hidden)]
3480pub struct Mark2ArrayFixedHeader {
3481 pub mark2_count: BigEndian<u16>,
3482}
3483
3484#[allow(clippy::absurd_extreme_comparisons)]
3485const _: () = assert!(std::mem::size_of::<Mark2ArrayFixedHeader>() <= Mark2Array::MIN_SIZE);
3486
3487#[derive(Clone)]
3489pub struct Mark2Array<'a> {
3490 data: TableDataRef<'a, Mark2ArrayFixedHeader>,
3491 mark_class_count: u16,
3492}
3493
3494#[allow(clippy::needless_lifetimes)]
3495impl<'a> Mark2Array<'a> {
3496 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
3497 basic_table_impls!(impl_the_methods);
3498
3499 pub fn mark2_count(&self) -> u16 {
3501 self.data.header().mark2_count.get()
3502 }
3503
3504 pub fn mark2_records(&self) -> ComputedArray<'a, Mark2Record<'a>> {
3506 let range = self.mark2_records_byte_range();
3507 ComputedArray::new(self.offset_data(), range, self.mark_class_count()).unwrap_or_default()
3508 }
3509
3510 pub(crate) fn mark_class_count(&self) -> u16 {
3511 self.mark_class_count
3512 }
3513
3514 pub fn mark2_count_byte_range(&self) -> Range<usize> {
3515 let start = 0;
3516 let end = start + u16::RAW_BYTE_LEN;
3517 start..end
3518 }
3519
3520 pub fn mark2_records_byte_range(&self) -> Range<usize> {
3521 let mark2_count = self.mark2_count();
3522 let start = self.mark2_count_byte_range().end;
3523 let end = start
3524 + (transforms::to_usize(mark2_count)).saturating_mul(
3525 <Mark2Record as ComputeSize>::compute_size(self.mark_class_count()).unwrap_or(0),
3526 );
3527 start..end
3528 }
3529}
3530
3531const _: () = assert!(FontData::default_data_long_enough(Mark2Array::MIN_SIZE));
3532
3533impl Default for Mark2Array<'_> {
3534 fn default() -> Self {
3535 Self {
3536 data: TableDataRef::new(FontData::default_table_data().as_bytes())
3537 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
3538 mark_class_count: Default::default(),
3539 }
3540 }
3541}
3542
3543#[derive(Clone, Debug)]
3545pub struct Mark2Record<'a> {
3546 pub mark2_anchor_offsets: &'a [BigEndian<Nullable<Offset16>>],
3550}
3551
3552impl<'a> Mark2Record<'a> {
3553 pub fn mark2_anchor_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
3557 self.mark2_anchor_offsets
3558 }
3559
3560 pub fn mark2_anchors(
3567 &self,
3568 data: FontData<'a>,
3569 ) -> ArrayOfNullableOffsets<'a, AnchorTable<'a>, Offset16> {
3570 let offsets = self.mark2_anchor_offsets();
3571 ArrayOfNullableOffsets::new(offsets, data, ())
3572 }
3573}
3574
3575impl ReadArgs for Mark2Record<'_> {
3576 type Args = u16;
3577}
3578
3579impl ComputeSize for Mark2Record<'_> {
3580 #[allow(clippy::needless_question_mark)]
3581 fn compute_size(args: u16) -> Result<usize, ReadError> {
3582 let mark_class_count = args;
3583 Ok((transforms::to_usize(mark_class_count)).saturating_mul(Offset16::RAW_BYTE_LEN))
3584 }
3585}
3586
3587impl<'a> FontRead<'a> for Mark2Record<'a> {
3588 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
3589 let mut cursor = data.cursor();
3590 let mark_class_count = args;
3591 Ok(Self {
3592 mark2_anchor_offsets: cursor.read_array(transforms::to_usize(mark_class_count))?,
3593 })
3594 }
3595}
3596
3597crate::impl_font_read_at!(Mark2Record<'a>);
3598
3599#[allow(clippy::needless_lifetimes)]
3600impl<'a> Mark2Record<'a> {
3601 pub fn read(data: FontData<'a>, mark_class_count: u16) -> Result<Self, ReadError> {
3606 let args = mark_class_count;
3607 Self::read_with_args(data, args)
3608 }
3609}
3610
3611impl Format<u16> for ExtensionPosFormat1<'_> {
3612 const FORMAT: u16 = 1;
3613}
3614
3615impl Discriminant for ExtensionPosFormat1<'_, ()> {
3616 fn read_discriminant(data: FontData<'_>) -> Result<u16, ReadError> {
3617 data.read_at(u16::RAW_BYTE_LEN)
3618 }
3619}
3620
3621impl<'a, T> MinByteRange<'a> for ExtensionPosFormat1<'a, T> {
3622 fn min_byte_range(&self) -> Range<usize> {
3623 0..self.extension_offset_byte_range().end
3624 }
3625 fn min_table_bytes(&self) -> &'a [u8] {
3626 let range = self.min_byte_range();
3627 self.offset_data().as_bytes().get(range).unwrap_or_default()
3628 }
3629}
3630
3631impl<T> ReadArgs for ExtensionPosFormat1<'_, T> {
3632 type Args = ();
3633}
3634
3635impl<'a, T> FontRead<'a> for ExtensionPosFormat1<'a, T> {
3636 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3637 #[allow(clippy::absurd_extreme_comparisons)]
3638 if data.len() < Self::MIN_SIZE {
3639 return Err(ReadError::OutOfBounds);
3640 }
3641 let Some(data) = TableDataRef::new(data.as_bytes()) else {
3642 return Err(ReadError::OutOfBounds);
3643 };
3644 Ok(Self {
3645 data,
3646 offset_type: std::marker::PhantomData,
3647 })
3648 }
3649}
3650
3651impl<'a, T> ExtensionPosFormat1<'a, T> {
3652 #[allow(dead_code)]
3653 pub(crate) fn of_unit_type(&self) -> ExtensionPosFormat1<'a, ()> {
3655 ExtensionPosFormat1 {
3656 data: self.data,
3657 offset_type: std::marker::PhantomData,
3658 }
3659 }
3660}
3661
3662#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
3664#[repr(C, packed)]
3665#[doc(hidden)]
3666pub struct ExtensionPosFormat1FixedHeader {
3667 pub pos_format: BigEndian<u16>,
3668 pub extension_lookup_type: BigEndian<u16>,
3669 pub extension_offset: BigEndian<Offset32>,
3670}
3671
3672#[allow(clippy::absurd_extreme_comparisons)]
3673const _: () = assert!(
3674 std::mem::size_of::<ExtensionPosFormat1FixedHeader>() <= ExtensionPosFormat1::<()>::MIN_SIZE
3675);
3676
3677#[derive(Clone)]
3679pub struct ExtensionPosFormat1<'a, T = ()> {
3680 data: TableDataRef<'a, ExtensionPosFormat1FixedHeader>,
3681 offset_type: std::marker::PhantomData<*const T>,
3682}
3683
3684#[allow(clippy::needless_lifetimes)]
3685impl<'a, T> ExtensionPosFormat1<'a, T> {
3686 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN);
3687 basic_table_impls!(impl_the_methods);
3688
3689 pub fn pos_format(&self) -> u16 {
3691 self.data.header().pos_format.get()
3692 }
3693
3694 pub fn extension_lookup_type(&self) -> u16 {
3697 self.data.header().extension_lookup_type.get()
3698 }
3699
3700 pub fn extension_offset(&self) -> Offset32 {
3704 self.data.header().extension_offset.get()
3705 }
3706
3707 pub fn extension(&self) -> Result<T, ReadError>
3709 where
3710 T: FontRead<'a, Args = ()>,
3711 {
3712 let data = self.offset_data();
3713 self.extension_offset().resolve(data)
3714 }
3715
3716 pub fn pos_format_byte_range(&self) -> Range<usize> {
3717 let start = 0;
3718 let end = start + u16::RAW_BYTE_LEN;
3719 start..end
3720 }
3721
3722 pub fn extension_lookup_type_byte_range(&self) -> Range<usize> {
3723 let start = self.pos_format_byte_range().end;
3724 let end = start + u16::RAW_BYTE_LEN;
3725 start..end
3726 }
3727
3728 pub fn extension_offset_byte_range(&self) -> Range<usize> {
3729 let start = self.extension_lookup_type_byte_range().end;
3730 let end = start + Offset32::RAW_BYTE_LEN;
3731 start..end
3732 }
3733}
3734
3735const _: () = assert!(FontData::default_data_long_enough(
3736 ExtensionPosFormat1::<()>::MIN_SIZE
3737));
3738
3739impl<T> Default for ExtensionPosFormat1<'_, T> {
3740 fn default() -> Self {
3741 Self {
3742 data: TableDataRef::new(FontData::default_format_1_u16_table_data().as_bytes())
3743 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
3744 offset_type: std::marker::PhantomData,
3745 }
3746 }
3747}
3748
3749pub enum ExtensionSubtable<'a> {
3751 Single(ExtensionPosFormat1<'a, SinglePos<'a>>),
3752 Pair(ExtensionPosFormat1<'a, PairPos<'a>>),
3753 Cursive(ExtensionPosFormat1<'a, CursivePosFormat1<'a>>),
3754 MarkToBase(ExtensionPosFormat1<'a, MarkBasePosFormat1<'a>>),
3755 MarkToLig(ExtensionPosFormat1<'a, MarkLigPosFormat1<'a>>),
3756 MarkToMark(ExtensionPosFormat1<'a, MarkMarkPosFormat1<'a>>),
3757 Contextual(ExtensionPosFormat1<'a, PositionSequenceContext<'a>>),
3758 ChainContextual(ExtensionPosFormat1<'a, PositionChainContext<'a>>),
3759}
3760
3761impl Default for ExtensionSubtable<'_> {
3762 fn default() -> Self {
3763 Self::Single(Default::default())
3764 }
3765}
3766
3767impl ReadArgs for ExtensionSubtable<'_> {
3768 type Args = ();
3769}
3770
3771impl<'a> FontRead<'a> for ExtensionSubtable<'a> {
3772 fn read_with_args(bytes: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3773 let discriminant = ExtensionPosFormat1::read_discriminant(bytes)?;
3774 match discriminant {
3775 1 => Ok(ExtensionSubtable::Single(FontRead::read(bytes)?)),
3776 2 => Ok(ExtensionSubtable::Pair(FontRead::read(bytes)?)),
3777 3 => Ok(ExtensionSubtable::Cursive(FontRead::read(bytes)?)),
3778 4 => Ok(ExtensionSubtable::MarkToBase(FontRead::read(bytes)?)),
3779 5 => Ok(ExtensionSubtable::MarkToLig(FontRead::read(bytes)?)),
3780 6 => Ok(ExtensionSubtable::MarkToMark(FontRead::read(bytes)?)),
3781 7 => Ok(ExtensionSubtable::Contextual(FontRead::read(bytes)?)),
3782 8 => Ok(ExtensionSubtable::ChainContextual(FontRead::read(bytes)?)),
3783 other => Err(ReadError::InvalidFormat(other.into())),
3784 }
3785 }
3786}
3787
3788impl<'a> ExtensionSubtable<'a> {
3789 #[allow(dead_code)]
3790 pub(crate) fn of_unit_type(&self) -> ExtensionPosFormat1<'a, ()> {
3794 match self {
3795 ExtensionSubtable::Single(inner) => inner.of_unit_type(),
3796 ExtensionSubtable::Pair(inner) => inner.of_unit_type(),
3797 ExtensionSubtable::Cursive(inner) => inner.of_unit_type(),
3798 ExtensionSubtable::MarkToBase(inner) => inner.of_unit_type(),
3799 ExtensionSubtable::MarkToLig(inner) => inner.of_unit_type(),
3800 ExtensionSubtable::MarkToMark(inner) => inner.of_unit_type(),
3801 ExtensionSubtable::Contextual(inner) => inner.of_unit_type(),
3802 ExtensionSubtable::ChainContextual(inner) => inner.of_unit_type(),
3803 }
3804 }
3805}