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