Skip to main content

read_fonts/generated/
generated_variations.rs

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