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> 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 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> FontRead<'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 ReadArgs for DeltaSetIndexMapFormat0<'_> {
243 type Args = ();
244}
245
246impl<'a> FontRead<'a> for DeltaSetIndexMapFormat0<'a> {
247 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
248 #[allow(clippy::absurd_extreme_comparisons)]
249 if data.len() < Self::MIN_SIZE {
250 return Err(ReadError::OutOfBounds);
251 }
252 Ok(Self { data })
253 }
254}
255
256#[derive(Clone)]
258pub struct DeltaSetIndexMapFormat0<'a> {
259 data: FontData<'a>,
260}
261
262#[allow(clippy::needless_lifetimes)]
263impl<'a> DeltaSetIndexMapFormat0<'a> {
264 pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + EntryFormat::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
265 basic_table_impls!(impl_the_methods);
266
267 pub fn format(&self) -> u8 {
269 let range = self.format_byte_range();
270 self.data.read_at(range.start).ok().unwrap()
271 }
272
273 pub fn entry_format(&self) -> EntryFormat {
276 let range = self.entry_format_byte_range();
277 self.data.read_at(range.start).ok().unwrap()
278 }
279
280 pub fn map_count(&self) -> u16 {
282 let range = self.map_count_byte_range();
283 self.data.read_at(range.start).ok().unwrap()
284 }
285
286 pub fn map_data(&self) -> &'a [u8] {
288 let range = self.map_data_byte_range();
289 self.data.read_array(range).ok().unwrap_or_default()
290 }
291
292 pub fn format_byte_range(&self) -> Range<usize> {
293 let start = 0;
294 let end = start + u8::RAW_BYTE_LEN;
295 start..end
296 }
297
298 pub fn entry_format_byte_range(&self) -> Range<usize> {
299 let start = self.format_byte_range().end;
300 let end = start + EntryFormat::RAW_BYTE_LEN;
301 start..end
302 }
303
304 pub fn map_count_byte_range(&self) -> Range<usize> {
305 let start = self.entry_format_byte_range().end;
306 let end = start + u16::RAW_BYTE_LEN;
307 start..end
308 }
309
310 pub fn map_data_byte_range(&self) -> Range<usize> {
311 let entry_format = self.entry_format();
312 let map_count = self.map_count();
313 let start = self.map_count_byte_range().end;
314 let end = start
315 + (EntryFormat::map_size(entry_format, map_count)).saturating_mul(u8::RAW_BYTE_LEN);
316 start..end
317 }
318}
319
320const _: () = assert!(FontData::default_data_long_enough(
321 DeltaSetIndexMapFormat0::MIN_SIZE
322));
323
324impl Default for DeltaSetIndexMapFormat0<'_> {
325 fn default() -> Self {
326 Self {
327 data: FontData::default_table_data(),
328 }
329 }
330}
331
332#[cfg(feature = "experimental_traverse")]
333impl<'a> SomeTable<'a> for DeltaSetIndexMapFormat0<'a> {
334 fn type_name(&self) -> &str {
335 "DeltaSetIndexMapFormat0"
336 }
337 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
338 match idx {
339 0usize => Some(Field::new("format", self.format())),
340 1usize => Some(Field::new("entry_format", self.entry_format())),
341 2usize => Some(Field::new("map_count", self.map_count())),
342 3usize => Some(Field::new("map_data", self.map_data())),
343 _ => None,
344 }
345 }
346}
347
348#[cfg(feature = "experimental_traverse")]
349#[allow(clippy::needless_lifetimes)]
350impl<'a> std::fmt::Debug for DeltaSetIndexMapFormat0<'a> {
351 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
352 (self as &dyn SomeTable<'a>).fmt(f)
353 }
354}
355
356impl Format<u8> for DeltaSetIndexMapFormat1<'_> {
357 const FORMAT: u8 = 1;
358}
359
360impl<'a> MinByteRange<'a> for DeltaSetIndexMapFormat1<'a> {
361 fn min_byte_range(&self) -> Range<usize> {
362 0..self.map_data_byte_range().end
363 }
364 fn min_table_bytes(&self) -> &'a [u8] {
365 let range = self.min_byte_range();
366 self.data.as_bytes().get(range).unwrap_or_default()
367 }
368}
369
370impl ReadArgs for DeltaSetIndexMapFormat1<'_> {
371 type Args = ();
372}
373
374impl<'a> FontRead<'a> for DeltaSetIndexMapFormat1<'a> {
375 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
376 #[allow(clippy::absurd_extreme_comparisons)]
377 if data.len() < Self::MIN_SIZE {
378 return Err(ReadError::OutOfBounds);
379 }
380 Ok(Self { data })
381 }
382}
383
384#[derive(Clone)]
386pub struct DeltaSetIndexMapFormat1<'a> {
387 data: FontData<'a>,
388}
389
390#[allow(clippy::needless_lifetimes)]
391impl<'a> DeltaSetIndexMapFormat1<'a> {
392 pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + EntryFormat::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
393 basic_table_impls!(impl_the_methods);
394
395 pub fn format(&self) -> u8 {
397 let range = self.format_byte_range();
398 self.data.read_at(range.start).ok().unwrap()
399 }
400
401 pub fn entry_format(&self) -> EntryFormat {
404 let range = self.entry_format_byte_range();
405 self.data.read_at(range.start).ok().unwrap()
406 }
407
408 pub fn map_count(&self) -> u32 {
410 let range = self.map_count_byte_range();
411 self.data.read_at(range.start).ok().unwrap()
412 }
413
414 pub fn map_data(&self) -> &'a [u8] {
416 let range = self.map_data_byte_range();
417 self.data.read_array(range).ok().unwrap_or_default()
418 }
419
420 pub fn format_byte_range(&self) -> Range<usize> {
421 let start = 0;
422 let end = start + u8::RAW_BYTE_LEN;
423 start..end
424 }
425
426 pub fn entry_format_byte_range(&self) -> Range<usize> {
427 let start = self.format_byte_range().end;
428 let end = start + EntryFormat::RAW_BYTE_LEN;
429 start..end
430 }
431
432 pub fn map_count_byte_range(&self) -> Range<usize> {
433 let start = self.entry_format_byte_range().end;
434 let end = start + u32::RAW_BYTE_LEN;
435 start..end
436 }
437
438 pub fn map_data_byte_range(&self) -> Range<usize> {
439 let entry_format = self.entry_format();
440 let map_count = self.map_count();
441 let start = self.map_count_byte_range().end;
442 let end = start
443 + (EntryFormat::map_size(entry_format, map_count)).saturating_mul(u8::RAW_BYTE_LEN);
444 start..end
445 }
446}
447
448const _: () = assert!(FontData::default_data_long_enough(
449 DeltaSetIndexMapFormat1::MIN_SIZE
450));
451
452impl Default for DeltaSetIndexMapFormat1<'_> {
453 fn default() -> Self {
454 Self {
455 data: FontData::default_format_1_u8_table_data(),
456 }
457 }
458}
459
460#[cfg(feature = "experimental_traverse")]
461impl<'a> SomeTable<'a> for DeltaSetIndexMapFormat1<'a> {
462 fn type_name(&self) -> &str {
463 "DeltaSetIndexMapFormat1"
464 }
465 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
466 match idx {
467 0usize => Some(Field::new("format", self.format())),
468 1usize => Some(Field::new("entry_format", self.entry_format())),
469 2usize => Some(Field::new("map_count", self.map_count())),
470 3usize => Some(Field::new("map_data", self.map_data())),
471 _ => None,
472 }
473 }
474}
475
476#[cfg(feature = "experimental_traverse")]
477#[allow(clippy::needless_lifetimes)]
478impl<'a> std::fmt::Debug for DeltaSetIndexMapFormat1<'a> {
479 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
480 (self as &dyn SomeTable<'a>).fmt(f)
481 }
482}
483
484#[derive(Clone)]
486pub enum DeltaSetIndexMap<'a> {
487 Format0(DeltaSetIndexMapFormat0<'a>),
488 Format1(DeltaSetIndexMapFormat1<'a>),
489}
490
491impl Default for DeltaSetIndexMap<'_> {
492 fn default() -> Self {
493 Self::Format0(Default::default())
494 }
495}
496
497impl<'a> DeltaSetIndexMap<'a> {
498 pub fn offset_data(&self) -> FontData<'a> {
500 match self {
501 Self::Format0(item) => item.offset_data(),
502 Self::Format1(item) => item.offset_data(),
503 }
504 }
505
506 pub fn format(&self) -> u8 {
508 match self {
509 Self::Format0(item) => item.format(),
510 Self::Format1(item) => item.format(),
511 }
512 }
513
514 pub fn entry_format(&self) -> EntryFormat {
517 match self {
518 Self::Format0(item) => item.entry_format(),
519 Self::Format1(item) => item.entry_format(),
520 }
521 }
522
523 pub fn map_data(&self) -> &'a [u8] {
525 match self {
526 Self::Format0(item) => item.map_data(),
527 Self::Format1(item) => item.map_data(),
528 }
529 }
530}
531
532impl ReadArgs for DeltaSetIndexMap<'_> {
533 type Args = ();
534}
535
536impl<'a> FontRead<'a> for DeltaSetIndexMap<'a> {
537 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
538 let format: u8 = data.read_at(0usize)?;
539 match format {
540 DeltaSetIndexMapFormat0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
541 DeltaSetIndexMapFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
542 other => Err(ReadError::InvalidFormat(other.into())),
543 }
544 }
545}
546
547impl<'a> MinByteRange<'a> for DeltaSetIndexMap<'a> {
548 fn min_byte_range(&self) -> Range<usize> {
549 match self {
550 Self::Format0(item) => item.min_byte_range(),
551 Self::Format1(item) => item.min_byte_range(),
552 }
553 }
554 fn min_table_bytes(&self) -> &'a [u8] {
555 match self {
556 Self::Format0(item) => item.min_table_bytes(),
557 Self::Format1(item) => item.min_table_bytes(),
558 }
559 }
560}
561
562#[cfg(feature = "experimental_traverse")]
563impl<'a> DeltaSetIndexMap<'a> {
564 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
565 match self {
566 Self::Format0(table) => table,
567 Self::Format1(table) => table,
568 }
569 }
570}
571
572#[cfg(feature = "experimental_traverse")]
573impl std::fmt::Debug for DeltaSetIndexMap<'_> {
574 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
575 self.dyn_inner().fmt(f)
576 }
577}
578
579#[cfg(feature = "experimental_traverse")]
580impl<'a> SomeTable<'a> for DeltaSetIndexMap<'a> {
581 fn type_name(&self) -> &str {
582 self.dyn_inner().type_name()
583 }
584 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
585 self.dyn_inner().get_field(idx)
586 }
587}
588
589#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
591#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
592#[repr(transparent)]
593pub struct EntryFormat {
594 bits: u8,
595}
596
597impl EntryFormat {
598 pub const INNER_INDEX_BIT_COUNT_MASK: Self = Self { bits: 0x0F };
600
601 pub const MAP_ENTRY_SIZE_MASK: Self = Self { bits: 0x30 };
603}
604
605impl EntryFormat {
606 #[inline]
608 pub const fn empty() -> Self {
609 Self { bits: 0 }
610 }
611
612 #[inline]
614 pub const fn all() -> Self {
615 Self {
616 bits: Self::INNER_INDEX_BIT_COUNT_MASK.bits | Self::MAP_ENTRY_SIZE_MASK.bits,
617 }
618 }
619
620 #[inline]
622 pub const fn bits(&self) -> u8 {
623 self.bits
624 }
625
626 #[inline]
629 pub const fn from_bits(bits: u8) -> Option<Self> {
630 if (bits & !Self::all().bits()) == 0 {
631 Some(Self { bits })
632 } else {
633 None
634 }
635 }
636
637 #[inline]
640 pub const fn from_bits_truncate(bits: u8) -> Self {
641 Self {
642 bits: bits & Self::all().bits,
643 }
644 }
645
646 #[inline]
648 pub const fn is_empty(&self) -> bool {
649 self.bits() == Self::empty().bits()
650 }
651
652 #[inline]
654 pub const fn intersects(&self, other: Self) -> bool {
655 !(Self {
656 bits: self.bits & other.bits,
657 })
658 .is_empty()
659 }
660
661 #[inline]
663 pub const fn contains(&self, other: Self) -> bool {
664 (self.bits & other.bits) == other.bits
665 }
666
667 #[inline]
669 pub fn insert(&mut self, other: Self) {
670 self.bits |= other.bits;
671 }
672
673 #[inline]
675 pub fn remove(&mut self, other: Self) {
676 self.bits &= !other.bits;
677 }
678
679 #[inline]
681 pub fn toggle(&mut self, other: Self) {
682 self.bits ^= other.bits;
683 }
684
685 #[inline]
696 #[must_use]
697 pub const fn intersection(self, other: Self) -> Self {
698 Self {
699 bits: self.bits & other.bits,
700 }
701 }
702
703 #[inline]
714 #[must_use]
715 pub const fn union(self, other: Self) -> Self {
716 Self {
717 bits: self.bits | other.bits,
718 }
719 }
720
721 #[inline]
734 #[must_use]
735 pub const fn difference(self, other: Self) -> Self {
736 Self {
737 bits: self.bits & !other.bits,
738 }
739 }
740}
741
742impl std::ops::BitOr for EntryFormat {
743 type Output = Self;
744
745 #[inline]
747 fn bitor(self, other: EntryFormat) -> Self {
748 Self {
749 bits: self.bits | other.bits,
750 }
751 }
752}
753
754impl std::ops::BitOrAssign for EntryFormat {
755 #[inline]
757 fn bitor_assign(&mut self, other: Self) {
758 self.bits |= other.bits;
759 }
760}
761
762impl std::ops::BitXor for EntryFormat {
763 type Output = Self;
764
765 #[inline]
767 fn bitxor(self, other: Self) -> Self {
768 Self {
769 bits: self.bits ^ other.bits,
770 }
771 }
772}
773
774impl std::ops::BitXorAssign for EntryFormat {
775 #[inline]
777 fn bitxor_assign(&mut self, other: Self) {
778 self.bits ^= other.bits;
779 }
780}
781
782impl std::ops::BitAnd for EntryFormat {
783 type Output = Self;
784
785 #[inline]
787 fn bitand(self, other: Self) -> Self {
788 Self {
789 bits: self.bits & other.bits,
790 }
791 }
792}
793
794impl std::ops::BitAndAssign for EntryFormat {
795 #[inline]
797 fn bitand_assign(&mut self, other: Self) {
798 self.bits &= other.bits;
799 }
800}
801
802impl std::ops::Sub for EntryFormat {
803 type Output = Self;
804
805 #[inline]
807 fn sub(self, other: Self) -> Self {
808 Self {
809 bits: self.bits & !other.bits,
810 }
811 }
812}
813
814impl std::ops::SubAssign for EntryFormat {
815 #[inline]
817 fn sub_assign(&mut self, other: Self) {
818 self.bits &= !other.bits;
819 }
820}
821
822impl std::ops::Not for EntryFormat {
823 type Output = Self;
824
825 #[inline]
827 fn not(self) -> Self {
828 Self { bits: !self.bits } & Self::all()
829 }
830}
831
832impl std::fmt::Debug for EntryFormat {
833 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
834 let members: &[(&str, Self)] = &[
835 (
836 "INNER_INDEX_BIT_COUNT_MASK",
837 Self::INNER_INDEX_BIT_COUNT_MASK,
838 ),
839 ("MAP_ENTRY_SIZE_MASK", Self::MAP_ENTRY_SIZE_MASK),
840 ];
841 let mut first = true;
842 for (name, value) in members {
843 if self.contains(*value) {
844 if !first {
845 f.write_str(" | ")?;
846 }
847 first = false;
848 f.write_str(name)?;
849 }
850 }
851 if first {
852 f.write_str("(empty)")?;
853 }
854 Ok(())
855 }
856}
857
858impl std::fmt::Binary for EntryFormat {
859 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
860 std::fmt::Binary::fmt(&self.bits, f)
861 }
862}
863
864impl std::fmt::Octal for EntryFormat {
865 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
866 std::fmt::Octal::fmt(&self.bits, f)
867 }
868}
869
870impl std::fmt::LowerHex for EntryFormat {
871 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
872 std::fmt::LowerHex::fmt(&self.bits, f)
873 }
874}
875
876impl std::fmt::UpperHex for EntryFormat {
877 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
878 std::fmt::UpperHex::fmt(&self.bits, f)
879 }
880}
881
882impl font_types::Scalar for EntryFormat {
883 type Raw = <u8 as font_types::Scalar>::Raw;
884 fn to_raw(self) -> Self::Raw {
885 self.bits().to_raw()
886 }
887 fn from_raw(raw: Self::Raw) -> Self {
888 let t = <u8>::from_raw(raw);
889 Self::from_bits_truncate(t)
890 }
891}
892
893#[cfg(feature = "experimental_traverse")]
894impl<'a> From<EntryFormat> for FieldType<'a> {
895 fn from(src: EntryFormat) -> FieldType<'a> {
896 src.bits().into()
897 }
898}
899
900impl<'a> MinByteRange<'a> for VariationRegionList<'a> {
901 fn min_byte_range(&self) -> Range<usize> {
902 0..self.variation_regions_byte_range().end
903 }
904 fn min_table_bytes(&self) -> &'a [u8] {
905 let range = self.min_byte_range();
906 self.data.as_bytes().get(range).unwrap_or_default()
907 }
908}
909
910impl ReadArgs for VariationRegionList<'_> {
911 type Args = ();
912}
913
914impl<'a> FontRead<'a> for VariationRegionList<'a> {
915 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
916 #[allow(clippy::absurd_extreme_comparisons)]
917 if data.len() < Self::MIN_SIZE {
918 return Err(ReadError::OutOfBounds);
919 }
920 Ok(Self { data })
921 }
922}
923
924#[derive(Clone)]
926pub struct VariationRegionList<'a> {
927 data: FontData<'a>,
928}
929
930#[allow(clippy::needless_lifetimes)]
931impl<'a> VariationRegionList<'a> {
932 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
933 basic_table_impls!(impl_the_methods);
934
935 pub fn axis_count(&self) -> u16 {
938 let range = self.axis_count_byte_range();
939 self.data.read_at(range.start).ok().unwrap()
940 }
941
942 pub fn region_count(&self) -> u16 {
945 let range = self.region_count_byte_range();
946 self.data.read_at(range.start).ok().unwrap()
947 }
948
949 pub fn variation_regions(&self) -> ComputedArray<'a, VariationRegion<'a>> {
951 let range = self.variation_regions_byte_range();
952 self.data
953 .read_with_args(range, self.axis_count())
954 .unwrap_or_default()
955 }
956
957 pub fn axis_count_byte_range(&self) -> Range<usize> {
958 let start = 0;
959 let end = start + u16::RAW_BYTE_LEN;
960 start..end
961 }
962
963 pub fn region_count_byte_range(&self) -> Range<usize> {
964 let start = self.axis_count_byte_range().end;
965 let end = start + u16::RAW_BYTE_LEN;
966 start..end
967 }
968
969 pub fn variation_regions_byte_range(&self) -> Range<usize> {
970 let region_count = self.region_count();
971 let start = self.region_count_byte_range().end;
972 let end = start
973 + (transforms::to_usize(region_count)).saturating_mul(
974 <VariationRegion as ComputeSize>::compute_size(self.axis_count()).unwrap_or(0),
975 );
976 start..end
977 }
978}
979
980const _: () = assert!(FontData::default_data_long_enough(
981 VariationRegionList::MIN_SIZE
982));
983
984impl Default for VariationRegionList<'_> {
985 fn default() -> Self {
986 Self {
987 data: FontData::default_table_data(),
988 }
989 }
990}
991
992#[cfg(feature = "experimental_traverse")]
993impl<'a> SomeTable<'a> for VariationRegionList<'a> {
994 fn type_name(&self) -> &str {
995 "VariationRegionList"
996 }
997 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
998 match idx {
999 0usize => Some(Field::new("axis_count", self.axis_count())),
1000 1usize => Some(Field::new("region_count", self.region_count())),
1001 2usize => Some(Field::new(
1002 "variation_regions",
1003 traversal::FieldType::computed_array(
1004 "VariationRegion",
1005 self.variation_regions(),
1006 self.offset_data(),
1007 ),
1008 )),
1009 _ => None,
1010 }
1011 }
1012}
1013
1014#[cfg(feature = "experimental_traverse")]
1015#[allow(clippy::needless_lifetimes)]
1016impl<'a> std::fmt::Debug for VariationRegionList<'a> {
1017 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1018 (self as &dyn SomeTable<'a>).fmt(f)
1019 }
1020}
1021
1022#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1024pub struct VariationRegion<'a> {
1025 pub region_axes: &'a [RegionAxisCoordinates],
1028}
1029
1030impl<'a> VariationRegion<'a> {
1031 pub fn region_axes(&self) -> &'a [RegionAxisCoordinates] {
1034 self.region_axes
1035 }
1036}
1037
1038impl ReadArgs for VariationRegion<'_> {
1039 type Args = u16;
1040}
1041
1042impl ComputeSize for VariationRegion<'_> {
1043 #[allow(clippy::needless_question_mark)]
1044 fn compute_size(args: u16) -> Result<usize, ReadError> {
1045 let axis_count = args;
1046 Ok((transforms::to_usize(axis_count)).saturating_mul(RegionAxisCoordinates::RAW_BYTE_LEN))
1047 }
1048}
1049
1050impl<'a> FontRead<'a> for VariationRegion<'a> {
1051 fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
1052 let mut cursor = data.cursor();
1053 let axis_count = args;
1054 Ok(Self {
1055 region_axes: cursor.read_array(transforms::to_usize(axis_count))?,
1056 })
1057 }
1058}
1059
1060#[allow(clippy::needless_lifetimes)]
1061impl<'a> VariationRegion<'a> {
1062 pub fn read(data: FontData<'a>, axis_count: u16) -> Result<Self, ReadError> {
1067 let args = axis_count;
1068 Self::read_with_args(data, args)
1069 }
1070}
1071
1072#[cfg(feature = "experimental_traverse")]
1073impl<'a> SomeRecord<'a> for VariationRegion<'a> {
1074 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1075 RecordResolver {
1076 name: "VariationRegion",
1077 get_field: Box::new(move |idx, _data| match idx {
1078 0usize => Some(Field::new(
1079 "region_axes",
1080 traversal::FieldType::array_of_records(
1081 stringify!(RegionAxisCoordinates),
1082 self.region_axes(),
1083 _data,
1084 ),
1085 )),
1086 _ => None,
1087 }),
1088 data,
1089 }
1090 }
1091}
1092
1093#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1095#[repr(C)]
1096#[repr(packed)]
1097pub struct RegionAxisCoordinates {
1098 pub start_coord: BigEndian<F2Dot14>,
1100 pub peak_coord: BigEndian<F2Dot14>,
1102 pub end_coord: BigEndian<F2Dot14>,
1104}
1105
1106impl RegionAxisCoordinates {
1107 pub fn start_coord(&self) -> F2Dot14 {
1109 self.start_coord.get()
1110 }
1111
1112 pub fn peak_coord(&self) -> F2Dot14 {
1114 self.peak_coord.get()
1115 }
1116
1117 pub fn end_coord(&self) -> F2Dot14 {
1119 self.end_coord.get()
1120 }
1121}
1122
1123impl FixedSize for RegionAxisCoordinates {
1124 const RAW_BYTE_LEN: usize =
1125 F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN;
1126}
1127
1128#[cfg(feature = "experimental_traverse")]
1129impl<'a> SomeRecord<'a> for RegionAxisCoordinates {
1130 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1131 RecordResolver {
1132 name: "RegionAxisCoordinates",
1133 get_field: Box::new(move |idx, _data| match idx {
1134 0usize => Some(Field::new("start_coord", self.start_coord())),
1135 1usize => Some(Field::new("peak_coord", self.peak_coord())),
1136 2usize => Some(Field::new("end_coord", self.end_coord())),
1137 _ => None,
1138 }),
1139 data,
1140 }
1141 }
1142}
1143
1144impl<'a> MinByteRange<'a> for ItemVariationStore<'a> {
1145 fn min_byte_range(&self) -> Range<usize> {
1146 0..self.item_variation_data_offsets_byte_range().end
1147 }
1148 fn min_table_bytes(&self) -> &'a [u8] {
1149 let range = self.min_byte_range();
1150 self.data.as_bytes().get(range).unwrap_or_default()
1151 }
1152}
1153
1154impl ReadArgs for ItemVariationStore<'_> {
1155 type Args = ();
1156}
1157
1158impl<'a> FontRead<'a> for ItemVariationStore<'a> {
1159 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1160 #[allow(clippy::absurd_extreme_comparisons)]
1161 if data.len() < Self::MIN_SIZE {
1162 return Err(ReadError::OutOfBounds);
1163 }
1164 Ok(Self { data })
1165 }
1166}
1167
1168#[derive(Clone)]
1170pub struct ItemVariationStore<'a> {
1171 data: FontData<'a>,
1172}
1173
1174#[allow(clippy::needless_lifetimes)]
1175impl<'a> ItemVariationStore<'a> {
1176 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1177 basic_table_impls!(impl_the_methods);
1178
1179 pub fn format(&self) -> u16 {
1181 let range = self.format_byte_range();
1182 self.data.read_at(range.start).ok().unwrap()
1183 }
1184
1185 pub fn variation_region_list_offset(&self) -> Offset32 {
1188 let range = self.variation_region_list_offset_byte_range();
1189 self.data.read_at(range.start).ok().unwrap()
1190 }
1191
1192 pub fn variation_region_list(&self) -> Result<VariationRegionList<'a>, ReadError> {
1194 let data = self.data;
1195 self.variation_region_list_offset().resolve(data)
1196 }
1197
1198 pub fn item_variation_data_count(&self) -> u16 {
1200 let range = self.item_variation_data_count_byte_range();
1201 self.data.read_at(range.start).ok().unwrap()
1202 }
1203
1204 pub fn item_variation_data_offsets(&self) -> &'a [BigEndian<Nullable<Offset32>>] {
1207 let range = self.item_variation_data_offsets_byte_range();
1208 self.data.read_array(range).ok().unwrap_or_default()
1209 }
1210
1211 pub fn item_variation_data(
1213 &self,
1214 ) -> ArrayOfNullableOffsets<'a, ItemVariationData<'a>, Offset32> {
1215 let data = self.data;
1216 let offsets = self.item_variation_data_offsets();
1217 ArrayOfNullableOffsets::new(offsets, data, ())
1218 }
1219
1220 pub fn format_byte_range(&self) -> Range<usize> {
1221 let start = 0;
1222 let end = start + u16::RAW_BYTE_LEN;
1223 start..end
1224 }
1225
1226 pub fn variation_region_list_offset_byte_range(&self) -> Range<usize> {
1227 let start = self.format_byte_range().end;
1228 let end = start + Offset32::RAW_BYTE_LEN;
1229 start..end
1230 }
1231
1232 pub fn item_variation_data_count_byte_range(&self) -> Range<usize> {
1233 let start = self.variation_region_list_offset_byte_range().end;
1234 let end = start + u16::RAW_BYTE_LEN;
1235 start..end
1236 }
1237
1238 pub fn item_variation_data_offsets_byte_range(&self) -> Range<usize> {
1239 let item_variation_data_count = self.item_variation_data_count();
1240 let start = self.item_variation_data_count_byte_range().end;
1241 let end = start
1242 + (transforms::to_usize(item_variation_data_count))
1243 .saturating_mul(Offset32::RAW_BYTE_LEN);
1244 start..end
1245 }
1246}
1247
1248const _: () = assert!(FontData::default_data_long_enough(
1249 ItemVariationStore::MIN_SIZE
1250));
1251
1252impl Default for ItemVariationStore<'_> {
1253 fn default() -> Self {
1254 Self {
1255 data: FontData::default_table_data(),
1256 }
1257 }
1258}
1259
1260#[cfg(feature = "experimental_traverse")]
1261impl<'a> SomeTable<'a> for ItemVariationStore<'a> {
1262 fn type_name(&self) -> &str {
1263 "ItemVariationStore"
1264 }
1265 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1266 match idx {
1267 0usize => Some(Field::new("format", self.format())),
1268 1usize => Some(Field::new(
1269 "variation_region_list_offset",
1270 FieldType::offset(
1271 self.variation_region_list_offset(),
1272 self.variation_region_list(),
1273 ),
1274 )),
1275 2usize => Some(Field::new(
1276 "item_variation_data_count",
1277 self.item_variation_data_count(),
1278 )),
1279 3usize => Some(Field::new(
1280 "item_variation_data_offsets",
1281 FieldType::from(self.item_variation_data()),
1282 )),
1283 _ => None,
1284 }
1285 }
1286}
1287
1288#[cfg(feature = "experimental_traverse")]
1289#[allow(clippy::needless_lifetimes)]
1290impl<'a> std::fmt::Debug for ItemVariationStore<'a> {
1291 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1292 (self as &dyn SomeTable<'a>).fmt(f)
1293 }
1294}
1295
1296impl<'a> MinByteRange<'a> for ItemVariationData<'a> {
1297 fn min_byte_range(&self) -> Range<usize> {
1298 0..self.delta_sets_byte_range().end
1299 }
1300 fn min_table_bytes(&self) -> &'a [u8] {
1301 let range = self.min_byte_range();
1302 self.data.as_bytes().get(range).unwrap_or_default()
1303 }
1304}
1305
1306impl ReadArgs for ItemVariationData<'_> {
1307 type Args = ();
1308}
1309
1310impl<'a> FontRead<'a> for ItemVariationData<'a> {
1311 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1312 #[allow(clippy::absurd_extreme_comparisons)]
1313 if data.len() < Self::MIN_SIZE {
1314 return Err(ReadError::OutOfBounds);
1315 }
1316 Ok(Self { data })
1317 }
1318}
1319
1320#[derive(Clone)]
1322pub struct ItemVariationData<'a> {
1323 data: FontData<'a>,
1324}
1325
1326#[allow(clippy::needless_lifetimes)]
1327impl<'a> ItemVariationData<'a> {
1328 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1329 basic_table_impls!(impl_the_methods);
1330
1331 pub fn item_count(&self) -> u16 {
1333 let range = self.item_count_byte_range();
1334 self.data.read_at(range.start).ok().unwrap()
1335 }
1336
1337 pub fn word_delta_count(&self) -> u16 {
1339 let range = self.word_delta_count_byte_range();
1340 self.data.read_at(range.start).ok().unwrap()
1341 }
1342
1343 pub fn region_index_count(&self) -> u16 {
1345 let range = self.region_index_count_byte_range();
1346 self.data.read_at(range.start).ok().unwrap()
1347 }
1348
1349 pub fn region_indexes(&self) -> &'a [BigEndian<u16>] {
1352 let range = self.region_indexes_byte_range();
1353 self.data.read_array(range).ok().unwrap_or_default()
1354 }
1355
1356 pub fn delta_sets(&self) -> &'a [u8] {
1358 let range = self.delta_sets_byte_range();
1359 self.data.read_array(range).ok().unwrap_or_default()
1360 }
1361
1362 pub fn item_count_byte_range(&self) -> Range<usize> {
1363 let start = 0;
1364 let end = start + u16::RAW_BYTE_LEN;
1365 start..end
1366 }
1367
1368 pub fn word_delta_count_byte_range(&self) -> Range<usize> {
1369 let start = self.item_count_byte_range().end;
1370 let end = start + u16::RAW_BYTE_LEN;
1371 start..end
1372 }
1373
1374 pub fn region_index_count_byte_range(&self) -> Range<usize> {
1375 let start = self.word_delta_count_byte_range().end;
1376 let end = start + u16::RAW_BYTE_LEN;
1377 start..end
1378 }
1379
1380 pub fn region_indexes_byte_range(&self) -> Range<usize> {
1381 let region_index_count = self.region_index_count();
1382 let start = self.region_index_count_byte_range().end;
1383 let end =
1384 start + (transforms::to_usize(region_index_count)).saturating_mul(u16::RAW_BYTE_LEN);
1385 start..end
1386 }
1387
1388 pub fn delta_sets_byte_range(&self) -> Range<usize> {
1389 let item_count = self.item_count();
1390 let word_delta_count = self.word_delta_count();
1391 let region_index_count = self.region_index_count();
1392 let start = self.region_indexes_byte_range().end;
1393 let end = start
1394 + (ItemVariationData::delta_sets_len(item_count, word_delta_count, region_index_count))
1395 .saturating_mul(u8::RAW_BYTE_LEN);
1396 start..end
1397 }
1398}
1399
1400const _: () = assert!(FontData::default_data_long_enough(
1401 ItemVariationData::MIN_SIZE
1402));
1403
1404impl Default for ItemVariationData<'_> {
1405 fn default() -> Self {
1406 Self {
1407 data: FontData::default_table_data(),
1408 }
1409 }
1410}
1411
1412#[cfg(feature = "experimental_traverse")]
1413impl<'a> SomeTable<'a> for ItemVariationData<'a> {
1414 fn type_name(&self) -> &str {
1415 "ItemVariationData"
1416 }
1417 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1418 match idx {
1419 0usize => Some(Field::new("item_count", self.item_count())),
1420 1usize => Some(Field::new("word_delta_count", self.word_delta_count())),
1421 2usize => Some(Field::new("region_index_count", self.region_index_count())),
1422 3usize => Some(Field::new("region_indexes", self.region_indexes())),
1423 4usize => Some(Field::new("delta_sets", self.delta_sets())),
1424 _ => None,
1425 }
1426 }
1427}
1428
1429#[cfg(feature = "experimental_traverse")]
1430#[allow(clippy::needless_lifetimes)]
1431impl<'a> std::fmt::Debug for ItemVariationData<'a> {
1432 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1433 (self as &dyn SomeTable<'a>).fmt(f)
1434 }
1435}