Skip to main content

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