1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for TupleVariationHeader<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.intermediate_end_tuple_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 ReadArgs for TupleVariationHeader<'_> {
19 type Args = u16;
20}
21
22impl<'a> FontRead<'a> for TupleVariationHeader<'a> {
23 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
24 let axis_count = args;
25
26 #[allow(clippy::absurd_extreme_comparisons)]
27 if data.len() < Self::MIN_SIZE {
28 return Err(ReadError::OutOfBounds);
29 }
30 let Some(data) = TableDataRef::new(data.as_bytes()) else {
31 return Err(ReadError::OutOfBounds);
32 };
33 Ok(Self { data, axis_count })
34 }
35}
36
37impl<'a> TupleVariationHeader<'a> {
38 pub fn read(data: FontData<'a>, axis_count: u16) -> Result<Self, ReadError> {
43 let args = axis_count;
44 Self::read_with_args(data, args)
45 }
46}
47
48#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
50#[repr(C, packed)]
51#[doc(hidden)]
52pub struct TupleVariationHeaderFixedHeader {
53 pub variation_data_size: BigEndian<u16>,
54 pub tuple_index: BigEndian<TupleIndex>,
55}
56
57#[allow(clippy::absurd_extreme_comparisons)]
58const _: () = assert!(
59 std::mem::size_of::<TupleVariationHeaderFixedHeader>() <= TupleVariationHeader::MIN_SIZE
60);
61
62#[derive(Clone)]
64pub struct TupleVariationHeader<'a> {
65 data: TableDataRef<'a, TupleVariationHeaderFixedHeader>,
66 axis_count: u16,
67}
68
69#[allow(clippy::needless_lifetimes)]
70impl<'a> TupleVariationHeader<'a> {
71 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + TupleIndex::RAW_BYTE_LEN);
72 basic_table_impls!(impl_the_methods);
73
74 pub fn variation_data_size(&self) -> u16 {
77 self.data.header().variation_data_size.get()
78 }
79
80 pub fn tuple_index(&self) -> TupleIndex {
83 self.data.header().tuple_index.get()
84 }
85
86 pub(crate) fn axis_count(&self) -> u16 {
87 self.axis_count
88 }
89
90 pub fn variation_data_size_byte_range(&self) -> Range<usize> {
91 let start = 0;
92 let end = start + u16::RAW_BYTE_LEN;
93 start..end
94 }
95
96 pub fn tuple_index_byte_range(&self) -> Range<usize> {
97 let start = self.variation_data_size_byte_range().end;
98 let end = start + TupleIndex::RAW_BYTE_LEN;
99 start..end
100 }
101
102 pub fn peak_tuple_byte_range(&self) -> Range<usize> {
103 let tuple_index = self.tuple_index();
104 let axis_count = self.axis_count();
105 let start = self.tuple_index_byte_range().end;
106 let end = start
107 + (TupleIndex::tuple_len(tuple_index, axis_count, 0_usize))
108 .saturating_mul(F2Dot14::RAW_BYTE_LEN);
109 start..end
110 }
111
112 pub fn intermediate_start_tuple_byte_range(&self) -> Range<usize> {
113 let tuple_index = self.tuple_index();
114 let axis_count = self.axis_count();
115 let start = self.peak_tuple_byte_range().end;
116 let end = start
117 + (TupleIndex::tuple_len(tuple_index, axis_count, 1_usize))
118 .saturating_mul(F2Dot14::RAW_BYTE_LEN);
119 start..end
120 }
121
122 pub fn intermediate_end_tuple_byte_range(&self) -> Range<usize> {
123 let tuple_index = self.tuple_index();
124 let axis_count = self.axis_count();
125 let start = self.intermediate_start_tuple_byte_range().end;
126 let end = start
127 + (TupleIndex::tuple_len(tuple_index, axis_count, 1_usize))
128 .saturating_mul(F2Dot14::RAW_BYTE_LEN);
129 start..end
130 }
131}
132
133const _: () = assert!(FontData::default_data_long_enough(
134 TupleVariationHeader::MIN_SIZE
135));
136
137impl Default for TupleVariationHeader<'_> {
138 fn default() -> Self {
139 Self {
140 data: TableDataRef::new(FontData::default_table_data().as_bytes())
141 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
142 axis_count: Default::default(),
143 }
144 }
145}
146
147#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
153pub struct Tuple<'a> {
154 pub values: &'a [BigEndian<F2Dot14>],
159}
160
161impl<'a> Tuple<'a> {
162 pub fn values(&self) -> &'a [BigEndian<F2Dot14>] {
167 self.values
168 }
169}
170
171impl ReadArgs for Tuple<'_> {
172 type Args = u16;
173}
174
175impl ComputeSize for Tuple<'_> {
176 #[allow(clippy::needless_question_mark)]
177 fn compute_size(args: u16) -> Result<usize, ReadError> {
178 let axis_count = args;
179 Ok((transforms::to_usize(axis_count)).saturating_mul(F2Dot14::RAW_BYTE_LEN))
180 }
181}
182
183impl<'a> FontRead<'a> for Tuple<'a> {
184 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
185 let mut cursor = data.cursor();
186 let axis_count = args;
187 Ok(Self {
188 values: cursor.read_array(transforms::to_usize(axis_count))?,
189 })
190 }
191}
192
193crate::impl_font_read_at!(Tuple<'a>);
194
195#[allow(clippy::needless_lifetimes)]
196impl<'a> Tuple<'a> {
197 pub fn read(data: FontData<'a>, axis_count: u16) -> Result<Self, ReadError> {
202 let args = axis_count;
203 Self::read_with_args(data, args)
204 }
205}
206
207impl Format<u8> for DeltaSetIndexMapFormat0<'_> {
208 const FORMAT: u8 = 0;
209}
210
211impl<'a> MinByteRange<'a> for DeltaSetIndexMapFormat0<'a> {
212 fn min_byte_range(&self) -> Range<usize> {
213 0..self.map_data_byte_range().end
214 }
215 fn min_table_bytes(&self) -> &'a [u8] {
216 let range = self.min_byte_range();
217 self.offset_data().as_bytes().get(range).unwrap_or_default()
218 }
219}
220
221impl ReadArgs for DeltaSetIndexMapFormat0<'_> {
222 type Args = ();
223}
224
225impl<'a> FontRead<'a> for DeltaSetIndexMapFormat0<'a> {
226 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
227 #[allow(clippy::absurd_extreme_comparisons)]
228 if data.len() < Self::MIN_SIZE {
229 return Err(ReadError::OutOfBounds);
230 }
231 let Some(data) = TableDataRef::new(data.as_bytes()) else {
232 return Err(ReadError::OutOfBounds);
233 };
234 Ok(Self { data })
235 }
236}
237
238#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
240#[repr(C, packed)]
241#[doc(hidden)]
242pub struct DeltaSetIndexMapFormat0FixedHeader {
243 pub format: u8,
244 pub entry_format: BigEndian<EntryFormat>,
245 pub map_count: BigEndian<u16>,
246}
247
248#[allow(clippy::absurd_extreme_comparisons)]
249const _: () = assert!(
250 std::mem::size_of::<DeltaSetIndexMapFormat0FixedHeader>() <= DeltaSetIndexMapFormat0::MIN_SIZE
251);
252
253#[derive(Clone)]
255pub struct DeltaSetIndexMapFormat0<'a> {
256 data: TableDataRef<'a, DeltaSetIndexMapFormat0FixedHeader>,
257}
258
259#[allow(clippy::needless_lifetimes)]
260impl<'a> DeltaSetIndexMapFormat0<'a> {
261 pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + EntryFormat::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
262 basic_table_impls!(impl_the_methods);
263
264 pub fn format(&self) -> u8 {
266 self.data.header().format
267 }
268
269 pub fn entry_format(&self) -> EntryFormat {
272 self.data.header().entry_format.get()
273 }
274
275 pub fn map_count(&self) -> u16 {
277 self.data.header().map_count.get()
278 }
279
280 pub fn map_data(&self) -> &'a [u8] {
282 let range = self.map_data_byte_range();
283 self.offset_data()
284 .read_array(range)
285 .ok()
286 .unwrap_or_default()
287 }
288
289 pub fn format_byte_range(&self) -> Range<usize> {
290 let start = 0;
291 let end = start + u8::RAW_BYTE_LEN;
292 start..end
293 }
294
295 pub fn entry_format_byte_range(&self) -> Range<usize> {
296 let start = self.format_byte_range().end;
297 let end = start + EntryFormat::RAW_BYTE_LEN;
298 start..end
299 }
300
301 pub fn map_count_byte_range(&self) -> Range<usize> {
302 let start = self.entry_format_byte_range().end;
303 let end = start + u16::RAW_BYTE_LEN;
304 start..end
305 }
306
307 pub fn map_data_byte_range(&self) -> Range<usize> {
308 let entry_format = self.entry_format();
309 let map_count = self.map_count();
310 let start = self.map_count_byte_range().end;
311 let end = start
312 + (EntryFormat::map_size(entry_format, map_count)).saturating_mul(u8::RAW_BYTE_LEN);
313 start..end
314 }
315}
316
317const _: () = assert!(FontData::default_data_long_enough(
318 DeltaSetIndexMapFormat0::MIN_SIZE
319));
320
321impl Default for DeltaSetIndexMapFormat0<'_> {
322 fn default() -> Self {
323 Self {
324 data: TableDataRef::new(FontData::default_table_data().as_bytes())
325 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
326 }
327 }
328}
329
330impl Format<u8> for DeltaSetIndexMapFormat1<'_> {
331 const FORMAT: u8 = 1;
332}
333
334impl<'a> MinByteRange<'a> for DeltaSetIndexMapFormat1<'a> {
335 fn min_byte_range(&self) -> Range<usize> {
336 0..self.map_data_byte_range().end
337 }
338 fn min_table_bytes(&self) -> &'a [u8] {
339 let range = self.min_byte_range();
340 self.offset_data().as_bytes().get(range).unwrap_or_default()
341 }
342}
343
344impl ReadArgs for DeltaSetIndexMapFormat1<'_> {
345 type Args = ();
346}
347
348impl<'a> FontRead<'a> for DeltaSetIndexMapFormat1<'a> {
349 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
350 #[allow(clippy::absurd_extreme_comparisons)]
351 if data.len() < Self::MIN_SIZE {
352 return Err(ReadError::OutOfBounds);
353 }
354 let Some(data) = TableDataRef::new(data.as_bytes()) else {
355 return Err(ReadError::OutOfBounds);
356 };
357 Ok(Self { data })
358 }
359}
360
361#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
363#[repr(C, packed)]
364#[doc(hidden)]
365pub struct DeltaSetIndexMapFormat1FixedHeader {
366 pub format: u8,
367 pub entry_format: BigEndian<EntryFormat>,
368 pub map_count: BigEndian<u32>,
369}
370
371#[allow(clippy::absurd_extreme_comparisons)]
372const _: () = assert!(
373 std::mem::size_of::<DeltaSetIndexMapFormat1FixedHeader>() <= DeltaSetIndexMapFormat1::MIN_SIZE
374);
375
376#[derive(Clone)]
378pub struct DeltaSetIndexMapFormat1<'a> {
379 data: TableDataRef<'a, DeltaSetIndexMapFormat1FixedHeader>,
380}
381
382#[allow(clippy::needless_lifetimes)]
383impl<'a> DeltaSetIndexMapFormat1<'a> {
384 pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + EntryFormat::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
385 basic_table_impls!(impl_the_methods);
386
387 pub fn format(&self) -> u8 {
389 self.data.header().format
390 }
391
392 pub fn entry_format(&self) -> EntryFormat {
395 self.data.header().entry_format.get()
396 }
397
398 pub fn map_count(&self) -> u32 {
400 self.data.header().map_count.get()
401 }
402
403 pub fn map_data(&self) -> &'a [u8] {
405 let range = self.map_data_byte_range();
406 self.offset_data()
407 .read_array(range)
408 .ok()
409 .unwrap_or_default()
410 }
411
412 pub fn format_byte_range(&self) -> Range<usize> {
413 let start = 0;
414 let end = start + u8::RAW_BYTE_LEN;
415 start..end
416 }
417
418 pub fn entry_format_byte_range(&self) -> Range<usize> {
419 let start = self.format_byte_range().end;
420 let end = start + EntryFormat::RAW_BYTE_LEN;
421 start..end
422 }
423
424 pub fn map_count_byte_range(&self) -> Range<usize> {
425 let start = self.entry_format_byte_range().end;
426 let end = start + u32::RAW_BYTE_LEN;
427 start..end
428 }
429
430 pub fn map_data_byte_range(&self) -> Range<usize> {
431 let entry_format = self.entry_format();
432 let map_count = self.map_count();
433 let start = self.map_count_byte_range().end;
434 let end = start
435 + (EntryFormat::map_size(entry_format, map_count)).saturating_mul(u8::RAW_BYTE_LEN);
436 start..end
437 }
438}
439
440const _: () = assert!(FontData::default_data_long_enough(
441 DeltaSetIndexMapFormat1::MIN_SIZE
442));
443
444impl Default for DeltaSetIndexMapFormat1<'_> {
445 fn default() -> Self {
446 Self {
447 data: TableDataRef::new(FontData::default_format_1_u8_table_data().as_bytes())
448 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
449 }
450 }
451}
452
453#[derive(Clone)]
455pub enum DeltaSetIndexMap<'a> {
456 Format0(DeltaSetIndexMapFormat0<'a>),
457 Format1(DeltaSetIndexMapFormat1<'a>),
458}
459
460impl Default for DeltaSetIndexMap<'_> {
461 fn default() -> Self {
462 Self::Format0(Default::default())
463 }
464}
465
466impl<'a> DeltaSetIndexMap<'a> {
467 pub fn offset_data(&self) -> FontData<'a> {
469 match self {
470 Self::Format0(item) => item.offset_data(),
471 Self::Format1(item) => item.offset_data(),
472 }
473 }
474
475 pub fn format(&self) -> u8 {
477 match self {
478 Self::Format0(item) => item.format(),
479 Self::Format1(item) => item.format(),
480 }
481 }
482
483 pub fn entry_format(&self) -> EntryFormat {
486 match self {
487 Self::Format0(item) => item.entry_format(),
488 Self::Format1(item) => item.entry_format(),
489 }
490 }
491
492 pub fn map_data(&self) -> &'a [u8] {
494 match self {
495 Self::Format0(item) => item.map_data(),
496 Self::Format1(item) => item.map_data(),
497 }
498 }
499}
500
501impl ReadArgs for DeltaSetIndexMap<'_> {
502 type Args = ();
503}
504
505impl<'a> FontRead<'a> for DeltaSetIndexMap<'a> {
506 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
507 let format: u8 = data.read_at(0usize)?;
508 match format {
509 DeltaSetIndexMapFormat0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
510 DeltaSetIndexMapFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
511 other => Err(ReadError::InvalidFormat(other.into())),
512 }
513 }
514}
515
516impl<'a> MinByteRange<'a> for DeltaSetIndexMap<'a> {
517 fn min_byte_range(&self) -> Range<usize> {
518 match self {
519 Self::Format0(item) => item.min_byte_range(),
520 Self::Format1(item) => item.min_byte_range(),
521 }
522 }
523 fn min_table_bytes(&self) -> &'a [u8] {
524 match self {
525 Self::Format0(item) => item.min_table_bytes(),
526 Self::Format1(item) => item.min_table_bytes(),
527 }
528 }
529}
530
531#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
533#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
534#[repr(transparent)]
535pub struct EntryFormat {
536 bits: u8,
537}
538
539impl EntryFormat {
540 pub const INNER_INDEX_BIT_COUNT_MASK: Self = Self { bits: 0x0F };
542
543 pub const MAP_ENTRY_SIZE_MASK: Self = Self { bits: 0x30 };
545}
546
547impl EntryFormat {
548 #[inline]
550 pub const fn empty() -> Self {
551 Self { bits: 0 }
552 }
553
554 #[inline]
556 pub const fn all() -> Self {
557 Self {
558 bits: Self::INNER_INDEX_BIT_COUNT_MASK.bits | Self::MAP_ENTRY_SIZE_MASK.bits,
559 }
560 }
561
562 #[inline]
564 pub const fn bits(&self) -> u8 {
565 self.bits
566 }
567
568 #[inline]
571 pub const fn from_bits(bits: u8) -> Option<Self> {
572 if (bits & !Self::all().bits()) == 0 {
573 Some(Self { bits })
574 } else {
575 None
576 }
577 }
578
579 #[inline]
582 pub const fn from_bits_truncate(bits: u8) -> Self {
583 Self {
584 bits: bits & Self::all().bits,
585 }
586 }
587
588 #[inline]
590 pub const fn is_empty(&self) -> bool {
591 self.bits() == Self::empty().bits()
592 }
593
594 #[inline]
596 pub const fn intersects(&self, other: Self) -> bool {
597 !(Self {
598 bits: self.bits & other.bits,
599 })
600 .is_empty()
601 }
602
603 #[inline]
605 pub const fn contains(&self, other: Self) -> bool {
606 (self.bits & other.bits) == other.bits
607 }
608
609 #[inline]
611 pub fn insert(&mut self, other: Self) {
612 self.bits |= other.bits;
613 }
614
615 #[inline]
617 pub fn remove(&mut self, other: Self) {
618 self.bits &= !other.bits;
619 }
620
621 #[inline]
623 pub fn toggle(&mut self, other: Self) {
624 self.bits ^= other.bits;
625 }
626
627 #[inline]
638 #[must_use]
639 pub const fn intersection(self, other: Self) -> Self {
640 Self {
641 bits: self.bits & other.bits,
642 }
643 }
644
645 #[inline]
656 #[must_use]
657 pub const fn union(self, other: Self) -> Self {
658 Self {
659 bits: self.bits | other.bits,
660 }
661 }
662
663 #[inline]
676 #[must_use]
677 pub const fn difference(self, other: Self) -> Self {
678 Self {
679 bits: self.bits & !other.bits,
680 }
681 }
682}
683
684impl std::ops::BitOr for EntryFormat {
685 type Output = Self;
686
687 #[inline]
689 fn bitor(self, other: EntryFormat) -> Self {
690 Self {
691 bits: self.bits | other.bits,
692 }
693 }
694}
695
696impl std::ops::BitOrAssign for EntryFormat {
697 #[inline]
699 fn bitor_assign(&mut self, other: Self) {
700 self.bits |= other.bits;
701 }
702}
703
704impl std::ops::BitXor for EntryFormat {
705 type Output = Self;
706
707 #[inline]
709 fn bitxor(self, other: Self) -> Self {
710 Self {
711 bits: self.bits ^ other.bits,
712 }
713 }
714}
715
716impl std::ops::BitXorAssign for EntryFormat {
717 #[inline]
719 fn bitxor_assign(&mut self, other: Self) {
720 self.bits ^= other.bits;
721 }
722}
723
724impl std::ops::BitAnd for EntryFormat {
725 type Output = Self;
726
727 #[inline]
729 fn bitand(self, other: Self) -> Self {
730 Self {
731 bits: self.bits & other.bits,
732 }
733 }
734}
735
736impl std::ops::BitAndAssign for EntryFormat {
737 #[inline]
739 fn bitand_assign(&mut self, other: Self) {
740 self.bits &= other.bits;
741 }
742}
743
744impl std::ops::Sub for EntryFormat {
745 type Output = Self;
746
747 #[inline]
749 fn sub(self, other: Self) -> Self {
750 Self {
751 bits: self.bits & !other.bits,
752 }
753 }
754}
755
756impl std::ops::SubAssign for EntryFormat {
757 #[inline]
759 fn sub_assign(&mut self, other: Self) {
760 self.bits &= !other.bits;
761 }
762}
763
764impl std::ops::Not for EntryFormat {
765 type Output = Self;
766
767 #[inline]
769 fn not(self) -> Self {
770 Self { bits: !self.bits } & Self::all()
771 }
772}
773
774impl std::fmt::Debug for EntryFormat {
775 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
776 let members: &[(&str, Self)] = &[
777 (
778 "INNER_INDEX_BIT_COUNT_MASK",
779 Self::INNER_INDEX_BIT_COUNT_MASK,
780 ),
781 ("MAP_ENTRY_SIZE_MASK", Self::MAP_ENTRY_SIZE_MASK),
782 ];
783 let mut first = true;
784 for (name, value) in members {
785 if self.contains(*value) {
786 if !first {
787 f.write_str(" | ")?;
788 }
789 first = false;
790 f.write_str(name)?;
791 }
792 }
793 if first {
794 f.write_str("(empty)")?;
795 }
796 Ok(())
797 }
798}
799
800impl std::fmt::Binary for EntryFormat {
801 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
802 std::fmt::Binary::fmt(&self.bits, f)
803 }
804}
805
806impl std::fmt::Octal for EntryFormat {
807 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
808 std::fmt::Octal::fmt(&self.bits, f)
809 }
810}
811
812impl std::fmt::LowerHex for EntryFormat {
813 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
814 std::fmt::LowerHex::fmt(&self.bits, f)
815 }
816}
817
818impl std::fmt::UpperHex for EntryFormat {
819 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
820 std::fmt::UpperHex::fmt(&self.bits, f)
821 }
822}
823
824impl font_types::Scalar for EntryFormat {
825 type Raw = <u8 as font_types::Scalar>::Raw;
826 fn to_raw(self) -> Self::Raw {
827 self.bits().to_raw()
828 }
829 fn from_raw(raw: Self::Raw) -> Self {
830 let t = <u8>::from_raw(raw);
831 Self::from_bits_truncate(t)
832 }
833}
834
835impl<'a> MinByteRange<'a> for VariationRegionList<'a> {
836 fn min_byte_range(&self) -> Range<usize> {
837 0..self.variation_regions_byte_range().end
838 }
839 fn min_table_bytes(&self) -> &'a [u8] {
840 let range = self.min_byte_range();
841 self.offset_data().as_bytes().get(range).unwrap_or_default()
842 }
843}
844
845impl ReadArgs for VariationRegionList<'_> {
846 type Args = ();
847}
848
849impl<'a> FontRead<'a> for VariationRegionList<'a> {
850 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
851 #[allow(clippy::absurd_extreme_comparisons)]
852 if data.len() < Self::MIN_SIZE {
853 return Err(ReadError::OutOfBounds);
854 }
855 let Some(data) = TableDataRef::new(data.as_bytes()) else {
856 return Err(ReadError::OutOfBounds);
857 };
858 Ok(Self { data })
859 }
860}
861
862#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
864#[repr(C, packed)]
865#[doc(hidden)]
866pub struct VariationRegionListFixedHeader {
867 pub axis_count: BigEndian<u16>,
868 pub region_count: BigEndian<u16>,
869}
870
871#[allow(clippy::absurd_extreme_comparisons)]
872const _: () =
873 assert!(std::mem::size_of::<VariationRegionListFixedHeader>() <= VariationRegionList::MIN_SIZE);
874
875#[derive(Clone)]
877pub struct VariationRegionList<'a> {
878 data: TableDataRef<'a, VariationRegionListFixedHeader>,
879}
880
881#[allow(clippy::needless_lifetimes)]
882impl<'a> VariationRegionList<'a> {
883 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
884 basic_table_impls!(impl_the_methods);
885
886 pub fn axis_count(&self) -> u16 {
889 self.data.header().axis_count.get()
890 }
891
892 pub fn region_count(&self) -> u16 {
895 self.data.header().region_count.get()
896 }
897
898 pub fn variation_regions(&self) -> ComputedArray<'a, VariationRegion<'a>> {
900 let range = self.variation_regions_byte_range();
901 ComputedArray::new(self.offset_data(), range, self.axis_count()).unwrap_or_default()
902 }
903
904 pub fn axis_count_byte_range(&self) -> Range<usize> {
905 let start = 0;
906 let end = start + u16::RAW_BYTE_LEN;
907 start..end
908 }
909
910 pub fn region_count_byte_range(&self) -> Range<usize> {
911 let start = self.axis_count_byte_range().end;
912 let end = start + u16::RAW_BYTE_LEN;
913 start..end
914 }
915
916 pub fn variation_regions_byte_range(&self) -> Range<usize> {
917 let region_count = self.region_count();
918 let start = self.region_count_byte_range().end;
919 let end = start
920 + (transforms::to_usize(region_count)).saturating_mul(
921 <VariationRegion as ComputeSize>::compute_size(self.axis_count()).unwrap_or(0),
922 );
923 start..end
924 }
925}
926
927const _: () = assert!(FontData::default_data_long_enough(
928 VariationRegionList::MIN_SIZE
929));
930
931impl Default for VariationRegionList<'_> {
932 fn default() -> Self {
933 Self {
934 data: TableDataRef::new(FontData::default_table_data().as_bytes())
935 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
936 }
937 }
938}
939
940#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
942pub struct VariationRegion<'a> {
943 pub region_axes: &'a [RegionAxisCoordinates],
946}
947
948impl<'a> VariationRegion<'a> {
949 pub fn region_axes(&self) -> &'a [RegionAxisCoordinates] {
952 self.region_axes
953 }
954}
955
956impl ReadArgs for VariationRegion<'_> {
957 type Args = u16;
958}
959
960impl ComputeSize for VariationRegion<'_> {
961 #[allow(clippy::needless_question_mark)]
962 fn compute_size(args: u16) -> Result<usize, ReadError> {
963 let axis_count = args;
964 Ok((transforms::to_usize(axis_count)).saturating_mul(RegionAxisCoordinates::RAW_BYTE_LEN))
965 }
966}
967
968impl<'a> FontRead<'a> for VariationRegion<'a> {
969 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
970 let mut cursor = data.cursor();
971 let axis_count = args;
972 Ok(Self {
973 region_axes: cursor.read_array(transforms::to_usize(axis_count))?,
974 })
975 }
976}
977
978crate::impl_font_read_at!(VariationRegion<'a>);
979
980#[allow(clippy::needless_lifetimes)]
981impl<'a> VariationRegion<'a> {
982 pub fn read(data: FontData<'a>, axis_count: u16) -> Result<Self, ReadError> {
987 let args = axis_count;
988 Self::read_with_args(data, args)
989 }
990}
991
992#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
994#[repr(C)]
995#[repr(packed)]
996pub struct RegionAxisCoordinates {
997 pub start_coord: BigEndian<F2Dot14>,
999 pub peak_coord: BigEndian<F2Dot14>,
1001 pub end_coord: BigEndian<F2Dot14>,
1003}
1004
1005impl RegionAxisCoordinates {
1006 pub fn start_coord(&self) -> F2Dot14 {
1008 self.start_coord.get()
1009 }
1010
1011 pub fn peak_coord(&self) -> F2Dot14 {
1013 self.peak_coord.get()
1014 }
1015
1016 pub fn end_coord(&self) -> F2Dot14 {
1018 self.end_coord.get()
1019 }
1020}
1021
1022impl FixedSize for RegionAxisCoordinates {
1023 const RAW_BYTE_LEN: usize =
1024 F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN;
1025}
1026
1027impl<'a> MinByteRange<'a> for ItemVariationStore<'a> {
1028 fn min_byte_range(&self) -> Range<usize> {
1029 0..self.item_variation_data_offsets_byte_range().end
1030 }
1031 fn min_table_bytes(&self) -> &'a [u8] {
1032 let range = self.min_byte_range();
1033 self.offset_data().as_bytes().get(range).unwrap_or_default()
1034 }
1035}
1036
1037impl ReadArgs for ItemVariationStore<'_> {
1038 type Args = ();
1039}
1040
1041impl<'a> FontRead<'a> for ItemVariationStore<'a> {
1042 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1043 #[allow(clippy::absurd_extreme_comparisons)]
1044 if data.len() < Self::MIN_SIZE {
1045 return Err(ReadError::OutOfBounds);
1046 }
1047 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1048 return Err(ReadError::OutOfBounds);
1049 };
1050 Ok(Self { data })
1051 }
1052}
1053
1054#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1056#[repr(C, packed)]
1057#[doc(hidden)]
1058pub struct ItemVariationStoreFixedHeader {
1059 pub format: BigEndian<u16>,
1060 pub variation_region_list_offset: BigEndian<Offset32>,
1061 pub item_variation_data_count: BigEndian<u16>,
1062}
1063
1064#[allow(clippy::absurd_extreme_comparisons)]
1065const _: () =
1066 assert!(std::mem::size_of::<ItemVariationStoreFixedHeader>() <= ItemVariationStore::MIN_SIZE);
1067
1068#[derive(Clone)]
1070pub struct ItemVariationStore<'a> {
1071 data: TableDataRef<'a, ItemVariationStoreFixedHeader>,
1072}
1073
1074#[allow(clippy::needless_lifetimes)]
1075impl<'a> ItemVariationStore<'a> {
1076 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1077 basic_table_impls!(impl_the_methods);
1078
1079 pub fn format(&self) -> u16 {
1081 self.data.header().format.get()
1082 }
1083
1084 pub fn variation_region_list_offset(&self) -> Offset32 {
1087 self.data.header().variation_region_list_offset.get()
1088 }
1089
1090 pub fn variation_region_list(&self) -> Result<VariationRegionList<'a>, ReadError> {
1092 let data = self.offset_data();
1093 self.variation_region_list_offset().resolve(data)
1094 }
1095
1096 pub fn item_variation_data_count(&self) -> u16 {
1098 self.data.header().item_variation_data_count.get()
1099 }
1100
1101 pub fn item_variation_data_offsets(&self) -> &'a [BigEndian<Nullable<Offset32>>] {
1104 let range = self.item_variation_data_offsets_byte_range();
1105 self.offset_data()
1106 .read_array(range)
1107 .ok()
1108 .unwrap_or_default()
1109 }
1110
1111 pub fn item_variation_data(
1113 &self,
1114 ) -> ArrayOfNullableOffsets<'a, ItemVariationData<'a>, Offset32> {
1115 let data = self.offset_data();
1116 let offsets = self.item_variation_data_offsets();
1117 ArrayOfNullableOffsets::new(offsets, data, ())
1118 }
1119
1120 pub fn format_byte_range(&self) -> Range<usize> {
1121 let start = 0;
1122 let end = start + u16::RAW_BYTE_LEN;
1123 start..end
1124 }
1125
1126 pub fn variation_region_list_offset_byte_range(&self) -> Range<usize> {
1127 let start = self.format_byte_range().end;
1128 let end = start + Offset32::RAW_BYTE_LEN;
1129 start..end
1130 }
1131
1132 pub fn item_variation_data_count_byte_range(&self) -> Range<usize> {
1133 let start = self.variation_region_list_offset_byte_range().end;
1134 let end = start + u16::RAW_BYTE_LEN;
1135 start..end
1136 }
1137
1138 pub fn item_variation_data_offsets_byte_range(&self) -> Range<usize> {
1139 let item_variation_data_count = self.item_variation_data_count();
1140 let start = self.item_variation_data_count_byte_range().end;
1141 let end = start
1142 + (transforms::to_usize(item_variation_data_count))
1143 .saturating_mul(Offset32::RAW_BYTE_LEN);
1144 start..end
1145 }
1146}
1147
1148const _: () = assert!(FontData::default_data_long_enough(
1149 ItemVariationStore::MIN_SIZE
1150));
1151
1152impl Default for ItemVariationStore<'_> {
1153 fn default() -> Self {
1154 Self {
1155 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1156 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1157 }
1158 }
1159}
1160
1161impl<'a> MinByteRange<'a> for ItemVariationData<'a> {
1162 fn min_byte_range(&self) -> Range<usize> {
1163 0..self.delta_sets_byte_range().end
1164 }
1165 fn min_table_bytes(&self) -> &'a [u8] {
1166 let range = self.min_byte_range();
1167 self.offset_data().as_bytes().get(range).unwrap_or_default()
1168 }
1169}
1170
1171impl ReadArgs for ItemVariationData<'_> {
1172 type Args = ();
1173}
1174
1175impl<'a> FontRead<'a> for ItemVariationData<'a> {
1176 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1177 #[allow(clippy::absurd_extreme_comparisons)]
1178 if data.len() < Self::MIN_SIZE {
1179 return Err(ReadError::OutOfBounds);
1180 }
1181 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1182 return Err(ReadError::OutOfBounds);
1183 };
1184 Ok(Self { data })
1185 }
1186}
1187
1188#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1190#[repr(C, packed)]
1191#[doc(hidden)]
1192pub struct ItemVariationDataFixedHeader {
1193 pub item_count: BigEndian<u16>,
1194 pub word_delta_count: BigEndian<u16>,
1195 pub region_index_count: BigEndian<u16>,
1196}
1197
1198#[allow(clippy::absurd_extreme_comparisons)]
1199const _: () =
1200 assert!(std::mem::size_of::<ItemVariationDataFixedHeader>() <= ItemVariationData::MIN_SIZE);
1201
1202#[derive(Clone)]
1204pub struct ItemVariationData<'a> {
1205 data: TableDataRef<'a, ItemVariationDataFixedHeader>,
1206}
1207
1208#[allow(clippy::needless_lifetimes)]
1209impl<'a> ItemVariationData<'a> {
1210 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1211 basic_table_impls!(impl_the_methods);
1212
1213 pub fn item_count(&self) -> u16 {
1215 self.data.header().item_count.get()
1216 }
1217
1218 pub fn word_delta_count(&self) -> u16 {
1220 self.data.header().word_delta_count.get()
1221 }
1222
1223 pub fn region_index_count(&self) -> u16 {
1225 self.data.header().region_index_count.get()
1226 }
1227
1228 pub fn region_indexes(&self) -> &'a [BigEndian<u16>] {
1231 let range = self.region_indexes_byte_range();
1232 self.offset_data()
1233 .read_array(range)
1234 .ok()
1235 .unwrap_or_default()
1236 }
1237
1238 pub fn delta_sets(&self) -> &'a [u8] {
1240 let range = self.delta_sets_byte_range();
1241 self.offset_data()
1242 .read_array(range)
1243 .ok()
1244 .unwrap_or_default()
1245 }
1246
1247 pub fn item_count_byte_range(&self) -> Range<usize> {
1248 let start = 0;
1249 let end = start + u16::RAW_BYTE_LEN;
1250 start..end
1251 }
1252
1253 pub fn word_delta_count_byte_range(&self) -> Range<usize> {
1254 let start = self.item_count_byte_range().end;
1255 let end = start + u16::RAW_BYTE_LEN;
1256 start..end
1257 }
1258
1259 pub fn region_index_count_byte_range(&self) -> Range<usize> {
1260 let start = self.word_delta_count_byte_range().end;
1261 let end = start + u16::RAW_BYTE_LEN;
1262 start..end
1263 }
1264
1265 pub fn region_indexes_byte_range(&self) -> Range<usize> {
1266 let region_index_count = self.region_index_count();
1267 let start = self.region_index_count_byte_range().end;
1268 let end =
1269 start + (transforms::to_usize(region_index_count)).saturating_mul(u16::RAW_BYTE_LEN);
1270 start..end
1271 }
1272
1273 pub fn delta_sets_byte_range(&self) -> Range<usize> {
1274 let item_count = self.item_count();
1275 let word_delta_count = self.word_delta_count();
1276 let region_index_count = self.region_index_count();
1277 let start = self.region_indexes_byte_range().end;
1278 let end = start
1279 + (ItemVariationData::delta_sets_len(item_count, word_delta_count, region_index_count))
1280 .saturating_mul(u8::RAW_BYTE_LEN);
1281 start..end
1282 }
1283}
1284
1285const _: () = assert!(FontData::default_data_long_enough(
1286 ItemVariationData::MIN_SIZE
1287));
1288
1289impl Default for ItemVariationData<'_> {
1290 fn default() -> Self {
1291 Self {
1292 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1293 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1294 }
1295 }
1296}