Skip to main content

read_fonts/generated/
generated_variations.rs

1// THIS FILE IS AUTOGENERATED.
2// Any changes to this file will be overwritten.
3// For more information about how codegen works, see font-codegen/README.md
4
5#[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    /// A constructor that requires additional arguments.
36    ///
37    /// This type requires some external state in order to be
38    /// parsed.
39    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/// [TupleVariationHeader](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader)
46#[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    /// The size in bytes of the serialized data for this tuple
58    /// variation table.
59    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    /// A packed field. The high 4 bits are flags (see below). The low
65    /// 12 bits are an index into a shared tuple records array.
66    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/// A [Tuple Record](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuple-records)
157///
158/// The tuple variation store formats reference regions within the font’s
159/// variation space using tuple records. A tuple record identifies a position
160/// in terms of normalized coordinates, which use F2DOT14 values.
161#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
162pub struct Tuple<'a> {
163    /// Coordinate array specifying a position within the font’s variation space.
164    ///
165    /// The number of elements must match the axisCount specified in the
166    /// 'fvar' table.
167    pub values: &'a [BigEndian<F2Dot14>],
168}
169
170impl<'a> Tuple<'a> {
171    /// Coordinate array specifying a position within the font’s variation space.
172    ///
173    /// The number of elements must match the axisCount specified in the
174    /// 'fvar' table.
175    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    /// A constructor that requires additional arguments.
205    ///
206    /// This type requires some external state in order to be
207    /// parsed.
208    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/// The [DeltaSetIndexMap](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#associating-target-items-to-variation-data) table format 0
257#[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    /// DeltaSetIndexMap format: set to 0.
268    pub fn format(&self) -> u8 {
269        let range = self.format_byte_range();
270        self.data.read_at(range.start).ok().unwrap()
271    }
272
273    /// A packed field that describes the compressed representation of
274    /// delta-set indices. See details below.
275    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    /// The number of mapping entries.
281    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    /// The delta-set index mapping data. See details below.
287    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/// The [DeltaSetIndexMap](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#associating-target-items-to-variation-data) table format 1
385#[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    /// DeltaSetIndexMap format: set to 1.
396    pub fn format(&self) -> u8 {
397        let range = self.format_byte_range();
398        self.data.read_at(range.start).ok().unwrap()
399    }
400
401    /// A packed field that describes the compressed representation of
402    /// delta-set indices. See details below.
403    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    /// The number of mapping entries.
409    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    /// The delta-set index mapping data. See details below.
415    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/// The [DeltaSetIndexMap](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#associating-target-items-to-variation-data) table
485#[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    ///Return the `FontData` used to resolve offsets for this table.
499    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    /// DeltaSetIndexMap format: set to 0.
507    pub fn format(&self) -> u8 {
508        match self {
509            Self::Format0(item) => item.format(),
510            Self::Format1(item) => item.format(),
511        }
512    }
513
514    /// A packed field that describes the compressed representation of
515    /// delta-set indices. See details below.
516    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    /// The delta-set index mapping data. See details below.
524    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/// Entry format for a [DeltaSetIndexMap].
590#[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    /// Mask for the low 4 bits, which give the count of bits minus one that are used in each entry for the inner-level index.
599    pub const INNER_INDEX_BIT_COUNT_MASK: Self = Self { bits: 0x0F };
600
601    /// Mask for bits that indicate the size in bytes minus one of each entry.
602    pub const MAP_ENTRY_SIZE_MASK: Self = Self { bits: 0x30 };
603}
604
605impl EntryFormat {
606    ///  Returns an empty set of flags.
607    #[inline]
608    pub const fn empty() -> Self {
609        Self { bits: 0 }
610    }
611
612    /// Returns the set containing all flags.
613    #[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    /// Returns the raw value of the flags currently stored.
621    #[inline]
622    pub const fn bits(&self) -> u8 {
623        self.bits
624    }
625
626    /// Convert from underlying bit representation, unless that
627    /// representation contains bits that do not correspond to a flag.
628    #[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    /// Convert from underlying bit representation, dropping any bits
638    /// that do not correspond to flags.
639    #[inline]
640    pub const fn from_bits_truncate(bits: u8) -> Self {
641        Self {
642            bits: bits & Self::all().bits,
643        }
644    }
645
646    /// Returns `true` if no flags are currently stored.
647    #[inline]
648    pub const fn is_empty(&self) -> bool {
649        self.bits() == Self::empty().bits()
650    }
651
652    /// Returns `true` if there are flags common to both `self` and `other`.
653    #[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    /// Returns `true` if all of the flags in `other` are contained within `self`.
662    #[inline]
663    pub const fn contains(&self, other: Self) -> bool {
664        (self.bits & other.bits) == other.bits
665    }
666
667    /// Inserts the specified flags in-place.
668    #[inline]
669    pub fn insert(&mut self, other: Self) {
670        self.bits |= other.bits;
671    }
672
673    /// Removes the specified flags in-place.
674    #[inline]
675    pub fn remove(&mut self, other: Self) {
676        self.bits &= !other.bits;
677    }
678
679    /// Toggles the specified flags in-place.
680    #[inline]
681    pub fn toggle(&mut self, other: Self) {
682        self.bits ^= other.bits;
683    }
684
685    /// Returns the intersection between the flags in `self` and
686    /// `other`.
687    ///
688    /// Specifically, the returned set contains only the flags which are
689    /// present in *both* `self` *and* `other`.
690    ///
691    /// This is equivalent to using the `&` operator (e.g.
692    /// [`ops::BitAnd`]), as in `flags & other`.
693    ///
694    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
695    #[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    /// Returns the union of between the flags in `self` and `other`.
704    ///
705    /// Specifically, the returned set contains all flags which are
706    /// present in *either* `self` *or* `other`, including any which are
707    /// present in both.
708    ///
709    /// This is equivalent to using the `|` operator (e.g.
710    /// [`ops::BitOr`]), as in `flags | other`.
711    ///
712    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
713    #[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    /// Returns the difference between the flags in `self` and `other`.
722    ///
723    /// Specifically, the returned set contains all flags present in
724    /// `self`, except for the ones present in `other`.
725    ///
726    /// It is also conceptually equivalent to the "bit-clear" operation:
727    /// `flags & !other` (and this syntax is also supported).
728    ///
729    /// This is equivalent to using the `-` operator (e.g.
730    /// [`ops::Sub`]), as in `flags - other`.
731    ///
732    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
733    #[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    /// Returns the union of the two sets of flags.
746    #[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    /// Adds the set of flags.
756    #[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    /// Returns the left flags, but with all the right flags toggled.
766    #[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    /// Toggles the set of flags.
776    #[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    /// Returns the intersection between the two sets of flags.
786    #[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    /// Disables all flags disabled in the set.
796    #[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    /// Returns the set difference of the two sets of flags.
806    #[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    /// Disables all flags enabled in the set.
816    #[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    /// Returns the complement of this set of flags.
826    #[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/// The [VariationRegionList](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#variation-regions) table
925#[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    /// The number of variation axes for this font. This must be the
936    /// same number as axisCount in the 'fvar' table.
937    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    /// The number of variation region tables in the variation region
943    /// list. Must be less than 32,768.
944    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    /// Array of variation regions.
950    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/// The [VariationRegion](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#variation-regions) record
1023#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1024pub struct VariationRegion<'a> {
1025    /// Array of region axis coordinates records, in the order of axes
1026    /// given in the 'fvar' table.
1027    pub region_axes: &'a [RegionAxisCoordinates],
1028}
1029
1030impl<'a> VariationRegion<'a> {
1031    /// Array of region axis coordinates records, in the order of axes
1032    /// given in the 'fvar' table.
1033    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    /// A constructor that requires additional arguments.
1063    ///
1064    /// This type requires some external state in order to be
1065    /// parsed.
1066    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/// The [RegionAxisCoordinates](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#variation-regions) record
1094#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1095#[repr(C)]
1096#[repr(packed)]
1097pub struct RegionAxisCoordinates {
1098    /// The region start coordinate value for the current axis.
1099    pub start_coord: BigEndian<F2Dot14>,
1100    /// The region peak coordinate value for the current axis.
1101    pub peak_coord: BigEndian<F2Dot14>,
1102    /// The region end coordinate value for the current axis.
1103    pub end_coord: BigEndian<F2Dot14>,
1104}
1105
1106impl RegionAxisCoordinates {
1107    /// The region start coordinate value for the current axis.
1108    pub fn start_coord(&self) -> F2Dot14 {
1109        self.start_coord.get()
1110    }
1111
1112    /// The region peak coordinate value for the current axis.
1113    pub fn peak_coord(&self) -> F2Dot14 {
1114        self.peak_coord.get()
1115    }
1116
1117    /// The region end coordinate value for the current axis.
1118    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/// The [ItemVariationStore](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables) table
1169#[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    /// Format— set to 1
1180    pub fn format(&self) -> u16 {
1181        let range = self.format_byte_range();
1182        self.data.read_at(range.start).ok().unwrap()
1183    }
1184
1185    /// Offset in bytes from the start of the item variation store to
1186    /// the variation region list.
1187    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    /// Attempt to resolve [`variation_region_list_offset`][Self::variation_region_list_offset].
1193    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    /// The number of item variation data subtables.
1199    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    /// Offsets in bytes from the start of the item variation store to
1205    /// each item variation data subtable.
1206    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    /// A dynamically resolving wrapper for [`item_variation_data_offsets`][Self::item_variation_data_offsets].
1212    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/// The [ItemVariationData](https://learn.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables) subtable
1321#[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    /// The number of delta sets for distinct items.
1332    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    /// A packed field: the high bit is a flag—see details below.
1338    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    /// The number of variation regions referenced.
1344    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    /// Array of indices into the variation region list for the regions
1350    /// referenced by this item variation data table.
1351    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    /// Delta-set rows.
1357    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}