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 #[inline]
507 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
508 let format: u8 = data.read_at(0usize)?;
509 match format {
510 DeltaSetIndexMapFormat0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
511 DeltaSetIndexMapFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
512 other => Err(ReadError::InvalidFormat(other.into())),
513 }
514 }
515}
516
517impl<'a> MinByteRange<'a> for DeltaSetIndexMap<'a> {
518 fn min_byte_range(&self) -> Range<usize> {
519 match self {
520 Self::Format0(item) => item.min_byte_range(),
521 Self::Format1(item) => item.min_byte_range(),
522 }
523 }
524 fn min_table_bytes(&self) -> &'a [u8] {
525 match self {
526 Self::Format0(item) => item.min_table_bytes(),
527 Self::Format1(item) => item.min_table_bytes(),
528 }
529 }
530}
531
532#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
534#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
535#[repr(transparent)]
536pub struct EntryFormat {
537 bits: u8,
538}
539
540impl EntryFormat {
541 pub const INNER_INDEX_BIT_COUNT_MASK: Self = Self { bits: 0x0F };
543
544 pub const MAP_ENTRY_SIZE_MASK: Self = Self { bits: 0x30 };
546}
547
548impl EntryFormat {
549 #[inline]
551 pub const fn empty() -> Self {
552 Self { bits: 0 }
553 }
554
555 #[inline]
557 pub const fn all() -> Self {
558 Self {
559 bits: Self::INNER_INDEX_BIT_COUNT_MASK.bits | Self::MAP_ENTRY_SIZE_MASK.bits,
560 }
561 }
562
563 #[inline]
565 pub const fn bits(&self) -> u8 {
566 self.bits
567 }
568
569 #[inline]
572 pub const fn from_bits(bits: u8) -> Option<Self> {
573 if (bits & !Self::all().bits()) == 0 {
574 Some(Self { bits })
575 } else {
576 None
577 }
578 }
579
580 #[inline]
583 pub const fn from_bits_truncate(bits: u8) -> Self {
584 Self {
585 bits: bits & Self::all().bits,
586 }
587 }
588
589 #[inline]
591 pub const fn is_empty(&self) -> bool {
592 self.bits() == Self::empty().bits()
593 }
594
595 #[inline]
597 pub const fn intersects(&self, other: Self) -> bool {
598 !(Self {
599 bits: self.bits & other.bits,
600 })
601 .is_empty()
602 }
603
604 #[inline]
606 pub const fn contains(&self, other: Self) -> bool {
607 (self.bits & other.bits) == other.bits
608 }
609
610 #[inline]
612 pub fn insert(&mut self, other: Self) {
613 self.bits |= other.bits;
614 }
615
616 #[inline]
618 pub fn remove(&mut self, other: Self) {
619 self.bits &= !other.bits;
620 }
621
622 #[inline]
624 pub fn toggle(&mut self, other: Self) {
625 self.bits ^= other.bits;
626 }
627
628 #[inline]
639 #[must_use]
640 pub const fn intersection(self, other: Self) -> Self {
641 Self {
642 bits: self.bits & other.bits,
643 }
644 }
645
646 #[inline]
657 #[must_use]
658 pub const fn union(self, other: Self) -> Self {
659 Self {
660 bits: self.bits | other.bits,
661 }
662 }
663
664 #[inline]
677 #[must_use]
678 pub const fn difference(self, other: Self) -> Self {
679 Self {
680 bits: self.bits & !other.bits,
681 }
682 }
683}
684
685impl std::ops::BitOr for EntryFormat {
686 type Output = Self;
687
688 #[inline]
690 fn bitor(self, other: EntryFormat) -> Self {
691 Self {
692 bits: self.bits | other.bits,
693 }
694 }
695}
696
697impl std::ops::BitOrAssign for EntryFormat {
698 #[inline]
700 fn bitor_assign(&mut self, other: Self) {
701 self.bits |= other.bits;
702 }
703}
704
705impl std::ops::BitXor for EntryFormat {
706 type Output = Self;
707
708 #[inline]
710 fn bitxor(self, other: Self) -> Self {
711 Self {
712 bits: self.bits ^ other.bits,
713 }
714 }
715}
716
717impl std::ops::BitXorAssign for EntryFormat {
718 #[inline]
720 fn bitxor_assign(&mut self, other: Self) {
721 self.bits ^= other.bits;
722 }
723}
724
725impl std::ops::BitAnd for EntryFormat {
726 type Output = Self;
727
728 #[inline]
730 fn bitand(self, other: Self) -> Self {
731 Self {
732 bits: self.bits & other.bits,
733 }
734 }
735}
736
737impl std::ops::BitAndAssign for EntryFormat {
738 #[inline]
740 fn bitand_assign(&mut self, other: Self) {
741 self.bits &= other.bits;
742 }
743}
744
745impl std::ops::Sub for EntryFormat {
746 type Output = Self;
747
748 #[inline]
750 fn sub(self, other: Self) -> Self {
751 Self {
752 bits: self.bits & !other.bits,
753 }
754 }
755}
756
757impl std::ops::SubAssign for EntryFormat {
758 #[inline]
760 fn sub_assign(&mut self, other: Self) {
761 self.bits &= !other.bits;
762 }
763}
764
765impl std::ops::Not for EntryFormat {
766 type Output = Self;
767
768 #[inline]
770 fn not(self) -> Self {
771 Self { bits: !self.bits } & Self::all()
772 }
773}
774
775impl std::fmt::Debug for EntryFormat {
776 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
777 let members: &[(&str, Self)] = &[
778 (
779 "INNER_INDEX_BIT_COUNT_MASK",
780 Self::INNER_INDEX_BIT_COUNT_MASK,
781 ),
782 ("MAP_ENTRY_SIZE_MASK", Self::MAP_ENTRY_SIZE_MASK),
783 ];
784 let mut first = true;
785 for (name, value) in members {
786 if self.contains(*value) {
787 if !first {
788 f.write_str(" | ")?;
789 }
790 first = false;
791 f.write_str(name)?;
792 }
793 }
794 if first {
795 f.write_str("(empty)")?;
796 }
797 Ok(())
798 }
799}
800
801impl std::fmt::Binary for EntryFormat {
802 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
803 std::fmt::Binary::fmt(&self.bits, f)
804 }
805}
806
807impl std::fmt::Octal for EntryFormat {
808 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
809 std::fmt::Octal::fmt(&self.bits, f)
810 }
811}
812
813impl std::fmt::LowerHex for EntryFormat {
814 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
815 std::fmt::LowerHex::fmt(&self.bits, f)
816 }
817}
818
819impl std::fmt::UpperHex for EntryFormat {
820 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
821 std::fmt::UpperHex::fmt(&self.bits, f)
822 }
823}
824
825impl font_types::Scalar for EntryFormat {
826 type Raw = <u8 as font_types::Scalar>::Raw;
827 fn to_raw(self) -> Self::Raw {
828 self.bits().to_raw()
829 }
830 fn from_raw(raw: Self::Raw) -> Self {
831 let t = <u8>::from_raw(raw);
832 Self::from_bits_truncate(t)
833 }
834}
835
836impl<'a> MinByteRange<'a> for VariationRegionList<'a> {
837 fn min_byte_range(&self) -> Range<usize> {
838 0..self.variation_regions_byte_range().end
839 }
840 fn min_table_bytes(&self) -> &'a [u8] {
841 let range = self.min_byte_range();
842 self.offset_data().as_bytes().get(range).unwrap_or_default()
843 }
844}
845
846impl ReadArgs for VariationRegionList<'_> {
847 type Args = ();
848}
849
850impl<'a> FontRead<'a> for VariationRegionList<'a> {
851 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
852 #[allow(clippy::absurd_extreme_comparisons)]
853 if data.len() < Self::MIN_SIZE {
854 return Err(ReadError::OutOfBounds);
855 }
856 let Some(data) = TableDataRef::new(data.as_bytes()) else {
857 return Err(ReadError::OutOfBounds);
858 };
859 Ok(Self { data })
860 }
861}
862
863#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
865#[repr(C, packed)]
866#[doc(hidden)]
867pub struct VariationRegionListFixedHeader {
868 pub axis_count: BigEndian<u16>,
869 pub region_count: BigEndian<u16>,
870}
871
872#[allow(clippy::absurd_extreme_comparisons)]
873const _: () =
874 assert!(std::mem::size_of::<VariationRegionListFixedHeader>() <= VariationRegionList::MIN_SIZE);
875
876#[derive(Clone)]
878pub struct VariationRegionList<'a> {
879 data: TableDataRef<'a, VariationRegionListFixedHeader>,
880}
881
882#[allow(clippy::needless_lifetimes)]
883impl<'a> VariationRegionList<'a> {
884 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
885 basic_table_impls!(impl_the_methods);
886
887 pub fn axis_count(&self) -> u16 {
890 self.data.header().axis_count.get()
891 }
892
893 pub fn region_count(&self) -> u16 {
896 self.data.header().region_count.get()
897 }
898
899 pub fn variation_regions(&self) -> ComputedArray<'a, VariationRegion<'a>> {
901 let range = self.variation_regions_byte_range();
902 ComputedArray::new(self.offset_data(), range, self.axis_count()).unwrap_or_default()
903 }
904
905 pub fn axis_count_byte_range(&self) -> Range<usize> {
906 let start = 0;
907 let end = start + u16::RAW_BYTE_LEN;
908 start..end
909 }
910
911 pub fn region_count_byte_range(&self) -> Range<usize> {
912 let start = self.axis_count_byte_range().end;
913 let end = start + u16::RAW_BYTE_LEN;
914 start..end
915 }
916
917 pub fn variation_regions_byte_range(&self) -> Range<usize> {
918 let region_count = self.region_count();
919 let start = self.region_count_byte_range().end;
920 let end = start
921 + (transforms::to_usize(region_count)).saturating_mul(
922 <VariationRegion as ComputeSize>::compute_size(self.axis_count()).unwrap_or(0),
923 );
924 start..end
925 }
926}
927
928const _: () = assert!(FontData::default_data_long_enough(
929 VariationRegionList::MIN_SIZE
930));
931
932impl Default for VariationRegionList<'_> {
933 fn default() -> Self {
934 Self {
935 data: TableDataRef::new(FontData::default_table_data().as_bytes())
936 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
937 }
938 }
939}
940
941#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
943pub struct VariationRegion<'a> {
944 pub region_axes: &'a [RegionAxisCoordinates],
947}
948
949impl<'a> VariationRegion<'a> {
950 pub fn region_axes(&self) -> &'a [RegionAxisCoordinates] {
953 self.region_axes
954 }
955}
956
957impl ReadArgs for VariationRegion<'_> {
958 type Args = u16;
959}
960
961impl ComputeSize for VariationRegion<'_> {
962 #[allow(clippy::needless_question_mark)]
963 fn compute_size(args: u16) -> Result<usize, ReadError> {
964 let axis_count = args;
965 Ok((transforms::to_usize(axis_count)).saturating_mul(RegionAxisCoordinates::RAW_BYTE_LEN))
966 }
967}
968
969impl<'a> FontRead<'a> for VariationRegion<'a> {
970 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
971 let mut cursor = data.cursor();
972 let axis_count = args;
973 Ok(Self {
974 region_axes: cursor.read_array(transforms::to_usize(axis_count))?,
975 })
976 }
977}
978
979crate::impl_font_read_at!(VariationRegion<'a>);
980
981#[allow(clippy::needless_lifetimes)]
982impl<'a> VariationRegion<'a> {
983 pub fn read(data: FontData<'a>, axis_count: u16) -> Result<Self, ReadError> {
988 let args = axis_count;
989 Self::read_with_args(data, args)
990 }
991}
992
993#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
995#[repr(C)]
996#[repr(packed)]
997pub struct RegionAxisCoordinates {
998 pub start_coord: BigEndian<F2Dot14>,
1000 pub peak_coord: BigEndian<F2Dot14>,
1002 pub end_coord: BigEndian<F2Dot14>,
1004}
1005
1006impl RegionAxisCoordinates {
1007 pub fn start_coord(&self) -> F2Dot14 {
1009 self.start_coord.get()
1010 }
1011
1012 pub fn peak_coord(&self) -> F2Dot14 {
1014 self.peak_coord.get()
1015 }
1016
1017 pub fn end_coord(&self) -> F2Dot14 {
1019 self.end_coord.get()
1020 }
1021}
1022
1023impl FixedSize for RegionAxisCoordinates {
1024 const RAW_BYTE_LEN: usize =
1025 F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN;
1026}
1027
1028impl<'a> MinByteRange<'a> for ItemVariationStore<'a> {
1029 fn min_byte_range(&self) -> Range<usize> {
1030 0..self.item_variation_data_offsets_byte_range().end
1031 }
1032 fn min_table_bytes(&self) -> &'a [u8] {
1033 let range = self.min_byte_range();
1034 self.offset_data().as_bytes().get(range).unwrap_or_default()
1035 }
1036}
1037
1038impl ReadArgs for ItemVariationStore<'_> {
1039 type Args = ();
1040}
1041
1042impl<'a> FontRead<'a> for ItemVariationStore<'a> {
1043 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1044 #[allow(clippy::absurd_extreme_comparisons)]
1045 if data.len() < Self::MIN_SIZE {
1046 return Err(ReadError::OutOfBounds);
1047 }
1048 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1049 return Err(ReadError::OutOfBounds);
1050 };
1051 Ok(Self { data })
1052 }
1053}
1054
1055#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1057#[repr(C, packed)]
1058#[doc(hidden)]
1059pub struct ItemVariationStoreFixedHeader {
1060 pub format: BigEndian<u16>,
1061 pub variation_region_list_offset: BigEndian<Offset32>,
1062 pub item_variation_data_count: BigEndian<u16>,
1063}
1064
1065#[allow(clippy::absurd_extreme_comparisons)]
1066const _: () =
1067 assert!(std::mem::size_of::<ItemVariationStoreFixedHeader>() <= ItemVariationStore::MIN_SIZE);
1068
1069#[derive(Clone)]
1071pub struct ItemVariationStore<'a> {
1072 data: TableDataRef<'a, ItemVariationStoreFixedHeader>,
1073}
1074
1075#[allow(clippy::needless_lifetimes)]
1076impl<'a> ItemVariationStore<'a> {
1077 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1078 basic_table_impls!(impl_the_methods);
1079
1080 pub fn format(&self) -> u16 {
1082 self.data.header().format.get()
1083 }
1084
1085 pub fn variation_region_list_offset(&self) -> Offset32 {
1088 self.data.header().variation_region_list_offset.get()
1089 }
1090
1091 pub fn variation_region_list(&self) -> Result<VariationRegionList<'a>, ReadError> {
1093 let data = self.offset_data();
1094 self.variation_region_list_offset().resolve(data)
1095 }
1096
1097 pub fn item_variation_data_count(&self) -> u16 {
1099 self.data.header().item_variation_data_count.get()
1100 }
1101
1102 pub fn item_variation_data_offsets(&self) -> &'a [BigEndian<Nullable<Offset32>>] {
1105 let range = self.item_variation_data_offsets_byte_range();
1106 self.offset_data()
1107 .read_array(range)
1108 .ok()
1109 .unwrap_or_default()
1110 }
1111
1112 pub fn item_variation_data(
1114 &self,
1115 ) -> ArrayOfNullableOffsets<'a, ItemVariationData<'a>, Offset32> {
1116 let data = self.offset_data();
1117 let offsets = self.item_variation_data_offsets();
1118 ArrayOfNullableOffsets::new(offsets, data, ())
1119 }
1120
1121 pub fn format_byte_range(&self) -> Range<usize> {
1122 let start = 0;
1123 let end = start + u16::RAW_BYTE_LEN;
1124 start..end
1125 }
1126
1127 pub fn variation_region_list_offset_byte_range(&self) -> Range<usize> {
1128 let start = self.format_byte_range().end;
1129 let end = start + Offset32::RAW_BYTE_LEN;
1130 start..end
1131 }
1132
1133 pub fn item_variation_data_count_byte_range(&self) -> Range<usize> {
1134 let start = self.variation_region_list_offset_byte_range().end;
1135 let end = start + u16::RAW_BYTE_LEN;
1136 start..end
1137 }
1138
1139 pub fn item_variation_data_offsets_byte_range(&self) -> Range<usize> {
1140 let item_variation_data_count = self.item_variation_data_count();
1141 let start = self.item_variation_data_count_byte_range().end;
1142 let end = start
1143 + (transforms::to_usize(item_variation_data_count))
1144 .saturating_mul(Offset32::RAW_BYTE_LEN);
1145 start..end
1146 }
1147}
1148
1149const _: () = assert!(FontData::default_data_long_enough(
1150 ItemVariationStore::MIN_SIZE
1151));
1152
1153impl Default for ItemVariationStore<'_> {
1154 fn default() -> Self {
1155 Self {
1156 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1157 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1158 }
1159 }
1160}
1161
1162impl<'a> MinByteRange<'a> for ItemVariationData<'a> {
1163 fn min_byte_range(&self) -> Range<usize> {
1164 0..self.delta_sets_byte_range().end
1165 }
1166 fn min_table_bytes(&self) -> &'a [u8] {
1167 let range = self.min_byte_range();
1168 self.offset_data().as_bytes().get(range).unwrap_or_default()
1169 }
1170}
1171
1172impl ReadArgs for ItemVariationData<'_> {
1173 type Args = ();
1174}
1175
1176impl<'a> FontRead<'a> for ItemVariationData<'a> {
1177 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1178 #[allow(clippy::absurd_extreme_comparisons)]
1179 if data.len() < Self::MIN_SIZE {
1180 return Err(ReadError::OutOfBounds);
1181 }
1182 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1183 return Err(ReadError::OutOfBounds);
1184 };
1185 Ok(Self { data })
1186 }
1187}
1188
1189#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1191#[repr(C, packed)]
1192#[doc(hidden)]
1193pub struct ItemVariationDataFixedHeader {
1194 pub item_count: BigEndian<u16>,
1195 pub word_delta_count: BigEndian<u16>,
1196 pub region_index_count: BigEndian<u16>,
1197}
1198
1199#[allow(clippy::absurd_extreme_comparisons)]
1200const _: () =
1201 assert!(std::mem::size_of::<ItemVariationDataFixedHeader>() <= ItemVariationData::MIN_SIZE);
1202
1203#[derive(Clone)]
1205pub struct ItemVariationData<'a> {
1206 data: TableDataRef<'a, ItemVariationDataFixedHeader>,
1207}
1208
1209#[allow(clippy::needless_lifetimes)]
1210impl<'a> ItemVariationData<'a> {
1211 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1212 basic_table_impls!(impl_the_methods);
1213
1214 pub fn item_count(&self) -> u16 {
1216 self.data.header().item_count.get()
1217 }
1218
1219 pub fn word_delta_count(&self) -> u16 {
1221 self.data.header().word_delta_count.get()
1222 }
1223
1224 pub fn region_index_count(&self) -> u16 {
1226 self.data.header().region_index_count.get()
1227 }
1228
1229 pub fn region_indexes(&self) -> &'a [BigEndian<u16>] {
1232 let range = self.region_indexes_byte_range();
1233 self.offset_data()
1234 .read_array(range)
1235 .ok()
1236 .unwrap_or_default()
1237 }
1238
1239 pub fn delta_sets(&self) -> &'a [u8] {
1241 let range = self.delta_sets_byte_range();
1242 self.offset_data()
1243 .read_array(range)
1244 .ok()
1245 .unwrap_or_default()
1246 }
1247
1248 pub fn item_count_byte_range(&self) -> Range<usize> {
1249 let start = 0;
1250 let end = start + u16::RAW_BYTE_LEN;
1251 start..end
1252 }
1253
1254 pub fn word_delta_count_byte_range(&self) -> Range<usize> {
1255 let start = self.item_count_byte_range().end;
1256 let end = start + u16::RAW_BYTE_LEN;
1257 start..end
1258 }
1259
1260 pub fn region_index_count_byte_range(&self) -> Range<usize> {
1261 let start = self.word_delta_count_byte_range().end;
1262 let end = start + u16::RAW_BYTE_LEN;
1263 start..end
1264 }
1265
1266 pub fn region_indexes_byte_range(&self) -> Range<usize> {
1267 let region_index_count = self.region_index_count();
1268 let start = self.region_index_count_byte_range().end;
1269 let end =
1270 start + (transforms::to_usize(region_index_count)).saturating_mul(u16::RAW_BYTE_LEN);
1271 start..end
1272 }
1273
1274 pub fn delta_sets_byte_range(&self) -> Range<usize> {
1275 let item_count = self.item_count();
1276 let word_delta_count = self.word_delta_count();
1277 let region_index_count = self.region_index_count();
1278 let start = self.region_indexes_byte_range().end;
1279 let end = start
1280 + (ItemVariationData::delta_sets_len(item_count, word_delta_count, region_index_count))
1281 .saturating_mul(u8::RAW_BYTE_LEN);
1282 start..end
1283 }
1284}
1285
1286const _: () = assert!(FontData::default_data_long_enough(
1287 ItemVariationData::MIN_SIZE
1288));
1289
1290impl Default for ItemVariationData<'_> {
1291 fn default() -> Self {
1292 Self {
1293 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1294 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1295 }
1296 }
1297}