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.data.as_bytes().get(range).unwrap_or_default()
15 }
16}
17
18impl ReadArgs for TupleVariationHeader<'_> {
19 type Args = u16;
20}
21
22impl<'a> FontReadWithArgs<'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 Ok(Self { data, axis_count })
31 }
32}
33
34impl<'a> TupleVariationHeader<'a> {
35 pub fn read(data: FontData<'a>, axis_count: u16) -> Result<Self, ReadError> {
40 let args = axis_count;
41 Self::read_with_args(data, &args)
42 }
43}
44
45#[derive(Clone)]
47pub struct TupleVariationHeader<'a> {
48 data: FontData<'a>,
49 axis_count: u16,
50}
51
52#[allow(clippy::needless_lifetimes)]
53impl<'a> TupleVariationHeader<'a> {
54 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + TupleIndex::RAW_BYTE_LEN);
55 basic_table_impls!(impl_the_methods);
56
57 pub fn variation_data_size(&self) -> u16 {
60 let range = self.variation_data_size_byte_range();
61 self.data.read_at(range.start).ok().unwrap()
62 }
63
64 pub fn tuple_index(&self) -> TupleIndex {
67 let range = self.tuple_index_byte_range();
68 self.data.read_at(range.start).ok().unwrap()
69 }
70
71 pub(crate) fn axis_count(&self) -> u16 {
72 self.axis_count
73 }
74
75 pub fn variation_data_size_byte_range(&self) -> Range<usize> {
76 let start = 0;
77 start..start + u16::RAW_BYTE_LEN
78 }
79
80 pub fn tuple_index_byte_range(&self) -> Range<usize> {
81 let start = self.variation_data_size_byte_range().end;
82 start..start + TupleIndex::RAW_BYTE_LEN
83 }
84
85 pub fn peak_tuple_byte_range(&self) -> Range<usize> {
86 let tuple_index = self.tuple_index();
87 let axis_count = self.axis_count();
88 let start = self.tuple_index_byte_range().end;
89 start
90 ..start
91 + (TupleIndex::tuple_len(tuple_index, axis_count, 0_usize))
92 .saturating_mul(F2Dot14::RAW_BYTE_LEN)
93 }
94
95 pub fn intermediate_start_tuple_byte_range(&self) -> Range<usize> {
96 let tuple_index = self.tuple_index();
97 let axis_count = self.axis_count();
98 let start = self.peak_tuple_byte_range().end;
99 start
100 ..start
101 + (TupleIndex::tuple_len(tuple_index, axis_count, 1_usize))
102 .saturating_mul(F2Dot14::RAW_BYTE_LEN)
103 }
104
105 pub fn intermediate_end_tuple_byte_range(&self) -> Range<usize> {
106 let tuple_index = self.tuple_index();
107 let axis_count = self.axis_count();
108 let start = self.intermediate_start_tuple_byte_range().end;
109 start
110 ..start
111 + (TupleIndex::tuple_len(tuple_index, axis_count, 1_usize))
112 .saturating_mul(F2Dot14::RAW_BYTE_LEN)
113 }
114}
115
116#[cfg(feature = "experimental_traverse")]
117impl<'a> SomeTable<'a> for TupleVariationHeader<'a> {
118 fn type_name(&self) -> &str {
119 "TupleVariationHeader"
120 }
121 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
122 match idx {
123 0usize => Some(Field::new(
124 "variation_data_size",
125 self.variation_data_size(),
126 )),
127 1usize => Some(Field::new("tuple_index", self.traverse_tuple_index())),
128 _ => None,
129 }
130 }
131}
132
133#[cfg(feature = "experimental_traverse")]
134#[allow(clippy::needless_lifetimes)]
135impl<'a> std::fmt::Debug for TupleVariationHeader<'a> {
136 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137 (self as &dyn SomeTable<'a>).fmt(f)
138 }
139}
140
141#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
147pub struct Tuple<'a> {
148 pub values: &'a [BigEndian<F2Dot14>],
153}
154
155impl<'a> Tuple<'a> {
156 pub fn values(&self) -> &'a [BigEndian<F2Dot14>] {
161 self.values
162 }
163}
164
165impl ReadArgs for Tuple<'_> {
166 type Args = u16;
167}
168
169impl ComputeSize for Tuple<'_> {
170 #[allow(clippy::needless_question_mark)]
171 fn compute_size(args: &u16) -> Result<usize, ReadError> {
172 let axis_count = *args;
173 Ok((axis_count as usize).saturating_mul(F2Dot14::RAW_BYTE_LEN))
174 }
175}
176
177impl<'a> FontReadWithArgs<'a> for Tuple<'a> {
178 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
179 let mut cursor = data.cursor();
180 let axis_count = *args;
181 Ok(Self {
182 values: cursor.read_array(axis_count as usize)?,
183 })
184 }
185}
186
187#[allow(clippy::needless_lifetimes)]
188impl<'a> Tuple<'a> {
189 pub fn read(data: FontData<'a>, axis_count: u16) -> Result<Self, ReadError> {
194 let args = axis_count;
195 Self::read_with_args(data, &args)
196 }
197}
198
199#[cfg(feature = "experimental_traverse")]
200impl<'a> SomeRecord<'a> for Tuple<'a> {
201 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
202 RecordResolver {
203 name: "Tuple",
204 get_field: Box::new(move |idx, _data| match idx {
205 0usize => Some(Field::new("values", self.values())),
206 _ => None,
207 }),
208 data,
209 }
210 }
211}
212
213impl Format<u8> for DeltaSetIndexMapFormat0<'_> {
214 const FORMAT: u8 = 0;
215}
216
217impl<'a> MinByteRange<'a> for DeltaSetIndexMapFormat0<'a> {
218 fn min_byte_range(&self) -> Range<usize> {
219 0..self.map_data_byte_range().end
220 }
221 fn min_table_bytes(&self) -> &'a [u8] {
222 let range = self.min_byte_range();
223 self.data.as_bytes().get(range).unwrap_or_default()
224 }
225}
226
227impl<'a> FontRead<'a> for DeltaSetIndexMapFormat0<'a> {
228 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
229 #[allow(clippy::absurd_extreme_comparisons)]
230 if data.len() < Self::MIN_SIZE {
231 return Err(ReadError::OutOfBounds);
232 }
233 Ok(Self { data })
234 }
235}
236
237#[derive(Clone)]
239pub struct DeltaSetIndexMapFormat0<'a> {
240 data: FontData<'a>,
241}
242
243#[allow(clippy::needless_lifetimes)]
244impl<'a> DeltaSetIndexMapFormat0<'a> {
245 pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + EntryFormat::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
246 basic_table_impls!(impl_the_methods);
247
248 pub fn format(&self) -> u8 {
250 let range = self.format_byte_range();
251 self.data.read_at(range.start).ok().unwrap()
252 }
253
254 pub fn entry_format(&self) -> EntryFormat {
257 let range = self.entry_format_byte_range();
258 self.data.read_at(range.start).ok().unwrap()
259 }
260
261 pub fn map_count(&self) -> u16 {
263 let range = self.map_count_byte_range();
264 self.data.read_at(range.start).ok().unwrap()
265 }
266
267 pub fn map_data(&self) -> &'a [u8] {
269 let range = self.map_data_byte_range();
270 self.data.read_array(range).ok().unwrap_or_default()
271 }
272
273 pub fn format_byte_range(&self) -> Range<usize> {
274 let start = 0;
275 start..start + u8::RAW_BYTE_LEN
276 }
277
278 pub fn entry_format_byte_range(&self) -> Range<usize> {
279 let start = self.format_byte_range().end;
280 start..start + EntryFormat::RAW_BYTE_LEN
281 }
282
283 pub fn map_count_byte_range(&self) -> Range<usize> {
284 let start = self.entry_format_byte_range().end;
285 start..start + u16::RAW_BYTE_LEN
286 }
287
288 pub fn map_data_byte_range(&self) -> Range<usize> {
289 let entry_format = self.entry_format();
290 let map_count = self.map_count();
291 let start = self.map_count_byte_range().end;
292 start
293 ..start
294 + (EntryFormat::map_size(entry_format, map_count)).saturating_mul(u8::RAW_BYTE_LEN)
295 }
296}
297
298#[cfg(feature = "experimental_traverse")]
299impl<'a> SomeTable<'a> for DeltaSetIndexMapFormat0<'a> {
300 fn type_name(&self) -> &str {
301 "DeltaSetIndexMapFormat0"
302 }
303 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
304 match idx {
305 0usize => Some(Field::new("format", self.format())),
306 1usize => Some(Field::new("entry_format", self.entry_format())),
307 2usize => Some(Field::new("map_count", self.map_count())),
308 3usize => Some(Field::new("map_data", self.map_data())),
309 _ => None,
310 }
311 }
312}
313
314#[cfg(feature = "experimental_traverse")]
315#[allow(clippy::needless_lifetimes)]
316impl<'a> std::fmt::Debug for DeltaSetIndexMapFormat0<'a> {
317 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
318 (self as &dyn SomeTable<'a>).fmt(f)
319 }
320}
321
322impl Format<u8> for DeltaSetIndexMapFormat1<'_> {
323 const FORMAT: u8 = 1;
324}
325
326impl<'a> MinByteRange<'a> for DeltaSetIndexMapFormat1<'a> {
327 fn min_byte_range(&self) -> Range<usize> {
328 0..self.map_data_byte_range().end
329 }
330 fn min_table_bytes(&self) -> &'a [u8] {
331 let range = self.min_byte_range();
332 self.data.as_bytes().get(range).unwrap_or_default()
333 }
334}
335
336impl<'a> FontRead<'a> for DeltaSetIndexMapFormat1<'a> {
337 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
338 #[allow(clippy::absurd_extreme_comparisons)]
339 if data.len() < Self::MIN_SIZE {
340 return Err(ReadError::OutOfBounds);
341 }
342 Ok(Self { data })
343 }
344}
345
346#[derive(Clone)]
348pub struct DeltaSetIndexMapFormat1<'a> {
349 data: FontData<'a>,
350}
351
352#[allow(clippy::needless_lifetimes)]
353impl<'a> DeltaSetIndexMapFormat1<'a> {
354 pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + EntryFormat::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
355 basic_table_impls!(impl_the_methods);
356
357 pub fn format(&self) -> u8 {
359 let range = self.format_byte_range();
360 self.data.read_at(range.start).ok().unwrap()
361 }
362
363 pub fn entry_format(&self) -> EntryFormat {
366 let range = self.entry_format_byte_range();
367 self.data.read_at(range.start).ok().unwrap()
368 }
369
370 pub fn map_count(&self) -> u32 {
372 let range = self.map_count_byte_range();
373 self.data.read_at(range.start).ok().unwrap()
374 }
375
376 pub fn map_data(&self) -> &'a [u8] {
378 let range = self.map_data_byte_range();
379 self.data.read_array(range).ok().unwrap_or_default()
380 }
381
382 pub fn format_byte_range(&self) -> Range<usize> {
383 let start = 0;
384 start..start + u8::RAW_BYTE_LEN
385 }
386
387 pub fn entry_format_byte_range(&self) -> Range<usize> {
388 let start = self.format_byte_range().end;
389 start..start + EntryFormat::RAW_BYTE_LEN
390 }
391
392 pub fn map_count_byte_range(&self) -> Range<usize> {
393 let start = self.entry_format_byte_range().end;
394 start..start + u32::RAW_BYTE_LEN
395 }
396
397 pub fn map_data_byte_range(&self) -> Range<usize> {
398 let entry_format = self.entry_format();
399 let map_count = self.map_count();
400 let start = self.map_count_byte_range().end;
401 start
402 ..start
403 + (EntryFormat::map_size(entry_format, map_count)).saturating_mul(u8::RAW_BYTE_LEN)
404 }
405}
406
407#[cfg(feature = "experimental_traverse")]
408impl<'a> SomeTable<'a> for DeltaSetIndexMapFormat1<'a> {
409 fn type_name(&self) -> &str {
410 "DeltaSetIndexMapFormat1"
411 }
412 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
413 match idx {
414 0usize => Some(Field::new("format", self.format())),
415 1usize => Some(Field::new("entry_format", self.entry_format())),
416 2usize => Some(Field::new("map_count", self.map_count())),
417 3usize => Some(Field::new("map_data", self.map_data())),
418 _ => None,
419 }
420 }
421}
422
423#[cfg(feature = "experimental_traverse")]
424#[allow(clippy::needless_lifetimes)]
425impl<'a> std::fmt::Debug for DeltaSetIndexMapFormat1<'a> {
426 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
427 (self as &dyn SomeTable<'a>).fmt(f)
428 }
429}
430
431#[derive(Clone)]
433pub enum DeltaSetIndexMap<'a> {
434 Format0(DeltaSetIndexMapFormat0<'a>),
435 Format1(DeltaSetIndexMapFormat1<'a>),
436}
437
438impl<'a> DeltaSetIndexMap<'a> {
439 pub fn offset_data(&self) -> FontData<'a> {
441 match self {
442 Self::Format0(item) => item.offset_data(),
443 Self::Format1(item) => item.offset_data(),
444 }
445 }
446
447 pub fn format(&self) -> u8 {
449 match self {
450 Self::Format0(item) => item.format(),
451 Self::Format1(item) => item.format(),
452 }
453 }
454
455 pub fn entry_format(&self) -> EntryFormat {
458 match self {
459 Self::Format0(item) => item.entry_format(),
460 Self::Format1(item) => item.entry_format(),
461 }
462 }
463
464 pub fn map_data(&self) -> &'a [u8] {
466 match self {
467 Self::Format0(item) => item.map_data(),
468 Self::Format1(item) => item.map_data(),
469 }
470 }
471}
472
473impl<'a> FontRead<'a> for DeltaSetIndexMap<'a> {
474 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
475 let format: u8 = data.read_at(0usize)?;
476 match format {
477 DeltaSetIndexMapFormat0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
478 DeltaSetIndexMapFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
479 other => Err(ReadError::InvalidFormat(other.into())),
480 }
481 }
482}
483
484impl<'a> MinByteRange<'a> for DeltaSetIndexMap<'a> {
485 fn min_byte_range(&self) -> Range<usize> {
486 match self {
487 Self::Format0(item) => item.min_byte_range(),
488 Self::Format1(item) => item.min_byte_range(),
489 }
490 }
491 fn min_table_bytes(&self) -> &'a [u8] {
492 match self {
493 Self::Format0(item) => item.min_table_bytes(),
494 Self::Format1(item) => item.min_table_bytes(),
495 }
496 }
497}
498
499#[cfg(feature = "experimental_traverse")]
500impl<'a> DeltaSetIndexMap<'a> {
501 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
502 match self {
503 Self::Format0(table) => table,
504 Self::Format1(table) => table,
505 }
506 }
507}
508
509#[cfg(feature = "experimental_traverse")]
510impl std::fmt::Debug for DeltaSetIndexMap<'_> {
511 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
512 self.dyn_inner().fmt(f)
513 }
514}
515
516#[cfg(feature = "experimental_traverse")]
517impl<'a> SomeTable<'a> for DeltaSetIndexMap<'a> {
518 fn type_name(&self) -> &str {
519 self.dyn_inner().type_name()
520 }
521 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
522 self.dyn_inner().get_field(idx)
523 }
524}
525
526#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
528#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
529#[repr(transparent)]
530pub struct EntryFormat {
531 bits: u8,
532}
533
534impl EntryFormat {
535 pub const INNER_INDEX_BIT_COUNT_MASK: Self = Self { bits: 0x0F };
537
538 pub const MAP_ENTRY_SIZE_MASK: Self = Self { bits: 0x30 };
540}
541
542impl EntryFormat {
543 #[inline]
545 pub const fn empty() -> Self {
546 Self { bits: 0 }
547 }
548
549 #[inline]
551 pub const fn all() -> Self {
552 Self {
553 bits: Self::INNER_INDEX_BIT_COUNT_MASK.bits | Self::MAP_ENTRY_SIZE_MASK.bits,
554 }
555 }
556
557 #[inline]
559 pub const fn bits(&self) -> u8 {
560 self.bits
561 }
562
563 #[inline]
566 pub const fn from_bits(bits: u8) -> Option<Self> {
567 if (bits & !Self::all().bits()) == 0 {
568 Some(Self { bits })
569 } else {
570 None
571 }
572 }
573
574 #[inline]
577 pub const fn from_bits_truncate(bits: u8) -> Self {
578 Self {
579 bits: bits & Self::all().bits,
580 }
581 }
582
583 #[inline]
585 pub const fn is_empty(&self) -> bool {
586 self.bits() == Self::empty().bits()
587 }
588
589 #[inline]
591 pub const fn intersects(&self, other: Self) -> bool {
592 !(Self {
593 bits: self.bits & other.bits,
594 })
595 .is_empty()
596 }
597
598 #[inline]
600 pub const fn contains(&self, other: Self) -> bool {
601 (self.bits & other.bits) == other.bits
602 }
603
604 #[inline]
606 pub fn insert(&mut self, other: Self) {
607 self.bits |= other.bits;
608 }
609
610 #[inline]
612 pub fn remove(&mut self, other: Self) {
613 self.bits &= !other.bits;
614 }
615
616 #[inline]
618 pub fn toggle(&mut self, other: Self) {
619 self.bits ^= other.bits;
620 }
621
622 #[inline]
633 #[must_use]
634 pub const fn intersection(self, other: Self) -> Self {
635 Self {
636 bits: self.bits & other.bits,
637 }
638 }
639
640 #[inline]
651 #[must_use]
652 pub const fn union(self, other: Self) -> Self {
653 Self {
654 bits: self.bits | other.bits,
655 }
656 }
657
658 #[inline]
671 #[must_use]
672 pub const fn difference(self, other: Self) -> Self {
673 Self {
674 bits: self.bits & !other.bits,
675 }
676 }
677}
678
679impl std::ops::BitOr for EntryFormat {
680 type Output = Self;
681
682 #[inline]
684 fn bitor(self, other: EntryFormat) -> Self {
685 Self {
686 bits: self.bits | other.bits,
687 }
688 }
689}
690
691impl std::ops::BitOrAssign for EntryFormat {
692 #[inline]
694 fn bitor_assign(&mut self, other: Self) {
695 self.bits |= other.bits;
696 }
697}
698
699impl std::ops::BitXor for EntryFormat {
700 type Output = Self;
701
702 #[inline]
704 fn bitxor(self, other: Self) -> Self {
705 Self {
706 bits: self.bits ^ other.bits,
707 }
708 }
709}
710
711impl std::ops::BitXorAssign for EntryFormat {
712 #[inline]
714 fn bitxor_assign(&mut self, other: Self) {
715 self.bits ^= other.bits;
716 }
717}
718
719impl std::ops::BitAnd for EntryFormat {
720 type Output = Self;
721
722 #[inline]
724 fn bitand(self, other: Self) -> Self {
725 Self {
726 bits: self.bits & other.bits,
727 }
728 }
729}
730
731impl std::ops::BitAndAssign for EntryFormat {
732 #[inline]
734 fn bitand_assign(&mut self, other: Self) {
735 self.bits &= other.bits;
736 }
737}
738
739impl std::ops::Sub for EntryFormat {
740 type Output = Self;
741
742 #[inline]
744 fn sub(self, other: Self) -> Self {
745 Self {
746 bits: self.bits & !other.bits,
747 }
748 }
749}
750
751impl std::ops::SubAssign for EntryFormat {
752 #[inline]
754 fn sub_assign(&mut self, other: Self) {
755 self.bits &= !other.bits;
756 }
757}
758
759impl std::ops::Not for EntryFormat {
760 type Output = Self;
761
762 #[inline]
764 fn not(self) -> Self {
765 Self { bits: !self.bits } & Self::all()
766 }
767}
768
769impl std::fmt::Debug for EntryFormat {
770 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
771 let members: &[(&str, Self)] = &[
772 (
773 "INNER_INDEX_BIT_COUNT_MASK",
774 Self::INNER_INDEX_BIT_COUNT_MASK,
775 ),
776 ("MAP_ENTRY_SIZE_MASK", Self::MAP_ENTRY_SIZE_MASK),
777 ];
778 let mut first = true;
779 for (name, value) in members {
780 if self.contains(*value) {
781 if !first {
782 f.write_str(" | ")?;
783 }
784 first = false;
785 f.write_str(name)?;
786 }
787 }
788 if first {
789 f.write_str("(empty)")?;
790 }
791 Ok(())
792 }
793}
794
795impl std::fmt::Binary for EntryFormat {
796 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
797 std::fmt::Binary::fmt(&self.bits, f)
798 }
799}
800
801impl std::fmt::Octal for EntryFormat {
802 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
803 std::fmt::Octal::fmt(&self.bits, f)
804 }
805}
806
807impl std::fmt::LowerHex for EntryFormat {
808 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
809 std::fmt::LowerHex::fmt(&self.bits, f)
810 }
811}
812
813impl std::fmt::UpperHex for EntryFormat {
814 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
815 std::fmt::UpperHex::fmt(&self.bits, f)
816 }
817}
818
819impl font_types::Scalar for EntryFormat {
820 type Raw = <u8 as font_types::Scalar>::Raw;
821 fn to_raw(self) -> Self::Raw {
822 self.bits().to_raw()
823 }
824 fn from_raw(raw: Self::Raw) -> Self {
825 let t = <u8>::from_raw(raw);
826 Self::from_bits_truncate(t)
827 }
828}
829
830#[cfg(feature = "experimental_traverse")]
831impl<'a> From<EntryFormat> for FieldType<'a> {
832 fn from(src: EntryFormat) -> FieldType<'a> {
833 src.bits().into()
834 }
835}
836
837impl<'a> MinByteRange<'a> for VariationRegionList<'a> {
838 fn min_byte_range(&self) -> Range<usize> {
839 0..self.variation_regions_byte_range().end
840 }
841 fn min_table_bytes(&self) -> &'a [u8] {
842 let range = self.min_byte_range();
843 self.data.as_bytes().get(range).unwrap_or_default()
844 }
845}
846
847impl<'a> FontRead<'a> for VariationRegionList<'a> {
848 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
849 #[allow(clippy::absurd_extreme_comparisons)]
850 if data.len() < Self::MIN_SIZE {
851 return Err(ReadError::OutOfBounds);
852 }
853 Ok(Self { data })
854 }
855}
856
857#[derive(Clone)]
859pub struct VariationRegionList<'a> {
860 data: FontData<'a>,
861}
862
863#[allow(clippy::needless_lifetimes)]
864impl<'a> VariationRegionList<'a> {
865 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
866 basic_table_impls!(impl_the_methods);
867
868 pub fn axis_count(&self) -> u16 {
871 let range = self.axis_count_byte_range();
872 self.data.read_at(range.start).ok().unwrap()
873 }
874
875 pub fn region_count(&self) -> u16 {
878 let range = self.region_count_byte_range();
879 self.data.read_at(range.start).ok().unwrap()
880 }
881
882 pub fn variation_regions(&self) -> ComputedArray<'a, VariationRegion<'a>> {
884 let range = self.variation_regions_byte_range();
885 self.data
886 .read_with_args(range, &self.axis_count())
887 .unwrap_or_default()
888 }
889
890 pub fn axis_count_byte_range(&self) -> Range<usize> {
891 let start = 0;
892 start..start + u16::RAW_BYTE_LEN
893 }
894
895 pub fn region_count_byte_range(&self) -> Range<usize> {
896 let start = self.axis_count_byte_range().end;
897 start..start + u16::RAW_BYTE_LEN
898 }
899
900 pub fn variation_regions_byte_range(&self) -> Range<usize> {
901 let region_count = self.region_count();
902 let start = self.region_count_byte_range().end;
903 start
904 ..start
905 + (region_count as usize).saturating_mul(
906 <VariationRegion as ComputeSize>::compute_size(&self.axis_count()).unwrap_or(0),
907 )
908 }
909}
910
911#[cfg(feature = "experimental_traverse")]
912impl<'a> SomeTable<'a> for VariationRegionList<'a> {
913 fn type_name(&self) -> &str {
914 "VariationRegionList"
915 }
916 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
917 match idx {
918 0usize => Some(Field::new("axis_count", self.axis_count())),
919 1usize => Some(Field::new("region_count", self.region_count())),
920 2usize => Some(Field::new(
921 "variation_regions",
922 traversal::FieldType::computed_array(
923 "VariationRegion",
924 self.variation_regions(),
925 self.offset_data(),
926 ),
927 )),
928 _ => None,
929 }
930 }
931}
932
933#[cfg(feature = "experimental_traverse")]
934#[allow(clippy::needless_lifetimes)]
935impl<'a> std::fmt::Debug for VariationRegionList<'a> {
936 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
937 (self as &dyn SomeTable<'a>).fmt(f)
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((axis_count as usize).saturating_mul(RegionAxisCoordinates::RAW_BYTE_LEN))
966 }
967}
968
969impl<'a> FontReadWithArgs<'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(axis_count as usize)?,
975 })
976 }
977}
978
979#[allow(clippy::needless_lifetimes)]
980impl<'a> VariationRegion<'a> {
981 pub fn read(data: FontData<'a>, axis_count: u16) -> Result<Self, ReadError> {
986 let args = axis_count;
987 Self::read_with_args(data, &args)
988 }
989}
990
991#[cfg(feature = "experimental_traverse")]
992impl<'a> SomeRecord<'a> for VariationRegion<'a> {
993 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
994 RecordResolver {
995 name: "VariationRegion",
996 get_field: Box::new(move |idx, _data| match idx {
997 0usize => Some(Field::new(
998 "region_axes",
999 traversal::FieldType::array_of_records(
1000 stringify!(RegionAxisCoordinates),
1001 self.region_axes(),
1002 _data,
1003 ),
1004 )),
1005 _ => None,
1006 }),
1007 data,
1008 }
1009 }
1010}
1011
1012#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1014#[repr(C)]
1015#[repr(packed)]
1016pub struct RegionAxisCoordinates {
1017 pub start_coord: BigEndian<F2Dot14>,
1019 pub peak_coord: BigEndian<F2Dot14>,
1021 pub end_coord: BigEndian<F2Dot14>,
1023}
1024
1025impl RegionAxisCoordinates {
1026 pub fn start_coord(&self) -> F2Dot14 {
1028 self.start_coord.get()
1029 }
1030
1031 pub fn peak_coord(&self) -> F2Dot14 {
1033 self.peak_coord.get()
1034 }
1035
1036 pub fn end_coord(&self) -> F2Dot14 {
1038 self.end_coord.get()
1039 }
1040}
1041
1042impl FixedSize for RegionAxisCoordinates {
1043 const RAW_BYTE_LEN: usize =
1044 F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN;
1045}
1046
1047#[cfg(feature = "experimental_traverse")]
1048impl<'a> SomeRecord<'a> for RegionAxisCoordinates {
1049 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1050 RecordResolver {
1051 name: "RegionAxisCoordinates",
1052 get_field: Box::new(move |idx, _data| match idx {
1053 0usize => Some(Field::new("start_coord", self.start_coord())),
1054 1usize => Some(Field::new("peak_coord", self.peak_coord())),
1055 2usize => Some(Field::new("end_coord", self.end_coord())),
1056 _ => None,
1057 }),
1058 data,
1059 }
1060 }
1061}
1062
1063impl<'a> MinByteRange<'a> for ItemVariationStore<'a> {
1064 fn min_byte_range(&self) -> Range<usize> {
1065 0..self.item_variation_data_offsets_byte_range().end
1066 }
1067 fn min_table_bytes(&self) -> &'a [u8] {
1068 let range = self.min_byte_range();
1069 self.data.as_bytes().get(range).unwrap_or_default()
1070 }
1071}
1072
1073impl<'a> FontRead<'a> for ItemVariationStore<'a> {
1074 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1075 #[allow(clippy::absurd_extreme_comparisons)]
1076 if data.len() < Self::MIN_SIZE {
1077 return Err(ReadError::OutOfBounds);
1078 }
1079 Ok(Self { data })
1080 }
1081}
1082
1083#[derive(Clone)]
1085pub struct ItemVariationStore<'a> {
1086 data: FontData<'a>,
1087}
1088
1089#[allow(clippy::needless_lifetimes)]
1090impl<'a> ItemVariationStore<'a> {
1091 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1092 basic_table_impls!(impl_the_methods);
1093
1094 pub fn format(&self) -> u16 {
1096 let range = self.format_byte_range();
1097 self.data.read_at(range.start).ok().unwrap()
1098 }
1099
1100 pub fn variation_region_list_offset(&self) -> Offset32 {
1103 let range = self.variation_region_list_offset_byte_range();
1104 self.data.read_at(range.start).ok().unwrap()
1105 }
1106
1107 pub fn variation_region_list(&self) -> Result<VariationRegionList<'a>, ReadError> {
1109 let data = self.data;
1110 self.variation_region_list_offset().resolve(data)
1111 }
1112
1113 pub fn item_variation_data_count(&self) -> u16 {
1115 let range = self.item_variation_data_count_byte_range();
1116 self.data.read_at(range.start).ok().unwrap()
1117 }
1118
1119 pub fn item_variation_data_offsets(&self) -> &'a [BigEndian<Nullable<Offset32>>] {
1122 let range = self.item_variation_data_offsets_byte_range();
1123 self.data.read_array(range).ok().unwrap_or_default()
1124 }
1125
1126 pub fn item_variation_data(
1128 &self,
1129 ) -> ArrayOfNullableOffsets<'a, ItemVariationData<'a>, Offset32> {
1130 let data = self.data;
1131 let offsets = self.item_variation_data_offsets();
1132 ArrayOfNullableOffsets::new(offsets, data, ())
1133 }
1134
1135 pub fn format_byte_range(&self) -> Range<usize> {
1136 let start = 0;
1137 start..start + u16::RAW_BYTE_LEN
1138 }
1139
1140 pub fn variation_region_list_offset_byte_range(&self) -> Range<usize> {
1141 let start = self.format_byte_range().end;
1142 start..start + Offset32::RAW_BYTE_LEN
1143 }
1144
1145 pub fn item_variation_data_count_byte_range(&self) -> Range<usize> {
1146 let start = self.variation_region_list_offset_byte_range().end;
1147 start..start + u16::RAW_BYTE_LEN
1148 }
1149
1150 pub fn item_variation_data_offsets_byte_range(&self) -> Range<usize> {
1151 let item_variation_data_count = self.item_variation_data_count();
1152 let start = self.item_variation_data_count_byte_range().end;
1153 start..start + (item_variation_data_count as usize).saturating_mul(Offset32::RAW_BYTE_LEN)
1154 }
1155}
1156
1157#[cfg(feature = "experimental_traverse")]
1158impl<'a> SomeTable<'a> for ItemVariationStore<'a> {
1159 fn type_name(&self) -> &str {
1160 "ItemVariationStore"
1161 }
1162 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1163 match idx {
1164 0usize => Some(Field::new("format", self.format())),
1165 1usize => Some(Field::new(
1166 "variation_region_list_offset",
1167 FieldType::offset(
1168 self.variation_region_list_offset(),
1169 self.variation_region_list(),
1170 ),
1171 )),
1172 2usize => Some(Field::new(
1173 "item_variation_data_count",
1174 self.item_variation_data_count(),
1175 )),
1176 3usize => Some({
1177 let data = self.data;
1178 Field::new(
1179 "item_variation_data_offsets",
1180 FieldType::array_of_offsets(
1181 better_type_name::<ItemVariationData>(),
1182 self.item_variation_data_offsets(),
1183 move |off| {
1184 let target = off.get().resolve::<ItemVariationData>(data);
1185 FieldType::offset(off.get(), target)
1186 },
1187 ),
1188 )
1189 }),
1190 _ => None,
1191 }
1192 }
1193}
1194
1195#[cfg(feature = "experimental_traverse")]
1196#[allow(clippy::needless_lifetimes)]
1197impl<'a> std::fmt::Debug for ItemVariationStore<'a> {
1198 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1199 (self as &dyn SomeTable<'a>).fmt(f)
1200 }
1201}
1202
1203impl<'a> MinByteRange<'a> for ItemVariationData<'a> {
1204 fn min_byte_range(&self) -> Range<usize> {
1205 0..self.delta_sets_byte_range().end
1206 }
1207 fn min_table_bytes(&self) -> &'a [u8] {
1208 let range = self.min_byte_range();
1209 self.data.as_bytes().get(range).unwrap_or_default()
1210 }
1211}
1212
1213impl<'a> FontRead<'a> for ItemVariationData<'a> {
1214 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1215 #[allow(clippy::absurd_extreme_comparisons)]
1216 if data.len() < Self::MIN_SIZE {
1217 return Err(ReadError::OutOfBounds);
1218 }
1219 Ok(Self { data })
1220 }
1221}
1222
1223#[derive(Clone)]
1225pub struct ItemVariationData<'a> {
1226 data: FontData<'a>,
1227}
1228
1229#[allow(clippy::needless_lifetimes)]
1230impl<'a> ItemVariationData<'a> {
1231 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1232 basic_table_impls!(impl_the_methods);
1233
1234 pub fn item_count(&self) -> u16 {
1236 let range = self.item_count_byte_range();
1237 self.data.read_at(range.start).ok().unwrap()
1238 }
1239
1240 pub fn word_delta_count(&self) -> u16 {
1242 let range = self.word_delta_count_byte_range();
1243 self.data.read_at(range.start).ok().unwrap()
1244 }
1245
1246 pub fn region_index_count(&self) -> u16 {
1248 let range = self.region_index_count_byte_range();
1249 self.data.read_at(range.start).ok().unwrap()
1250 }
1251
1252 pub fn region_indexes(&self) -> &'a [BigEndian<u16>] {
1255 let range = self.region_indexes_byte_range();
1256 self.data.read_array(range).ok().unwrap_or_default()
1257 }
1258
1259 pub fn delta_sets(&self) -> &'a [u8] {
1261 let range = self.delta_sets_byte_range();
1262 self.data.read_array(range).ok().unwrap_or_default()
1263 }
1264
1265 pub fn item_count_byte_range(&self) -> Range<usize> {
1266 let start = 0;
1267 start..start + u16::RAW_BYTE_LEN
1268 }
1269
1270 pub fn word_delta_count_byte_range(&self) -> Range<usize> {
1271 let start = self.item_count_byte_range().end;
1272 start..start + u16::RAW_BYTE_LEN
1273 }
1274
1275 pub fn region_index_count_byte_range(&self) -> Range<usize> {
1276 let start = self.word_delta_count_byte_range().end;
1277 start..start + u16::RAW_BYTE_LEN
1278 }
1279
1280 pub fn region_indexes_byte_range(&self) -> Range<usize> {
1281 let region_index_count = self.region_index_count();
1282 let start = self.region_index_count_byte_range().end;
1283 start..start + (region_index_count as usize).saturating_mul(u16::RAW_BYTE_LEN)
1284 }
1285
1286 pub fn delta_sets_byte_range(&self) -> Range<usize> {
1287 let item_count = self.item_count();
1288 let word_delta_count = self.word_delta_count();
1289 let region_index_count = self.region_index_count();
1290 let start = self.region_indexes_byte_range().end;
1291 start
1292 ..start
1293 + (ItemVariationData::delta_sets_len(
1294 item_count,
1295 word_delta_count,
1296 region_index_count,
1297 ))
1298 .saturating_mul(u8::RAW_BYTE_LEN)
1299 }
1300}
1301
1302#[cfg(feature = "experimental_traverse")]
1303impl<'a> SomeTable<'a> for ItemVariationData<'a> {
1304 fn type_name(&self) -> &str {
1305 "ItemVariationData"
1306 }
1307 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1308 match idx {
1309 0usize => Some(Field::new("item_count", self.item_count())),
1310 1usize => Some(Field::new("word_delta_count", self.word_delta_count())),
1311 2usize => Some(Field::new("region_index_count", self.region_index_count())),
1312 3usize => Some(Field::new("region_indexes", self.region_indexes())),
1313 4usize => Some(Field::new("delta_sets", self.delta_sets())),
1314 _ => None,
1315 }
1316 }
1317}
1318
1319#[cfg(feature = "experimental_traverse")]
1320#[allow(clippy::needless_lifetimes)]
1321impl<'a> std::fmt::Debug for ItemVariationData<'a> {
1322 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1323 (self as &dyn SomeTable<'a>).fmt(f)
1324 }
1325}