Coverage Report

Created: 2026-09-14 08:06

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