Skip to main content

read_fonts/generated/
generated_gvar.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 Gvar<'a> {
9    fn min_byte_range(&self) -> Range<usize> {
10        0..self.glyph_variation_data_offsets_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 TopLevelTable for Gvar<'_> {
19    /// `gvar`
20    const TAG: Tag = Tag::new(b"gvar");
21}
22
23impl<'a> FontRead<'a> for Gvar<'a> {
24    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
25        #[allow(clippy::absurd_extreme_comparisons)]
26        if data.len() < Self::MIN_SIZE {
27            return Err(ReadError::OutOfBounds);
28        }
29        Ok(Self { data })
30    }
31}
32
33/// The ['gvar' header](https://learn.microsoft.com/en-us/typography/opentype/spec/gvar#gvar-header)
34#[derive(Clone)]
35pub struct Gvar<'a> {
36    data: FontData<'a>,
37}
38
39#[allow(clippy::needless_lifetimes)]
40impl<'a> Gvar<'a> {
41    pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
42        + u16::RAW_BYTE_LEN
43        + u16::RAW_BYTE_LEN
44        + Offset32::RAW_BYTE_LEN
45        + u16::RAW_BYTE_LEN
46        + GvarFlags::RAW_BYTE_LEN
47        + u32::RAW_BYTE_LEN);
48    basic_table_impls!(impl_the_methods);
49
50    /// Major/minor version number of the glyph variations table — set to (1,0).
51    pub fn version(&self) -> MajorMinor {
52        let range = self.version_byte_range();
53        self.data.read_at(range.start).ok().unwrap()
54    }
55
56    /// The number of variation axes for this font. This must be the
57    /// same number as axisCount in the 'fvar' table.
58    pub fn axis_count(&self) -> u16 {
59        let range = self.axis_count_byte_range();
60        self.data.read_at(range.start).ok().unwrap()
61    }
62
63    /// The number of shared tuple records. Shared tuple records can be
64    /// referenced within glyph variation data tables for multiple
65    /// glyphs, as opposed to other tuple records stored directly
66    /// within a glyph variation data table.
67    pub fn shared_tuple_count(&self) -> u16 {
68        let range = self.shared_tuple_count_byte_range();
69        self.data.read_at(range.start).ok().unwrap()
70    }
71
72    /// Offset from the start of this table to the shared tuple records.
73    pub fn shared_tuples_offset(&self) -> Offset32 {
74        let range = self.shared_tuples_offset_byte_range();
75        self.data.read_at(range.start).ok().unwrap()
76    }
77
78    /// Attempt to resolve [`shared_tuples_offset`][Self::shared_tuples_offset].
79    pub fn shared_tuples(&self) -> Result<SharedTuples<'a>, ReadError> {
80        let data = self.data;
81        let args = (self.shared_tuple_count(), self.axis_count());
82        self.shared_tuples_offset().resolve_with_args(data, &args)
83    }
84
85    /// The number of glyphs in this font. This must match the number
86    /// of glyphs stored elsewhere in the font.
87    pub fn glyph_count(&self) -> u16 {
88        let range = self.glyph_count_byte_range();
89        self.data.read_at(range.start).ok().unwrap()
90    }
91
92    /// Bit-field that gives the format of the offset array that
93    /// follows. If bit 0 is clear, the offsets are uint16; if bit 0 is
94    /// set, the offsets are uint32.
95    pub fn flags(&self) -> GvarFlags {
96        let range = self.flags_byte_range();
97        self.data.read_at(range.start).ok().unwrap()
98    }
99
100    /// Offset from the start of this table to the array of
101    /// GlyphVariationData tables.
102    pub fn glyph_variation_data_array_offset(&self) -> u32 {
103        let range = self.glyph_variation_data_array_offset_byte_range();
104        self.data.read_at(range.start).ok().unwrap()
105    }
106
107    /// Offsets from the start of the GlyphVariationData array to each
108    /// GlyphVariationData table.
109    pub fn glyph_variation_data_offsets(&self) -> ComputedArray<'a, U16Or32> {
110        let range = self.glyph_variation_data_offsets_byte_range();
111        self.data
112            .read_with_args(range, &self.flags())
113            .unwrap_or_default()
114    }
115
116    pub fn version_byte_range(&self) -> Range<usize> {
117        let start = 0;
118        let end = start + MajorMinor::RAW_BYTE_LEN;
119        start..end
120    }
121
122    pub fn axis_count_byte_range(&self) -> Range<usize> {
123        let start = self.version_byte_range().end;
124        let end = start + u16::RAW_BYTE_LEN;
125        start..end
126    }
127
128    pub fn shared_tuple_count_byte_range(&self) -> Range<usize> {
129        let start = self.axis_count_byte_range().end;
130        let end = start + u16::RAW_BYTE_LEN;
131        start..end
132    }
133
134    pub fn shared_tuples_offset_byte_range(&self) -> Range<usize> {
135        let start = self.shared_tuple_count_byte_range().end;
136        let end = start + Offset32::RAW_BYTE_LEN;
137        start..end
138    }
139
140    pub fn glyph_count_byte_range(&self) -> Range<usize> {
141        let start = self.shared_tuples_offset_byte_range().end;
142        let end = start + u16::RAW_BYTE_LEN;
143        start..end
144    }
145
146    pub fn flags_byte_range(&self) -> Range<usize> {
147        let start = self.glyph_count_byte_range().end;
148        let end = start + GvarFlags::RAW_BYTE_LEN;
149        start..end
150    }
151
152    pub fn glyph_variation_data_array_offset_byte_range(&self) -> Range<usize> {
153        let start = self.flags_byte_range().end;
154        let end = start + u32::RAW_BYTE_LEN;
155        start..end
156    }
157
158    pub fn glyph_variation_data_offsets_byte_range(&self) -> Range<usize> {
159        let glyph_count = self.glyph_count();
160        let start = self.glyph_variation_data_array_offset_byte_range().end;
161        let end = start
162            + (transforms::add(glyph_count, 1_usize))
163                .saturating_mul(<U16Or32 as ComputeSize>::compute_size(&self.flags()).unwrap_or(0));
164        start..end
165    }
166}
167
168const _: () = assert!(FontData::default_data_long_enough(Gvar::MIN_SIZE));
169
170impl Default for Gvar<'_> {
171    fn default() -> Self {
172        Self {
173            data: FontData::default_table_data(),
174        }
175    }
176}
177
178#[cfg(feature = "experimental_traverse")]
179impl<'a> SomeTable<'a> for Gvar<'a> {
180    fn type_name(&self) -> &str {
181        "Gvar"
182    }
183    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
184        match idx {
185            0usize => Some(Field::new("version", self.version())),
186            1usize => Some(Field::new("axis_count", self.axis_count())),
187            2usize => Some(Field::new("shared_tuple_count", self.shared_tuple_count())),
188            3usize => Some(Field::new(
189                "shared_tuples_offset",
190                FieldType::offset(self.shared_tuples_offset(), self.shared_tuples()),
191            )),
192            4usize => Some(Field::new("glyph_count", self.glyph_count())),
193            5usize => Some(Field::new("flags", self.flags())),
194            6usize => Some(Field::new(
195                "glyph_variation_data_array_offset",
196                self.glyph_variation_data_array_offset(),
197            )),
198            7usize => Some(Field::new(
199                "glyph_variation_data_offsets",
200                traversal::FieldType::Unknown,
201            )),
202            _ => None,
203        }
204    }
205}
206
207#[cfg(feature = "experimental_traverse")]
208#[allow(clippy::needless_lifetimes)]
209impl<'a> std::fmt::Debug for Gvar<'a> {
210    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
211        (self as &dyn SomeTable<'a>).fmt(f)
212    }
213}
214
215#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
216#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
217#[repr(transparent)]
218pub struct GvarFlags {
219    bits: u16,
220}
221
222impl GvarFlags {
223    /// If set, offsets to GlyphVariationData are 32 bits
224    pub const LONG_OFFSETS: Self = Self { bits: 1 };
225}
226
227impl GvarFlags {
228    ///  Returns an empty set of flags.
229    #[inline]
230    pub const fn empty() -> Self {
231        Self { bits: 0 }
232    }
233
234    /// Returns the set containing all flags.
235    #[inline]
236    pub const fn all() -> Self {
237        Self {
238            bits: Self::LONG_OFFSETS.bits,
239        }
240    }
241
242    /// Returns the raw value of the flags currently stored.
243    #[inline]
244    pub const fn bits(&self) -> u16 {
245        self.bits
246    }
247
248    /// Convert from underlying bit representation, unless that
249    /// representation contains bits that do not correspond to a flag.
250    #[inline]
251    pub const fn from_bits(bits: u16) -> Option<Self> {
252        if (bits & !Self::all().bits()) == 0 {
253            Some(Self { bits })
254        } else {
255            None
256        }
257    }
258
259    /// Convert from underlying bit representation, dropping any bits
260    /// that do not correspond to flags.
261    #[inline]
262    pub const fn from_bits_truncate(bits: u16) -> Self {
263        Self {
264            bits: bits & Self::all().bits,
265        }
266    }
267
268    /// Returns `true` if no flags are currently stored.
269    #[inline]
270    pub const fn is_empty(&self) -> bool {
271        self.bits() == Self::empty().bits()
272    }
273
274    /// Returns `true` if there are flags common to both `self` and `other`.
275    #[inline]
276    pub const fn intersects(&self, other: Self) -> bool {
277        !(Self {
278            bits: self.bits & other.bits,
279        })
280        .is_empty()
281    }
282
283    /// Returns `true` if all of the flags in `other` are contained within `self`.
284    #[inline]
285    pub const fn contains(&self, other: Self) -> bool {
286        (self.bits & other.bits) == other.bits
287    }
288
289    /// Inserts the specified flags in-place.
290    #[inline]
291    pub fn insert(&mut self, other: Self) {
292        self.bits |= other.bits;
293    }
294
295    /// Removes the specified flags in-place.
296    #[inline]
297    pub fn remove(&mut self, other: Self) {
298        self.bits &= !other.bits;
299    }
300
301    /// Toggles the specified flags in-place.
302    #[inline]
303    pub fn toggle(&mut self, other: Self) {
304        self.bits ^= other.bits;
305    }
306
307    /// Returns the intersection between the flags in `self` and
308    /// `other`.
309    ///
310    /// Specifically, the returned set contains only the flags which are
311    /// present in *both* `self` *and* `other`.
312    ///
313    /// This is equivalent to using the `&` operator (e.g.
314    /// [`ops::BitAnd`]), as in `flags & other`.
315    ///
316    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
317    #[inline]
318    #[must_use]
319    pub const fn intersection(self, other: Self) -> Self {
320        Self {
321            bits: self.bits & other.bits,
322        }
323    }
324
325    /// Returns the union of between the flags in `self` and `other`.
326    ///
327    /// Specifically, the returned set contains all flags which are
328    /// present in *either* `self` *or* `other`, including any which are
329    /// present in both.
330    ///
331    /// This is equivalent to using the `|` operator (e.g.
332    /// [`ops::BitOr`]), as in `flags | other`.
333    ///
334    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
335    #[inline]
336    #[must_use]
337    pub const fn union(self, other: Self) -> Self {
338        Self {
339            bits: self.bits | other.bits,
340        }
341    }
342
343    /// Returns the difference between the flags in `self` and `other`.
344    ///
345    /// Specifically, the returned set contains all flags present in
346    /// `self`, except for the ones present in `other`.
347    ///
348    /// It is also conceptually equivalent to the "bit-clear" operation:
349    /// `flags & !other` (and this syntax is also supported).
350    ///
351    /// This is equivalent to using the `-` operator (e.g.
352    /// [`ops::Sub`]), as in `flags - other`.
353    ///
354    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
355    #[inline]
356    #[must_use]
357    pub const fn difference(self, other: Self) -> Self {
358        Self {
359            bits: self.bits & !other.bits,
360        }
361    }
362}
363
364impl std::ops::BitOr for GvarFlags {
365    type Output = Self;
366
367    /// Returns the union of the two sets of flags.
368    #[inline]
369    fn bitor(self, other: GvarFlags) -> Self {
370        Self {
371            bits: self.bits | other.bits,
372        }
373    }
374}
375
376impl std::ops::BitOrAssign for GvarFlags {
377    /// Adds the set of flags.
378    #[inline]
379    fn bitor_assign(&mut self, other: Self) {
380        self.bits |= other.bits;
381    }
382}
383
384impl std::ops::BitXor for GvarFlags {
385    type Output = Self;
386
387    /// Returns the left flags, but with all the right flags toggled.
388    #[inline]
389    fn bitxor(self, other: Self) -> Self {
390        Self {
391            bits: self.bits ^ other.bits,
392        }
393    }
394}
395
396impl std::ops::BitXorAssign for GvarFlags {
397    /// Toggles the set of flags.
398    #[inline]
399    fn bitxor_assign(&mut self, other: Self) {
400        self.bits ^= other.bits;
401    }
402}
403
404impl std::ops::BitAnd for GvarFlags {
405    type Output = Self;
406
407    /// Returns the intersection between the two sets of flags.
408    #[inline]
409    fn bitand(self, other: Self) -> Self {
410        Self {
411            bits: self.bits & other.bits,
412        }
413    }
414}
415
416impl std::ops::BitAndAssign for GvarFlags {
417    /// Disables all flags disabled in the set.
418    #[inline]
419    fn bitand_assign(&mut self, other: Self) {
420        self.bits &= other.bits;
421    }
422}
423
424impl std::ops::Sub for GvarFlags {
425    type Output = Self;
426
427    /// Returns the set difference of the two sets of flags.
428    #[inline]
429    fn sub(self, other: Self) -> Self {
430        Self {
431            bits: self.bits & !other.bits,
432        }
433    }
434}
435
436impl std::ops::SubAssign for GvarFlags {
437    /// Disables all flags enabled in the set.
438    #[inline]
439    fn sub_assign(&mut self, other: Self) {
440        self.bits &= !other.bits;
441    }
442}
443
444impl std::ops::Not for GvarFlags {
445    type Output = Self;
446
447    /// Returns the complement of this set of flags.
448    #[inline]
449    fn not(self) -> Self {
450        Self { bits: !self.bits } & Self::all()
451    }
452}
453
454impl std::fmt::Debug for GvarFlags {
455    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
456        let members: &[(&str, Self)] = &[("LONG_OFFSETS", Self::LONG_OFFSETS)];
457        let mut first = true;
458        for (name, value) in members {
459            if self.contains(*value) {
460                if !first {
461                    f.write_str(" | ")?;
462                }
463                first = false;
464                f.write_str(name)?;
465            }
466        }
467        if first {
468            f.write_str("(empty)")?;
469        }
470        Ok(())
471    }
472}
473
474impl std::fmt::Binary for GvarFlags {
475    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
476        std::fmt::Binary::fmt(&self.bits, f)
477    }
478}
479
480impl std::fmt::Octal for GvarFlags {
481    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
482        std::fmt::Octal::fmt(&self.bits, f)
483    }
484}
485
486impl std::fmt::LowerHex for GvarFlags {
487    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
488        std::fmt::LowerHex::fmt(&self.bits, f)
489    }
490}
491
492impl std::fmt::UpperHex for GvarFlags {
493    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
494        std::fmt::UpperHex::fmt(&self.bits, f)
495    }
496}
497
498impl font_types::Scalar for GvarFlags {
499    type Raw = <u16 as font_types::Scalar>::Raw;
500    fn to_raw(self) -> Self::Raw {
501        self.bits().to_raw()
502    }
503    fn from_raw(raw: Self::Raw) -> Self {
504        let t = <u16>::from_raw(raw);
505        Self::from_bits_truncate(t)
506    }
507}
508
509#[cfg(feature = "experimental_traverse")]
510impl<'a> From<GvarFlags> for FieldType<'a> {
511    fn from(src: GvarFlags) -> FieldType<'a> {
512        src.bits().into()
513    }
514}
515
516impl<'a> MinByteRange<'a> for SharedTuples<'a> {
517    fn min_byte_range(&self) -> Range<usize> {
518        0..self.tuples_byte_range().end
519    }
520    fn min_table_bytes(&self) -> &'a [u8] {
521        let range = self.min_byte_range();
522        self.data.as_bytes().get(range).unwrap_or_default()
523    }
524}
525
526impl ReadArgs for SharedTuples<'_> {
527    type Args = (u16, u16);
528}
529
530impl<'a> FontReadWithArgs<'a> for SharedTuples<'a> {
531    fn read_with_args(data: FontData<'a>, args: &(u16, u16)) -> Result<Self, ReadError> {
532        let (shared_tuple_count, axis_count) = *args;
533
534        #[allow(clippy::absurd_extreme_comparisons)]
535        if data.len() < Self::MIN_SIZE {
536            return Err(ReadError::OutOfBounds);
537        }
538        Ok(Self {
539            data,
540            shared_tuple_count,
541            axis_count,
542        })
543    }
544}
545
546impl<'a> SharedTuples<'a> {
547    /// A constructor that requires additional arguments.
548    ///
549    /// This type requires some external state in order to be
550    /// parsed.
551    pub fn read(
552        data: FontData<'a>,
553        shared_tuple_count: u16,
554        axis_count: u16,
555    ) -> Result<Self, ReadError> {
556        let args = (shared_tuple_count, axis_count);
557        Self::read_with_args(data, &args)
558    }
559}
560
561/// Array of tuple records shared across all glyph variation data tables.
562#[derive(Clone)]
563pub struct SharedTuples<'a> {
564    data: FontData<'a>,
565    shared_tuple_count: u16,
566    axis_count: u16,
567}
568
569#[allow(clippy::needless_lifetimes)]
570impl<'a> SharedTuples<'a> {
571    pub const MIN_SIZE: usize = 0;
572    basic_table_impls!(impl_the_methods);
573
574    pub fn tuples(&self) -> ComputedArray<'a, Tuple<'a>> {
575        let range = self.tuples_byte_range();
576        self.data
577            .read_with_args(range, &self.axis_count())
578            .unwrap_or_default()
579    }
580
581    pub(crate) fn shared_tuple_count(&self) -> u16 {
582        self.shared_tuple_count
583    }
584
585    pub(crate) fn axis_count(&self) -> u16 {
586        self.axis_count
587    }
588
589    pub fn tuples_byte_range(&self) -> Range<usize> {
590        let shared_tuple_count = self.shared_tuple_count();
591        let start = 0;
592        let end = start
593            + (transforms::to_usize(shared_tuple_count)).saturating_mul(
594                <Tuple as ComputeSize>::compute_size(&self.axis_count()).unwrap_or(0),
595            );
596        start..end
597    }
598}
599
600#[allow(clippy::absurd_extreme_comparisons)]
601const _: () = assert!(FontData::default_data_long_enough(SharedTuples::MIN_SIZE));
602
603impl Default for SharedTuples<'_> {
604    fn default() -> Self {
605        Self {
606            data: FontData::default_table_data(),
607            shared_tuple_count: Default::default(),
608            axis_count: Default::default(),
609        }
610    }
611}
612
613#[cfg(feature = "experimental_traverse")]
614impl<'a> SomeTable<'a> for SharedTuples<'a> {
615    fn type_name(&self) -> &str {
616        "SharedTuples"
617    }
618    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
619        match idx {
620            0usize => Some(Field::new(
621                "tuples",
622                traversal::FieldType::computed_array("Tuple", self.tuples(), self.offset_data()),
623            )),
624            _ => None,
625        }
626    }
627}
628
629#[cfg(feature = "experimental_traverse")]
630#[allow(clippy::needless_lifetimes)]
631impl<'a> std::fmt::Debug for SharedTuples<'a> {
632    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
633        (self as &dyn SomeTable<'a>).fmt(f)
634    }
635}
636
637impl<'a> MinByteRange<'a> for GlyphVariationDataHeader<'a> {
638    fn min_byte_range(&self) -> Range<usize> {
639        0..self.tuple_variation_headers_byte_range().end
640    }
641    fn min_table_bytes(&self) -> &'a [u8] {
642        let range = self.min_byte_range();
643        self.data.as_bytes().get(range).unwrap_or_default()
644    }
645}
646
647impl<'a> FontRead<'a> for GlyphVariationDataHeader<'a> {
648    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
649        #[allow(clippy::absurd_extreme_comparisons)]
650        if data.len() < Self::MIN_SIZE {
651            return Err(ReadError::OutOfBounds);
652        }
653        Ok(Self { data })
654    }
655}
656
657/// The [GlyphVariationData](https://learn.microsoft.com/en-us/typography/opentype/spec/gvar#the-glyphvariationdata-table-array) table
658#[derive(Clone)]
659pub struct GlyphVariationDataHeader<'a> {
660    data: FontData<'a>,
661}
662
663#[allow(clippy::needless_lifetimes)]
664impl<'a> GlyphVariationDataHeader<'a> {
665    pub const MIN_SIZE: usize = (TupleVariationCount::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
666    basic_table_impls!(impl_the_methods);
667
668    /// A packed field. The high 4 bits are flags, and the low 12 bits
669    /// are the number of tuple variation tables for this glyph. The
670    /// number of tuple variation tables can be any number between 1
671    /// and 4095.
672    pub fn tuple_variation_count(&self) -> TupleVariationCount {
673        let range = self.tuple_variation_count_byte_range();
674        self.data.read_at(range.start).ok().unwrap()
675    }
676
677    /// Offset from the start of the GlyphVariationData table to the
678    /// serialized data
679    pub fn serialized_data_offset(&self) -> Offset16 {
680        let range = self.serialized_data_offset_byte_range();
681        self.data.read_at(range.start).ok().unwrap()
682    }
683
684    /// Attempt to resolve [`serialized_data_offset`][Self::serialized_data_offset].
685    pub fn serialized_data(&self) -> Result<FontData<'a>, ReadError> {
686        let data = self.data;
687        self.serialized_data_offset().resolve(data)
688    }
689
690    /// Array of tuple variation headers.
691    pub fn tuple_variation_headers(&self) -> VarLenArray<'a, TupleVariationHeader<'a>> {
692        let range = self.tuple_variation_headers_byte_range();
693        self.data
694            .split_off(range.start)
695            .and_then(|d| VarLenArray::read(d).ok())
696            .unwrap_or_default()
697    }
698
699    pub fn tuple_variation_count_byte_range(&self) -> Range<usize> {
700        let start = 0;
701        let end = start + TupleVariationCount::RAW_BYTE_LEN;
702        start..end
703    }
704
705    pub fn serialized_data_offset_byte_range(&self) -> Range<usize> {
706        let start = self.tuple_variation_count_byte_range().end;
707        let end = start + Offset16::RAW_BYTE_LEN;
708        start..end
709    }
710
711    pub fn tuple_variation_headers_byte_range(&self) -> Range<usize> {
712        let start = self.serialized_data_offset_byte_range().end;
713        let end = start + self.data.len().saturating_sub(start);
714        start..end
715    }
716}
717
718const _: () = assert!(FontData::default_data_long_enough(
719    GlyphVariationDataHeader::MIN_SIZE
720));
721
722impl Default for GlyphVariationDataHeader<'_> {
723    fn default() -> Self {
724        Self {
725            data: FontData::default_table_data(),
726        }
727    }
728}
729
730#[cfg(feature = "experimental_traverse")]
731impl<'a> SomeTable<'a> for GlyphVariationDataHeader<'a> {
732    fn type_name(&self) -> &str {
733        "GlyphVariationDataHeader"
734    }
735    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
736        match idx {
737            0usize => Some(Field::new(
738                "tuple_variation_count",
739                traversal::FieldType::Unknown,
740            )),
741            1usize => Some(Field::new(
742                "serialized_data_offset",
743                traversal::FieldType::Unknown,
744            )),
745            2usize => Some(Field::new(
746                "tuple_variation_headers",
747                traversal::FieldType::Unknown,
748            )),
749            _ => None,
750        }
751    }
752}
753
754#[cfg(feature = "experimental_traverse")]
755#[allow(clippy::needless_lifetimes)]
756impl<'a> std::fmt::Debug for GlyphVariationDataHeader<'a> {
757    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
758        (self as &dyn SomeTable<'a>).fmt(f)
759    }
760}