Skip to main content

read_fonts/generated/
generated_varc.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 Varc<'a> {
9    fn min_byte_range(&self) -> Range<usize> {
10        0..self.var_composite_glyphs_offset_byte_range().end
11    }
12    fn min_table_bytes(&self) -> &'a [u8] {
13        let range = self.min_byte_range();
14        self.data.as_bytes().get(range).unwrap_or_default()
15    }
16}
17
18impl TopLevelTable for Varc<'_> {
19    /// `VARC`
20    const TAG: Tag = Tag::new(b"VARC");
21}
22
23impl<'a> FontRead<'a> for Varc<'a> {
24    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
25        #[allow(clippy::absurd_extreme_comparisons)]
26        if data.len() < Self::MIN_SIZE {
27            return Err(ReadError::OutOfBounds);
28        }
29        Ok(Self { data })
30    }
31}
32
33/// [VARC](https://github.com/harfbuzz/boring-expansion-spec/blob/main/VARC.md) (Variable Composites / Components Table)
34///
35/// [FontTools VARC](https://github.com/fonttools/fonttools/blob/5e6b12d12fa08abafbeb7570f47707fbedf69a45/Lib/fontTools/ttLib/tables/otData.py#L3459-L3476)
36#[derive(Clone)]
37pub struct Varc<'a> {
38    data: FontData<'a>,
39}
40
41#[allow(clippy::needless_lifetimes)]
42impl<'a> Varc<'a> {
43    pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
44        + Offset32::RAW_BYTE_LEN
45        + Offset32::RAW_BYTE_LEN
46        + Offset32::RAW_BYTE_LEN
47        + Offset32::RAW_BYTE_LEN
48        + Offset32::RAW_BYTE_LEN);
49    basic_table_impls!(impl_the_methods);
50
51    /// Major/minor version number. Set to 1.0.
52    pub fn version(&self) -> MajorMinor {
53        let range = self.version_byte_range();
54        self.data.read_at(range.start).ok().unwrap()
55    }
56
57    pub fn coverage_offset(&self) -> Offset32 {
58        let range = self.coverage_offset_byte_range();
59        self.data.read_at(range.start).ok().unwrap()
60    }
61
62    /// Attempt to resolve [`coverage_offset`][Self::coverage_offset].
63    pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
64        let data = self.data;
65        self.coverage_offset().resolve(data)
66    }
67
68    pub fn multi_var_store_offset(&self) -> Nullable<Offset32> {
69        let range = self.multi_var_store_offset_byte_range();
70        self.data.read_at(range.start).ok().unwrap()
71    }
72
73    /// Attempt to resolve [`multi_var_store_offset`][Self::multi_var_store_offset].
74    pub fn multi_var_store(&self) -> Option<Result<MultiItemVariationStore<'a>, ReadError>> {
75        let data = self.data;
76        self.multi_var_store_offset().resolve(data)
77    }
78
79    pub fn condition_list_offset(&self) -> Nullable<Offset32> {
80        let range = self.condition_list_offset_byte_range();
81        self.data.read_at(range.start).ok().unwrap()
82    }
83
84    /// Attempt to resolve [`condition_list_offset`][Self::condition_list_offset].
85    pub fn condition_list(&self) -> Option<Result<ConditionList<'a>, ReadError>> {
86        let data = self.data;
87        self.condition_list_offset().resolve(data)
88    }
89
90    pub fn axis_indices_list_offset(&self) -> Nullable<Offset32> {
91        let range = self.axis_indices_list_offset_byte_range();
92        self.data.read_at(range.start).ok().unwrap()
93    }
94
95    /// Attempt to resolve [`axis_indices_list_offset`][Self::axis_indices_list_offset].
96    pub fn axis_indices_list(&self) -> Option<Result<Index2<'a>, ReadError>> {
97        let data = self.data;
98        self.axis_indices_list_offset().resolve(data)
99    }
100
101    pub fn var_composite_glyphs_offset(&self) -> Offset32 {
102        let range = self.var_composite_glyphs_offset_byte_range();
103        self.data.read_at(range.start).ok().unwrap()
104    }
105
106    /// Attempt to resolve [`var_composite_glyphs_offset`][Self::var_composite_glyphs_offset].
107    pub fn var_composite_glyphs(&self) -> Result<Index2<'a>, ReadError> {
108        let data = self.data;
109        self.var_composite_glyphs_offset().resolve(data)
110    }
111
112    pub fn version_byte_range(&self) -> Range<usize> {
113        let start = 0;
114        start..start + MajorMinor::RAW_BYTE_LEN
115    }
116
117    pub fn coverage_offset_byte_range(&self) -> Range<usize> {
118        let start = self.version_byte_range().end;
119        start..start + Offset32::RAW_BYTE_LEN
120    }
121
122    pub fn multi_var_store_offset_byte_range(&self) -> Range<usize> {
123        let start = self.coverage_offset_byte_range().end;
124        start..start + Offset32::RAW_BYTE_LEN
125    }
126
127    pub fn condition_list_offset_byte_range(&self) -> Range<usize> {
128        let start = self.multi_var_store_offset_byte_range().end;
129        start..start + Offset32::RAW_BYTE_LEN
130    }
131
132    pub fn axis_indices_list_offset_byte_range(&self) -> Range<usize> {
133        let start = self.condition_list_offset_byte_range().end;
134        start..start + Offset32::RAW_BYTE_LEN
135    }
136
137    pub fn var_composite_glyphs_offset_byte_range(&self) -> Range<usize> {
138        let start = self.axis_indices_list_offset_byte_range().end;
139        start..start + Offset32::RAW_BYTE_LEN
140    }
141}
142
143const _: () = assert!(FontData::default_data_long_enough(Varc::MIN_SIZE));
144
145impl Default for Varc<'_> {
146    fn default() -> Self {
147        Self {
148            data: FontData::default_table_data(),
149        }
150    }
151}
152
153#[cfg(feature = "experimental_traverse")]
154impl<'a> SomeTable<'a> for Varc<'a> {
155    fn type_name(&self) -> &str {
156        "Varc"
157    }
158    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
159        match idx {
160            0usize => Some(Field::new("version", self.version())),
161            1usize => Some(Field::new(
162                "coverage_offset",
163                FieldType::offset(self.coverage_offset(), self.coverage()),
164            )),
165            2usize => Some(Field::new(
166                "multi_var_store_offset",
167                FieldType::offset(self.multi_var_store_offset(), self.multi_var_store()),
168            )),
169            3usize => Some(Field::new(
170                "condition_list_offset",
171                FieldType::offset(self.condition_list_offset(), self.condition_list()),
172            )),
173            4usize => Some(Field::new(
174                "axis_indices_list_offset",
175                FieldType::offset(self.axis_indices_list_offset(), self.axis_indices_list()),
176            )),
177            5usize => Some(Field::new(
178                "var_composite_glyphs_offset",
179                FieldType::offset(
180                    self.var_composite_glyphs_offset(),
181                    self.var_composite_glyphs(),
182                ),
183            )),
184            _ => None,
185        }
186    }
187}
188
189#[cfg(feature = "experimental_traverse")]
190#[allow(clippy::needless_lifetimes)]
191impl<'a> std::fmt::Debug for Varc<'a> {
192    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
193        (self as &dyn SomeTable<'a>).fmt(f)
194    }
195}
196
197impl Format<u16> for MultiItemVariationStore<'_> {
198    const FORMAT: u16 = 1;
199}
200
201impl<'a> MinByteRange<'a> for MultiItemVariationStore<'a> {
202    fn min_byte_range(&self) -> Range<usize> {
203        0..self.variation_data_offsets_byte_range().end
204    }
205    fn min_table_bytes(&self) -> &'a [u8] {
206        let range = self.min_byte_range();
207        self.data.as_bytes().get(range).unwrap_or_default()
208    }
209}
210
211impl<'a> FontRead<'a> for MultiItemVariationStore<'a> {
212    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
213        #[allow(clippy::absurd_extreme_comparisons)]
214        if data.len() < Self::MIN_SIZE {
215            return Err(ReadError::OutOfBounds);
216        }
217        Ok(Self { data })
218    }
219}
220
221/// * <https://github.com/fonttools/fonttools/blob/5e6b12d12fa08abafbeb7570f47707fbedf69a45/Lib/fontTools/ttLib/tables/otData.py#L3451-L3457>
222/// * <https://github.com/harfbuzz/harfbuzz/blob/7be12b33e3f07067c159d8f516eb31df58c75876/src/hb-ot-layout-common.hh#L3517-L3520C3>
223#[derive(Clone)]
224pub struct MultiItemVariationStore<'a> {
225    data: FontData<'a>,
226}
227
228#[allow(clippy::needless_lifetimes)]
229impl<'a> MultiItemVariationStore<'a> {
230    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
231    basic_table_impls!(impl_the_methods);
232
233    pub fn format(&self) -> u16 {
234        let range = self.format_byte_range();
235        self.data.read_at(range.start).ok().unwrap()
236    }
237
238    pub fn region_list_offset(&self) -> Offset32 {
239        let range = self.region_list_offset_byte_range();
240        self.data.read_at(range.start).ok().unwrap()
241    }
242
243    /// Attempt to resolve [`region_list_offset`][Self::region_list_offset].
244    pub fn region_list(&self) -> Result<SparseVariationRegionList<'a>, ReadError> {
245        let data = self.data;
246        self.region_list_offset().resolve(data)
247    }
248
249    pub fn variation_data_count(&self) -> u16 {
250        let range = self.variation_data_count_byte_range();
251        self.data.read_at(range.start).ok().unwrap()
252    }
253
254    pub fn variation_data_offsets(&self) -> &'a [BigEndian<Offset32>] {
255        let range = self.variation_data_offsets_byte_range();
256        self.data.read_array(range).ok().unwrap_or_default()
257    }
258
259    /// A dynamically resolving wrapper for [`variation_data_offsets`][Self::variation_data_offsets].
260    pub fn variation_data(&self) -> ArrayOfOffsets<'a, MultiItemVariationData<'a>, Offset32> {
261        let data = self.data;
262        let offsets = self.variation_data_offsets();
263        ArrayOfOffsets::new(offsets, data, ())
264    }
265
266    pub fn format_byte_range(&self) -> Range<usize> {
267        let start = 0;
268        start..start + u16::RAW_BYTE_LEN
269    }
270
271    pub fn region_list_offset_byte_range(&self) -> Range<usize> {
272        let start = self.format_byte_range().end;
273        start..start + Offset32::RAW_BYTE_LEN
274    }
275
276    pub fn variation_data_count_byte_range(&self) -> Range<usize> {
277        let start = self.region_list_offset_byte_range().end;
278        start..start + u16::RAW_BYTE_LEN
279    }
280
281    pub fn variation_data_offsets_byte_range(&self) -> Range<usize> {
282        let variation_data_count = self.variation_data_count();
283        let start = self.variation_data_count_byte_range().end;
284        start..start + (variation_data_count as usize).saturating_mul(Offset32::RAW_BYTE_LEN)
285    }
286}
287
288const _: () = assert!(FontData::default_data_long_enough(
289    MultiItemVariationStore::MIN_SIZE
290));
291
292impl Default for MultiItemVariationStore<'_> {
293    fn default() -> Self {
294        Self {
295            data: FontData::default_format_1_u16_table_data(),
296        }
297    }
298}
299
300#[cfg(feature = "experimental_traverse")]
301impl<'a> SomeTable<'a> for MultiItemVariationStore<'a> {
302    fn type_name(&self) -> &str {
303        "MultiItemVariationStore"
304    }
305    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
306        match idx {
307            0usize => Some(Field::new("format", self.format())),
308            1usize => Some(Field::new(
309                "region_list_offset",
310                FieldType::offset(self.region_list_offset(), self.region_list()),
311            )),
312            2usize => Some(Field::new(
313                "variation_data_count",
314                self.variation_data_count(),
315            )),
316            3usize => Some(Field::new(
317                "variation_data_offsets",
318                FieldType::from(self.variation_data()),
319            )),
320            _ => None,
321        }
322    }
323}
324
325#[cfg(feature = "experimental_traverse")]
326#[allow(clippy::needless_lifetimes)]
327impl<'a> std::fmt::Debug for MultiItemVariationStore<'a> {
328    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
329        (self as &dyn SomeTable<'a>).fmt(f)
330    }
331}
332
333impl<'a> MinByteRange<'a> for SparseVariationRegionList<'a> {
334    fn min_byte_range(&self) -> Range<usize> {
335        0..self.region_offsets_byte_range().end
336    }
337    fn min_table_bytes(&self) -> &'a [u8] {
338        let range = self.min_byte_range();
339        self.data.as_bytes().get(range).unwrap_or_default()
340    }
341}
342
343impl<'a> FontRead<'a> for SparseVariationRegionList<'a> {
344    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
345        #[allow(clippy::absurd_extreme_comparisons)]
346        if data.len() < Self::MIN_SIZE {
347            return Err(ReadError::OutOfBounds);
348        }
349        Ok(Self { data })
350    }
351}
352
353#[derive(Clone)]
354pub struct SparseVariationRegionList<'a> {
355    data: FontData<'a>,
356}
357
358#[allow(clippy::needless_lifetimes)]
359impl<'a> SparseVariationRegionList<'a> {
360    pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
361    basic_table_impls!(impl_the_methods);
362
363    pub fn region_count(&self) -> u16 {
364        let range = self.region_count_byte_range();
365        self.data.read_at(range.start).ok().unwrap()
366    }
367
368    pub fn region_offsets(&self) -> &'a [BigEndian<Offset32>] {
369        let range = self.region_offsets_byte_range();
370        self.data.read_array(range).ok().unwrap_or_default()
371    }
372
373    /// A dynamically resolving wrapper for [`region_offsets`][Self::region_offsets].
374    pub fn regions(&self) -> ArrayOfOffsets<'a, SparseVariationRegion<'a>, Offset32> {
375        let data = self.data;
376        let offsets = self.region_offsets();
377        ArrayOfOffsets::new(offsets, data, ())
378    }
379
380    pub fn region_count_byte_range(&self) -> Range<usize> {
381        let start = 0;
382        start..start + u16::RAW_BYTE_LEN
383    }
384
385    pub fn region_offsets_byte_range(&self) -> Range<usize> {
386        let region_count = self.region_count();
387        let start = self.region_count_byte_range().end;
388        start..start + (region_count as usize).saturating_mul(Offset32::RAW_BYTE_LEN)
389    }
390}
391
392const _: () = assert!(FontData::default_data_long_enough(
393    SparseVariationRegionList::MIN_SIZE
394));
395
396impl Default for SparseVariationRegionList<'_> {
397    fn default() -> Self {
398        Self {
399            data: FontData::default_table_data(),
400        }
401    }
402}
403
404#[cfg(feature = "experimental_traverse")]
405impl<'a> SomeTable<'a> for SparseVariationRegionList<'a> {
406    fn type_name(&self) -> &str {
407        "SparseVariationRegionList"
408    }
409    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
410        match idx {
411            0usize => Some(Field::new("region_count", self.region_count())),
412            1usize => Some(Field::new(
413                "region_offsets",
414                FieldType::from(self.regions()),
415            )),
416            _ => None,
417        }
418    }
419}
420
421#[cfg(feature = "experimental_traverse")]
422#[allow(clippy::needless_lifetimes)]
423impl<'a> std::fmt::Debug for SparseVariationRegionList<'a> {
424    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
425        (self as &dyn SomeTable<'a>).fmt(f)
426    }
427}
428
429impl<'a> MinByteRange<'a> for SparseVariationRegion<'a> {
430    fn min_byte_range(&self) -> Range<usize> {
431        0..self.region_axes_byte_range().end
432    }
433    fn min_table_bytes(&self) -> &'a [u8] {
434        let range = self.min_byte_range();
435        self.data.as_bytes().get(range).unwrap_or_default()
436    }
437}
438
439impl<'a> FontRead<'a> for SparseVariationRegion<'a> {
440    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
441        #[allow(clippy::absurd_extreme_comparisons)]
442        if data.len() < Self::MIN_SIZE {
443            return Err(ReadError::OutOfBounds);
444        }
445        Ok(Self { data })
446    }
447}
448
449#[derive(Clone)]
450pub struct SparseVariationRegion<'a> {
451    data: FontData<'a>,
452}
453
454#[allow(clippy::needless_lifetimes)]
455impl<'a> SparseVariationRegion<'a> {
456    pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
457    basic_table_impls!(impl_the_methods);
458
459    pub fn region_axis_count(&self) -> u16 {
460        let range = self.region_axis_count_byte_range();
461        self.data.read_at(range.start).ok().unwrap()
462    }
463
464    pub fn region_axes(&self) -> &'a [SparseRegionAxisCoordinates] {
465        let range = self.region_axes_byte_range();
466        self.data.read_array(range).ok().unwrap_or_default()
467    }
468
469    pub fn region_axis_count_byte_range(&self) -> Range<usize> {
470        let start = 0;
471        start..start + u16::RAW_BYTE_LEN
472    }
473
474    pub fn region_axes_byte_range(&self) -> Range<usize> {
475        let region_axis_count = self.region_axis_count();
476        let start = self.region_axis_count_byte_range().end;
477        start
478            ..start
479                + (region_axis_count as usize)
480                    .saturating_mul(SparseRegionAxisCoordinates::RAW_BYTE_LEN)
481    }
482}
483
484const _: () = assert!(FontData::default_data_long_enough(
485    SparseVariationRegion::MIN_SIZE
486));
487
488impl Default for SparseVariationRegion<'_> {
489    fn default() -> Self {
490        Self {
491            data: FontData::default_table_data(),
492        }
493    }
494}
495
496#[cfg(feature = "experimental_traverse")]
497impl<'a> SomeTable<'a> for SparseVariationRegion<'a> {
498    fn type_name(&self) -> &str {
499        "SparseVariationRegion"
500    }
501    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
502        match idx {
503            0usize => Some(Field::new("region_axis_count", self.region_axis_count())),
504            1usize => Some(Field::new(
505                "region_axes",
506                traversal::FieldType::array_of_records(
507                    stringify!(SparseRegionAxisCoordinates),
508                    self.region_axes(),
509                    self.offset_data(),
510                ),
511            )),
512            _ => None,
513        }
514    }
515}
516
517#[cfg(feature = "experimental_traverse")]
518#[allow(clippy::needless_lifetimes)]
519impl<'a> std::fmt::Debug for SparseVariationRegion<'a> {
520    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
521        (self as &dyn SomeTable<'a>).fmt(f)
522    }
523}
524
525#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
526#[repr(C)]
527#[repr(packed)]
528pub struct SparseRegionAxisCoordinates {
529    pub axis_index: BigEndian<u16>,
530    pub start: BigEndian<F2Dot14>,
531    pub peak: BigEndian<F2Dot14>,
532    pub end: BigEndian<F2Dot14>,
533}
534
535impl SparseRegionAxisCoordinates {
536    pub fn axis_index(&self) -> u16 {
537        self.axis_index.get()
538    }
539
540    pub fn start(&self) -> F2Dot14 {
541        self.start.get()
542    }
543
544    pub fn peak(&self) -> F2Dot14 {
545        self.peak.get()
546    }
547
548    pub fn end(&self) -> F2Dot14 {
549        self.end.get()
550    }
551}
552
553impl FixedSize for SparseRegionAxisCoordinates {
554    const RAW_BYTE_LEN: usize =
555        u16::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN + F2Dot14::RAW_BYTE_LEN;
556}
557
558#[cfg(feature = "experimental_traverse")]
559impl<'a> SomeRecord<'a> for SparseRegionAxisCoordinates {
560    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
561        RecordResolver {
562            name: "SparseRegionAxisCoordinates",
563            get_field: Box::new(move |idx, _data| match idx {
564                0usize => Some(Field::new("axis_index", self.axis_index())),
565                1usize => Some(Field::new("start", self.start())),
566                2usize => Some(Field::new("peak", self.peak())),
567                3usize => Some(Field::new("end", self.end())),
568                _ => None,
569            }),
570            data,
571        }
572    }
573}
574
575impl Format<u8> for MultiItemVariationData<'_> {
576    const FORMAT: u8 = 1;
577}
578
579impl<'a> MinByteRange<'a> for MultiItemVariationData<'a> {
580    fn min_byte_range(&self) -> Range<usize> {
581        0..self.raw_delta_sets_byte_range().end
582    }
583    fn min_table_bytes(&self) -> &'a [u8] {
584        let range = self.min_byte_range();
585        self.data.as_bytes().get(range).unwrap_or_default()
586    }
587}
588
589impl<'a> FontRead<'a> for MultiItemVariationData<'a> {
590    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
591        #[allow(clippy::absurd_extreme_comparisons)]
592        if data.len() < Self::MIN_SIZE {
593            return Err(ReadError::OutOfBounds);
594        }
595        Ok(Self { data })
596    }
597}
598
599#[derive(Clone)]
600pub struct MultiItemVariationData<'a> {
601    data: FontData<'a>,
602}
603
604#[allow(clippy::needless_lifetimes)]
605impl<'a> MultiItemVariationData<'a> {
606    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
607    basic_table_impls!(impl_the_methods);
608
609    pub fn format(&self) -> u8 {
610        let range = self.format_byte_range();
611        self.data.read_at(range.start).ok().unwrap()
612    }
613
614    pub fn region_index_count(&self) -> u16 {
615        let range = self.region_index_count_byte_range();
616        self.data.read_at(range.start).ok().unwrap()
617    }
618
619    pub fn region_indices(&self) -> &'a [BigEndian<u16>] {
620        let range = self.region_indices_byte_range();
621        self.data.read_array(range).ok().unwrap_or_default()
622    }
623
624    pub fn raw_delta_sets(&self) -> &'a [u8] {
625        let range = self.raw_delta_sets_byte_range();
626        self.data.read_array(range).ok().unwrap_or_default()
627    }
628
629    pub fn format_byte_range(&self) -> Range<usize> {
630        let start = 0;
631        start..start + u8::RAW_BYTE_LEN
632    }
633
634    pub fn region_index_count_byte_range(&self) -> Range<usize> {
635        let start = self.format_byte_range().end;
636        start..start + u16::RAW_BYTE_LEN
637    }
638
639    pub fn region_indices_byte_range(&self) -> Range<usize> {
640        let region_index_count = self.region_index_count();
641        let start = self.region_index_count_byte_range().end;
642        start..start + (region_index_count as usize).saturating_mul(u16::RAW_BYTE_LEN)
643    }
644
645    pub fn raw_delta_sets_byte_range(&self) -> Range<usize> {
646        let start = self.region_indices_byte_range().end;
647        start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
648    }
649}
650
651const _: () = assert!(FontData::default_data_long_enough(
652    MultiItemVariationData::MIN_SIZE
653));
654
655impl Default for MultiItemVariationData<'_> {
656    fn default() -> Self {
657        Self {
658            data: FontData::default_format_1_u8_table_data(),
659        }
660    }
661}
662
663#[cfg(feature = "experimental_traverse")]
664impl<'a> SomeTable<'a> for MultiItemVariationData<'a> {
665    fn type_name(&self) -> &str {
666        "MultiItemVariationData"
667    }
668    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
669        match idx {
670            0usize => Some(Field::new("format", self.format())),
671            1usize => Some(Field::new("region_index_count", self.region_index_count())),
672            2usize => Some(Field::new("region_indices", self.region_indices())),
673            3usize => Some(Field::new("raw_delta_sets", self.raw_delta_sets())),
674            _ => None,
675        }
676    }
677}
678
679#[cfg(feature = "experimental_traverse")]
680#[allow(clippy::needless_lifetimes)]
681impl<'a> std::fmt::Debug for MultiItemVariationData<'a> {
682    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
683        (self as &dyn SomeTable<'a>).fmt(f)
684    }
685}
686
687impl<'a> MinByteRange<'a> for ConditionList<'a> {
688    fn min_byte_range(&self) -> Range<usize> {
689        0..self.condition_offsets_byte_range().end
690    }
691    fn min_table_bytes(&self) -> &'a [u8] {
692        let range = self.min_byte_range();
693        self.data.as_bytes().get(range).unwrap_or_default()
694    }
695}
696
697impl<'a> FontRead<'a> for ConditionList<'a> {
698    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
699        #[allow(clippy::absurd_extreme_comparisons)]
700        if data.len() < Self::MIN_SIZE {
701            return Err(ReadError::OutOfBounds);
702        }
703        Ok(Self { data })
704    }
705}
706
707#[derive(Clone)]
708pub struct ConditionList<'a> {
709    data: FontData<'a>,
710}
711
712#[allow(clippy::needless_lifetimes)]
713impl<'a> ConditionList<'a> {
714    pub const MIN_SIZE: usize = u32::RAW_BYTE_LEN;
715    basic_table_impls!(impl_the_methods);
716
717    pub fn condition_count(&self) -> u32 {
718        let range = self.condition_count_byte_range();
719        self.data.read_at(range.start).ok().unwrap()
720    }
721
722    pub fn condition_offsets(&self) -> &'a [BigEndian<Offset32>] {
723        let range = self.condition_offsets_byte_range();
724        self.data.read_array(range).ok().unwrap_or_default()
725    }
726
727    /// A dynamically resolving wrapper for [`condition_offsets`][Self::condition_offsets].
728    pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset32> {
729        let data = self.data;
730        let offsets = self.condition_offsets();
731        ArrayOfOffsets::new(offsets, data, ())
732    }
733
734    pub fn condition_count_byte_range(&self) -> Range<usize> {
735        let start = 0;
736        start..start + u32::RAW_BYTE_LEN
737    }
738
739    pub fn condition_offsets_byte_range(&self) -> Range<usize> {
740        let condition_count = self.condition_count();
741        let start = self.condition_count_byte_range().end;
742        start..start + (condition_count as usize).saturating_mul(Offset32::RAW_BYTE_LEN)
743    }
744}
745
746const _: () = assert!(FontData::default_data_long_enough(ConditionList::MIN_SIZE));
747
748impl Default for ConditionList<'_> {
749    fn default() -> Self {
750        Self {
751            data: FontData::default_table_data(),
752        }
753    }
754}
755
756#[cfg(feature = "experimental_traverse")]
757impl<'a> SomeTable<'a> for ConditionList<'a> {
758    fn type_name(&self) -> &str {
759        "ConditionList"
760    }
761    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
762        match idx {
763            0usize => Some(Field::new("condition_count", self.condition_count())),
764            1usize => Some(Field::new(
765                "condition_offsets",
766                FieldType::from(self.conditions()),
767            )),
768            _ => None,
769        }
770    }
771}
772
773#[cfg(feature = "experimental_traverse")]
774#[allow(clippy::needless_lifetimes)]
775impl<'a> std::fmt::Debug for ConditionList<'a> {
776    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
777        (self as &dyn SomeTable<'a>).fmt(f)
778    }
779}
780
781/// Flags used in the [VarcComponent] byte stream
782///
783/// <https://github.com/harfbuzz/boring-expansion-spec/blob/main/VARC.md#variable-component-flags>
784#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
785#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
786#[repr(transparent)]
787pub struct VarcFlags {
788    bits: u32,
789}
790
791impl VarcFlags {
792    pub const RESET_UNSPECIFIED_AXES: Self = Self {
793        bits: 0b0000_0000_0000_0001,
794    };
795
796    pub const HAVE_AXES: Self = Self {
797        bits: 0b0000_0000_0000_0010,
798    };
799
800    pub const AXIS_VALUES_HAVE_VARIATION: Self = Self {
801        bits: 0b0000_0000_0000_0100,
802    };
803
804    pub const TRANSFORM_HAS_VARIATION: Self = Self {
805        bits: 0b0000_0000_0000_1000,
806    };
807
808    pub const HAVE_TRANSLATE_X: Self = Self {
809        bits: 0b0000_0000_0001_0000,
810    };
811
812    pub const HAVE_TRANSLATE_Y: Self = Self {
813        bits: 0b0000_0000_0010_0000,
814    };
815
816    pub const HAVE_ROTATION: Self = Self {
817        bits: 0b0000_0000_0100_0000,
818    };
819
820    pub const HAVE_CONDITION: Self = Self {
821        bits: 0b0000_0000_1000_0000,
822    };
823
824    pub const HAVE_SCALE_X: Self = Self {
825        bits: 0b0000_0001_0000_0000,
826    };
827
828    pub const HAVE_SCALE_Y: Self = Self {
829        bits: 0b0000_0010_0000_0000,
830    };
831
832    pub const HAVE_TCENTER_X: Self = Self {
833        bits: 0b0000_0100_0000_0000,
834    };
835
836    pub const HAVE_TCENTER_Y: Self = Self {
837        bits: 0b0000_1000_0000_0000,
838    };
839
840    pub const GID_IS_24BIT: Self = Self {
841        bits: 0b0001_0000_0000_0000,
842    };
843
844    pub const HAVE_SKEW_X: Self = Self {
845        bits: 0b0010_0000_0000_0000,
846    };
847
848    pub const HAVE_SKEW_Y: Self = Self {
849        bits: 0b0100_0000_0000_0000,
850    };
851
852    pub const RESERVED_MASK: Self = Self { bits: 0xFFFF8000 };
853}
854
855impl VarcFlags {
856    ///  Returns an empty set of flags.
857    #[inline]
858    pub const fn empty() -> Self {
859        Self { bits: 0 }
860    }
861
862    /// Returns the set containing all flags.
863    #[inline]
864    pub const fn all() -> Self {
865        Self {
866            bits: Self::RESET_UNSPECIFIED_AXES.bits
867                | Self::HAVE_AXES.bits
868                | Self::AXIS_VALUES_HAVE_VARIATION.bits
869                | Self::TRANSFORM_HAS_VARIATION.bits
870                | Self::HAVE_TRANSLATE_X.bits
871                | Self::HAVE_TRANSLATE_Y.bits
872                | Self::HAVE_ROTATION.bits
873                | Self::HAVE_CONDITION.bits
874                | Self::HAVE_SCALE_X.bits
875                | Self::HAVE_SCALE_Y.bits
876                | Self::HAVE_TCENTER_X.bits
877                | Self::HAVE_TCENTER_Y.bits
878                | Self::GID_IS_24BIT.bits
879                | Self::HAVE_SKEW_X.bits
880                | Self::HAVE_SKEW_Y.bits
881                | Self::RESERVED_MASK.bits,
882        }
883    }
884
885    /// Returns the raw value of the flags currently stored.
886    #[inline]
887    pub const fn bits(&self) -> u32 {
888        self.bits
889    }
890
891    /// Convert from underlying bit representation, unless that
892    /// representation contains bits that do not correspond to a flag.
893    #[inline]
894    pub const fn from_bits(bits: u32) -> Option<Self> {
895        if (bits & !Self::all().bits()) == 0 {
896            Some(Self { bits })
897        } else {
898            None
899        }
900    }
901
902    /// Convert from underlying bit representation, dropping any bits
903    /// that do not correspond to flags.
904    #[inline]
905    pub const fn from_bits_truncate(bits: u32) -> Self {
906        Self {
907            bits: bits & Self::all().bits,
908        }
909    }
910
911    /// Returns `true` if no flags are currently stored.
912    #[inline]
913    pub const fn is_empty(&self) -> bool {
914        self.bits() == Self::empty().bits()
915    }
916
917    /// Returns `true` if there are flags common to both `self` and `other`.
918    #[inline]
919    pub const fn intersects(&self, other: Self) -> bool {
920        !(Self {
921            bits: self.bits & other.bits,
922        })
923        .is_empty()
924    }
925
926    /// Returns `true` if all of the flags in `other` are contained within `self`.
927    #[inline]
928    pub const fn contains(&self, other: Self) -> bool {
929        (self.bits & other.bits) == other.bits
930    }
931
932    /// Inserts the specified flags in-place.
933    #[inline]
934    pub fn insert(&mut self, other: Self) {
935        self.bits |= other.bits;
936    }
937
938    /// Removes the specified flags in-place.
939    #[inline]
940    pub fn remove(&mut self, other: Self) {
941        self.bits &= !other.bits;
942    }
943
944    /// Toggles the specified flags in-place.
945    #[inline]
946    pub fn toggle(&mut self, other: Self) {
947        self.bits ^= other.bits;
948    }
949
950    /// Returns the intersection between the flags in `self` and
951    /// `other`.
952    ///
953    /// Specifically, the returned set contains only the flags which are
954    /// present in *both* `self` *and* `other`.
955    ///
956    /// This is equivalent to using the `&` operator (e.g.
957    /// [`ops::BitAnd`]), as in `flags & other`.
958    ///
959    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
960    #[inline]
961    #[must_use]
962    pub const fn intersection(self, other: Self) -> Self {
963        Self {
964            bits: self.bits & other.bits,
965        }
966    }
967
968    /// Returns the union of between the flags in `self` and `other`.
969    ///
970    /// Specifically, the returned set contains all flags which are
971    /// present in *either* `self` *or* `other`, including any which are
972    /// present in both.
973    ///
974    /// This is equivalent to using the `|` operator (e.g.
975    /// [`ops::BitOr`]), as in `flags | other`.
976    ///
977    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
978    #[inline]
979    #[must_use]
980    pub const fn union(self, other: Self) -> Self {
981        Self {
982            bits: self.bits | other.bits,
983        }
984    }
985
986    /// Returns the difference between the flags in `self` and `other`.
987    ///
988    /// Specifically, the returned set contains all flags present in
989    /// `self`, except for the ones present in `other`.
990    ///
991    /// It is also conceptually equivalent to the "bit-clear" operation:
992    /// `flags & !other` (and this syntax is also supported).
993    ///
994    /// This is equivalent to using the `-` operator (e.g.
995    /// [`ops::Sub`]), as in `flags - other`.
996    ///
997    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
998    #[inline]
999    #[must_use]
1000    pub const fn difference(self, other: Self) -> Self {
1001        Self {
1002            bits: self.bits & !other.bits,
1003        }
1004    }
1005}
1006
1007impl std::ops::BitOr for VarcFlags {
1008    type Output = Self;
1009
1010    /// Returns the union of the two sets of flags.
1011    #[inline]
1012    fn bitor(self, other: VarcFlags) -> Self {
1013        Self {
1014            bits: self.bits | other.bits,
1015        }
1016    }
1017}
1018
1019impl std::ops::BitOrAssign for VarcFlags {
1020    /// Adds the set of flags.
1021    #[inline]
1022    fn bitor_assign(&mut self, other: Self) {
1023        self.bits |= other.bits;
1024    }
1025}
1026
1027impl std::ops::BitXor for VarcFlags {
1028    type Output = Self;
1029
1030    /// Returns the left flags, but with all the right flags toggled.
1031    #[inline]
1032    fn bitxor(self, other: Self) -> Self {
1033        Self {
1034            bits: self.bits ^ other.bits,
1035        }
1036    }
1037}
1038
1039impl std::ops::BitXorAssign for VarcFlags {
1040    /// Toggles the set of flags.
1041    #[inline]
1042    fn bitxor_assign(&mut self, other: Self) {
1043        self.bits ^= other.bits;
1044    }
1045}
1046
1047impl std::ops::BitAnd for VarcFlags {
1048    type Output = Self;
1049
1050    /// Returns the intersection between the two sets of flags.
1051    #[inline]
1052    fn bitand(self, other: Self) -> Self {
1053        Self {
1054            bits: self.bits & other.bits,
1055        }
1056    }
1057}
1058
1059impl std::ops::BitAndAssign for VarcFlags {
1060    /// Disables all flags disabled in the set.
1061    #[inline]
1062    fn bitand_assign(&mut self, other: Self) {
1063        self.bits &= other.bits;
1064    }
1065}
1066
1067impl std::ops::Sub for VarcFlags {
1068    type Output = Self;
1069
1070    /// Returns the set difference of the two sets of flags.
1071    #[inline]
1072    fn sub(self, other: Self) -> Self {
1073        Self {
1074            bits: self.bits & !other.bits,
1075        }
1076    }
1077}
1078
1079impl std::ops::SubAssign for VarcFlags {
1080    /// Disables all flags enabled in the set.
1081    #[inline]
1082    fn sub_assign(&mut self, other: Self) {
1083        self.bits &= !other.bits;
1084    }
1085}
1086
1087impl std::ops::Not for VarcFlags {
1088    type Output = Self;
1089
1090    /// Returns the complement of this set of flags.
1091    #[inline]
1092    fn not(self) -> Self {
1093        Self { bits: !self.bits } & Self::all()
1094    }
1095}
1096
1097impl std::fmt::Debug for VarcFlags {
1098    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1099        let members: &[(&str, Self)] = &[
1100            ("RESET_UNSPECIFIED_AXES", Self::RESET_UNSPECIFIED_AXES),
1101            ("HAVE_AXES", Self::HAVE_AXES),
1102            (
1103                "AXIS_VALUES_HAVE_VARIATION",
1104                Self::AXIS_VALUES_HAVE_VARIATION,
1105            ),
1106            ("TRANSFORM_HAS_VARIATION", Self::TRANSFORM_HAS_VARIATION),
1107            ("HAVE_TRANSLATE_X", Self::HAVE_TRANSLATE_X),
1108            ("HAVE_TRANSLATE_Y", Self::HAVE_TRANSLATE_Y),
1109            ("HAVE_ROTATION", Self::HAVE_ROTATION),
1110            ("HAVE_CONDITION", Self::HAVE_CONDITION),
1111            ("HAVE_SCALE_X", Self::HAVE_SCALE_X),
1112            ("HAVE_SCALE_Y", Self::HAVE_SCALE_Y),
1113            ("HAVE_TCENTER_X", Self::HAVE_TCENTER_X),
1114            ("HAVE_TCENTER_Y", Self::HAVE_TCENTER_Y),
1115            ("GID_IS_24BIT", Self::GID_IS_24BIT),
1116            ("HAVE_SKEW_X", Self::HAVE_SKEW_X),
1117            ("HAVE_SKEW_Y", Self::HAVE_SKEW_Y),
1118            ("RESERVED_MASK", Self::RESERVED_MASK),
1119        ];
1120        let mut first = true;
1121        for (name, value) in members {
1122            if self.contains(*value) {
1123                if !first {
1124                    f.write_str(" | ")?;
1125                }
1126                first = false;
1127                f.write_str(name)?;
1128            }
1129        }
1130        if first {
1131            f.write_str("(empty)")?;
1132        }
1133        Ok(())
1134    }
1135}
1136
1137impl std::fmt::Binary for VarcFlags {
1138    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1139        std::fmt::Binary::fmt(&self.bits, f)
1140    }
1141}
1142
1143impl std::fmt::Octal for VarcFlags {
1144    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1145        std::fmt::Octal::fmt(&self.bits, f)
1146    }
1147}
1148
1149impl std::fmt::LowerHex for VarcFlags {
1150    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1151        std::fmt::LowerHex::fmt(&self.bits, f)
1152    }
1153}
1154
1155impl std::fmt::UpperHex for VarcFlags {
1156    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1157        std::fmt::UpperHex::fmt(&self.bits, f)
1158    }
1159}
1160
1161impl font_types::Scalar for VarcFlags {
1162    type Raw = <u32 as font_types::Scalar>::Raw;
1163    fn to_raw(self) -> Self::Raw {
1164        self.bits().to_raw()
1165    }
1166    fn from_raw(raw: Self::Raw) -> Self {
1167        let t = <u32>::from_raw(raw);
1168        Self::from_bits_truncate(t)
1169    }
1170}
1171
1172#[cfg(feature = "experimental_traverse")]
1173impl<'a> From<VarcFlags> for FieldType<'a> {
1174    fn from(src: VarcFlags) -> FieldType<'a> {
1175        src.bits().into()
1176    }
1177}