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 let end = start + u16::RAW_BYTE_LEN;
78 start..end
79 }
80
81 pub fn tuple_index_byte_range(&self) -> Range<usize> {
82 let start = self.variation_data_size_byte_range().end;
83 let end = start + TupleIndex::RAW_BYTE_LEN;
84 start..end
85 }
86
87 pub fn peak_tuple_byte_range(&self) -> Range<usize> {
88 let tuple_index = self.tuple_index();
89 let axis_count = self.axis_count();
90 let start = self.tuple_index_byte_range().end;
91 let end = start
92 + (TupleIndex::tuple_len(tuple_index, axis_count, 0_usize))
93 .saturating_mul(F2Dot14::RAW_BYTE_LEN);
94 start..end
95 }
96
97 pub fn intermediate_start_tuple_byte_range(&self) -> Range<usize> {
98 let tuple_index = self.tuple_index();
99 let axis_count = self.axis_count();
100 let start = self.peak_tuple_byte_range().end;
101 let end = start
102 + (TupleIndex::tuple_len(tuple_index, axis_count, 1_usize))
103 .saturating_mul(F2Dot14::RAW_BYTE_LEN);
104 start..end
105 }
106
107 pub fn intermediate_end_tuple_byte_range(&self) -> Range<usize> {
108 let tuple_index = self.tuple_index();
109 let axis_count = self.axis_count();
110 let start = self.intermediate_start_tuple_byte_range().end;
111 let end = start
112 + (TupleIndex::tuple_len(tuple_index, axis_count, 1_usize))
113 .saturating_mul(F2Dot14::RAW_BYTE_LEN);
114 start..end
115 }
116}
117
118const _: () = assert!(FontData::default_data_long_enough(
119 TupleVariationHeader::MIN_SIZE
120));
121
122impl Default for TupleVariationHeader<'_> {
123 fn default() -> Self {
124 Self {
125 data: FontData::default_table_data(),
126 axis_count: Default::default(),
127 }
128 }
129}
130
131#[cfg(feature = "experimental_traverse")]
132impl<'a> SomeTable<'a> for TupleVariationHeader<'a> {
133 fn type_name(&self) -> &str {
134 "TupleVariationHeader"
135 }
136 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
137 match idx {
138 0usize => Some(Field::new(
139 "variation_data_size",
140 self.variation_data_size(),
141 )),
142 1usize => Some(Field::new("tuple_index", self.traverse_tuple_index())),
143 _ => None,
144 }
145 }
146}
147
148#[cfg(feature = "experimental_traverse")]
149#[allow(clippy::needless_lifetimes)]
150impl<'a> std::fmt::Debug for TupleVariationHeader<'a> {
151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
152 (self as &dyn SomeTable<'a>).fmt(f)
153 }
154}
155
156#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
162pub struct Tuple<'a> {
163 pub values: &'a [BigEndian<F2Dot14>],
168}
169
170impl<'a> Tuple<'a> {
171 pub fn values(&self) -> &'a [BigEndian<F2Dot14>] {
176 self.values
177 }
178}
179
180impl ReadArgs for Tuple<'_> {
181 type Args = u16;
182}
183
184impl ComputeSize for Tuple<'_> {
185 #[allow(clippy::needless_question_mark)]
186 fn compute_size(args: &u16) -> Result<usize, ReadError> {
187 let axis_count = *args;
188 Ok((transforms::to_usize(axis_count)).saturating_mul(F2Dot14::RAW_BYTE_LEN))
189 }
190}
191
192impl<'a> FontReadWithArgs<'a> for Tuple<'a> {
193 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
194 let mut cursor = data.cursor();
195 let axis_count = *args;
196 Ok(Self {
197 values: cursor.read_array(transforms::to_usize(axis_count))?,
198 })
199 }
200}
201
202#[allow(clippy::needless_lifetimes)]
203impl<'a> Tuple<'a> {
204 pub fn read(data: FontData<'a>, axis_count: u16) -> Result<Self, ReadError> {
209 let args = axis_count;
210 Self::read_with_args(data, &args)
211 }
212}
213
214#[cfg(feature = "experimental_traverse")]
215impl<'a> SomeRecord<'a> for Tuple<'a> {
216 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
217 RecordResolver {
218 name: "Tuple",
219 get_field: Box::new(move |idx, _data| match idx {
220 0usize => Some(Field::new("values", self.values())),
221 _ => None,
222 }),
223 data,
224 }
225 }
226}
227
228impl Format<u8> for DeltaSetIndexMapFormat0<'_> {
229 const FORMAT: u8 = 0;
230}
231
232impl<'a> MinByteRange<'a> for DeltaSetIndexMapFormat0<'a> {
233 fn min_byte_range(&self) -> Range<usize> {
234 0..self.map_data_byte_range().end
235 }
236 fn min_table_bytes(&self) -> &'a [u8] {
237 let range = self.min_byte_range();
238 self.data.as_bytes().get(range).unwrap_or_default()
239 }
240}
241
242impl<'a> FontRead<'a> for DeltaSetIndexMapFormat0<'a> {
243 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
244 #[allow(clippy::absurd_extreme_comparisons)]
245 if data.len() < Self::MIN_SIZE {
246 return Err(ReadError::OutOfBounds);
247 }
248 Ok(Self { data })
249 }
250}
251
252#[derive(Clone)]
254pub struct DeltaSetIndexMapFormat0<'a> {
255 data: FontData<'a>,
256}
257
258#[allow(clippy::needless_lifetimes)]
259impl<'a> DeltaSetIndexMapFormat0<'a> {
260 pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + EntryFormat::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
261 basic_table_impls!(impl_the_methods);
262
263 pub fn format(&self) -> u8 {
265 let range = self.format_byte_range();
266 self.data.read_at(range.start).ok().unwrap()
267 }
268
269 pub fn entry_format(&self) -> EntryFormat {
272 let range = self.entry_format_byte_range();
273 self.data.read_at(range.start).ok().unwrap()
274 }
275
276 pub fn map_count(&self) -> u16 {
278 let range = self.map_count_byte_range();
279 self.data.read_at(range.start).ok().unwrap()
280 }
281
282 pub fn map_data(&self) -> &'a [u8] {
284 let range = self.map_data_byte_range();
285 self.data.read_array(range).ok().unwrap_or_default()
286 }
287
288 pub fn format_byte_range(&self) -> Range<usize> {
289 let start = 0;
290 let end = start + u8::RAW_BYTE_LEN;
291 start..end
292 }
293
294 pub fn entry_format_byte_range(&self) -> Range<usize> {
295 let start = self.format_byte_range().end;
296 let end = start + EntryFormat::RAW_BYTE_LEN;
297 start..end
298 }
299
300 pub fn map_count_byte_range(&self) -> Range<usize> {
301 let start = self.entry_format_byte_range().end;
302 let end = start + u16::RAW_BYTE_LEN;
303 start..end
304 }
305
306 pub fn map_data_byte_range(&self) -> Range<usize> {
307 let entry_format = self.entry_format();
308 let map_count = self.map_count();
309 let start = self.map_count_byte_range().end;
310 let end = start
311 + (EntryFormat::map_size(entry_format, map_count)).saturating_mul(u8::RAW_BYTE_LEN);
312 start..end
313 }
314}
315
316const _: () = assert!(FontData::default_data_long_enough(
317 DeltaSetIndexMapFormat0::MIN_SIZE
318));
319
320impl Default for DeltaSetIndexMapFormat0<'_> {
321 fn default() -> Self {
322 Self {
323 data: FontData::default_table_data(),
324 }
325 }
326}
327
328#[cfg(feature = "experimental_traverse")]
329impl<'a> SomeTable<'a> for DeltaSetIndexMapFormat0<'a> {
330 fn type_name(&self) -> &str {
331 "DeltaSetIndexMapFormat0"
332 }
333 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
334 match idx {
335 0usize => Some(Field::new("format", self.format())),
336 1usize => Some(Field::new("entry_format", self.entry_format())),
337 2usize => Some(Field::new("map_count", self.map_count())),
338 3usize => Some(Field::new("map_data", self.map_data())),
339 _ => None,
340 }
341 }
342}
343
344#[cfg(feature = "experimental_traverse")]
345#[allow(clippy::needless_lifetimes)]
346impl<'a> std::fmt::Debug for DeltaSetIndexMapFormat0<'a> {
347 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
348 (self as &dyn SomeTable<'a>).fmt(f)
349 }
350}
351
352impl Format<u8> for DeltaSetIndexMapFormat1<'_> {
353 const FORMAT: u8 = 1;
354}
355
356impl<'a> MinByteRange<'a> for DeltaSetIndexMapFormat1<'a> {
357 fn min_byte_range(&self) -> Range<usize> {
358 0..self.map_data_byte_range().end
359 }
360 fn min_table_bytes(&self) -> &'a [u8] {
361 let range = self.min_byte_range();
362 self.data.as_bytes().get(range).unwrap_or_default()
363 }
364}
365
366impl<'a> FontRead<'a> for DeltaSetIndexMapFormat1<'a> {
367 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
368 #[allow(clippy::absurd_extreme_comparisons)]
369 if data.len() < Self::MIN_SIZE {
370 return Err(ReadError::OutOfBounds);
371 }
372 Ok(Self { data })
373 }
374}
375
376#[derive(Clone)]
378pub struct DeltaSetIndexMapFormat1<'a> {
379 data: FontData<'a>,
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 let range = self.format_byte_range();
390 self.data.read_at(range.start).ok().unwrap()
391 }
392
393 pub fn entry_format(&self) -> EntryFormat {
396 let range = self.entry_format_byte_range();
397 self.data.read_at(range.start).ok().unwrap()
398 }
399
400 pub fn map_count(&self) -> u32 {
402 let range = self.map_count_byte_range();
403 self.data.read_at(range.start).ok().unwrap()
404 }
405
406 pub fn map_data(&self) -> &'a [u8] {
408 let range = self.map_data_byte_range();
409 self.data.read_array(range).ok().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: FontData::default_format_1_u8_table_data(),
448 }
449 }
450}
451
452#[cfg(feature = "experimental_traverse")]
453impl<'a> SomeTable<'a> for DeltaSetIndexMapFormat1<'a> {
454 fn type_name(&self) -> &str {
455 "DeltaSetIndexMapFormat1"
456 }
457 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
458 match idx {
459 0usize => Some(Field::new("format", self.format())),
460 1usize => Some(Field::new("entry_format", self.entry_format())),
461 2usize => Some(Field::new("map_count", self.map_count())),
462 3usize => Some(Field::new("map_data", self.map_data())),
463 _ => None,
464 }
465 }
466}
467
468#[cfg(feature = "experimental_traverse")]
469#[allow(clippy::needless_lifetimes)]
470impl<'a> std::fmt::Debug for DeltaSetIndexMapFormat1<'a> {
471 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
472 (self as &dyn SomeTable<'a>).fmt(f)
473 }
474}
475
476#[derive(Clone)]
478pub enum DeltaSetIndexMap<'a> {
479 Format0(DeltaSetIndexMapFormat0<'a>),
480 Format1(DeltaSetIndexMapFormat1<'a>),
481}
482
483impl Default for DeltaSetIndexMap<'_> {
484 fn default() -> Self {
485 Self::Format0(Default::default())
486 }
487}
488
489impl<'a> DeltaSetIndexMap<'a> {
490 pub fn offset_data(&self) -> FontData<'a> {
492 match self {
493 Self::Format0(item) => item.offset_data(),
494 Self::Format1(item) => item.offset_data(),
495 }
496 }
497
498 pub fn format(&self) -> u8 {
500 match self {
501 Self::Format0(item) => item.format(),
502 Self::Format1(item) => item.format(),
503 }
504 }
505
506 pub fn entry_format(&self) -> EntryFormat {
509 match self {
510 Self::Format0(item) => item.entry_format(),
511 Self::Format1(item) => item.entry_format(),
512 }
513 }
514
515 pub fn map_data(&self) -> &'a [u8] {
517 match self {
518 Self::Format0(item) => item.map_data(),
519 Self::Format1(item) => item.map_data(),
520 }
521 }
522}
523
524impl<'a> FontRead<'a> for DeltaSetIndexMap<'a> {
525 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
526 let format: u8 = data.read_at(0usize)?;
527 match format {
528 DeltaSetIndexMapFormat0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
529 DeltaSetIndexMapFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
530 other => Err(ReadError::InvalidFormat(other.into())),
531 }
532 }
533}
534
535impl<'a> MinByteRange<'a> for DeltaSetIndexMap<'a> {
536 fn min_byte_range(&self) -> Range<usize> {
537 match self {
538 Self::Format0(item) => item.min_byte_range(),
539 Self::Format1(item) => item.min_byte_range(),
540 }
541 }
542 fn min_table_bytes(&self) -> &'a [u8] {
543 match self {
544 Self::Format0(item) => item.min_table_bytes(),
545 Self::Format1(item) => item.min_table_bytes(),
546 }
547 }
548}
549
550#[cfg(feature = "experimental_traverse")]
551impl<'a> DeltaSetIndexMap<'a> {
552 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
553 match self {
554 Self::Format0(table) => table,
555 Self::Format1(table) => table,
556 }
557 }
558}
559
560#[cfg(feature = "experimental_traverse")]
561impl std::fmt::Debug for DeltaSetIndexMap<'_> {
562 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
563 self.dyn_inner().fmt(f)
564 }
565}
566
567#[cfg(feature = "experimental_traverse")]
568impl<'a> SomeTable<'a> for DeltaSetIndexMap<'a> {
569 fn type_name(&self) -> &str {
570 self.dyn_inner().type_name()
571 }
572 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
573 self.dyn_inner().get_field(idx)
574 }
575}
576
577#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
579#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
580#[repr(transparent)]
581pub struct EntryFormat {
582 bits: u8,
583}
584
585impl EntryFormat {
586 pub const INNER_INDEX_BIT_COUNT_MASK: Self = Self { bits: 0x0F };
588
589 pub const MAP_ENTRY_SIZE_MASK: Self = Self { bits: 0x30 };
591}
592
593impl EntryFormat {
594 #[inline]
596 pub const fn empty() -> Self {
597 Self { bits: 0 }
598 }
599
600 #[inline]
602 pub const fn all() -> Self {
603 Self {
604 bits: Self::INNER_INDEX_BIT_COUNT_MASK.bits | Self::MAP_ENTRY_SIZE_MASK.bits,
605 }
606 }
607
608 #[inline]
610 pub const fn bits(&self) -> u8 {
611 self.bits
612 }
613
614 #[inline]
617 pub const fn from_bits(bits: u8) -> Option<Self> {
618 if (bits & !Self::all().bits()) == 0 {
619 Some(Self { bits })
620 } else {
621 None
622 }
623 }
624
625 #[inline]
628 pub const fn from_bits_truncate(bits: u8) -> Self {
629 Self {
630 bits: bits & Self::all().bits,
631 }
632 }
633
634 #[inline]
636 pub const fn is_empty(&self) -> bool {
637 self.bits() == Self::empty().bits()
638 }
639
640 #[inline]
642 pub const fn intersects(&self, other: Self) -> bool {
643 !(Self {
644 bits: self.bits & other.bits,
645 })
646 .is_empty()
647 }
648
649 #[inline]
651 pub const fn contains(&self, other: Self) -> bool {
652 (self.bits & other.bits) == other.bits
653 }
654
655 #[inline]
657 pub fn insert(&mut self, other: Self) {
658 self.bits |= other.bits;
659 }
660
661 #[inline]
663 pub fn remove(&mut self, other: Self) {
664 self.bits &= !other.bits;
665 }
666
667 #[inline]
669 pub fn toggle(&mut self, other: Self) {
670 self.bits ^= other.bits;
671 }
672
673 #[inline]
684 #[must_use]
685 pub const fn intersection(self, other: Self) -> Self {
686 Self {
687 bits: self.bits & other.bits,
688 }
689 }
690
691 #[inline]
702 #[must_use]
703 pub const fn union(self, other: Self) -> Self {
704 Self {
705 bits: self.bits | other.bits,
706 }
707 }
708
709 #[inline]
722 #[must_use]
723 pub const fn difference(self, other: Self) -> Self {
724 Self {
725 bits: self.bits & !other.bits,
726 }
727 }
728}
729
730impl std::ops::BitOr for EntryFormat {
731 type Output = Self;
732
733 #[inline]
735 fn bitor(self, other: EntryFormat) -> Self {
736 Self {
737 bits: self.bits | other.bits,
738 }
739 }
740}
741
742impl std::ops::BitOrAssign for EntryFormat {
743 #[inline]
745 fn bitor_assign(&mut self, other: Self) {
746 self.bits |= other.bits;
747 }
748}
749
750impl std::ops::BitXor for EntryFormat {
751 type Output = Self;
752
753 #[inline]
755 fn bitxor(self, other: Self) -> Self {
756 Self {
757 bits: self.bits ^ other.bits,
758 }
759 }
760}
761
762impl std::ops::BitXorAssign for EntryFormat {
763 #[inline]
765 fn bitxor_assign(&mut self, other: Self) {
766 self.bits ^= other.bits;
767 }
768}
769
770impl std::ops::BitAnd for EntryFormat {
771 type Output = Self;
772
773 #[inline]
775 fn bitand(self, other: Self) -> Self {
776 Self {
777 bits: self.bits & other.bits,
778 }
779 }
780}
781
782impl std::ops::BitAndAssign for EntryFormat {
783 #[inline]
785 fn bitand_assign(&mut self, other: Self) {
786 self.bits &= other.bits;
787 }
788}
789
790impl std::ops::Sub for EntryFormat {
791 type Output = Self;
792
793 #[inline]
795 fn sub(self, other: Self) -> Self {
796 Self {
797 bits: self.bits & !other.bits,
798 }
799 }
800}
801
802impl std::ops::SubAssign for EntryFormat {
803 #[inline]
805 fn sub_assign(&mut self, other: Self) {
806 self.bits &= !other.bits;
807 }
808}
809
810impl std::ops::Not for EntryFormat {
811 type Output = Self;
812
813 #[inline]
815 fn not(self) -> Self {
816 Self { bits: !self.bits } & Self::all()
817 }
818}
819
820impl std::fmt::Debug for EntryFormat {
821 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
822 let members: &[(&str, Self)] = &[
823 (
824 "INNER_INDEX_BIT_COUNT_MASK",
825 Self::INNER_INDEX_BIT_COUNT_MASK,
826 ),
827 ("MAP_ENTRY_SIZE_MASK", Self::MAP_ENTRY_SIZE_MASK),
828 ];
829 let mut first = true;
830 for (name, value) in members {
831 if self.contains(*value) {
832 if !first {
833 f.write_str(" | ")?;
834 }
835 first = false;
836 f.write_str(name)?;
837 }
838 }
839 if first {
840 f.write_str("(empty)")?;
841 }
842 Ok(())
843 }
844}
845
846impl std::fmt::Binary for EntryFormat {
847 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
848 std::fmt::Binary::fmt(&self.bits, f)
849 }
850}
851
852impl std::fmt::Octal for EntryFormat {
853 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
854 std::fmt::Octal::fmt(&self.bits, f)
855 }
856}
857
858impl std::fmt::LowerHex for EntryFormat {
859 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
860 std::fmt::LowerHex::fmt(&self.bits, f)
861 }
862}
863
864impl std::fmt::UpperHex for EntryFormat {
865 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
866 std::fmt::UpperHex::fmt(&self.bits, f)
867 }
868}
869
870impl font_types::Scalar for EntryFormat {
871 type Raw = <u8 as font_types::Scalar>::Raw;
872 fn to_raw(self) -> Self::Raw {
873 self.bits().to_raw()
874 }
875 fn from_raw(raw: Self::Raw) -> Self {
876 let t = <u8>::from_raw(raw);
877 Self::from_bits_truncate(t)
878 }
879}
880
881#[cfg(feature = "experimental_traverse")]
882impl<'a> From<EntryFormat> for FieldType<'a> {
883 fn from(src: EntryFormat) -> FieldType<'a> {
884 src.bits().into()
885 }
886}
887
888impl<'a> MinByteRange<'a> for VariationRegionList<'a> {
889 fn min_byte_range(&self) -> Range<usize> {
890 0..self.variation_regions_byte_range().end
891 }
892 fn min_table_bytes(&self) -> &'a [u8] {
893 let range = self.min_byte_range();
894 self.data.as_bytes().get(range).unwrap_or_default()
895 }
896}
897
898impl<'a> FontRead<'a> for VariationRegionList<'a> {
899 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
900 #[allow(clippy::absurd_extreme_comparisons)]
901 if data.len() < Self::MIN_SIZE {
902 return Err(ReadError::OutOfBounds);
903 }
904 Ok(Self { data })
905 }
906}
907
908#[derive(Clone)]
910pub struct VariationRegionList<'a> {
911 data: FontData<'a>,
912}
913
914#[allow(clippy::needless_lifetimes)]
915impl<'a> VariationRegionList<'a> {
916 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
917 basic_table_impls!(impl_the_methods);
918
919 pub fn axis_count(&self) -> u16 {
922 let range = self.axis_count_byte_range();
923 self.data.read_at(range.start).ok().unwrap()
924 }
925
926 pub fn region_count(&self) -> u16 {
929 let range = self.region_count_byte_range();
930 self.data.read_at(range.start).ok().unwrap()
931 }
932
933 pub fn variation_regions(&self) -> ComputedArray<'a, VariationRegion<'a>> {
935 let range = self.variation_regions_byte_range();
936 self.data
937 .read_with_args(range, &self.axis_count())
938 .unwrap_or_default()
939 }
940
941 pub fn axis_count_byte_range(&self) -> Range<usize> {
942 let start = 0;
943 let end = start + u16::RAW_BYTE_LEN;
944 start..end
945 }
946
947 pub fn region_count_byte_range(&self) -> Range<usize> {
948 let start = self.axis_count_byte_range().end;
949 let end = start + u16::RAW_BYTE_LEN;
950 start..end
951 }
952
953 pub fn variation_regions_byte_range(&self) -> Range<usize> {
954 let region_count = self.region_count();
955 let start = self.region_count_byte_range().end;
956 let end = start
957 + (transforms::to_usize(region_count)).saturating_mul(
958 <VariationRegion as ComputeSize>::compute_size(&self.axis_count()).unwrap_or(0),
959 );
960 start..end
961 }
962}
963
964const _: () = assert!(FontData::default_data_long_enough(
965 VariationRegionList::MIN_SIZE
966));
967
968impl Default for VariationRegionList<'_> {
969 fn default() -> Self {
970 Self {
971 data: FontData::default_table_data(),
972 }
973 }
974}
975
976#[cfg(feature = "experimental_traverse")]
977impl<'a> SomeTable<'a> for VariationRegionList<'a> {
978 fn type_name(&self) -> &str {
979 "VariationRegionList"
980 }
981 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
982 match idx {
983 0usize => Some(Field::new("axis_count", self.axis_count())),
984 1usize => Some(Field::new("region_count", self.region_count())),
985 2usize => Some(Field::new(
986 "variation_regions",
987 traversal::FieldType::computed_array(
988 "VariationRegion",
989 self.variation_regions(),
990 self.offset_data(),
991 ),
992 )),
993 _ => None,
994 }
995 }
996}
997
998#[cfg(feature = "experimental_traverse")]
999#[allow(clippy::needless_lifetimes)]
1000impl<'a> std::fmt::Debug for VariationRegionList<'a> {
1001 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1002 (self as &dyn SomeTable<'a>).fmt(f)
1003 }
1004}
1005
1006#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1008pub struct VariationRegion<'a> {
1009 pub region_axes: &'a [RegionAxisCoordinates],
1012}
1013
1014impl<'a> VariationRegion<'a> {
1015 pub fn region_axes(&self) -> &'a [RegionAxisCoordinates] {
1018 self.region_axes
1019 }
1020}
1021
1022impl ReadArgs for VariationRegion<'_> {
1023 type Args = u16;
1024}
1025
1026impl ComputeSize for VariationRegion<'_> {
1027 #[allow(clippy::needless_question_mark)]
1028 fn compute_size(args: &u16) -> Result<usize, ReadError> {
1029 let axis_count = *args;
1030 Ok((transforms::to_usize(axis_count)).saturating_mul(RegionAxisCoordinates::RAW_BYTE_LEN))
1031 }
1032}
1033
1034impl<'a> FontReadWithArgs<'a> for VariationRegion<'a> {
1035 fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
1036 let mut cursor = data.cursor();
1037 let axis_count = *args;
1038 Ok(Self {
1039 region_axes: cursor.read_array(transforms::to_usize(axis_count))?,
1040 })
1041 }
1042}
1043
1044#[allow(clippy::needless_lifetimes)]
1045impl<'a> VariationRegion<'a> {
1046 pub fn read(data: FontData<'a>, axis_count: u16) -> Result<Self, ReadError> {
1051 let args = axis_count;
1052 Self::read_with_args(data, &args)
1053 }
1054}
1055
1056#[cfg(feature = "experimental_traverse")]
1057impl<'a> SomeRecord<'a> for VariationRegion<'a> {
1058 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1059 RecordResolver {
1060 name: "VariationRegion",
1061 get_field: Box::new(move |idx, _data| match idx {
1062 0usize => Some(Field::new(
1063 "region_axes",
1064 traversal::FieldType::array_of_records(
1065 stringify!(RegionAxisCoordinates),
1066 self.region_axes(),
1067 _data,
1068 ),
1069 )),
1070 _ => None,
1071 }),
1072 data,
1073 }
1074 }
1075}
1076
1077#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1079#[repr(C)]
1080#[repr(packed)]
1081pub struct RegionAxisCoordinates {
1082 pub start_coord: BigEndian<F2Dot14>,
1084 pub peak_coord: BigEndian<F2Dot14>,
1086 pub end_coord: BigEndian<F2Dot14>,
1088}
1089
1090impl RegionAxisCoordinates {
1091 pub fn start_coord(&self) -> F2Dot14 {
1093 self.start_coord.get()
1094 }
1095
1096 pub fn peak_coord(&self) -> F2Dot14 {
1098 self.peak_coord.get()
1099 }
1100
1101 pub fn end_coord(&self) -> F2Dot14 {
1103 self.end_coord.get()
1104 }
1105}
1106
1107impl FixedSize for RegionAxisCoordinates {
1108 const RAW_BYTE_LEN: usize =
1109 F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN;
1110}
1111
1112#[cfg(feature = "experimental_traverse")]
1113impl<'a> SomeRecord<'a> for RegionAxisCoordinates {
1114 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1115 RecordResolver {
1116 name: "RegionAxisCoordinates",
1117 get_field: Box::new(move |idx, _data| match idx {
1118 0usize => Some(Field::new("start_coord", self.start_coord())),
1119 1usize => Some(Field::new("peak_coord", self.peak_coord())),
1120 2usize => Some(Field::new("end_coord", self.end_coord())),
1121 _ => None,
1122 }),
1123 data,
1124 }
1125 }
1126}
1127
1128impl<'a> MinByteRange<'a> for ItemVariationStore<'a> {
1129 fn min_byte_range(&self) -> Range<usize> {
1130 0..self.item_variation_data_offsets_byte_range().end
1131 }
1132 fn min_table_bytes(&self) -> &'a [u8] {
1133 let range = self.min_byte_range();
1134 self.data.as_bytes().get(range).unwrap_or_default()
1135 }
1136}
1137
1138impl<'a> FontRead<'a> for ItemVariationStore<'a> {
1139 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1140 #[allow(clippy::absurd_extreme_comparisons)]
1141 if data.len() < Self::MIN_SIZE {
1142 return Err(ReadError::OutOfBounds);
1143 }
1144 Ok(Self { data })
1145 }
1146}
1147
1148#[derive(Clone)]
1150pub struct ItemVariationStore<'a> {
1151 data: FontData<'a>,
1152}
1153
1154#[allow(clippy::needless_lifetimes)]
1155impl<'a> ItemVariationStore<'a> {
1156 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1157 basic_table_impls!(impl_the_methods);
1158
1159 pub fn format(&self) -> u16 {
1161 let range = self.format_byte_range();
1162 self.data.read_at(range.start).ok().unwrap()
1163 }
1164
1165 pub fn variation_region_list_offset(&self) -> Offset32 {
1168 let range = self.variation_region_list_offset_byte_range();
1169 self.data.read_at(range.start).ok().unwrap()
1170 }
1171
1172 pub fn variation_region_list(&self) -> Result<VariationRegionList<'a>, ReadError> {
1174 let data = self.data;
1175 self.variation_region_list_offset().resolve(data)
1176 }
1177
1178 pub fn item_variation_data_count(&self) -> u16 {
1180 let range = self.item_variation_data_count_byte_range();
1181 self.data.read_at(range.start).ok().unwrap()
1182 }
1183
1184 pub fn item_variation_data_offsets(&self) -> &'a [BigEndian<Nullable<Offset32>>] {
1187 let range = self.item_variation_data_offsets_byte_range();
1188 self.data.read_array(range).ok().unwrap_or_default()
1189 }
1190
1191 pub fn item_variation_data(
1193 &self,
1194 ) -> ArrayOfNullableOffsets<'a, ItemVariationData<'a>, Offset32> {
1195 let data = self.data;
1196 let offsets = self.item_variation_data_offsets();
1197 ArrayOfNullableOffsets::new(offsets, data, ())
1198 }
1199
1200 pub fn format_byte_range(&self) -> Range<usize> {
1201 let start = 0;
1202 let end = start + u16::RAW_BYTE_LEN;
1203 start..end
1204 }
1205
1206 pub fn variation_region_list_offset_byte_range(&self) -> Range<usize> {
1207 let start = self.format_byte_range().end;
1208 let end = start + Offset32::RAW_BYTE_LEN;
1209 start..end
1210 }
1211
1212 pub fn item_variation_data_count_byte_range(&self) -> Range<usize> {
1213 let start = self.variation_region_list_offset_byte_range().end;
1214 let end = start + u16::RAW_BYTE_LEN;
1215 start..end
1216 }
1217
1218 pub fn item_variation_data_offsets_byte_range(&self) -> Range<usize> {
1219 let item_variation_data_count = self.item_variation_data_count();
1220 let start = self.item_variation_data_count_byte_range().end;
1221 let end = start
1222 + (transforms::to_usize(item_variation_data_count))
1223 .saturating_mul(Offset32::RAW_BYTE_LEN);
1224 start..end
1225 }
1226}
1227
1228const _: () = assert!(FontData::default_data_long_enough(
1229 ItemVariationStore::MIN_SIZE
1230));
1231
1232impl Default for ItemVariationStore<'_> {
1233 fn default() -> Self {
1234 Self {
1235 data: FontData::default_table_data(),
1236 }
1237 }
1238}
1239
1240#[cfg(feature = "experimental_traverse")]
1241impl<'a> SomeTable<'a> for ItemVariationStore<'a> {
1242 fn type_name(&self) -> &str {
1243 "ItemVariationStore"
1244 }
1245 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1246 match idx {
1247 0usize => Some(Field::new("format", self.format())),
1248 1usize => Some(Field::new(
1249 "variation_region_list_offset",
1250 FieldType::offset(
1251 self.variation_region_list_offset(),
1252 self.variation_region_list(),
1253 ),
1254 )),
1255 2usize => Some(Field::new(
1256 "item_variation_data_count",
1257 self.item_variation_data_count(),
1258 )),
1259 3usize => Some(Field::new(
1260 "item_variation_data_offsets",
1261 FieldType::from(self.item_variation_data()),
1262 )),
1263 _ => None,
1264 }
1265 }
1266}
1267
1268#[cfg(feature = "experimental_traverse")]
1269#[allow(clippy::needless_lifetimes)]
1270impl<'a> std::fmt::Debug for ItemVariationStore<'a> {
1271 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1272 (self as &dyn SomeTable<'a>).fmt(f)
1273 }
1274}
1275
1276impl<'a> MinByteRange<'a> for ItemVariationData<'a> {
1277 fn min_byte_range(&self) -> Range<usize> {
1278 0..self.delta_sets_byte_range().end
1279 }
1280 fn min_table_bytes(&self) -> &'a [u8] {
1281 let range = self.min_byte_range();
1282 self.data.as_bytes().get(range).unwrap_or_default()
1283 }
1284}
1285
1286impl<'a> FontRead<'a> for ItemVariationData<'a> {
1287 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1288 #[allow(clippy::absurd_extreme_comparisons)]
1289 if data.len() < Self::MIN_SIZE {
1290 return Err(ReadError::OutOfBounds);
1291 }
1292 Ok(Self { data })
1293 }
1294}
1295
1296#[derive(Clone)]
1298pub struct ItemVariationData<'a> {
1299 data: FontData<'a>,
1300}
1301
1302#[allow(clippy::needless_lifetimes)]
1303impl<'a> ItemVariationData<'a> {
1304 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1305 basic_table_impls!(impl_the_methods);
1306
1307 pub fn item_count(&self) -> u16 {
1309 let range = self.item_count_byte_range();
1310 self.data.read_at(range.start).ok().unwrap()
1311 }
1312
1313 pub fn word_delta_count(&self) -> u16 {
1315 let range = self.word_delta_count_byte_range();
1316 self.data.read_at(range.start).ok().unwrap()
1317 }
1318
1319 pub fn region_index_count(&self) -> u16 {
1321 let range = self.region_index_count_byte_range();
1322 self.data.read_at(range.start).ok().unwrap()
1323 }
1324
1325 pub fn region_indexes(&self) -> &'a [BigEndian<u16>] {
1328 let range = self.region_indexes_byte_range();
1329 self.data.read_array(range).ok().unwrap_or_default()
1330 }
1331
1332 pub fn delta_sets(&self) -> &'a [u8] {
1334 let range = self.delta_sets_byte_range();
1335 self.data.read_array(range).ok().unwrap_or_default()
1336 }
1337
1338 pub fn item_count_byte_range(&self) -> Range<usize> {
1339 let start = 0;
1340 let end = start + u16::RAW_BYTE_LEN;
1341 start..end
1342 }
1343
1344 pub fn word_delta_count_byte_range(&self) -> Range<usize> {
1345 let start = self.item_count_byte_range().end;
1346 let end = start + u16::RAW_BYTE_LEN;
1347 start..end
1348 }
1349
1350 pub fn region_index_count_byte_range(&self) -> Range<usize> {
1351 let start = self.word_delta_count_byte_range().end;
1352 let end = start + u16::RAW_BYTE_LEN;
1353 start..end
1354 }
1355
1356 pub fn region_indexes_byte_range(&self) -> Range<usize> {
1357 let region_index_count = self.region_index_count();
1358 let start = self.region_index_count_byte_range().end;
1359 let end =
1360 start + (transforms::to_usize(region_index_count)).saturating_mul(u16::RAW_BYTE_LEN);
1361 start..end
1362 }
1363
1364 pub fn delta_sets_byte_range(&self) -> Range<usize> {
1365 let item_count = self.item_count();
1366 let word_delta_count = self.word_delta_count();
1367 let region_index_count = self.region_index_count();
1368 let start = self.region_indexes_byte_range().end;
1369 let end = start
1370 + (ItemVariationData::delta_sets_len(item_count, word_delta_count, region_index_count))
1371 .saturating_mul(u8::RAW_BYTE_LEN);
1372 start..end
1373 }
1374}
1375
1376const _: () = assert!(FontData::default_data_long_enough(
1377 ItemVariationData::MIN_SIZE
1378));
1379
1380impl Default for ItemVariationData<'_> {
1381 fn default() -> Self {
1382 Self {
1383 data: FontData::default_table_data(),
1384 }
1385 }
1386}
1387
1388#[cfg(feature = "experimental_traverse")]
1389impl<'a> SomeTable<'a> for ItemVariationData<'a> {
1390 fn type_name(&self) -> &str {
1391 "ItemVariationData"
1392 }
1393 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1394 match idx {
1395 0usize => Some(Field::new("item_count", self.item_count())),
1396 1usize => Some(Field::new("word_delta_count", self.word_delta_count())),
1397 2usize => Some(Field::new("region_index_count", self.region_index_count())),
1398 3usize => Some(Field::new("region_indexes", self.region_indexes())),
1399 4usize => Some(Field::new("delta_sets", self.delta_sets())),
1400 _ => None,
1401 }
1402 }
1403}
1404
1405#[cfg(feature = "experimental_traverse")]
1406#[allow(clippy::needless_lifetimes)]
1407impl<'a> std::fmt::Debug for ItemVariationData<'a> {
1408 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1409 (self as &dyn SomeTable<'a>).fmt(f)
1410 }
1411}