Coverage Report

Created: 2026-10-24 07:19

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