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