read_fonts/generated/
generated_stat.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
8/// [STAT](https://docs.microsoft.com/en-us/typography/opentype/spec/stat) (Style Attributes Table)
9#[derive(Debug, Clone, Copy)]
10#[doc(hidden)]
11pub struct StatMarker {
12    elided_fallback_name_id_byte_start: Option<usize>,
13}
14
15impl StatMarker {
16    pub fn version_byte_range(&self) -> Range<usize> {
17        let start = 0;
18        start..start + MajorMinor::RAW_BYTE_LEN
19    }
20
21    pub fn design_axis_size_byte_range(&self) -> Range<usize> {
22        let start = self.version_byte_range().end;
23        start..start + u16::RAW_BYTE_LEN
24    }
25
26    pub fn design_axis_count_byte_range(&self) -> Range<usize> {
27        let start = self.design_axis_size_byte_range().end;
28        start..start + u16::RAW_BYTE_LEN
29    }
30
31    pub fn design_axes_offset_byte_range(&self) -> Range<usize> {
32        let start = self.design_axis_count_byte_range().end;
33        start..start + Offset32::RAW_BYTE_LEN
34    }
35
36    pub fn axis_value_count_byte_range(&self) -> Range<usize> {
37        let start = self.design_axes_offset_byte_range().end;
38        start..start + u16::RAW_BYTE_LEN
39    }
40
41    pub fn offset_to_axis_value_offsets_byte_range(&self) -> Range<usize> {
42        let start = self.axis_value_count_byte_range().end;
43        start..start + Offset32::RAW_BYTE_LEN
44    }
45
46    pub fn elided_fallback_name_id_byte_range(&self) -> Option<Range<usize>> {
47        let start = self.elided_fallback_name_id_byte_start?;
48        Some(start..start + NameId::RAW_BYTE_LEN)
49    }
50}
51
52impl MinByteRange for StatMarker {
53    fn min_byte_range(&self) -> Range<usize> {
54        0..self.offset_to_axis_value_offsets_byte_range().end
55    }
56}
57
58impl TopLevelTable for Stat<'_> {
59    /// `STAT`
60    const TAG: Tag = Tag::new(b"STAT");
61}
62
63impl<'a> FontRead<'a> for Stat<'a> {
64    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
65        let mut cursor = data.cursor();
66        let version: MajorMinor = cursor.read()?;
67        cursor.advance::<u16>();
68        cursor.advance::<u16>();
69        cursor.advance::<Offset32>();
70        cursor.advance::<u16>();
71        cursor.advance::<Offset32>();
72        let elided_fallback_name_id_byte_start = version
73            .compatible((1u16, 1u16))
74            .then(|| cursor.position())
75            .transpose()?;
76        version
77            .compatible((1u16, 1u16))
78            .then(|| cursor.advance::<NameId>());
79        cursor.finish(StatMarker {
80            elided_fallback_name_id_byte_start,
81        })
82    }
83}
84
85/// [STAT](https://docs.microsoft.com/en-us/typography/opentype/spec/stat) (Style Attributes Table)
86pub type Stat<'a> = TableRef<'a, StatMarker>;
87
88#[allow(clippy::needless_lifetimes)]
89impl<'a> Stat<'a> {
90    /// Major/minor version number. Set to 1.2 for new fonts.
91    pub fn version(&self) -> MajorMinor {
92        let range = self.shape.version_byte_range();
93        self.data.read_at(range.start).unwrap()
94    }
95
96    /// The size in bytes of each axis record.
97    pub fn design_axis_size(&self) -> u16 {
98        let range = self.shape.design_axis_size_byte_range();
99        self.data.read_at(range.start).unwrap()
100    }
101
102    /// The number of axis records. In a font with an 'fvar' table,
103    /// this value must be greater than or equal to the axisCount value
104    /// in the 'fvar' table. In all fonts, must be greater than zero if
105    /// axisValueCount is greater than zero.
106    pub fn design_axis_count(&self) -> u16 {
107        let range = self.shape.design_axis_count_byte_range();
108        self.data.read_at(range.start).unwrap()
109    }
110
111    /// Offset in bytes from the beginning of the STAT table to the
112    /// start of the design axes array. If designAxisCount is zero, set
113    /// to zero; if designAxisCount is greater than zero, must be
114    /// greater than zero.
115    pub fn design_axes_offset(&self) -> Offset32 {
116        let range = self.shape.design_axes_offset_byte_range();
117        self.data.read_at(range.start).unwrap()
118    }
119
120    /// Attempt to resolve [`design_axes_offset`][Self::design_axes_offset].
121    pub fn design_axes(&self) -> Result<&'a [AxisRecord], ReadError> {
122        let data = self.data;
123        let args = self.design_axis_count();
124        self.design_axes_offset().resolve_with_args(data, &args)
125    }
126
127    /// The number of axis value tables.
128    pub fn axis_value_count(&self) -> u16 {
129        let range = self.shape.axis_value_count_byte_range();
130        self.data.read_at(range.start).unwrap()
131    }
132
133    /// Offset in bytes from the beginning of the STAT table to the
134    /// start of the design axes value offsets array. If axisValueCount
135    /// is zero, set to zero; if axisValueCount is greater than zero,
136    /// must be greater than zero.
137    pub fn offset_to_axis_value_offsets(&self) -> Nullable<Offset32> {
138        let range = self.shape.offset_to_axis_value_offsets_byte_range();
139        self.data.read_at(range.start).unwrap()
140    }
141
142    /// Attempt to resolve [`offset_to_axis_value_offsets`][Self::offset_to_axis_value_offsets].
143    pub fn offset_to_axis_values(&self) -> Option<Result<AxisValueArray<'a>, ReadError>> {
144        let data = self.data;
145        let args = self.axis_value_count();
146        self.offset_to_axis_value_offsets()
147            .resolve_with_args(data, &args)
148    }
149
150    /// Name ID used as fallback when projection of names into a
151    /// particular font model produces a subfamily name containing only
152    /// elidable elements.
153    pub fn elided_fallback_name_id(&self) -> Option<NameId> {
154        let range = self.shape.elided_fallback_name_id_byte_range()?;
155        Some(self.data.read_at(range.start).unwrap())
156    }
157}
158
159#[cfg(feature = "experimental_traverse")]
160impl<'a> SomeTable<'a> for Stat<'a> {
161    fn type_name(&self) -> &str {
162        "Stat"
163    }
164    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
165        let version = self.version();
166        match idx {
167            0usize => Some(Field::new("version", self.version())),
168            1usize => Some(Field::new("design_axis_size", self.design_axis_size())),
169            2usize => Some(Field::new("design_axis_count", self.design_axis_count())),
170            3usize => Some(Field::new(
171                "design_axes_offset",
172                traversal::FieldType::offset_to_array_of_records(
173                    self.design_axes_offset(),
174                    self.design_axes(),
175                    stringify!(AxisRecord),
176                    self.offset_data(),
177                ),
178            )),
179            4usize => Some(Field::new("axis_value_count", self.axis_value_count())),
180            5usize => Some(Field::new(
181                "offset_to_axis_value_offsets",
182                FieldType::offset(
183                    self.offset_to_axis_value_offsets(),
184                    self.offset_to_axis_values(),
185                ),
186            )),
187            6usize if version.compatible((1u16, 1u16)) => Some(Field::new(
188                "elided_fallback_name_id",
189                self.elided_fallback_name_id().unwrap(),
190            )),
191            _ => None,
192        }
193    }
194}
195
196#[cfg(feature = "experimental_traverse")]
197#[allow(clippy::needless_lifetimes)]
198impl<'a> std::fmt::Debug for Stat<'a> {
199    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200        (self as &dyn SomeTable<'a>).fmt(f)
201    }
202}
203
204/// [Axis Records](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-records)
205#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
206#[repr(C)]
207#[repr(packed)]
208pub struct AxisRecord {
209    /// A tag identifying the axis of design variation.
210    pub axis_tag: BigEndian<Tag>,
211    /// The name ID for entries in the 'name' table that provide a
212    /// display string for this axis.
213    pub axis_name_id: BigEndian<NameId>,
214    /// A value that applications can use to determine primary sorting
215    /// of face names, or for ordering of labels when composing family
216    /// or face names.
217    pub axis_ordering: BigEndian<u16>,
218}
219
220impl AxisRecord {
221    /// A tag identifying the axis of design variation.
222    pub fn axis_tag(&self) -> Tag {
223        self.axis_tag.get()
224    }
225
226    /// The name ID for entries in the 'name' table that provide a
227    /// display string for this axis.
228    pub fn axis_name_id(&self) -> NameId {
229        self.axis_name_id.get()
230    }
231
232    /// A value that applications can use to determine primary sorting
233    /// of face names, or for ordering of labels when composing family
234    /// or face names.
235    pub fn axis_ordering(&self) -> u16 {
236        self.axis_ordering.get()
237    }
238}
239
240impl FixedSize for AxisRecord {
241    const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + NameId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
242}
243
244#[cfg(feature = "experimental_traverse")]
245impl<'a> SomeRecord<'a> for AxisRecord {
246    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
247        RecordResolver {
248            name: "AxisRecord",
249            get_field: Box::new(move |idx, _data| match idx {
250                0usize => Some(Field::new("axis_tag", self.axis_tag())),
251                1usize => Some(Field::new("axis_name_id", self.axis_name_id())),
252                2usize => Some(Field::new("axis_ordering", self.axis_ordering())),
253                _ => None,
254            }),
255            data,
256        }
257    }
258}
259
260/// An array of [AxisValue] tables.
261#[derive(Debug, Clone, Copy)]
262#[doc(hidden)]
263pub struct AxisValueArrayMarker {
264    axis_value_offsets_byte_len: usize,
265}
266
267impl AxisValueArrayMarker {
268    pub fn axis_value_offsets_byte_range(&self) -> Range<usize> {
269        let start = 0;
270        start..start + self.axis_value_offsets_byte_len
271    }
272}
273
274impl MinByteRange for AxisValueArrayMarker {
275    fn min_byte_range(&self) -> Range<usize> {
276        0..self.axis_value_offsets_byte_range().end
277    }
278}
279
280impl ReadArgs for AxisValueArray<'_> {
281    type Args = u16;
282}
283
284impl<'a> FontReadWithArgs<'a> for AxisValueArray<'a> {
285    fn read_with_args(data: FontData<'a>, args: &u16) -> Result<Self, ReadError> {
286        let axis_value_count = *args;
287        let mut cursor = data.cursor();
288        let axis_value_offsets_byte_len = (axis_value_count as usize)
289            .checked_mul(Offset16::RAW_BYTE_LEN)
290            .ok_or(ReadError::OutOfBounds)?;
291        cursor.advance_by(axis_value_offsets_byte_len);
292        cursor.finish(AxisValueArrayMarker {
293            axis_value_offsets_byte_len,
294        })
295    }
296}
297
298impl<'a> AxisValueArray<'a> {
299    /// A constructor that requires additional arguments.
300    ///
301    /// This type requires some external state in order to be
302    /// parsed.
303    pub fn read(data: FontData<'a>, axis_value_count: u16) -> Result<Self, ReadError> {
304        let args = axis_value_count;
305        Self::read_with_args(data, &args)
306    }
307}
308
309/// An array of [AxisValue] tables.
310pub type AxisValueArray<'a> = TableRef<'a, AxisValueArrayMarker>;
311
312#[allow(clippy::needless_lifetimes)]
313impl<'a> AxisValueArray<'a> {
314    /// Array of offsets to axis value tables, in bytes from the start
315    /// of the axis value offsets array.
316    pub fn axis_value_offsets(&self) -> &'a [BigEndian<Offset16>] {
317        let range = self.shape.axis_value_offsets_byte_range();
318        self.data.read_array(range).unwrap()
319    }
320
321    /// A dynamically resolving wrapper for [`axis_value_offsets`][Self::axis_value_offsets].
322    pub fn axis_values(&self) -> ArrayOfOffsets<'a, AxisValue<'a>, Offset16> {
323        let data = self.data;
324        let offsets = self.axis_value_offsets();
325        ArrayOfOffsets::new(offsets, data, ())
326    }
327}
328
329#[cfg(feature = "experimental_traverse")]
330impl<'a> SomeTable<'a> for AxisValueArray<'a> {
331    fn type_name(&self) -> &str {
332        "AxisValueArray"
333    }
334    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
335        match idx {
336            0usize => Some({
337                let data = self.data;
338                Field::new(
339                    "axis_value_offsets",
340                    FieldType::array_of_offsets(
341                        better_type_name::<AxisValue>(),
342                        self.axis_value_offsets(),
343                        move |off| {
344                            let target = off.get().resolve::<AxisValue>(data);
345                            FieldType::offset(off.get(), target)
346                        },
347                    ),
348                )
349            }),
350            _ => None,
351        }
352    }
353}
354
355#[cfg(feature = "experimental_traverse")]
356#[allow(clippy::needless_lifetimes)]
357impl<'a> std::fmt::Debug for AxisValueArray<'a> {
358    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
359        (self as &dyn SomeTable<'a>).fmt(f)
360    }
361}
362
363/// [Axis Value Tables](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-tables)
364#[derive(Clone)]
365pub enum AxisValue<'a> {
366    Format1(AxisValueFormat1<'a>),
367    Format2(AxisValueFormat2<'a>),
368    Format3(AxisValueFormat3<'a>),
369    Format4(AxisValueFormat4<'a>),
370}
371
372impl<'a> AxisValue<'a> {
373    ///Return the `FontData` used to resolve offsets for this table.
374    pub fn offset_data(&self) -> FontData<'a> {
375        match self {
376            Self::Format1(item) => item.offset_data(),
377            Self::Format2(item) => item.offset_data(),
378            Self::Format3(item) => item.offset_data(),
379            Self::Format4(item) => item.offset_data(),
380        }
381    }
382
383    /// Format identifier — set to 1.
384    pub fn format(&self) -> u16 {
385        match self {
386            Self::Format1(item) => item.format(),
387            Self::Format2(item) => item.format(),
388            Self::Format3(item) => item.format(),
389            Self::Format4(item) => item.format(),
390        }
391    }
392
393    /// Flags — see below for details.
394    pub fn flags(&self) -> AxisValueTableFlags {
395        match self {
396            Self::Format1(item) => item.flags(),
397            Self::Format2(item) => item.flags(),
398            Self::Format3(item) => item.flags(),
399            Self::Format4(item) => item.flags(),
400        }
401    }
402
403    /// The name ID for entries in the 'name' table that provide a
404    /// display string for this attribute value.
405    pub fn value_name_id(&self) -> NameId {
406        match self {
407            Self::Format1(item) => item.value_name_id(),
408            Self::Format2(item) => item.value_name_id(),
409            Self::Format3(item) => item.value_name_id(),
410            Self::Format4(item) => item.value_name_id(),
411        }
412    }
413}
414
415impl<'a> FontRead<'a> for AxisValue<'a> {
416    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
417        let format: u16 = data.read_at(0usize)?;
418        match format {
419            AxisValueFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
420            AxisValueFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
421            AxisValueFormat3Marker::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
422            AxisValueFormat4Marker::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
423            other => Err(ReadError::InvalidFormat(other.into())),
424        }
425    }
426}
427
428impl MinByteRange for AxisValue<'_> {
429    fn min_byte_range(&self) -> Range<usize> {
430        match self {
431            Self::Format1(item) => item.min_byte_range(),
432            Self::Format2(item) => item.min_byte_range(),
433            Self::Format3(item) => item.min_byte_range(),
434            Self::Format4(item) => item.min_byte_range(),
435        }
436    }
437}
438
439#[cfg(feature = "experimental_traverse")]
440impl<'a> AxisValue<'a> {
441    fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
442        match self {
443            Self::Format1(table) => table,
444            Self::Format2(table) => table,
445            Self::Format3(table) => table,
446            Self::Format4(table) => table,
447        }
448    }
449}
450
451#[cfg(feature = "experimental_traverse")]
452impl std::fmt::Debug for AxisValue<'_> {
453    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
454        self.dyn_inner().fmt(f)
455    }
456}
457
458#[cfg(feature = "experimental_traverse")]
459impl<'a> SomeTable<'a> for AxisValue<'a> {
460    fn type_name(&self) -> &str {
461        self.dyn_inner().type_name()
462    }
463    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
464        self.dyn_inner().get_field(idx)
465    }
466}
467
468impl Format<u16> for AxisValueFormat1Marker {
469    const FORMAT: u16 = 1;
470}
471
472/// [Axis value table format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-1)
473#[derive(Debug, Clone, Copy)]
474#[doc(hidden)]
475pub struct AxisValueFormat1Marker {}
476
477impl AxisValueFormat1Marker {
478    pub fn format_byte_range(&self) -> Range<usize> {
479        let start = 0;
480        start..start + u16::RAW_BYTE_LEN
481    }
482
483    pub fn axis_index_byte_range(&self) -> Range<usize> {
484        let start = self.format_byte_range().end;
485        start..start + u16::RAW_BYTE_LEN
486    }
487
488    pub fn flags_byte_range(&self) -> Range<usize> {
489        let start = self.axis_index_byte_range().end;
490        start..start + AxisValueTableFlags::RAW_BYTE_LEN
491    }
492
493    pub fn value_name_id_byte_range(&self) -> Range<usize> {
494        let start = self.flags_byte_range().end;
495        start..start + NameId::RAW_BYTE_LEN
496    }
497
498    pub fn value_byte_range(&self) -> Range<usize> {
499        let start = self.value_name_id_byte_range().end;
500        start..start + Fixed::RAW_BYTE_LEN
501    }
502}
503
504impl MinByteRange for AxisValueFormat1Marker {
505    fn min_byte_range(&self) -> Range<usize> {
506        0..self.value_byte_range().end
507    }
508}
509
510impl<'a> FontRead<'a> for AxisValueFormat1<'a> {
511    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
512        let mut cursor = data.cursor();
513        cursor.advance::<u16>();
514        cursor.advance::<u16>();
515        cursor.advance::<AxisValueTableFlags>();
516        cursor.advance::<NameId>();
517        cursor.advance::<Fixed>();
518        cursor.finish(AxisValueFormat1Marker {})
519    }
520}
521
522/// [Axis value table format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-1)
523pub type AxisValueFormat1<'a> = TableRef<'a, AxisValueFormat1Marker>;
524
525#[allow(clippy::needless_lifetimes)]
526impl<'a> AxisValueFormat1<'a> {
527    /// Format identifier — set to 1.
528    pub fn format(&self) -> u16 {
529        let range = self.shape.format_byte_range();
530        self.data.read_at(range.start).unwrap()
531    }
532
533    /// Zero-base index into the axis record array identifying the axis
534    /// of design variation to which the axis value table applies. Must
535    /// be less than designAxisCount.
536    pub fn axis_index(&self) -> u16 {
537        let range = self.shape.axis_index_byte_range();
538        self.data.read_at(range.start).unwrap()
539    }
540
541    /// Flags — see below for details.
542    pub fn flags(&self) -> AxisValueTableFlags {
543        let range = self.shape.flags_byte_range();
544        self.data.read_at(range.start).unwrap()
545    }
546
547    /// The name ID for entries in the 'name' table that provide a
548    /// display string for this attribute value.
549    pub fn value_name_id(&self) -> NameId {
550        let range = self.shape.value_name_id_byte_range();
551        self.data.read_at(range.start).unwrap()
552    }
553
554    /// A numeric value for this attribute value.
555    pub fn value(&self) -> Fixed {
556        let range = self.shape.value_byte_range();
557        self.data.read_at(range.start).unwrap()
558    }
559}
560
561#[cfg(feature = "experimental_traverse")]
562impl<'a> SomeTable<'a> for AxisValueFormat1<'a> {
563    fn type_name(&self) -> &str {
564        "AxisValueFormat1"
565    }
566    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
567        match idx {
568            0usize => Some(Field::new("format", self.format())),
569            1usize => Some(Field::new("axis_index", self.axis_index())),
570            2usize => Some(Field::new("flags", self.flags())),
571            3usize => Some(Field::new("value_name_id", self.value_name_id())),
572            4usize => Some(Field::new("value", self.value())),
573            _ => None,
574        }
575    }
576}
577
578#[cfg(feature = "experimental_traverse")]
579#[allow(clippy::needless_lifetimes)]
580impl<'a> std::fmt::Debug for AxisValueFormat1<'a> {
581    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
582        (self as &dyn SomeTable<'a>).fmt(f)
583    }
584}
585
586impl Format<u16> for AxisValueFormat2Marker {
587    const FORMAT: u16 = 2;
588}
589
590/// [Axis value table format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-2)
591#[derive(Debug, Clone, Copy)]
592#[doc(hidden)]
593pub struct AxisValueFormat2Marker {}
594
595impl AxisValueFormat2Marker {
596    pub fn format_byte_range(&self) -> Range<usize> {
597        let start = 0;
598        start..start + u16::RAW_BYTE_LEN
599    }
600
601    pub fn axis_index_byte_range(&self) -> Range<usize> {
602        let start = self.format_byte_range().end;
603        start..start + u16::RAW_BYTE_LEN
604    }
605
606    pub fn flags_byte_range(&self) -> Range<usize> {
607        let start = self.axis_index_byte_range().end;
608        start..start + AxisValueTableFlags::RAW_BYTE_LEN
609    }
610
611    pub fn value_name_id_byte_range(&self) -> Range<usize> {
612        let start = self.flags_byte_range().end;
613        start..start + NameId::RAW_BYTE_LEN
614    }
615
616    pub fn nominal_value_byte_range(&self) -> Range<usize> {
617        let start = self.value_name_id_byte_range().end;
618        start..start + Fixed::RAW_BYTE_LEN
619    }
620
621    pub fn range_min_value_byte_range(&self) -> Range<usize> {
622        let start = self.nominal_value_byte_range().end;
623        start..start + Fixed::RAW_BYTE_LEN
624    }
625
626    pub fn range_max_value_byte_range(&self) -> Range<usize> {
627        let start = self.range_min_value_byte_range().end;
628        start..start + Fixed::RAW_BYTE_LEN
629    }
630}
631
632impl MinByteRange for AxisValueFormat2Marker {
633    fn min_byte_range(&self) -> Range<usize> {
634        0..self.range_max_value_byte_range().end
635    }
636}
637
638impl<'a> FontRead<'a> for AxisValueFormat2<'a> {
639    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
640        let mut cursor = data.cursor();
641        cursor.advance::<u16>();
642        cursor.advance::<u16>();
643        cursor.advance::<AxisValueTableFlags>();
644        cursor.advance::<NameId>();
645        cursor.advance::<Fixed>();
646        cursor.advance::<Fixed>();
647        cursor.advance::<Fixed>();
648        cursor.finish(AxisValueFormat2Marker {})
649    }
650}
651
652/// [Axis value table format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-2)
653pub type AxisValueFormat2<'a> = TableRef<'a, AxisValueFormat2Marker>;
654
655#[allow(clippy::needless_lifetimes)]
656impl<'a> AxisValueFormat2<'a> {
657    /// Format identifier — set to 2.
658    pub fn format(&self) -> u16 {
659        let range = self.shape.format_byte_range();
660        self.data.read_at(range.start).unwrap()
661    }
662
663    /// Zero-base index into the axis record array identifying the axis
664    /// of design variation to which the axis value table applies. Must
665    /// be less than designAxisCount.
666    pub fn axis_index(&self) -> u16 {
667        let range = self.shape.axis_index_byte_range();
668        self.data.read_at(range.start).unwrap()
669    }
670
671    /// Flags — see below for details.
672    pub fn flags(&self) -> AxisValueTableFlags {
673        let range = self.shape.flags_byte_range();
674        self.data.read_at(range.start).unwrap()
675    }
676
677    /// The name ID for entries in the 'name' table that provide a
678    /// display string for this attribute value.
679    pub fn value_name_id(&self) -> NameId {
680        let range = self.shape.value_name_id_byte_range();
681        self.data.read_at(range.start).unwrap()
682    }
683
684    /// A nominal numeric value for this attribute value.
685    pub fn nominal_value(&self) -> Fixed {
686        let range = self.shape.nominal_value_byte_range();
687        self.data.read_at(range.start).unwrap()
688    }
689
690    /// The minimum value for a range associated with the specified
691    /// name ID.
692    pub fn range_min_value(&self) -> Fixed {
693        let range = self.shape.range_min_value_byte_range();
694        self.data.read_at(range.start).unwrap()
695    }
696
697    /// The maximum value for a range associated with the specified
698    /// name ID.
699    pub fn range_max_value(&self) -> Fixed {
700        let range = self.shape.range_max_value_byte_range();
701        self.data.read_at(range.start).unwrap()
702    }
703}
704
705#[cfg(feature = "experimental_traverse")]
706impl<'a> SomeTable<'a> for AxisValueFormat2<'a> {
707    fn type_name(&self) -> &str {
708        "AxisValueFormat2"
709    }
710    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
711        match idx {
712            0usize => Some(Field::new("format", self.format())),
713            1usize => Some(Field::new("axis_index", self.axis_index())),
714            2usize => Some(Field::new("flags", self.flags())),
715            3usize => Some(Field::new("value_name_id", self.value_name_id())),
716            4usize => Some(Field::new("nominal_value", self.nominal_value())),
717            5usize => Some(Field::new("range_min_value", self.range_min_value())),
718            6usize => Some(Field::new("range_max_value", self.range_max_value())),
719            _ => None,
720        }
721    }
722}
723
724#[cfg(feature = "experimental_traverse")]
725#[allow(clippy::needless_lifetimes)]
726impl<'a> std::fmt::Debug for AxisValueFormat2<'a> {
727    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
728        (self as &dyn SomeTable<'a>).fmt(f)
729    }
730}
731
732impl Format<u16> for AxisValueFormat3Marker {
733    const FORMAT: u16 = 3;
734}
735
736/// [Axis value table format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-3)
737#[derive(Debug, Clone, Copy)]
738#[doc(hidden)]
739pub struct AxisValueFormat3Marker {}
740
741impl AxisValueFormat3Marker {
742    pub fn format_byte_range(&self) -> Range<usize> {
743        let start = 0;
744        start..start + u16::RAW_BYTE_LEN
745    }
746
747    pub fn axis_index_byte_range(&self) -> Range<usize> {
748        let start = self.format_byte_range().end;
749        start..start + u16::RAW_BYTE_LEN
750    }
751
752    pub fn flags_byte_range(&self) -> Range<usize> {
753        let start = self.axis_index_byte_range().end;
754        start..start + AxisValueTableFlags::RAW_BYTE_LEN
755    }
756
757    pub fn value_name_id_byte_range(&self) -> Range<usize> {
758        let start = self.flags_byte_range().end;
759        start..start + NameId::RAW_BYTE_LEN
760    }
761
762    pub fn value_byte_range(&self) -> Range<usize> {
763        let start = self.value_name_id_byte_range().end;
764        start..start + Fixed::RAW_BYTE_LEN
765    }
766
767    pub fn linked_value_byte_range(&self) -> Range<usize> {
768        let start = self.value_byte_range().end;
769        start..start + Fixed::RAW_BYTE_LEN
770    }
771}
772
773impl MinByteRange for AxisValueFormat3Marker {
774    fn min_byte_range(&self) -> Range<usize> {
775        0..self.linked_value_byte_range().end
776    }
777}
778
779impl<'a> FontRead<'a> for AxisValueFormat3<'a> {
780    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
781        let mut cursor = data.cursor();
782        cursor.advance::<u16>();
783        cursor.advance::<u16>();
784        cursor.advance::<AxisValueTableFlags>();
785        cursor.advance::<NameId>();
786        cursor.advance::<Fixed>();
787        cursor.advance::<Fixed>();
788        cursor.finish(AxisValueFormat3Marker {})
789    }
790}
791
792/// [Axis value table format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-3)
793pub type AxisValueFormat3<'a> = TableRef<'a, AxisValueFormat3Marker>;
794
795#[allow(clippy::needless_lifetimes)]
796impl<'a> AxisValueFormat3<'a> {
797    /// Format identifier — set to 3.
798    pub fn format(&self) -> u16 {
799        let range = self.shape.format_byte_range();
800        self.data.read_at(range.start).unwrap()
801    }
802
803    /// Zero-base index into the axis record array identifying the axis
804    /// of design variation to which the axis value table applies. Must
805    /// be less than designAxisCount.
806    pub fn axis_index(&self) -> u16 {
807        let range = self.shape.axis_index_byte_range();
808        self.data.read_at(range.start).unwrap()
809    }
810
811    /// Flags — see below for details.
812    pub fn flags(&self) -> AxisValueTableFlags {
813        let range = self.shape.flags_byte_range();
814        self.data.read_at(range.start).unwrap()
815    }
816
817    /// The name ID for entries in the 'name' table that provide a
818    /// display string for this attribute value.
819    pub fn value_name_id(&self) -> NameId {
820        let range = self.shape.value_name_id_byte_range();
821        self.data.read_at(range.start).unwrap()
822    }
823
824    /// A numeric value for this attribute value.
825    pub fn value(&self) -> Fixed {
826        let range = self.shape.value_byte_range();
827        self.data.read_at(range.start).unwrap()
828    }
829
830    /// The numeric value for a style-linked mapping from this value.
831    pub fn linked_value(&self) -> Fixed {
832        let range = self.shape.linked_value_byte_range();
833        self.data.read_at(range.start).unwrap()
834    }
835}
836
837#[cfg(feature = "experimental_traverse")]
838impl<'a> SomeTable<'a> for AxisValueFormat3<'a> {
839    fn type_name(&self) -> &str {
840        "AxisValueFormat3"
841    }
842    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
843        match idx {
844            0usize => Some(Field::new("format", self.format())),
845            1usize => Some(Field::new("axis_index", self.axis_index())),
846            2usize => Some(Field::new("flags", self.flags())),
847            3usize => Some(Field::new("value_name_id", self.value_name_id())),
848            4usize => Some(Field::new("value", self.value())),
849            5usize => Some(Field::new("linked_value", self.linked_value())),
850            _ => None,
851        }
852    }
853}
854
855#[cfg(feature = "experimental_traverse")]
856#[allow(clippy::needless_lifetimes)]
857impl<'a> std::fmt::Debug for AxisValueFormat3<'a> {
858    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
859        (self as &dyn SomeTable<'a>).fmt(f)
860    }
861}
862
863impl Format<u16> for AxisValueFormat4Marker {
864    const FORMAT: u16 = 4;
865}
866
867/// [Axis value table format 4](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-4)
868#[derive(Debug, Clone, Copy)]
869#[doc(hidden)]
870pub struct AxisValueFormat4Marker {
871    axis_values_byte_len: usize,
872}
873
874impl AxisValueFormat4Marker {
875    pub fn format_byte_range(&self) -> Range<usize> {
876        let start = 0;
877        start..start + u16::RAW_BYTE_LEN
878    }
879
880    pub fn axis_count_byte_range(&self) -> Range<usize> {
881        let start = self.format_byte_range().end;
882        start..start + u16::RAW_BYTE_LEN
883    }
884
885    pub fn flags_byte_range(&self) -> Range<usize> {
886        let start = self.axis_count_byte_range().end;
887        start..start + AxisValueTableFlags::RAW_BYTE_LEN
888    }
889
890    pub fn value_name_id_byte_range(&self) -> Range<usize> {
891        let start = self.flags_byte_range().end;
892        start..start + NameId::RAW_BYTE_LEN
893    }
894
895    pub fn axis_values_byte_range(&self) -> Range<usize> {
896        let start = self.value_name_id_byte_range().end;
897        start..start + self.axis_values_byte_len
898    }
899}
900
901impl MinByteRange for AxisValueFormat4Marker {
902    fn min_byte_range(&self) -> Range<usize> {
903        0..self.axis_values_byte_range().end
904    }
905}
906
907impl<'a> FontRead<'a> for AxisValueFormat4<'a> {
908    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
909        let mut cursor = data.cursor();
910        cursor.advance::<u16>();
911        let axis_count: u16 = cursor.read()?;
912        cursor.advance::<AxisValueTableFlags>();
913        cursor.advance::<NameId>();
914        let axis_values_byte_len = (axis_count as usize)
915            .checked_mul(AxisValueRecord::RAW_BYTE_LEN)
916            .ok_or(ReadError::OutOfBounds)?;
917        cursor.advance_by(axis_values_byte_len);
918        cursor.finish(AxisValueFormat4Marker {
919            axis_values_byte_len,
920        })
921    }
922}
923
924/// [Axis value table format 4](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-4)
925pub type AxisValueFormat4<'a> = TableRef<'a, AxisValueFormat4Marker>;
926
927#[allow(clippy::needless_lifetimes)]
928impl<'a> AxisValueFormat4<'a> {
929    /// Format identifier — set to 4.
930    pub fn format(&self) -> u16 {
931        let range = self.shape.format_byte_range();
932        self.data.read_at(range.start).unwrap()
933    }
934
935    /// The total number of axes contributing to this axis-values
936    /// combination.
937    pub fn axis_count(&self) -> u16 {
938        let range = self.shape.axis_count_byte_range();
939        self.data.read_at(range.start).unwrap()
940    }
941
942    /// Flags — see below for details.
943    pub fn flags(&self) -> AxisValueTableFlags {
944        let range = self.shape.flags_byte_range();
945        self.data.read_at(range.start).unwrap()
946    }
947
948    /// The name ID for entries in the 'name' table that provide a
949    /// display string for this combination of axis values.
950    pub fn value_name_id(&self) -> NameId {
951        let range = self.shape.value_name_id_byte_range();
952        self.data.read_at(range.start).unwrap()
953    }
954
955    /// Array of AxisValue records that provide the combination of axis
956    /// values, one for each contributing axis.
957    pub fn axis_values(&self) -> &'a [AxisValueRecord] {
958        let range = self.shape.axis_values_byte_range();
959        self.data.read_array(range).unwrap()
960    }
961}
962
963#[cfg(feature = "experimental_traverse")]
964impl<'a> SomeTable<'a> for AxisValueFormat4<'a> {
965    fn type_name(&self) -> &str {
966        "AxisValueFormat4"
967    }
968    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
969        match idx {
970            0usize => Some(Field::new("format", self.format())),
971            1usize => Some(Field::new("axis_count", self.axis_count())),
972            2usize => Some(Field::new("flags", self.flags())),
973            3usize => Some(Field::new("value_name_id", self.value_name_id())),
974            4usize => Some(Field::new(
975                "axis_values",
976                traversal::FieldType::array_of_records(
977                    stringify!(AxisValueRecord),
978                    self.axis_values(),
979                    self.offset_data(),
980                ),
981            )),
982            _ => None,
983        }
984    }
985}
986
987#[cfg(feature = "experimental_traverse")]
988#[allow(clippy::needless_lifetimes)]
989impl<'a> std::fmt::Debug for AxisValueFormat4<'a> {
990    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
991        (self as &dyn SomeTable<'a>).fmt(f)
992    }
993}
994
995/// Part of [AxisValueFormat4]
996#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
997#[repr(C)]
998#[repr(packed)]
999pub struct AxisValueRecord {
1000    /// Zero-base index into the axis record array identifying the axis
1001    /// to which this value applies. Must be less than designAxisCount.
1002    pub axis_index: BigEndian<u16>,
1003    /// A numeric value for this attribute value.
1004    pub value: BigEndian<Fixed>,
1005}
1006
1007impl AxisValueRecord {
1008    /// Zero-base index into the axis record array identifying the axis
1009    /// to which this value applies. Must be less than designAxisCount.
1010    pub fn axis_index(&self) -> u16 {
1011        self.axis_index.get()
1012    }
1013
1014    /// A numeric value for this attribute value.
1015    pub fn value(&self) -> Fixed {
1016        self.value.get()
1017    }
1018}
1019
1020impl FixedSize for AxisValueRecord {
1021    const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN;
1022}
1023
1024#[cfg(feature = "experimental_traverse")]
1025impl<'a> SomeRecord<'a> for AxisValueRecord {
1026    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1027        RecordResolver {
1028            name: "AxisValueRecord",
1029            get_field: Box::new(move |idx, _data| match idx {
1030                0usize => Some(Field::new("axis_index", self.axis_index())),
1031                1usize => Some(Field::new("value", self.value())),
1032                _ => None,
1033            }),
1034            data,
1035        }
1036    }
1037}
1038
1039/// [Axis value table flags](https://docs.microsoft.com/en-us/typography/opentype/spec/stat#flags).
1040#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
1041#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1042#[repr(transparent)]
1043pub struct AxisValueTableFlags {
1044    bits: u16,
1045}
1046
1047impl AxisValueTableFlags {
1048    /// If set, this axis value table provides axis value information
1049    /// that is applicable to other fonts within the same font family.
1050    /// This is used if the other fonts were released earlier and did
1051    /// not include information about values for some axis. If newer
1052    /// versions of the other fonts include the information themselves
1053    /// and are present, then this table is ignored.
1054    pub const OLDER_SIBLING_FONT_ATTRIBUTE: Self = Self { bits: 0x0001 };
1055
1056    /// If set, it indicates that the axis value represents the
1057    /// “normal” value for the axis and may be omitted when
1058    /// composing name strings.
1059    pub const ELIDABLE_AXIS_VALUE_NAME: Self = Self { bits: 0x0002 };
1060}
1061
1062impl AxisValueTableFlags {
1063    ///  Returns an empty set of flags.
1064    #[inline]
1065    pub const fn empty() -> Self {
1066        Self { bits: 0 }
1067    }
1068
1069    /// Returns the set containing all flags.
1070    #[inline]
1071    pub const fn all() -> Self {
1072        Self {
1073            bits: Self::OLDER_SIBLING_FONT_ATTRIBUTE.bits | Self::ELIDABLE_AXIS_VALUE_NAME.bits,
1074        }
1075    }
1076
1077    /// Returns the raw value of the flags currently stored.
1078    #[inline]
1079    pub const fn bits(&self) -> u16 {
1080        self.bits
1081    }
1082
1083    /// Convert from underlying bit representation, unless that
1084    /// representation contains bits that do not correspond to a flag.
1085    #[inline]
1086    pub const fn from_bits(bits: u16) -> Option<Self> {
1087        if (bits & !Self::all().bits()) == 0 {
1088            Some(Self { bits })
1089        } else {
1090            None
1091        }
1092    }
1093
1094    /// Convert from underlying bit representation, dropping any bits
1095    /// that do not correspond to flags.
1096    #[inline]
1097    pub const fn from_bits_truncate(bits: u16) -> Self {
1098        Self {
1099            bits: bits & Self::all().bits,
1100        }
1101    }
1102
1103    /// Returns `true` if no flags are currently stored.
1104    #[inline]
1105    pub const fn is_empty(&self) -> bool {
1106        self.bits() == Self::empty().bits()
1107    }
1108
1109    /// Returns `true` if there are flags common to both `self` and `other`.
1110    #[inline]
1111    pub const fn intersects(&self, other: Self) -> bool {
1112        !(Self {
1113            bits: self.bits & other.bits,
1114        })
1115        .is_empty()
1116    }
1117
1118    /// Returns `true` if all of the flags in `other` are contained within `self`.
1119    #[inline]
1120    pub const fn contains(&self, other: Self) -> bool {
1121        (self.bits & other.bits) == other.bits
1122    }
1123
1124    /// Inserts the specified flags in-place.
1125    #[inline]
1126    pub fn insert(&mut self, other: Self) {
1127        self.bits |= other.bits;
1128    }
1129
1130    /// Removes the specified flags in-place.
1131    #[inline]
1132    pub fn remove(&mut self, other: Self) {
1133        self.bits &= !other.bits;
1134    }
1135
1136    /// Toggles the specified flags in-place.
1137    #[inline]
1138    pub fn toggle(&mut self, other: Self) {
1139        self.bits ^= other.bits;
1140    }
1141
1142    /// Returns the intersection between the flags in `self` and
1143    /// `other`.
1144    ///
1145    /// Specifically, the returned set contains only the flags which are
1146    /// present in *both* `self` *and* `other`.
1147    ///
1148    /// This is equivalent to using the `&` operator (e.g.
1149    /// [`ops::BitAnd`]), as in `flags & other`.
1150    ///
1151    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
1152    #[inline]
1153    #[must_use]
1154    pub const fn intersection(self, other: Self) -> Self {
1155        Self {
1156            bits: self.bits & other.bits,
1157        }
1158    }
1159
1160    /// Returns the union of between the flags in `self` and `other`.
1161    ///
1162    /// Specifically, the returned set contains all flags which are
1163    /// present in *either* `self` *or* `other`, including any which are
1164    /// present in both.
1165    ///
1166    /// This is equivalent to using the `|` operator (e.g.
1167    /// [`ops::BitOr`]), as in `flags | other`.
1168    ///
1169    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
1170    #[inline]
1171    #[must_use]
1172    pub const fn union(self, other: Self) -> Self {
1173        Self {
1174            bits: self.bits | other.bits,
1175        }
1176    }
1177
1178    /// Returns the difference between the flags in `self` and `other`.
1179    ///
1180    /// Specifically, the returned set contains all flags present in
1181    /// `self`, except for the ones present in `other`.
1182    ///
1183    /// It is also conceptually equivalent to the "bit-clear" operation:
1184    /// `flags & !other` (and this syntax is also supported).
1185    ///
1186    /// This is equivalent to using the `-` operator (e.g.
1187    /// [`ops::Sub`]), as in `flags - other`.
1188    ///
1189    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
1190    #[inline]
1191    #[must_use]
1192    pub const fn difference(self, other: Self) -> Self {
1193        Self {
1194            bits: self.bits & !other.bits,
1195        }
1196    }
1197}
1198
1199impl std::ops::BitOr for AxisValueTableFlags {
1200    type Output = Self;
1201
1202    /// Returns the union of the two sets of flags.
1203    #[inline]
1204    fn bitor(self, other: AxisValueTableFlags) -> Self {
1205        Self {
1206            bits: self.bits | other.bits,
1207        }
1208    }
1209}
1210
1211impl std::ops::BitOrAssign for AxisValueTableFlags {
1212    /// Adds the set of flags.
1213    #[inline]
1214    fn bitor_assign(&mut self, other: Self) {
1215        self.bits |= other.bits;
1216    }
1217}
1218
1219impl std::ops::BitXor for AxisValueTableFlags {
1220    type Output = Self;
1221
1222    /// Returns the left flags, but with all the right flags toggled.
1223    #[inline]
1224    fn bitxor(self, other: Self) -> Self {
1225        Self {
1226            bits: self.bits ^ other.bits,
1227        }
1228    }
1229}
1230
1231impl std::ops::BitXorAssign for AxisValueTableFlags {
1232    /// Toggles the set of flags.
1233    #[inline]
1234    fn bitxor_assign(&mut self, other: Self) {
1235        self.bits ^= other.bits;
1236    }
1237}
1238
1239impl std::ops::BitAnd for AxisValueTableFlags {
1240    type Output = Self;
1241
1242    /// Returns the intersection between the two sets of flags.
1243    #[inline]
1244    fn bitand(self, other: Self) -> Self {
1245        Self {
1246            bits: self.bits & other.bits,
1247        }
1248    }
1249}
1250
1251impl std::ops::BitAndAssign for AxisValueTableFlags {
1252    /// Disables all flags disabled in the set.
1253    #[inline]
1254    fn bitand_assign(&mut self, other: Self) {
1255        self.bits &= other.bits;
1256    }
1257}
1258
1259impl std::ops::Sub for AxisValueTableFlags {
1260    type Output = Self;
1261
1262    /// Returns the set difference of the two sets of flags.
1263    #[inline]
1264    fn sub(self, other: Self) -> Self {
1265        Self {
1266            bits: self.bits & !other.bits,
1267        }
1268    }
1269}
1270
1271impl std::ops::SubAssign for AxisValueTableFlags {
1272    /// Disables all flags enabled in the set.
1273    #[inline]
1274    fn sub_assign(&mut self, other: Self) {
1275        self.bits &= !other.bits;
1276    }
1277}
1278
1279impl std::ops::Not for AxisValueTableFlags {
1280    type Output = Self;
1281
1282    /// Returns the complement of this set of flags.
1283    #[inline]
1284    fn not(self) -> Self {
1285        Self { bits: !self.bits } & Self::all()
1286    }
1287}
1288
1289impl std::fmt::Debug for AxisValueTableFlags {
1290    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1291        let members: &[(&str, Self)] = &[
1292            (
1293                "OLDER_SIBLING_FONT_ATTRIBUTE",
1294                Self::OLDER_SIBLING_FONT_ATTRIBUTE,
1295            ),
1296            ("ELIDABLE_AXIS_VALUE_NAME", Self::ELIDABLE_AXIS_VALUE_NAME),
1297        ];
1298        let mut first = true;
1299        for (name, value) in members {
1300            if self.contains(*value) {
1301                if !first {
1302                    f.write_str(" | ")?;
1303                }
1304                first = false;
1305                f.write_str(name)?;
1306            }
1307        }
1308        if first {
1309            f.write_str("(empty)")?;
1310        }
1311        Ok(())
1312    }
1313}
1314
1315impl std::fmt::Binary for AxisValueTableFlags {
1316    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1317        std::fmt::Binary::fmt(&self.bits, f)
1318    }
1319}
1320
1321impl std::fmt::Octal for AxisValueTableFlags {
1322    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1323        std::fmt::Octal::fmt(&self.bits, f)
1324    }
1325}
1326
1327impl std::fmt::LowerHex for AxisValueTableFlags {
1328    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1329        std::fmt::LowerHex::fmt(&self.bits, f)
1330    }
1331}
1332
1333impl std::fmt::UpperHex for AxisValueTableFlags {
1334    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1335        std::fmt::UpperHex::fmt(&self.bits, f)
1336    }
1337}
1338
1339impl font_types::Scalar for AxisValueTableFlags {
1340    type Raw = <u16 as font_types::Scalar>::Raw;
1341    fn to_raw(self) -> Self::Raw {
1342        self.bits().to_raw()
1343    }
1344    fn from_raw(raw: Self::Raw) -> Self {
1345        let t = <u16>::from_raw(raw);
1346        Self::from_bits_truncate(t)
1347    }
1348}
1349
1350#[cfg(feature = "experimental_traverse")]
1351impl<'a> From<AxisValueTableFlags> for FieldType<'a> {
1352    fn from(src: AxisValueTableFlags) -> FieldType<'a> {
1353        src.bits().into()
1354    }
1355}