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_math.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 Math<'a> {
9
0
    fn min_byte_range(&self) -> Range<usize> {
10
0
        0..self.math_variants_offset_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 Math<'_> {
19
    /// `MATH`
20
    const TAG: Tag = Tag::new(b"MATH");
21
}
22
23
impl ReadArgs for Math<'_> {
24
    type Args = ();
25
}
26
27
impl<'a> FontRead<'a> for Math<'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 MathFixedHeader {
45
    pub version: BigEndian<MajorMinor>,
46
    pub math_constants_offset: BigEndian<Offset16>,
47
    pub math_glyph_info_offset: BigEndian<Offset16>,
48
    pub math_variants_offset: BigEndian<Offset16>,
49
}
50
51
#[allow(clippy::absurd_extreme_comparisons)]
52
const _: () = assert!(std::mem::size_of::<MathFixedHeader>() <= Math::MIN_SIZE);
53
54
/// The [MATH](https://learn.microsoft.com/en-us/typography/opentype/spec/math) table
55
#[derive(Clone)]
56
pub struct Math<'a> {
57
    data: TableDataRef<'a, MathFixedHeader>,
58
}
59
60
#[allow(clippy::needless_lifetimes)]
61
impl<'a> Math<'a> {
62
    pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
63
        + Offset16::RAW_BYTE_LEN
64
        + Offset16::RAW_BYTE_LEN
65
        + Offset16::RAW_BYTE_LEN);
66
    basic_table_impls!(impl_the_methods);
67
68
    /// (major, minor) Version for the MATH table (1,0)
69
0
    pub fn version(&self) -> MajorMinor {
70
0
        self.data.header().version.get()
71
0
    }
72
73
    /// Offset to MathConstants table, from beginning of MATH table.
74
0
    pub fn math_constants_offset(&self) -> Offset16 {
75
0
        self.data.header().math_constants_offset.get()
76
0
    }
77
78
    /// Attempt to resolve [`math_constants_offset`][Self::math_constants_offset].
79
0
    pub fn math_constants(&self) -> Result<MathConstants<'a>, ReadError> {
80
0
        let data = self.offset_data();
81
0
        self.math_constants_offset().resolve(data)
82
0
    }
83
84
    /// Offset to MathGlyphInfo table, from beginning of MATH table.
85
0
    pub fn math_glyph_info_offset(&self) -> Offset16 {
86
0
        self.data.header().math_glyph_info_offset.get()
87
0
    }
88
89
    /// Attempt to resolve [`math_glyph_info_offset`][Self::math_glyph_info_offset].
90
0
    pub fn math_glyph_info(&self) -> Result<MathGlyphInfo<'a>, ReadError> {
91
0
        let data = self.offset_data();
92
0
        self.math_glyph_info_offset().resolve(data)
93
0
    }
94
95
    /// Offset to MathVariants table, from beginning of MATH table.
96
0
    pub fn math_variants_offset(&self) -> Offset16 {
97
0
        self.data.header().math_variants_offset.get()
98
0
    }
99
100
    /// Attempt to resolve [`math_variants_offset`][Self::math_variants_offset].
101
0
    pub fn math_variants(&self) -> Result<MathVariants<'a>, ReadError> {
102
0
        let data = self.offset_data();
103
0
        self.math_variants_offset().resolve(data)
104
0
    }
105
106
0
    pub fn version_byte_range(&self) -> Range<usize> {
107
0
        let start = 0;
108
0
        let end = start + MajorMinor::RAW_BYTE_LEN;
109
0
        start..end
110
0
    }
111
112
0
    pub fn math_constants_offset_byte_range(&self) -> Range<usize> {
113
0
        let start = self.version_byte_range().end;
114
0
        let end = start + Offset16::RAW_BYTE_LEN;
115
0
        start..end
116
0
    }
117
118
0
    pub fn math_glyph_info_offset_byte_range(&self) -> Range<usize> {
119
0
        let start = self.math_constants_offset_byte_range().end;
120
0
        let end = start + Offset16::RAW_BYTE_LEN;
121
0
        start..end
122
0
    }
123
124
0
    pub fn math_variants_offset_byte_range(&self) -> Range<usize> {
125
0
        let start = self.math_glyph_info_offset_byte_range().end;
126
0
        let end = start + Offset16::RAW_BYTE_LEN;
127
0
        start..end
128
0
    }
129
}
130
131
const _: () = assert!(FontData::default_data_long_enough(Math::MIN_SIZE));
132
133
impl Default for Math<'_> {
134
0
    fn default() -> Self {
135
        Self {
136
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
137
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
138
        }
139
0
    }
140
}
141
142
/// [MathValueRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathvaluerecord)
143
///
144
/// The device offset is measured from the beginning of the table that contains
145
/// the record, not from the record itself.
146
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
147
#[repr(C)]
148
#[repr(packed)]
149
pub struct MathValueRecord {
150
    /// The X or Y value in design units.
151
    pub value: BigEndian<FWord>,
152
    /// Offset to the Device table (non-variable font) / VariationIndex table
153
    /// (variable font) for this value, from the beginning of the parent table.
154
    /// May be NULL.
155
    pub device_offset: BigEndian<Nullable<Offset16>>,
156
}
157
158
impl MathValueRecord {
159
    /// The X or Y value in design units.
160
0
    pub fn value(&self) -> FWord {
161
0
        self.value.get()
162
0
    }
163
164
    /// Offset to the Device table (non-variable font) / VariationIndex table
165
    /// (variable font) for this value, from the beginning of the parent table.
166
    /// May be NULL.
167
0
    pub fn device_offset(&self) -> Nullable<Offset16> {
168
0
        self.device_offset.get()
169
0
    }
170
171
    /// Offset to the Device table (non-variable font) / VariationIndex table
172
    /// (variable font) for this value, from the beginning of the parent table.
173
    /// May be NULL.
174
    ///
175
    /// The `data` argument should be retrieved from the parent table
176
    /// By calling its `offset_data` method.
177
0
    pub fn device<'a>(
178
0
        &self,
179
0
        data: FontData<'a>,
180
0
    ) -> Option<Result<DeviceOrVariationIndex<'a>, ReadError>> {
181
0
        self.device_offset().resolve(data)
182
0
    }
183
}
184
185
impl FixedSize for MathValueRecord {
186
    const RAW_BYTE_LEN: usize = FWord::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
187
}
188
189
impl<'a> MinByteRange<'a> for MathConstants<'a> {
190
0
    fn min_byte_range(&self) -> Range<usize> {
191
0
        0..self.radical_degree_bottom_raise_percent_byte_range().end
192
0
    }
193
0
    fn min_table_bytes(&self) -> &'a [u8] {
194
0
        let range = self.min_byte_range();
195
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
196
0
    }
197
}
198
199
impl ReadArgs for MathConstants<'_> {
200
    type Args = ();
201
}
202
203
impl<'a> FontRead<'a> for MathConstants<'a> {
204
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
205
        #[allow(clippy::absurd_extreme_comparisons)]
206
0
        if data.len() < Self::MIN_SIZE {
207
0
            return Err(ReadError::OutOfBounds);
208
0
        }
209
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
210
0
            return Err(ReadError::OutOfBounds);
211
        };
212
0
        Ok(Self { data })
213
0
    }
214
}
215
216
/// The fields at the start of the table, which are read directly.
217
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
218
#[repr(C, packed)]
219
#[doc(hidden)]
220
pub struct MathConstantsFixedHeader {
221
    pub script_percent_scale_down: BigEndian<i16>,
222
    pub script_script_percent_scale_down: BigEndian<i16>,
223
    pub delimited_sub_formula_min_height: BigEndian<UfWord>,
224
    pub display_operator_min_height: BigEndian<UfWord>,
225
    pub math_leading: MathValueRecord,
226
    pub axis_height: MathValueRecord,
227
    pub accent_base_height: MathValueRecord,
228
    pub flattened_accent_base_height: MathValueRecord,
229
    pub subscript_shift_down: MathValueRecord,
230
    pub subscript_top_max: MathValueRecord,
231
    pub subscript_baseline_drop_min: MathValueRecord,
232
    pub superscript_shift_up: MathValueRecord,
233
    pub superscript_shift_up_cramped: MathValueRecord,
234
    pub superscript_bottom_min: MathValueRecord,
235
    pub superscript_baseline_drop_max: MathValueRecord,
236
    pub sub_superscript_gap_min: MathValueRecord,
237
    pub superscript_bottom_max_with_subscript: MathValueRecord,
238
    pub space_after_script: MathValueRecord,
239
    pub upper_limit_gap_min: MathValueRecord,
240
    pub upper_limit_baseline_rise_min: MathValueRecord,
241
    pub lower_limit_gap_min: MathValueRecord,
242
    pub lower_limit_baseline_drop_min: MathValueRecord,
243
    pub stack_top_shift_up: MathValueRecord,
244
    pub stack_top_display_style_shift_up: MathValueRecord,
245
    pub stack_bottom_shift_down: MathValueRecord,
246
    pub stack_bottom_display_style_shift_down: MathValueRecord,
247
    pub stack_gap_min: MathValueRecord,
248
    pub stack_display_style_gap_min: MathValueRecord,
249
    pub stretch_stack_top_shift_up: MathValueRecord,
250
    pub stretch_stack_bottom_shift_down: MathValueRecord,
251
    pub stretch_stack_gap_above_min: MathValueRecord,
252
    pub stretch_stack_gap_below_min: MathValueRecord,
253
    pub fraction_numerator_shift_up: MathValueRecord,
254
    pub fraction_numerator_display_style_shift_up: MathValueRecord,
255
    pub fraction_denominator_shift_down: MathValueRecord,
256
    pub fraction_denominator_display_style_shift_down: MathValueRecord,
257
    pub fraction_numerator_gap_min: MathValueRecord,
258
    pub fraction_num_display_style_gap_min: MathValueRecord,
259
    pub fraction_rule_thickness: MathValueRecord,
260
    pub fraction_denominator_gap_min: MathValueRecord,
261
    pub fraction_denom_display_style_gap_min: MathValueRecord,
262
    pub skewed_fraction_horizontal_gap: MathValueRecord,
263
    pub skewed_fraction_vertical_gap: MathValueRecord,
264
    pub overbar_vertical_gap: MathValueRecord,
265
    pub overbar_rule_thickness: MathValueRecord,
266
    pub overbar_extra_ascender: MathValueRecord,
267
    pub underbar_vertical_gap: MathValueRecord,
268
    pub underbar_rule_thickness: MathValueRecord,
269
    pub underbar_extra_descender: MathValueRecord,
270
    pub radical_vertical_gap: MathValueRecord,
271
    pub radical_display_style_vertical_gap: MathValueRecord,
272
    pub radical_rule_thickness: MathValueRecord,
273
    pub radical_extra_ascender: MathValueRecord,
274
    pub radical_kern_before_degree: MathValueRecord,
275
    pub radical_kern_after_degree: MathValueRecord,
276
    pub radical_degree_bottom_raise_percent: BigEndian<i16>,
277
}
278
279
#[allow(clippy::absurd_extreme_comparisons)]
280
const _: () = assert!(std::mem::size_of::<MathConstantsFixedHeader>() <= MathConstants::MIN_SIZE);
281
282
/// [MathConstants](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathconstants-table)
283
#[derive(Clone)]
284
pub struct MathConstants<'a> {
285
    data: TableDataRef<'a, MathConstantsFixedHeader>,
286
}
287
288
#[allow(clippy::needless_lifetimes)]
289
impl<'a> MathConstants<'a> {
290
    pub const MIN_SIZE: usize = (i16::RAW_BYTE_LEN
291
        + i16::RAW_BYTE_LEN
292
        + UfWord::RAW_BYTE_LEN
293
        + UfWord::RAW_BYTE_LEN
294
        + MathValueRecord::RAW_BYTE_LEN
295
        + MathValueRecord::RAW_BYTE_LEN
296
        + MathValueRecord::RAW_BYTE_LEN
297
        + MathValueRecord::RAW_BYTE_LEN
298
        + MathValueRecord::RAW_BYTE_LEN
299
        + MathValueRecord::RAW_BYTE_LEN
300
        + MathValueRecord::RAW_BYTE_LEN
301
        + MathValueRecord::RAW_BYTE_LEN
302
        + MathValueRecord::RAW_BYTE_LEN
303
        + MathValueRecord::RAW_BYTE_LEN
304
        + MathValueRecord::RAW_BYTE_LEN
305
        + MathValueRecord::RAW_BYTE_LEN
306
        + MathValueRecord::RAW_BYTE_LEN
307
        + MathValueRecord::RAW_BYTE_LEN
308
        + MathValueRecord::RAW_BYTE_LEN
309
        + MathValueRecord::RAW_BYTE_LEN
310
        + MathValueRecord::RAW_BYTE_LEN
311
        + MathValueRecord::RAW_BYTE_LEN
312
        + MathValueRecord::RAW_BYTE_LEN
313
        + MathValueRecord::RAW_BYTE_LEN
314
        + MathValueRecord::RAW_BYTE_LEN
315
        + MathValueRecord::RAW_BYTE_LEN
316
        + MathValueRecord::RAW_BYTE_LEN
317
        + MathValueRecord::RAW_BYTE_LEN
318
        + MathValueRecord::RAW_BYTE_LEN
319
        + MathValueRecord::RAW_BYTE_LEN
320
        + MathValueRecord::RAW_BYTE_LEN
321
        + MathValueRecord::RAW_BYTE_LEN
322
        + MathValueRecord::RAW_BYTE_LEN
323
        + MathValueRecord::RAW_BYTE_LEN
324
        + MathValueRecord::RAW_BYTE_LEN
325
        + MathValueRecord::RAW_BYTE_LEN
326
        + MathValueRecord::RAW_BYTE_LEN
327
        + MathValueRecord::RAW_BYTE_LEN
328
        + MathValueRecord::RAW_BYTE_LEN
329
        + MathValueRecord::RAW_BYTE_LEN
330
        + MathValueRecord::RAW_BYTE_LEN
331
        + MathValueRecord::RAW_BYTE_LEN
332
        + MathValueRecord::RAW_BYTE_LEN
333
        + MathValueRecord::RAW_BYTE_LEN
334
        + MathValueRecord::RAW_BYTE_LEN
335
        + MathValueRecord::RAW_BYTE_LEN
336
        + MathValueRecord::RAW_BYTE_LEN
337
        + MathValueRecord::RAW_BYTE_LEN
338
        + MathValueRecord::RAW_BYTE_LEN
339
        + MathValueRecord::RAW_BYTE_LEN
340
        + MathValueRecord::RAW_BYTE_LEN
341
        + MathValueRecord::RAW_BYTE_LEN
342
        + MathValueRecord::RAW_BYTE_LEN
343
        + MathValueRecord::RAW_BYTE_LEN
344
        + MathValueRecord::RAW_BYTE_LEN
345
        + i16::RAW_BYTE_LEN);
346
    basic_table_impls!(impl_the_methods);
347
348
    /// Percentage of scaling down for level 1 superscripts and subscripts.
349
0
    pub fn script_percent_scale_down(&self) -> i16 {
350
0
        self.data.header().script_percent_scale_down.get()
351
0
    }
352
353
    /// Percentage of scaling down for level 2 (scriptScript) superscripts and
354
    /// subscripts.
355
0
    pub fn script_script_percent_scale_down(&self) -> i16 {
356
0
        self.data.header().script_script_percent_scale_down.get()
357
0
    }
358
359
    /// Minimum height required for a delimited expression (contained within
360
    /// parentheses, etc.) to be treated as a sub-formula.
361
0
    pub fn delimited_sub_formula_min_height(&self) -> UfWord {
362
0
        self.data.header().delimited_sub_formula_min_height.get()
363
0
    }
364
365
    /// Minimum height of n-ary operators (such as integral and summation) for
366
    /// formulas in display mode (that is, appearing as standalone page
367
    /// elements, not embedded inline within text).
368
0
    pub fn display_operator_min_height(&self) -> UfWord {
369
0
        self.data.header().display_operator_min_height.get()
370
0
    }
371
372
    /// White space to be left between math formulas to ensure proper line
373
    /// spacing.
374
0
    pub fn math_leading(&self) -> &'a MathValueRecord {
375
0
        &self.data.header().math_leading
376
0
    }
377
378
    /// Axis height of the font.
379
0
    pub fn axis_height(&self) -> &'a MathValueRecord {
380
0
        &self.data.header().axis_height
381
0
    }
382
383
    /// Maximum (ink) height of accent base that does not require raising the
384
    /// accents.
385
0
    pub fn accent_base_height(&self) -> &'a MathValueRecord {
386
0
        &self.data.header().accent_base_height
387
0
    }
388
389
    /// Maximum (ink) height of accent base that does not require flattening the
390
    /// accents.
391
0
    pub fn flattened_accent_base_height(&self) -> &'a MathValueRecord {
392
0
        &self.data.header().flattened_accent_base_height
393
0
    }
394
395
    /// The standard shift down applied to subscript elements.
396
0
    pub fn subscript_shift_down(&self) -> &'a MathValueRecord {
397
0
        &self.data.header().subscript_shift_down
398
0
    }
399
400
    /// Maximum allowed height of the (ink) top of subscripts that does not
401
    /// require moving subscripts further down.
402
0
    pub fn subscript_top_max(&self) -> &'a MathValueRecord {
403
0
        &self.data.header().subscript_top_max
404
0
    }
405
406
    /// Minimum allowed drop of the baseline of subscripts relative to the (ink)
407
    /// bottom of the base.
408
0
    pub fn subscript_baseline_drop_min(&self) -> &'a MathValueRecord {
409
0
        &self.data.header().subscript_baseline_drop_min
410
0
    }
411
412
    /// Standard shift up applied to superscript elements.
413
0
    pub fn superscript_shift_up(&self) -> &'a MathValueRecord {
414
0
        &self.data.header().superscript_shift_up
415
0
    }
416
417
    /// Standard shift of superscripts relative to the base, in cramped style.
418
0
    pub fn superscript_shift_up_cramped(&self) -> &'a MathValueRecord {
419
0
        &self.data.header().superscript_shift_up_cramped
420
0
    }
421
422
    /// Minimum allowed height of the (ink) bottom of superscripts that does not
423
    /// require moving subscripts further up.
424
0
    pub fn superscript_bottom_min(&self) -> &'a MathValueRecord {
425
0
        &self.data.header().superscript_bottom_min
426
0
    }
427
428
    /// Maximum allowed drop of the baseline of superscripts relative to the
429
    /// (ink) top of the base.
430
0
    pub fn superscript_baseline_drop_max(&self) -> &'a MathValueRecord {
431
0
        &self.data.header().superscript_baseline_drop_max
432
0
    }
433
434
    /// Minimum gap between the superscript and subscript ink.
435
0
    pub fn sub_superscript_gap_min(&self) -> &'a MathValueRecord {
436
0
        &self.data.header().sub_superscript_gap_min
437
0
    }
438
439
    /// The maximum level to which the (ink) bottom of superscript can be
440
    /// pushed to increase the gap between superscript and subscript, before
441
    /// subscript starts being moved down.
442
0
    pub fn superscript_bottom_max_with_subscript(&self) -> &'a MathValueRecord {
443
0
        &self.data.header().superscript_bottom_max_with_subscript
444
0
    }
445
446
    /// Extra white space to be added after each subscript and superscript.
447
0
    pub fn space_after_script(&self) -> &'a MathValueRecord {
448
0
        &self.data.header().space_after_script
449
0
    }
450
451
    /// Minimum gap between the (ink) bottom of the upper limit, and the (ink)
452
    /// top of the base operator.
453
0
    pub fn upper_limit_gap_min(&self) -> &'a MathValueRecord {
454
0
        &self.data.header().upper_limit_gap_min
455
0
    }
456
457
    /// Minimum distance between baseline of upper limit and (ink) top of the
458
    /// base operator.
459
0
    pub fn upper_limit_baseline_rise_min(&self) -> &'a MathValueRecord {
460
0
        &self.data.header().upper_limit_baseline_rise_min
461
0
    }
462
463
    /// Minimum gap between (ink) top of the lower limit, and (ink) bottom of
464
    /// the base operator.
465
0
    pub fn lower_limit_gap_min(&self) -> &'a MathValueRecord {
466
0
        &self.data.header().lower_limit_gap_min
467
0
    }
468
469
    /// Minimum distance between baseline of the lower limit and (ink) bottom of
470
    /// the base operator.
471
0
    pub fn lower_limit_baseline_drop_min(&self) -> &'a MathValueRecord {
472
0
        &self.data.header().lower_limit_baseline_drop_min
473
0
    }
474
475
    /// Standard shift up applied to the top element of a stack.
476
0
    pub fn stack_top_shift_up(&self) -> &'a MathValueRecord {
477
0
        &self.data.header().stack_top_shift_up
478
0
    }
479
480
    /// Standard shift up applied to the top element of a stack in display
481
    /// style.
482
0
    pub fn stack_top_display_style_shift_up(&self) -> &'a MathValueRecord {
483
0
        &self.data.header().stack_top_display_style_shift_up
484
0
    }
485
486
    /// Standard shift down applied to the bottom element of a stack.
487
0
    pub fn stack_bottom_shift_down(&self) -> &'a MathValueRecord {
488
0
        &self.data.header().stack_bottom_shift_down
489
0
    }
490
491
    /// Standard shift down applied to the bottom element of a stack in display
492
    /// style.
493
0
    pub fn stack_bottom_display_style_shift_down(&self) -> &'a MathValueRecord {
494
0
        &self.data.header().stack_bottom_display_style_shift_down
495
0
    }
496
497
    /// Minimum gap between (ink) bottom of the top element of a stack, and the
498
    /// (ink) top of the bottom element.
499
0
    pub fn stack_gap_min(&self) -> &'a MathValueRecord {
500
0
        &self.data.header().stack_gap_min
501
0
    }
502
503
    /// Minimum gap between (ink) bottom of the top element of a stack, and the
504
    /// (ink) top of the bottom element in display style.
505
0
    pub fn stack_display_style_gap_min(&self) -> &'a MathValueRecord {
506
0
        &self.data.header().stack_display_style_gap_min
507
0
    }
508
509
    /// Standard shift up applied to the top element of the stretch stack.
510
0
    pub fn stretch_stack_top_shift_up(&self) -> &'a MathValueRecord {
511
0
        &self.data.header().stretch_stack_top_shift_up
512
0
    }
513
514
    /// Standard shift down applied to the bottom element of the stretch stack.
515
0
    pub fn stretch_stack_bottom_shift_down(&self) -> &'a MathValueRecord {
516
0
        &self.data.header().stretch_stack_bottom_shift_down
517
0
    }
518
519
    /// Minimum gap between the ink of the stretched element, and the (ink)
520
    /// bottom of the element above.
521
0
    pub fn stretch_stack_gap_above_min(&self) -> &'a MathValueRecord {
522
0
        &self.data.header().stretch_stack_gap_above_min
523
0
    }
524
525
    /// Minimum gap between the ink of the stretched element, and the (ink) top
526
    /// of the element below.
527
0
    pub fn stretch_stack_gap_below_min(&self) -> &'a MathValueRecord {
528
0
        &self.data.header().stretch_stack_gap_below_min
529
0
    }
530
531
    /// Standard shift up applied to the numerator.
532
0
    pub fn fraction_numerator_shift_up(&self) -> &'a MathValueRecord {
533
0
        &self.data.header().fraction_numerator_shift_up
534
0
    }
535
536
    /// Standard shift up applied to the numerator in display style.
537
0
    pub fn fraction_numerator_display_style_shift_up(&self) -> &'a MathValueRecord {
538
0
        &self.data.header().fraction_numerator_display_style_shift_up
539
0
    }
540
541
    /// Standard shift down applied to the denominator.
542
0
    pub fn fraction_denominator_shift_down(&self) -> &'a MathValueRecord {
543
0
        &self.data.header().fraction_denominator_shift_down
544
0
    }
545
546
    /// Standard shift down applied to the denominator in display style.
547
0
    pub fn fraction_denominator_display_style_shift_down(&self) -> &'a MathValueRecord {
548
0
        &self
549
0
            .data
550
0
            .header()
551
0
            .fraction_denominator_display_style_shift_down
552
0
    }
553
554
    /// Minimum tolerated gap between the (ink) bottom of the numerator and the
555
    /// ink of the fraction bar.
556
0
    pub fn fraction_numerator_gap_min(&self) -> &'a MathValueRecord {
557
0
        &self.data.header().fraction_numerator_gap_min
558
0
    }
559
560
    /// Minimum tolerated gap between the (ink) bottom of the numerator and the
561
    /// ink of the fraction bar in display style.
562
0
    pub fn fraction_num_display_style_gap_min(&self) -> &'a MathValueRecord {
563
0
        &self.data.header().fraction_num_display_style_gap_min
564
0
    }
565
566
    /// Thickness of the fraction bar.
567
0
    pub fn fraction_rule_thickness(&self) -> &'a MathValueRecord {
568
0
        &self.data.header().fraction_rule_thickness
569
0
    }
570
571
    /// Minimum tolerated gap between the ink of the fraction bar and the (ink)
572
    /// top of the denominator.
573
0
    pub fn fraction_denominator_gap_min(&self) -> &'a MathValueRecord {
574
0
        &self.data.header().fraction_denominator_gap_min
575
0
    }
576
577
    /// Minimum tolerated gap between the ink of the fraction bar and the (ink)
578
    /// top of the denominator in display style.
579
0
    pub fn fraction_denom_display_style_gap_min(&self) -> &'a MathValueRecord {
580
0
        &self.data.header().fraction_denom_display_style_gap_min
581
0
    }
582
583
    /// Horizontal distance between the top and bottom elements of a skewed
584
    /// fraction.
585
0
    pub fn skewed_fraction_horizontal_gap(&self) -> &'a MathValueRecord {
586
0
        &self.data.header().skewed_fraction_horizontal_gap
587
0
    }
588
589
    /// Vertical distance between the ink of the top and bottom elements of a
590
    /// skewed fraction.
591
0
    pub fn skewed_fraction_vertical_gap(&self) -> &'a MathValueRecord {
592
0
        &self.data.header().skewed_fraction_vertical_gap
593
0
    }
594
595
    /// Distance between the overbar and the (ink) top of he base.
596
0
    pub fn overbar_vertical_gap(&self) -> &'a MathValueRecord {
597
0
        &self.data.header().overbar_vertical_gap
598
0
    }
599
600
    /// Thickness of overbar.
601
0
    pub fn overbar_rule_thickness(&self) -> &'a MathValueRecord {
602
0
        &self.data.header().overbar_rule_thickness
603
0
    }
604
605
    /// Extra white space reserved above the overbar.
606
0
    pub fn overbar_extra_ascender(&self) -> &'a MathValueRecord {
607
0
        &self.data.header().overbar_extra_ascender
608
0
    }
609
610
    /// Distance between underbar and (ink) bottom of the base.
611
0
    pub fn underbar_vertical_gap(&self) -> &'a MathValueRecord {
612
0
        &self.data.header().underbar_vertical_gap
613
0
    }
614
615
    /// Thickness of underbar.
616
0
    pub fn underbar_rule_thickness(&self) -> &'a MathValueRecord {
617
0
        &self.data.header().underbar_rule_thickness
618
0
    }
619
620
    /// Extra white space reserved below the underbar.
621
0
    pub fn underbar_extra_descender(&self) -> &'a MathValueRecord {
622
0
        &self.data.header().underbar_extra_descender
623
0
    }
624
625
    /// Space between the (ink) top of the expression and the bar over it.
626
0
    pub fn radical_vertical_gap(&self) -> &'a MathValueRecord {
627
0
        &self.data.header().radical_vertical_gap
628
0
    }
629
630
    /// Space between the (ink) top of the expression and the bar over it in
631
    /// display style.
632
0
    pub fn radical_display_style_vertical_gap(&self) -> &'a MathValueRecord {
633
0
        &self.data.header().radical_display_style_vertical_gap
634
0
    }
635
636
    /// Thickness of the radical rule.
637
0
    pub fn radical_rule_thickness(&self) -> &'a MathValueRecord {
638
0
        &self.data.header().radical_rule_thickness
639
0
    }
640
641
    /// Extra white space reserved above the radical.
642
0
    pub fn radical_extra_ascender(&self) -> &'a MathValueRecord {
643
0
        &self.data.header().radical_extra_ascender
644
0
    }
645
646
    /// Extra horizontal kern before the degree of a radical, if such is
647
    /// present.
648
0
    pub fn radical_kern_before_degree(&self) -> &'a MathValueRecord {
649
0
        &self.data.header().radical_kern_before_degree
650
0
    }
651
652
    /// Negative kern after the degree of a radical, if such is present.
653
0
    pub fn radical_kern_after_degree(&self) -> &'a MathValueRecord {
654
0
        &self.data.header().radical_kern_after_degree
655
0
    }
656
657
    /// Height of the bottom of the radical degree, if such is present, in
658
    /// proportion to the ascender of the radical sign.
659
0
    pub fn radical_degree_bottom_raise_percent(&self) -> i16 {
660
0
        self.data.header().radical_degree_bottom_raise_percent.get()
661
0
    }
662
663
0
    pub fn script_percent_scale_down_byte_range(&self) -> Range<usize> {
664
0
        let start = 0;
665
0
        let end = start + i16::RAW_BYTE_LEN;
666
0
        start..end
667
0
    }
668
669
0
    pub fn script_script_percent_scale_down_byte_range(&self) -> Range<usize> {
670
0
        let start = self.script_percent_scale_down_byte_range().end;
671
0
        let end = start + i16::RAW_BYTE_LEN;
672
0
        start..end
673
0
    }
674
675
0
    pub fn delimited_sub_formula_min_height_byte_range(&self) -> Range<usize> {
676
0
        let start = self.script_script_percent_scale_down_byte_range().end;
677
0
        let end = start + UfWord::RAW_BYTE_LEN;
678
0
        start..end
679
0
    }
680
681
0
    pub fn display_operator_min_height_byte_range(&self) -> Range<usize> {
682
0
        let start = self.delimited_sub_formula_min_height_byte_range().end;
683
0
        let end = start + UfWord::RAW_BYTE_LEN;
684
0
        start..end
685
0
    }
686
687
0
    pub fn math_leading_byte_range(&self) -> Range<usize> {
688
0
        let start = self.display_operator_min_height_byte_range().end;
689
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
690
0
        start..end
691
0
    }
692
693
0
    pub fn axis_height_byte_range(&self) -> Range<usize> {
694
0
        let start = self.math_leading_byte_range().end;
695
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
696
0
        start..end
697
0
    }
698
699
0
    pub fn accent_base_height_byte_range(&self) -> Range<usize> {
700
0
        let start = self.axis_height_byte_range().end;
701
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
702
0
        start..end
703
0
    }
704
705
0
    pub fn flattened_accent_base_height_byte_range(&self) -> Range<usize> {
706
0
        let start = self.accent_base_height_byte_range().end;
707
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
708
0
        start..end
709
0
    }
710
711
0
    pub fn subscript_shift_down_byte_range(&self) -> Range<usize> {
712
0
        let start = self.flattened_accent_base_height_byte_range().end;
713
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
714
0
        start..end
715
0
    }
716
717
0
    pub fn subscript_top_max_byte_range(&self) -> Range<usize> {
718
0
        let start = self.subscript_shift_down_byte_range().end;
719
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
720
0
        start..end
721
0
    }
722
723
0
    pub fn subscript_baseline_drop_min_byte_range(&self) -> Range<usize> {
724
0
        let start = self.subscript_top_max_byte_range().end;
725
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
726
0
        start..end
727
0
    }
728
729
0
    pub fn superscript_shift_up_byte_range(&self) -> Range<usize> {
730
0
        let start = self.subscript_baseline_drop_min_byte_range().end;
731
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
732
0
        start..end
733
0
    }
734
735
0
    pub fn superscript_shift_up_cramped_byte_range(&self) -> Range<usize> {
736
0
        let start = self.superscript_shift_up_byte_range().end;
737
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
738
0
        start..end
739
0
    }
740
741
0
    pub fn superscript_bottom_min_byte_range(&self) -> Range<usize> {
742
0
        let start = self.superscript_shift_up_cramped_byte_range().end;
743
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
744
0
        start..end
745
0
    }
746
747
0
    pub fn superscript_baseline_drop_max_byte_range(&self) -> Range<usize> {
748
0
        let start = self.superscript_bottom_min_byte_range().end;
749
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
750
0
        start..end
751
0
    }
752
753
0
    pub fn sub_superscript_gap_min_byte_range(&self) -> Range<usize> {
754
0
        let start = self.superscript_baseline_drop_max_byte_range().end;
755
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
756
0
        start..end
757
0
    }
758
759
0
    pub fn superscript_bottom_max_with_subscript_byte_range(&self) -> Range<usize> {
760
0
        let start = self.sub_superscript_gap_min_byte_range().end;
761
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
762
0
        start..end
763
0
    }
764
765
0
    pub fn space_after_script_byte_range(&self) -> Range<usize> {
766
0
        let start = self.superscript_bottom_max_with_subscript_byte_range().end;
767
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
768
0
        start..end
769
0
    }
770
771
0
    pub fn upper_limit_gap_min_byte_range(&self) -> Range<usize> {
772
0
        let start = self.space_after_script_byte_range().end;
773
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
774
0
        start..end
775
0
    }
776
777
0
    pub fn upper_limit_baseline_rise_min_byte_range(&self) -> Range<usize> {
778
0
        let start = self.upper_limit_gap_min_byte_range().end;
779
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
780
0
        start..end
781
0
    }
782
783
0
    pub fn lower_limit_gap_min_byte_range(&self) -> Range<usize> {
784
0
        let start = self.upper_limit_baseline_rise_min_byte_range().end;
785
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
786
0
        start..end
787
0
    }
788
789
0
    pub fn lower_limit_baseline_drop_min_byte_range(&self) -> Range<usize> {
790
0
        let start = self.lower_limit_gap_min_byte_range().end;
791
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
792
0
        start..end
793
0
    }
794
795
0
    pub fn stack_top_shift_up_byte_range(&self) -> Range<usize> {
796
0
        let start = self.lower_limit_baseline_drop_min_byte_range().end;
797
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
798
0
        start..end
799
0
    }
800
801
0
    pub fn stack_top_display_style_shift_up_byte_range(&self) -> Range<usize> {
802
0
        let start = self.stack_top_shift_up_byte_range().end;
803
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
804
0
        start..end
805
0
    }
806
807
0
    pub fn stack_bottom_shift_down_byte_range(&self) -> Range<usize> {
808
0
        let start = self.stack_top_display_style_shift_up_byte_range().end;
809
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
810
0
        start..end
811
0
    }
812
813
0
    pub fn stack_bottom_display_style_shift_down_byte_range(&self) -> Range<usize> {
814
0
        let start = self.stack_bottom_shift_down_byte_range().end;
815
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
816
0
        start..end
817
0
    }
818
819
0
    pub fn stack_gap_min_byte_range(&self) -> Range<usize> {
820
0
        let start = self.stack_bottom_display_style_shift_down_byte_range().end;
821
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
822
0
        start..end
823
0
    }
824
825
0
    pub fn stack_display_style_gap_min_byte_range(&self) -> Range<usize> {
826
0
        let start = self.stack_gap_min_byte_range().end;
827
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
828
0
        start..end
829
0
    }
830
831
0
    pub fn stretch_stack_top_shift_up_byte_range(&self) -> Range<usize> {
832
0
        let start = self.stack_display_style_gap_min_byte_range().end;
833
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
834
0
        start..end
835
0
    }
836
837
0
    pub fn stretch_stack_bottom_shift_down_byte_range(&self) -> Range<usize> {
838
0
        let start = self.stretch_stack_top_shift_up_byte_range().end;
839
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
840
0
        start..end
841
0
    }
842
843
0
    pub fn stretch_stack_gap_above_min_byte_range(&self) -> Range<usize> {
844
0
        let start = self.stretch_stack_bottom_shift_down_byte_range().end;
845
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
846
0
        start..end
847
0
    }
848
849
0
    pub fn stretch_stack_gap_below_min_byte_range(&self) -> Range<usize> {
850
0
        let start = self.stretch_stack_gap_above_min_byte_range().end;
851
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
852
0
        start..end
853
0
    }
854
855
0
    pub fn fraction_numerator_shift_up_byte_range(&self) -> Range<usize> {
856
0
        let start = self.stretch_stack_gap_below_min_byte_range().end;
857
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
858
0
        start..end
859
0
    }
860
861
0
    pub fn fraction_numerator_display_style_shift_up_byte_range(&self) -> Range<usize> {
862
0
        let start = self.fraction_numerator_shift_up_byte_range().end;
863
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
864
0
        start..end
865
0
    }
866
867
0
    pub fn fraction_denominator_shift_down_byte_range(&self) -> Range<usize> {
868
0
        let start = self
869
0
            .fraction_numerator_display_style_shift_up_byte_range()
870
0
            .end;
871
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
872
0
        start..end
873
0
    }
874
875
0
    pub fn fraction_denominator_display_style_shift_down_byte_range(&self) -> Range<usize> {
876
0
        let start = self.fraction_denominator_shift_down_byte_range().end;
877
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
878
0
        start..end
879
0
    }
880
881
0
    pub fn fraction_numerator_gap_min_byte_range(&self) -> Range<usize> {
882
0
        let start = self
883
0
            .fraction_denominator_display_style_shift_down_byte_range()
884
0
            .end;
885
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
886
0
        start..end
887
0
    }
888
889
0
    pub fn fraction_num_display_style_gap_min_byte_range(&self) -> Range<usize> {
890
0
        let start = self.fraction_numerator_gap_min_byte_range().end;
891
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
892
0
        start..end
893
0
    }
894
895
0
    pub fn fraction_rule_thickness_byte_range(&self) -> Range<usize> {
896
0
        let start = self.fraction_num_display_style_gap_min_byte_range().end;
897
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
898
0
        start..end
899
0
    }
900
901
0
    pub fn fraction_denominator_gap_min_byte_range(&self) -> Range<usize> {
902
0
        let start = self.fraction_rule_thickness_byte_range().end;
903
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
904
0
        start..end
905
0
    }
906
907
0
    pub fn fraction_denom_display_style_gap_min_byte_range(&self) -> Range<usize> {
908
0
        let start = self.fraction_denominator_gap_min_byte_range().end;
909
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
910
0
        start..end
911
0
    }
912
913
0
    pub fn skewed_fraction_horizontal_gap_byte_range(&self) -> Range<usize> {
914
0
        let start = self.fraction_denom_display_style_gap_min_byte_range().end;
915
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
916
0
        start..end
917
0
    }
918
919
0
    pub fn skewed_fraction_vertical_gap_byte_range(&self) -> Range<usize> {
920
0
        let start = self.skewed_fraction_horizontal_gap_byte_range().end;
921
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
922
0
        start..end
923
0
    }
924
925
0
    pub fn overbar_vertical_gap_byte_range(&self) -> Range<usize> {
926
0
        let start = self.skewed_fraction_vertical_gap_byte_range().end;
927
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
928
0
        start..end
929
0
    }
930
931
0
    pub fn overbar_rule_thickness_byte_range(&self) -> Range<usize> {
932
0
        let start = self.overbar_vertical_gap_byte_range().end;
933
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
934
0
        start..end
935
0
    }
936
937
0
    pub fn overbar_extra_ascender_byte_range(&self) -> Range<usize> {
938
0
        let start = self.overbar_rule_thickness_byte_range().end;
939
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
940
0
        start..end
941
0
    }
942
943
0
    pub fn underbar_vertical_gap_byte_range(&self) -> Range<usize> {
944
0
        let start = self.overbar_extra_ascender_byte_range().end;
945
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
946
0
        start..end
947
0
    }
948
949
0
    pub fn underbar_rule_thickness_byte_range(&self) -> Range<usize> {
950
0
        let start = self.underbar_vertical_gap_byte_range().end;
951
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
952
0
        start..end
953
0
    }
954
955
0
    pub fn underbar_extra_descender_byte_range(&self) -> Range<usize> {
956
0
        let start = self.underbar_rule_thickness_byte_range().end;
957
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
958
0
        start..end
959
0
    }
960
961
0
    pub fn radical_vertical_gap_byte_range(&self) -> Range<usize> {
962
0
        let start = self.underbar_extra_descender_byte_range().end;
963
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
964
0
        start..end
965
0
    }
966
967
0
    pub fn radical_display_style_vertical_gap_byte_range(&self) -> Range<usize> {
968
0
        let start = self.radical_vertical_gap_byte_range().end;
969
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
970
0
        start..end
971
0
    }
972
973
0
    pub fn radical_rule_thickness_byte_range(&self) -> Range<usize> {
974
0
        let start = self.radical_display_style_vertical_gap_byte_range().end;
975
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
976
0
        start..end
977
0
    }
978
979
0
    pub fn radical_extra_ascender_byte_range(&self) -> Range<usize> {
980
0
        let start = self.radical_rule_thickness_byte_range().end;
981
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
982
0
        start..end
983
0
    }
984
985
0
    pub fn radical_kern_before_degree_byte_range(&self) -> Range<usize> {
986
0
        let start = self.radical_extra_ascender_byte_range().end;
987
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
988
0
        start..end
989
0
    }
990
991
0
    pub fn radical_kern_after_degree_byte_range(&self) -> Range<usize> {
992
0
        let start = self.radical_kern_before_degree_byte_range().end;
993
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
994
0
        start..end
995
0
    }
996
997
0
    pub fn radical_degree_bottom_raise_percent_byte_range(&self) -> Range<usize> {
998
0
        let start = self.radical_kern_after_degree_byte_range().end;
999
0
        let end = start + i16::RAW_BYTE_LEN;
1000
0
        start..end
1001
0
    }
1002
}
1003
1004
const _: () = assert!(FontData::default_data_long_enough(MathConstants::MIN_SIZE));
1005
1006
impl Default for MathConstants<'_> {
1007
0
    fn default() -> Self {
1008
        Self {
1009
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
1010
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1011
        }
1012
0
    }
1013
}
1014
1015
impl<'a> MinByteRange<'a> for MathGlyphInfo<'a> {
1016
0
    fn min_byte_range(&self) -> Range<usize> {
1017
0
        0..self.math_kern_info_offset_byte_range().end
1018
0
    }
1019
0
    fn min_table_bytes(&self) -> &'a [u8] {
1020
0
        let range = self.min_byte_range();
1021
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1022
0
    }
1023
}
1024
1025
impl ReadArgs for MathGlyphInfo<'_> {
1026
    type Args = ();
1027
}
1028
1029
impl<'a> FontRead<'a> for MathGlyphInfo<'a> {
1030
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1031
        #[allow(clippy::absurd_extreme_comparisons)]
1032
0
        if data.len() < Self::MIN_SIZE {
1033
0
            return Err(ReadError::OutOfBounds);
1034
0
        }
1035
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1036
0
            return Err(ReadError::OutOfBounds);
1037
        };
1038
0
        Ok(Self { data })
1039
0
    }
1040
}
1041
1042
/// The fields at the start of the table, which are read directly.
1043
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1044
#[repr(C, packed)]
1045
#[doc(hidden)]
1046
pub struct MathGlyphInfoFixedHeader {
1047
    pub math_italics_correction_info_offset: BigEndian<Nullable<Offset16>>,
1048
    pub math_top_accent_attachment_offset: BigEndian<Nullable<Offset16>>,
1049
    pub extended_shape_coverage_offset: BigEndian<Nullable<Offset16>>,
1050
    pub math_kern_info_offset: BigEndian<Nullable<Offset16>>,
1051
}
1052
1053
#[allow(clippy::absurd_extreme_comparisons)]
1054
const _: () = assert!(std::mem::size_of::<MathGlyphInfoFixedHeader>() <= MathGlyphInfo::MIN_SIZE);
1055
1056
/// [MathGlyphInfo](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathglyphinfo-table)
1057
#[derive(Clone)]
1058
pub struct MathGlyphInfo<'a> {
1059
    data: TableDataRef<'a, MathGlyphInfoFixedHeader>,
1060
}
1061
1062
#[allow(clippy::needless_lifetimes)]
1063
impl<'a> MathGlyphInfo<'a> {
1064
    pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN
1065
        + Offset16::RAW_BYTE_LEN
1066
        + Offset16::RAW_BYTE_LEN
1067
        + Offset16::RAW_BYTE_LEN);
1068
    basic_table_impls!(impl_the_methods);
1069
1070
    /// Offset to MathItalicsCorrectionInfo table, from the beginning of the
1071
    /// MathGlyphInfo table. May be NULL.
1072
0
    pub fn math_italics_correction_info_offset(&self) -> Nullable<Offset16> {
1073
0
        self.data.header().math_italics_correction_info_offset.get()
1074
0
    }
1075
1076
    /// Attempt to resolve [`math_italics_correction_info_offset`][Self::math_italics_correction_info_offset].
1077
0
    pub fn math_italics_correction_info(
1078
0
        &self,
1079
0
    ) -> Option<Result<MathItalicsCorrectionInfo<'a>, ReadError>> {
1080
0
        let data = self.offset_data();
1081
0
        self.math_italics_correction_info_offset().resolve(data)
1082
0
    }
1083
1084
    /// Offset to MathTopAccentAttachment table, from the beginning of the
1085
    /// MathGlyphInfo table. May be NULL.
1086
0
    pub fn math_top_accent_attachment_offset(&self) -> Nullable<Offset16> {
1087
0
        self.data.header().math_top_accent_attachment_offset.get()
1088
0
    }
1089
1090
    /// Attempt to resolve [`math_top_accent_attachment_offset`][Self::math_top_accent_attachment_offset].
1091
0
    pub fn math_top_accent_attachment(
1092
0
        &self,
1093
0
    ) -> Option<Result<MathTopAccentAttachment<'a>, ReadError>> {
1094
0
        let data = self.offset_data();
1095
0
        self.math_top_accent_attachment_offset().resolve(data)
1096
0
    }
1097
1098
    /// Offset to the Coverage table for glyphs with extended shapes, from the
1099
    /// beginning of the MathGlyphInfo table. May be NULL.
1100
0
    pub fn extended_shape_coverage_offset(&self) -> Nullable<Offset16> {
1101
0
        self.data.header().extended_shape_coverage_offset.get()
1102
0
    }
1103
1104
    /// Attempt to resolve [`extended_shape_coverage_offset`][Self::extended_shape_coverage_offset].
1105
0
    pub fn extended_shape_coverage(&self) -> Option<Result<CoverageTable<'a>, ReadError>> {
1106
0
        let data = self.offset_data();
1107
0
        self.extended_shape_coverage_offset().resolve(data)
1108
0
    }
1109
1110
    /// Offset to the MathKernInfo table, from the beginning of the
1111
    /// MathGlyphInfo table. May be NULL.
1112
0
    pub fn math_kern_info_offset(&self) -> Nullable<Offset16> {
1113
0
        self.data.header().math_kern_info_offset.get()
1114
0
    }
1115
1116
    /// Attempt to resolve [`math_kern_info_offset`][Self::math_kern_info_offset].
1117
0
    pub fn math_kern_info(&self) -> Option<Result<MathKernInfo<'a>, ReadError>> {
1118
0
        let data = self.offset_data();
1119
0
        self.math_kern_info_offset().resolve(data)
1120
0
    }
1121
1122
0
    pub fn math_italics_correction_info_offset_byte_range(&self) -> Range<usize> {
1123
0
        let start = 0;
1124
0
        let end = start + Offset16::RAW_BYTE_LEN;
1125
0
        start..end
1126
0
    }
1127
1128
0
    pub fn math_top_accent_attachment_offset_byte_range(&self) -> Range<usize> {
1129
0
        let start = self.math_italics_correction_info_offset_byte_range().end;
1130
0
        let end = start + Offset16::RAW_BYTE_LEN;
1131
0
        start..end
1132
0
    }
1133
1134
0
    pub fn extended_shape_coverage_offset_byte_range(&self) -> Range<usize> {
1135
0
        let start = self.math_top_accent_attachment_offset_byte_range().end;
1136
0
        let end = start + Offset16::RAW_BYTE_LEN;
1137
0
        start..end
1138
0
    }
1139
1140
0
    pub fn math_kern_info_offset_byte_range(&self) -> Range<usize> {
1141
0
        let start = self.extended_shape_coverage_offset_byte_range().end;
1142
0
        let end = start + Offset16::RAW_BYTE_LEN;
1143
0
        start..end
1144
0
    }
1145
}
1146
1147
const _: () = assert!(FontData::default_data_long_enough(MathGlyphInfo::MIN_SIZE));
1148
1149
impl Default for MathGlyphInfo<'_> {
1150
0
    fn default() -> Self {
1151
        Self {
1152
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
1153
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1154
        }
1155
0
    }
1156
}
1157
1158
impl<'a> MinByteRange<'a> for MathItalicsCorrectionInfo<'a> {
1159
0
    fn min_byte_range(&self) -> Range<usize> {
1160
0
        0..self.italics_correction_byte_range().end
1161
0
    }
1162
0
    fn min_table_bytes(&self) -> &'a [u8] {
1163
0
        let range = self.min_byte_range();
1164
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1165
0
    }
1166
}
1167
1168
impl ReadArgs for MathItalicsCorrectionInfo<'_> {
1169
    type Args = ();
1170
}
1171
1172
impl<'a> FontRead<'a> for MathItalicsCorrectionInfo<'a> {
1173
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1174
        #[allow(clippy::absurd_extreme_comparisons)]
1175
0
        if data.len() < Self::MIN_SIZE {
1176
0
            return Err(ReadError::OutOfBounds);
1177
0
        }
1178
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1179
0
            return Err(ReadError::OutOfBounds);
1180
        };
1181
0
        Ok(Self { data })
1182
0
    }
1183
}
1184
1185
/// The fields at the start of the table, which are read directly.
1186
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1187
#[repr(C, packed)]
1188
#[doc(hidden)]
1189
pub struct MathItalicsCorrectionInfoFixedHeader {
1190
    pub coverage_offset: BigEndian<Offset16>,
1191
    pub italics_correction_count: BigEndian<u16>,
1192
}
1193
1194
#[allow(clippy::absurd_extreme_comparisons)]
1195
const _: () = assert!(
1196
    std::mem::size_of::<MathItalicsCorrectionInfoFixedHeader>()
1197
        <= MathItalicsCorrectionInfo::MIN_SIZE
1198
);
1199
1200
/// [MathItalicsCorrectionInfo](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathitalicscorrectioninfo-table)
1201
#[derive(Clone)]
1202
pub struct MathItalicsCorrectionInfo<'a> {
1203
    data: TableDataRef<'a, MathItalicsCorrectionInfoFixedHeader>,
1204
}
1205
1206
#[allow(clippy::needless_lifetimes)]
1207
impl<'a> MathItalicsCorrectionInfo<'a> {
1208
    pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1209
    basic_table_impls!(impl_the_methods);
1210
1211
    /// Offset to the Coverage table, from the beginning of the
1212
    /// MathItalicsCorrectionInfo table.
1213
0
    pub fn coverage_offset(&self) -> Offset16 {
1214
0
        self.data.header().coverage_offset.get()
1215
0
    }
1216
1217
    /// Attempt to resolve [`coverage_offset`][Self::coverage_offset].
1218
0
    pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1219
0
        let data = self.offset_data();
1220
0
        self.coverage_offset().resolve(data)
1221
0
    }
1222
1223
    /// Number of italics correction values. Should coincide with the number of
1224
    /// covered glyphs.
1225
0
    pub fn italics_correction_count(&self) -> u16 {
1226
0
        self.data.header().italics_correction_count.get()
1227
0
    }
1228
1229
    /// Array of MathValueRecords defining italics correction values for each
1230
    /// covered glyph.
1231
0
    pub fn italics_correction(&self) -> &'a [MathValueRecord] {
1232
0
        let range = self.italics_correction_byte_range();
1233
0
        self.offset_data()
1234
0
            .read_array(range)
1235
0
            .ok()
1236
0
            .unwrap_or_default()
1237
0
    }
1238
1239
0
    pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1240
0
        let start = 0;
1241
0
        let end = start + Offset16::RAW_BYTE_LEN;
1242
0
        start..end
1243
0
    }
1244
1245
0
    pub fn italics_correction_count_byte_range(&self) -> Range<usize> {
1246
0
        let start = self.coverage_offset_byte_range().end;
1247
0
        let end = start + u16::RAW_BYTE_LEN;
1248
0
        start..end
1249
0
    }
1250
1251
0
    pub fn italics_correction_byte_range(&self) -> Range<usize> {
1252
0
        let italics_correction_count = self.italics_correction_count();
1253
0
        let start = self.italics_correction_count_byte_range().end;
1254
0
        let end = start
1255
0
            + (transforms::to_usize(italics_correction_count))
1256
0
                .saturating_mul(MathValueRecord::RAW_BYTE_LEN);
1257
0
        start..end
1258
0
    }
1259
}
1260
1261
const _: () = assert!(FontData::default_data_long_enough(
1262
    MathItalicsCorrectionInfo::MIN_SIZE
1263
));
1264
1265
impl Default for MathItalicsCorrectionInfo<'_> {
1266
0
    fn default() -> Self {
1267
        Self {
1268
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
1269
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1270
        }
1271
0
    }
1272
}
1273
1274
impl<'a> MinByteRange<'a> for MathTopAccentAttachment<'a> {
1275
0
    fn min_byte_range(&self) -> Range<usize> {
1276
0
        0..self.top_accent_attachment_byte_range().end
1277
0
    }
1278
0
    fn min_table_bytes(&self) -> &'a [u8] {
1279
0
        let range = self.min_byte_range();
1280
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1281
0
    }
1282
}
1283
1284
impl ReadArgs for MathTopAccentAttachment<'_> {
1285
    type Args = ();
1286
}
1287
1288
impl<'a> FontRead<'a> for MathTopAccentAttachment<'a> {
1289
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1290
        #[allow(clippy::absurd_extreme_comparisons)]
1291
0
        if data.len() < Self::MIN_SIZE {
1292
0
            return Err(ReadError::OutOfBounds);
1293
0
        }
1294
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1295
0
            return Err(ReadError::OutOfBounds);
1296
        };
1297
0
        Ok(Self { data })
1298
0
    }
1299
}
1300
1301
/// The fields at the start of the table, which are read directly.
1302
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1303
#[repr(C, packed)]
1304
#[doc(hidden)]
1305
pub struct MathTopAccentAttachmentFixedHeader {
1306
    pub top_accent_coverage_offset: BigEndian<Offset16>,
1307
    pub top_accent_attachment_count: BigEndian<u16>,
1308
}
1309
1310
#[allow(clippy::absurd_extreme_comparisons)]
1311
const _: () = assert!(
1312
    std::mem::size_of::<MathTopAccentAttachmentFixedHeader>() <= MathTopAccentAttachment::MIN_SIZE
1313
);
1314
1315
/// [MathTopAccentAttachment](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathtopaccentattachment-table)
1316
#[derive(Clone)]
1317
pub struct MathTopAccentAttachment<'a> {
1318
    data: TableDataRef<'a, MathTopAccentAttachmentFixedHeader>,
1319
}
1320
1321
#[allow(clippy::needless_lifetimes)]
1322
impl<'a> MathTopAccentAttachment<'a> {
1323
    pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1324
    basic_table_impls!(impl_the_methods);
1325
1326
    /// Offset to the Coverage table, from the beginning of the
1327
    /// MathTopAccentAttachment table.
1328
0
    pub fn top_accent_coverage_offset(&self) -> Offset16 {
1329
0
        self.data.header().top_accent_coverage_offset.get()
1330
0
    }
1331
1332
    /// Attempt to resolve [`top_accent_coverage_offset`][Self::top_accent_coverage_offset].
1333
0
    pub fn top_accent_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1334
0
        let data = self.offset_data();
1335
0
        self.top_accent_coverage_offset().resolve(data)
1336
0
    }
1337
1338
    /// Number of top accent attachment point values. Should coincide with the
1339
    /// number of covered glyphs.
1340
0
    pub fn top_accent_attachment_count(&self) -> u16 {
1341
0
        self.data.header().top_accent_attachment_count.get()
1342
0
    }
1343
1344
    /// Array of MathValueRecords defining top accent attachment points for each
1345
    /// covered glyph.
1346
0
    pub fn top_accent_attachment(&self) -> &'a [MathValueRecord] {
1347
0
        let range = self.top_accent_attachment_byte_range();
1348
0
        self.offset_data()
1349
0
            .read_array(range)
1350
0
            .ok()
1351
0
            .unwrap_or_default()
1352
0
    }
1353
1354
0
    pub fn top_accent_coverage_offset_byte_range(&self) -> Range<usize> {
1355
0
        let start = 0;
1356
0
        let end = start + Offset16::RAW_BYTE_LEN;
1357
0
        start..end
1358
0
    }
1359
1360
0
    pub fn top_accent_attachment_count_byte_range(&self) -> Range<usize> {
1361
0
        let start = self.top_accent_coverage_offset_byte_range().end;
1362
0
        let end = start + u16::RAW_BYTE_LEN;
1363
0
        start..end
1364
0
    }
1365
1366
0
    pub fn top_accent_attachment_byte_range(&self) -> Range<usize> {
1367
0
        let top_accent_attachment_count = self.top_accent_attachment_count();
1368
0
        let start = self.top_accent_attachment_count_byte_range().end;
1369
0
        let end = start
1370
0
            + (transforms::to_usize(top_accent_attachment_count))
1371
0
                .saturating_mul(MathValueRecord::RAW_BYTE_LEN);
1372
0
        start..end
1373
0
    }
1374
}
1375
1376
const _: () = assert!(FontData::default_data_long_enough(
1377
    MathTopAccentAttachment::MIN_SIZE
1378
));
1379
1380
impl Default for MathTopAccentAttachment<'_> {
1381
0
    fn default() -> Self {
1382
        Self {
1383
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
1384
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1385
        }
1386
0
    }
1387
}
1388
1389
impl<'a> MinByteRange<'a> for MathKernInfo<'a> {
1390
0
    fn min_byte_range(&self) -> Range<usize> {
1391
0
        0..self.math_kern_info_records_byte_range().end
1392
0
    }
1393
0
    fn min_table_bytes(&self) -> &'a [u8] {
1394
0
        let range = self.min_byte_range();
1395
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1396
0
    }
1397
}
1398
1399
impl ReadArgs for MathKernInfo<'_> {
1400
    type Args = ();
1401
}
1402
1403
impl<'a> FontRead<'a> for MathKernInfo<'a> {
1404
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1405
        #[allow(clippy::absurd_extreme_comparisons)]
1406
0
        if data.len() < Self::MIN_SIZE {
1407
0
            return Err(ReadError::OutOfBounds);
1408
0
        }
1409
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1410
0
            return Err(ReadError::OutOfBounds);
1411
        };
1412
0
        Ok(Self { data })
1413
0
    }
1414
}
1415
1416
/// The fields at the start of the table, which are read directly.
1417
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1418
#[repr(C, packed)]
1419
#[doc(hidden)]
1420
pub struct MathKernInfoFixedHeader {
1421
    pub math_kern_coverage_offset: BigEndian<Offset16>,
1422
    pub math_kern_count: BigEndian<u16>,
1423
}
1424
1425
#[allow(clippy::absurd_extreme_comparisons)]
1426
const _: () = assert!(std::mem::size_of::<MathKernInfoFixedHeader>() <= MathKernInfo::MIN_SIZE);
1427
1428
/// [MathKernInfo](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathkerninfo-table)
1429
#[derive(Clone)]
1430
pub struct MathKernInfo<'a> {
1431
    data: TableDataRef<'a, MathKernInfoFixedHeader>,
1432
}
1433
1434
#[allow(clippy::needless_lifetimes)]
1435
impl<'a> MathKernInfo<'a> {
1436
    pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1437
    basic_table_impls!(impl_the_methods);
1438
1439
    /// Offset to the Coverage table, from the beginning of the MathKernInfo
1440
    /// table.
1441
0
    pub fn math_kern_coverage_offset(&self) -> Offset16 {
1442
0
        self.data.header().math_kern_coverage_offset.get()
1443
0
    }
1444
1445
    /// Attempt to resolve [`math_kern_coverage_offset`][Self::math_kern_coverage_offset].
1446
0
    pub fn math_kern_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1447
0
        let data = self.offset_data();
1448
0
        self.math_kern_coverage_offset().resolve(data)
1449
0
    }
1450
1451
    /// Number of MathKernInfoRecords. Should coincide with the number of
1452
    /// covered glyphs.
1453
0
    pub fn math_kern_count(&self) -> u16 {
1454
0
        self.data.header().math_kern_count.get()
1455
0
    }
1456
1457
    /// Array of MathKernInfoRecords, one for each covered glyph.
1458
0
    pub fn math_kern_info_records(&self) -> &'a [MathKernInfoRecord] {
1459
0
        let range = self.math_kern_info_records_byte_range();
1460
0
        self.offset_data()
1461
0
            .read_array(range)
1462
0
            .ok()
1463
0
            .unwrap_or_default()
1464
0
    }
1465
1466
0
    pub fn math_kern_coverage_offset_byte_range(&self) -> Range<usize> {
1467
0
        let start = 0;
1468
0
        let end = start + Offset16::RAW_BYTE_LEN;
1469
0
        start..end
1470
0
    }
1471
1472
0
    pub fn math_kern_count_byte_range(&self) -> Range<usize> {
1473
0
        let start = self.math_kern_coverage_offset_byte_range().end;
1474
0
        let end = start + u16::RAW_BYTE_LEN;
1475
0
        start..end
1476
0
    }
1477
1478
0
    pub fn math_kern_info_records_byte_range(&self) -> Range<usize> {
1479
0
        let math_kern_count = self.math_kern_count();
1480
0
        let start = self.math_kern_count_byte_range().end;
1481
0
        let end = start
1482
0
            + (transforms::to_usize(math_kern_count))
1483
0
                .saturating_mul(MathKernInfoRecord::RAW_BYTE_LEN);
1484
0
        start..end
1485
0
    }
1486
}
1487
1488
const _: () = assert!(FontData::default_data_long_enough(MathKernInfo::MIN_SIZE));
1489
1490
impl Default for MathKernInfo<'_> {
1491
0
    fn default() -> Self {
1492
        Self {
1493
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
1494
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1495
        }
1496
0
    }
1497
}
1498
1499
/// [MathKernInfoRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathkerninforecord)
1500
///
1501
/// The offsets are measured from the beginning of the MathKernInfo table.
1502
#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
1503
#[repr(C)]
1504
#[repr(packed)]
1505
pub struct MathKernInfoRecord {
1506
    /// Offset to the MathKern table for the top right corner, from the
1507
    /// beginning of the MathKernInfo table. May be NULL.
1508
    pub top_right_math_kern_offset: BigEndian<Nullable<Offset16>>,
1509
    /// Offset to the MathKern table for the top left corner, from the beginning
1510
    /// of the MathKernInfo table. May be NULL.
1511
    pub top_left_math_kern_offset: BigEndian<Nullable<Offset16>>,
1512
    /// Offset to the MathKern table for the bottom right corner, from the
1513
    /// beginning of the MathKernInfo table. May be NULL.
1514
    pub bottom_right_math_kern_offset: BigEndian<Nullable<Offset16>>,
1515
    /// Offset to the MathKern table for the bottom left corner, from the
1516
    /// beginning of the MathKernInfo table. May be NULL.
1517
    pub bottom_left_math_kern_offset: BigEndian<Nullable<Offset16>>,
1518
}
1519
1520
impl MathKernInfoRecord {
1521
    /// Offset to the MathKern table for the top right corner, from the
1522
    /// beginning of the MathKernInfo table. May be NULL.
1523
0
    pub fn top_right_math_kern_offset(&self) -> Nullable<Offset16> {
1524
0
        self.top_right_math_kern_offset.get()
1525
0
    }
1526
1527
    /// Offset to the MathKern table for the top right corner, from the
1528
    /// beginning of the MathKernInfo table. May be NULL.
1529
    ///
1530
    /// The `data` argument should be retrieved from the parent table
1531
    /// By calling its `offset_data` method.
1532
0
    pub fn top_right_math_kern<'a>(
1533
0
        &self,
1534
0
        data: FontData<'a>,
1535
0
    ) -> Option<Result<MathKern<'a>, ReadError>> {
1536
0
        self.top_right_math_kern_offset().resolve(data)
1537
0
    }
1538
1539
    /// Offset to the MathKern table for the top left corner, from the beginning
1540
    /// of the MathKernInfo table. May be NULL.
1541
0
    pub fn top_left_math_kern_offset(&self) -> Nullable<Offset16> {
1542
0
        self.top_left_math_kern_offset.get()
1543
0
    }
1544
1545
    /// Offset to the MathKern table for the top left corner, from the beginning
1546
    /// of the MathKernInfo table. May be NULL.
1547
    ///
1548
    /// The `data` argument should be retrieved from the parent table
1549
    /// By calling its `offset_data` method.
1550
0
    pub fn top_left_math_kern<'a>(
1551
0
        &self,
1552
0
        data: FontData<'a>,
1553
0
    ) -> Option<Result<MathKern<'a>, ReadError>> {
1554
0
        self.top_left_math_kern_offset().resolve(data)
1555
0
    }
1556
1557
    /// Offset to the MathKern table for the bottom right corner, from the
1558
    /// beginning of the MathKernInfo table. May be NULL.
1559
0
    pub fn bottom_right_math_kern_offset(&self) -> Nullable<Offset16> {
1560
0
        self.bottom_right_math_kern_offset.get()
1561
0
    }
1562
1563
    /// Offset to the MathKern table for the bottom right corner, from the
1564
    /// beginning of the MathKernInfo table. May be NULL.
1565
    ///
1566
    /// The `data` argument should be retrieved from the parent table
1567
    /// By calling its `offset_data` method.
1568
0
    pub fn bottom_right_math_kern<'a>(
1569
0
        &self,
1570
0
        data: FontData<'a>,
1571
0
    ) -> Option<Result<MathKern<'a>, ReadError>> {
1572
0
        self.bottom_right_math_kern_offset().resolve(data)
1573
0
    }
1574
1575
    /// Offset to the MathKern table for the bottom left corner, from the
1576
    /// beginning of the MathKernInfo table. May be NULL.
1577
0
    pub fn bottom_left_math_kern_offset(&self) -> Nullable<Offset16> {
1578
0
        self.bottom_left_math_kern_offset.get()
1579
0
    }
1580
1581
    /// Offset to the MathKern table for the bottom left corner, from the
1582
    /// beginning of the MathKernInfo table. May be NULL.
1583
    ///
1584
    /// The `data` argument should be retrieved from the parent table
1585
    /// By calling its `offset_data` method.
1586
0
    pub fn bottom_left_math_kern<'a>(
1587
0
        &self,
1588
0
        data: FontData<'a>,
1589
0
    ) -> Option<Result<MathKern<'a>, ReadError>> {
1590
0
        self.bottom_left_math_kern_offset().resolve(data)
1591
0
    }
1592
}
1593
1594
impl FixedSize for MathKernInfoRecord {
1595
    const RAW_BYTE_LEN: usize = Offset16::RAW_BYTE_LEN
1596
        + Offset16::RAW_BYTE_LEN
1597
        + Offset16::RAW_BYTE_LEN
1598
        + Offset16::RAW_BYTE_LEN;
1599
}
1600
1601
impl<'a> MinByteRange<'a> for MathKern<'a> {
1602
0
    fn min_byte_range(&self) -> Range<usize> {
1603
0
        0..self.kern_values_byte_range().end
1604
0
    }
1605
0
    fn min_table_bytes(&self) -> &'a [u8] {
1606
0
        let range = self.min_byte_range();
1607
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1608
0
    }
1609
}
1610
1611
impl ReadArgs for MathKern<'_> {
1612
    type Args = ();
1613
}
1614
1615
impl<'a> FontRead<'a> for MathKern<'a> {
1616
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1617
        #[allow(clippy::absurd_extreme_comparisons)]
1618
0
        if data.len() < Self::MIN_SIZE {
1619
0
            return Err(ReadError::OutOfBounds);
1620
0
        }
1621
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1622
0
            return Err(ReadError::OutOfBounds);
1623
        };
1624
0
        Ok(Self { data })
1625
0
    }
1626
}
1627
1628
/// The fields at the start of the table, which are read directly.
1629
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1630
#[repr(C, packed)]
1631
#[doc(hidden)]
1632
pub struct MathKernFixedHeader {
1633
    pub height_count: BigEndian<u16>,
1634
}
1635
1636
#[allow(clippy::absurd_extreme_comparisons)]
1637
const _: () = assert!(std::mem::size_of::<MathKernFixedHeader>() <= MathKern::MIN_SIZE);
1638
1639
/// [MathKern](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathkern-table)
1640
#[derive(Clone)]
1641
pub struct MathKern<'a> {
1642
    data: TableDataRef<'a, MathKernFixedHeader>,
1643
}
1644
1645
#[allow(clippy::needless_lifetimes)]
1646
impl<'a> MathKern<'a> {
1647
    pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
1648
    basic_table_impls!(impl_the_methods);
1649
1650
    /// Number of heights at which the kern value changes.
1651
0
    pub fn height_count(&self) -> u16 {
1652
0
        self.data.header().height_count.get()
1653
0
    }
1654
1655
    /// Array of correction heights, in design units, sorted from lowest to
1656
    /// highest.
1657
0
    pub fn correction_height(&self) -> &'a [MathValueRecord] {
1658
0
        let range = self.correction_height_byte_range();
1659
0
        self.offset_data()
1660
0
            .read_array(range)
1661
0
            .ok()
1662
0
            .unwrap_or_default()
1663
0
    }
1664
1665
    /// Array of kerning values for different height ranges, in design units.
1666
    ///
1667
    /// There is one more of these than there are correction heights: the first
1668
    /// applies below the first correction height, and the last above the last.
1669
0
    pub fn kern_values(&self) -> &'a [MathValueRecord] {
1670
0
        let range = self.kern_values_byte_range();
1671
0
        self.offset_data()
1672
0
            .read_array(range)
1673
0
            .ok()
1674
0
            .unwrap_or_default()
1675
0
    }
1676
1677
0
    pub fn height_count_byte_range(&self) -> Range<usize> {
1678
0
        let start = 0;
1679
0
        let end = start + u16::RAW_BYTE_LEN;
1680
0
        start..end
1681
0
    }
1682
1683
0
    pub fn correction_height_byte_range(&self) -> Range<usize> {
1684
0
        let height_count = self.height_count();
1685
0
        let start = self.height_count_byte_range().end;
1686
0
        let end = start
1687
0
            + (transforms::to_usize(height_count)).saturating_mul(MathValueRecord::RAW_BYTE_LEN);
1688
0
        start..end
1689
0
    }
1690
1691
0
    pub fn kern_values_byte_range(&self) -> Range<usize> {
1692
0
        let height_count = self.height_count();
1693
0
        let start = self.correction_height_byte_range().end;
1694
0
        let end = start
1695
0
            + (transforms::add(height_count, 1_usize))
1696
0
                .saturating_mul(MathValueRecord::RAW_BYTE_LEN);
1697
0
        start..end
1698
0
    }
1699
}
1700
1701
const _: () = assert!(FontData::default_data_long_enough(MathKern::MIN_SIZE));
1702
1703
impl Default for MathKern<'_> {
1704
0
    fn default() -> Self {
1705
        Self {
1706
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
1707
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1708
        }
1709
0
    }
1710
}
1711
1712
impl<'a> MinByteRange<'a> for MathVariants<'a> {
1713
0
    fn min_byte_range(&self) -> Range<usize> {
1714
0
        0..self.horiz_glyph_construction_offsets_byte_range().end
1715
0
    }
1716
0
    fn min_table_bytes(&self) -> &'a [u8] {
1717
0
        let range = self.min_byte_range();
1718
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1719
0
    }
1720
}
1721
1722
impl ReadArgs for MathVariants<'_> {
1723
    type Args = ();
1724
}
1725
1726
impl<'a> FontRead<'a> for MathVariants<'a> {
1727
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1728
        #[allow(clippy::absurd_extreme_comparisons)]
1729
0
        if data.len() < Self::MIN_SIZE {
1730
0
            return Err(ReadError::OutOfBounds);
1731
0
        }
1732
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1733
0
            return Err(ReadError::OutOfBounds);
1734
        };
1735
0
        Ok(Self { data })
1736
0
    }
1737
}
1738
1739
/// The fields at the start of the table, which are read directly.
1740
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1741
#[repr(C, packed)]
1742
#[doc(hidden)]
1743
pub struct MathVariantsFixedHeader {
1744
    pub min_connector_overlap: BigEndian<UfWord>,
1745
    pub vert_glyph_coverage_offset: BigEndian<Nullable<Offset16>>,
1746
    pub horiz_glyph_coverage_offset: BigEndian<Nullable<Offset16>>,
1747
    pub vert_glyph_count: BigEndian<u16>,
1748
    pub horiz_glyph_count: BigEndian<u16>,
1749
}
1750
1751
#[allow(clippy::absurd_extreme_comparisons)]
1752
const _: () = assert!(std::mem::size_of::<MathVariantsFixedHeader>() <= MathVariants::MIN_SIZE);
1753
1754
/// [MathVariants](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathvariants-table)
1755
#[derive(Clone)]
1756
pub struct MathVariants<'a> {
1757
    data: TableDataRef<'a, MathVariantsFixedHeader>,
1758
}
1759
1760
#[allow(clippy::needless_lifetimes)]
1761
impl<'a> MathVariants<'a> {
1762
    pub const MIN_SIZE: usize = (UfWord::RAW_BYTE_LEN
1763
        + Offset16::RAW_BYTE_LEN
1764
        + Offset16::RAW_BYTE_LEN
1765
        + u16::RAW_BYTE_LEN
1766
        + u16::RAW_BYTE_LEN);
1767
    basic_table_impls!(impl_the_methods);
1768
1769
    /// Minimum overlap of connecting glyphs during glyph construction, in
1770
    /// design units.
1771
0
    pub fn min_connector_overlap(&self) -> UfWord {
1772
0
        self.data.header().min_connector_overlap.get()
1773
0
    }
1774
1775
    /// Offset to the Coverage table for shapes growing in the vertical
1776
    /// direction, from the beginning of the MathVariants table. May be NULL.
1777
0
    pub fn vert_glyph_coverage_offset(&self) -> Nullable<Offset16> {
1778
0
        self.data.header().vert_glyph_coverage_offset.get()
1779
0
    }
1780
1781
    /// Attempt to resolve [`vert_glyph_coverage_offset`][Self::vert_glyph_coverage_offset].
1782
0
    pub fn vert_glyph_coverage(&self) -> Option<Result<CoverageTable<'a>, ReadError>> {
1783
0
        let data = self.offset_data();
1784
0
        self.vert_glyph_coverage_offset().resolve(data)
1785
0
    }
1786
1787
    /// Offset to the Coverage table for shapes growing in the horizontal
1788
    /// direction, from the beginning of the MathVariants table. May be NULL.
1789
0
    pub fn horiz_glyph_coverage_offset(&self) -> Nullable<Offset16> {
1790
0
        self.data.header().horiz_glyph_coverage_offset.get()
1791
0
    }
1792
1793
    /// Attempt to resolve [`horiz_glyph_coverage_offset`][Self::horiz_glyph_coverage_offset].
1794
0
    pub fn horiz_glyph_coverage(&self) -> Option<Result<CoverageTable<'a>, ReadError>> {
1795
0
        let data = self.offset_data();
1796
0
        self.horiz_glyph_coverage_offset().resolve(data)
1797
0
    }
1798
1799
    /// Number of glyphs for which information is provided for vertically
1800
    /// growing variants. Must be the same as the number of glyph IDs referenced
1801
    /// in the vertical Coverage table.
1802
0
    pub fn vert_glyph_count(&self) -> u16 {
1803
0
        self.data.header().vert_glyph_count.get()
1804
0
    }
1805
1806
    /// Number of glyphs for which information is provided for horizontally
1807
    /// growing variants. Must be the same as the number of glyph IDs referenced
1808
    /// in the horizontal Coverage table.
1809
0
    pub fn horiz_glyph_count(&self) -> u16 {
1810
0
        self.data.header().horiz_glyph_count.get()
1811
0
    }
1812
1813
    /// Array of offsets to MathGlyphConstruction tables, from the beginning of
1814
    /// the MathVariants table, for shapes growing in the vertical direction.
1815
0
    pub fn vert_glyph_construction_offsets(&self) -> &'a [BigEndian<Offset16>] {
1816
0
        let range = self.vert_glyph_construction_offsets_byte_range();
1817
0
        self.offset_data()
1818
0
            .read_array(range)
1819
0
            .ok()
1820
0
            .unwrap_or_default()
1821
0
    }
1822
1823
    /// A dynamically resolving wrapper for [`vert_glyph_construction_offsets`][Self::vert_glyph_construction_offsets].
1824
0
    pub fn vert_glyph_constructions(
1825
0
        &self,
1826
0
    ) -> ArrayOfOffsets<'a, MathGlyphConstruction<'a>, Offset16> {
1827
0
        let data = self.offset_data();
1828
0
        let offsets = self.vert_glyph_construction_offsets();
1829
0
        ArrayOfOffsets::new(offsets, data, ())
1830
0
    }
1831
1832
    /// Array of offsets to MathGlyphConstruction tables, from the beginning of
1833
    /// the MathVariants table, for shapes growing in the horizontal direction.
1834
0
    pub fn horiz_glyph_construction_offsets(&self) -> &'a [BigEndian<Offset16>] {
1835
0
        let range = self.horiz_glyph_construction_offsets_byte_range();
1836
0
        self.offset_data()
1837
0
            .read_array(range)
1838
0
            .ok()
1839
0
            .unwrap_or_default()
1840
0
    }
1841
1842
    /// A dynamically resolving wrapper for [`horiz_glyph_construction_offsets`][Self::horiz_glyph_construction_offsets].
1843
0
    pub fn horiz_glyph_constructions(
1844
0
        &self,
1845
0
    ) -> ArrayOfOffsets<'a, MathGlyphConstruction<'a>, Offset16> {
1846
0
        let data = self.offset_data();
1847
0
        let offsets = self.horiz_glyph_construction_offsets();
1848
0
        ArrayOfOffsets::new(offsets, data, ())
1849
0
    }
1850
1851
0
    pub fn min_connector_overlap_byte_range(&self) -> Range<usize> {
1852
0
        let start = 0;
1853
0
        let end = start + UfWord::RAW_BYTE_LEN;
1854
0
        start..end
1855
0
    }
1856
1857
0
    pub fn vert_glyph_coverage_offset_byte_range(&self) -> Range<usize> {
1858
0
        let start = self.min_connector_overlap_byte_range().end;
1859
0
        let end = start + Offset16::RAW_BYTE_LEN;
1860
0
        start..end
1861
0
    }
1862
1863
0
    pub fn horiz_glyph_coverage_offset_byte_range(&self) -> Range<usize> {
1864
0
        let start = self.vert_glyph_coverage_offset_byte_range().end;
1865
0
        let end = start + Offset16::RAW_BYTE_LEN;
1866
0
        start..end
1867
0
    }
1868
1869
0
    pub fn vert_glyph_count_byte_range(&self) -> Range<usize> {
1870
0
        let start = self.horiz_glyph_coverage_offset_byte_range().end;
1871
0
        let end = start + u16::RAW_BYTE_LEN;
1872
0
        start..end
1873
0
    }
1874
1875
0
    pub fn horiz_glyph_count_byte_range(&self) -> Range<usize> {
1876
0
        let start = self.vert_glyph_count_byte_range().end;
1877
0
        let end = start + u16::RAW_BYTE_LEN;
1878
0
        start..end
1879
0
    }
1880
1881
0
    pub fn vert_glyph_construction_offsets_byte_range(&self) -> Range<usize> {
1882
0
        let vert_glyph_count = self.vert_glyph_count();
1883
0
        let start = self.horiz_glyph_count_byte_range().end;
1884
0
        let end =
1885
0
            start + (transforms::to_usize(vert_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1886
0
        start..end
1887
0
    }
1888
1889
0
    pub fn horiz_glyph_construction_offsets_byte_range(&self) -> Range<usize> {
1890
0
        let horiz_glyph_count = self.horiz_glyph_count();
1891
0
        let start = self.vert_glyph_construction_offsets_byte_range().end;
1892
0
        let end = start
1893
0
            + (transforms::to_usize(horiz_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1894
0
        start..end
1895
0
    }
1896
}
1897
1898
const _: () = assert!(FontData::default_data_long_enough(MathVariants::MIN_SIZE));
1899
1900
impl Default for MathVariants<'_> {
1901
0
    fn default() -> Self {
1902
        Self {
1903
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
1904
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1905
        }
1906
0
    }
1907
}
1908
1909
impl<'a> MinByteRange<'a> for MathGlyphConstruction<'a> {
1910
0
    fn min_byte_range(&self) -> Range<usize> {
1911
0
        0..self.math_glyph_variant_records_byte_range().end
1912
0
    }
1913
0
    fn min_table_bytes(&self) -> &'a [u8] {
1914
0
        let range = self.min_byte_range();
1915
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
1916
0
    }
1917
}
1918
1919
impl ReadArgs for MathGlyphConstruction<'_> {
1920
    type Args = ();
1921
}
1922
1923
impl<'a> FontRead<'a> for MathGlyphConstruction<'a> {
1924
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1925
        #[allow(clippy::absurd_extreme_comparisons)]
1926
0
        if data.len() < Self::MIN_SIZE {
1927
0
            return Err(ReadError::OutOfBounds);
1928
0
        }
1929
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
1930
0
            return Err(ReadError::OutOfBounds);
1931
        };
1932
0
        Ok(Self { data })
1933
0
    }
1934
}
1935
1936
/// The fields at the start of the table, which are read directly.
1937
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1938
#[repr(C, packed)]
1939
#[doc(hidden)]
1940
pub struct MathGlyphConstructionFixedHeader {
1941
    pub glyph_assembly_offset: BigEndian<Nullable<Offset16>>,
1942
    pub variant_count: BigEndian<u16>,
1943
}
1944
1945
#[allow(clippy::absurd_extreme_comparisons)]
1946
const _: () = assert!(
1947
    std::mem::size_of::<MathGlyphConstructionFixedHeader>() <= MathGlyphConstruction::MIN_SIZE
1948
);
1949
1950
/// [MathGlyphConstruction](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathglyphconstruction-table)
1951
#[derive(Clone)]
1952
pub struct MathGlyphConstruction<'a> {
1953
    data: TableDataRef<'a, MathGlyphConstructionFixedHeader>,
1954
}
1955
1956
#[allow(clippy::needless_lifetimes)]
1957
impl<'a> MathGlyphConstruction<'a> {
1958
    pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1959
    basic_table_impls!(impl_the_methods);
1960
1961
    /// Offset to the GlyphAssembly table for this shape, from the beginning of
1962
    /// the MathGlyphConstruction table. May be NULL.
1963
0
    pub fn glyph_assembly_offset(&self) -> Nullable<Offset16> {
1964
0
        self.data.header().glyph_assembly_offset.get()
1965
0
    }
1966
1967
    /// Attempt to resolve [`glyph_assembly_offset`][Self::glyph_assembly_offset].
1968
0
    pub fn glyph_assembly(&self) -> Option<Result<GlyphAssembly<'a>, ReadError>> {
1969
0
        let data = self.offset_data();
1970
0
        self.glyph_assembly_offset().resolve(data)
1971
0
    }
1972
1973
    /// Count of glyph growing variants for this glyph.
1974
0
    pub fn variant_count(&self) -> u16 {
1975
0
        self.data.header().variant_count.get()
1976
0
    }
1977
1978
    /// MathGlyphVariantRecords for alternative variants of the base glyph.
1979
0
    pub fn math_glyph_variant_records(&self) -> &'a [MathGlyphVariantRecord] {
1980
0
        let range = self.math_glyph_variant_records_byte_range();
1981
0
        self.offset_data()
1982
0
            .read_array(range)
1983
0
            .ok()
1984
0
            .unwrap_or_default()
1985
0
    }
1986
1987
0
    pub fn glyph_assembly_offset_byte_range(&self) -> Range<usize> {
1988
0
        let start = 0;
1989
0
        let end = start + Offset16::RAW_BYTE_LEN;
1990
0
        start..end
1991
0
    }
1992
1993
0
    pub fn variant_count_byte_range(&self) -> Range<usize> {
1994
0
        let start = self.glyph_assembly_offset_byte_range().end;
1995
0
        let end = start + u16::RAW_BYTE_LEN;
1996
0
        start..end
1997
0
    }
1998
1999
0
    pub fn math_glyph_variant_records_byte_range(&self) -> Range<usize> {
2000
0
        let variant_count = self.variant_count();
2001
0
        let start = self.variant_count_byte_range().end;
2002
0
        let end = start
2003
0
            + (transforms::to_usize(variant_count))
2004
0
                .saturating_mul(MathGlyphVariantRecord::RAW_BYTE_LEN);
2005
0
        start..end
2006
0
    }
2007
}
2008
2009
const _: () = assert!(FontData::default_data_long_enough(
2010
    MathGlyphConstruction::MIN_SIZE
2011
));
2012
2013
impl Default for MathGlyphConstruction<'_> {
2014
0
    fn default() -> Self {
2015
        Self {
2016
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
2017
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2018
        }
2019
0
    }
2020
}
2021
2022
/// [MathGlyphVariantRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathglyphvariantrecord)
2023
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
2024
#[repr(C)]
2025
#[repr(packed)]
2026
pub struct MathGlyphVariantRecord {
2027
    /// Glyph ID for the variant.
2028
    pub variant_glyph: BigEndian<GlyphId16>,
2029
    /// Advance width/height, in design units, of the variant, in the direction
2030
    /// of requested glyph extension.
2031
    pub advance_measurement: BigEndian<UfWord>,
2032
}
2033
2034
impl MathGlyphVariantRecord {
2035
    /// Glyph ID for the variant.
2036
0
    pub fn variant_glyph(&self) -> GlyphId16 {
2037
0
        self.variant_glyph.get()
2038
0
    }
2039
2040
    /// Advance width/height, in design units, of the variant, in the direction
2041
    /// of requested glyph extension.
2042
0
    pub fn advance_measurement(&self) -> UfWord {
2043
0
        self.advance_measurement.get()
2044
0
    }
2045
}
2046
2047
impl FixedSize for MathGlyphVariantRecord {
2048
    const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + UfWord::RAW_BYTE_LEN;
2049
}
2050
2051
impl<'a> MinByteRange<'a> for GlyphAssembly<'a> {
2052
0
    fn min_byte_range(&self) -> Range<usize> {
2053
0
        0..self.part_records_byte_range().end
2054
0
    }
2055
0
    fn min_table_bytes(&self) -> &'a [u8] {
2056
0
        let range = self.min_byte_range();
2057
0
        self.offset_data().as_bytes().get(range).unwrap_or_default()
2058
0
    }
2059
}
2060
2061
impl ReadArgs for GlyphAssembly<'_> {
2062
    type Args = ();
2063
}
2064
2065
impl<'a> FontRead<'a> for GlyphAssembly<'a> {
2066
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2067
        #[allow(clippy::absurd_extreme_comparisons)]
2068
0
        if data.len() < Self::MIN_SIZE {
2069
0
            return Err(ReadError::OutOfBounds);
2070
0
        }
2071
0
        let Some(data) = TableDataRef::new(data.as_bytes()) else {
2072
0
            return Err(ReadError::OutOfBounds);
2073
        };
2074
0
        Ok(Self { data })
2075
0
    }
2076
}
2077
2078
/// The fields at the start of the table, which are read directly.
2079
#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2080
#[repr(C, packed)]
2081
#[doc(hidden)]
2082
pub struct GlyphAssemblyFixedHeader {
2083
    pub italics_correction: MathValueRecord,
2084
    pub part_count: BigEndian<u16>,
2085
}
2086
2087
#[allow(clippy::absurd_extreme_comparisons)]
2088
const _: () = assert!(std::mem::size_of::<GlyphAssemblyFixedHeader>() <= GlyphAssembly::MIN_SIZE);
2089
2090
/// [GlyphAssembly](https://learn.microsoft.com/en-us/typography/opentype/spec/math#glyphassembly-table)
2091
#[derive(Clone)]
2092
pub struct GlyphAssembly<'a> {
2093
    data: TableDataRef<'a, GlyphAssemblyFixedHeader>,
2094
}
2095
2096
#[allow(clippy::needless_lifetimes)]
2097
impl<'a> GlyphAssembly<'a> {
2098
    pub const MIN_SIZE: usize = (MathValueRecord::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2099
    basic_table_impls!(impl_the_methods);
2100
2101
    /// Italics correction of this GlyphAssembly. Should not depend on the
2102
    /// assembly size.
2103
0
    pub fn italics_correction(&self) -> &'a MathValueRecord {
2104
0
        &self.data.header().italics_correction
2105
0
    }
2106
2107
    /// Number of parts in this assembly.
2108
0
    pub fn part_count(&self) -> u16 {
2109
0
        self.data.header().part_count.get()
2110
0
    }
2111
2112
    /// Array of part records, from left to right (for assemblies that extend
2113
    /// horizontally) or bottom to top (for assemblies that extend vertically).
2114
0
    pub fn part_records(&self) -> &'a [GlyphPartRecord] {
2115
0
        let range = self.part_records_byte_range();
2116
0
        self.offset_data()
2117
0
            .read_array(range)
2118
0
            .ok()
2119
0
            .unwrap_or_default()
2120
0
    }
2121
2122
0
    pub fn italics_correction_byte_range(&self) -> Range<usize> {
2123
0
        let start = 0;
2124
0
        let end = start + MathValueRecord::RAW_BYTE_LEN;
2125
0
        start..end
2126
0
    }
2127
2128
0
    pub fn part_count_byte_range(&self) -> Range<usize> {
2129
0
        let start = self.italics_correction_byte_range().end;
2130
0
        let end = start + u16::RAW_BYTE_LEN;
2131
0
        start..end
2132
0
    }
2133
2134
0
    pub fn part_records_byte_range(&self) -> Range<usize> {
2135
0
        let part_count = self.part_count();
2136
0
        let start = self.part_count_byte_range().end;
2137
0
        let end = start
2138
0
            + (transforms::to_usize(part_count)).saturating_mul(GlyphPartRecord::RAW_BYTE_LEN);
2139
0
        start..end
2140
0
    }
2141
}
2142
2143
const _: () = assert!(FontData::default_data_long_enough(GlyphAssembly::MIN_SIZE));
2144
2145
impl Default for GlyphAssembly<'_> {
2146
0
    fn default() -> Self {
2147
        Self {
2148
0
            data: TableDataRef::new(FontData::default_table_data().as_bytes())
2149
0
                .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2150
        }
2151
0
    }
2152
}
2153
2154
/// [GlyphPartRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/math#glyphpartrecord)
2155
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
2156
#[repr(C)]
2157
#[repr(packed)]
2158
pub struct GlyphPartRecord {
2159
    /// Glyph ID for the part.
2160
    pub glyph_id: BigEndian<GlyphId16>,
2161
    /// Advance width/ height, in design units, of the straight bar connector
2162
    /// material at the start of the glyph in the direction of the extension.
2163
    pub start_connector_length: BigEndian<UfWord>,
2164
    /// Advance width/ height, in design units, of the straight bar connector
2165
    /// material at the end of the glyph in the direction of the extension.
2166
    pub end_connector_length: BigEndian<UfWord>,
2167
    /// Full advance width/height for this part in the direction of the
2168
    /// extension, in design units.
2169
    pub full_advance: BigEndian<UfWord>,
2170
    /// Part qualifiers.
2171
    pub part_flags: BigEndian<PartFlags>,
2172
}
2173
2174
impl GlyphPartRecord {
2175
    /// Glyph ID for the part.
2176
0
    pub fn glyph_id(&self) -> GlyphId16 {
2177
0
        self.glyph_id.get()
2178
0
    }
2179
2180
    /// Advance width/ height, in design units, of the straight bar connector
2181
    /// material at the start of the glyph in the direction of the extension.
2182
0
    pub fn start_connector_length(&self) -> UfWord {
2183
0
        self.start_connector_length.get()
2184
0
    }
2185
2186
    /// Advance width/ height, in design units, of the straight bar connector
2187
    /// material at the end of the glyph in the direction of the extension.
2188
0
    pub fn end_connector_length(&self) -> UfWord {
2189
0
        self.end_connector_length.get()
2190
0
    }
2191
2192
    /// Full advance width/height for this part in the direction of the
2193
    /// extension, in design units.
2194
0
    pub fn full_advance(&self) -> UfWord {
2195
0
        self.full_advance.get()
2196
0
    }
2197
2198
    /// Part qualifiers.
2199
0
    pub fn part_flags(&self) -> PartFlags {
2200
0
        self.part_flags.get()
2201
0
    }
2202
}
2203
2204
impl FixedSize for GlyphPartRecord {
2205
    const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN
2206
        + UfWord::RAW_BYTE_LEN
2207
        + UfWord::RAW_BYTE_LEN
2208
        + UfWord::RAW_BYTE_LEN
2209
        + PartFlags::RAW_BYTE_LEN;
2210
}
2211
2212
/// Qualifiers for a [`GlyphPartRecord`].
2213
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
2214
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2215
#[repr(transparent)]
2216
pub struct PartFlags {
2217
    bits: u16,
2218
}
2219
2220
impl PartFlags {
2221
    /// If set, the part can be skipped or repeated.
2222
    pub const EXTENDER_FLAG: Self = Self { bits: 0x0001 };
2223
}
2224
2225
impl PartFlags {
2226
    ///  Returns an empty set of flags.
2227
    #[inline]
2228
0
    pub const fn empty() -> Self {
2229
0
        Self { bits: 0 }
2230
0
    }
2231
2232
    /// Returns the set containing all flags.
2233
    #[inline]
2234
0
    pub const fn all() -> Self {
2235
0
        Self {
2236
0
            bits: Self::EXTENDER_FLAG.bits,
2237
0
        }
2238
0
    }
2239
2240
    /// Returns the raw value of the flags currently stored.
2241
    #[inline]
2242
0
    pub const fn bits(&self) -> u16 {
2243
0
        self.bits
2244
0
    }
2245
2246
    /// Convert from underlying bit representation, unless that
2247
    /// representation contains bits that do not correspond to a flag.
2248
    #[inline]
2249
0
    pub const fn from_bits(bits: u16) -> Option<Self> {
2250
0
        if (bits & !Self::all().bits()) == 0 {
2251
0
            Some(Self { bits })
2252
        } else {
2253
0
            None
2254
        }
2255
0
    }
2256
2257
    /// Convert from underlying bit representation, dropping any bits
2258
    /// that do not correspond to flags.
2259
    #[inline]
2260
0
    pub const fn from_bits_truncate(bits: u16) -> Self {
2261
0
        Self {
2262
0
            bits: bits & Self::all().bits,
2263
0
        }
2264
0
    }
2265
2266
    /// Returns `true` if no flags are currently stored.
2267
    #[inline]
2268
0
    pub const fn is_empty(&self) -> bool {
2269
0
        self.bits() == Self::empty().bits()
2270
0
    }
2271
2272
    /// Returns `true` if there are flags common to both `self` and `other`.
2273
    #[inline]
2274
0
    pub const fn intersects(&self, other: Self) -> bool {
2275
0
        !(Self {
2276
0
            bits: self.bits & other.bits,
2277
0
        })
2278
0
        .is_empty()
2279
0
    }
2280
2281
    /// Returns `true` if all of the flags in `other` are contained within `self`.
2282
    #[inline]
2283
0
    pub const fn contains(&self, other: Self) -> bool {
2284
0
        (self.bits & other.bits) == other.bits
2285
0
    }
2286
2287
    /// Inserts the specified flags in-place.
2288
    #[inline]
2289
0
    pub fn insert(&mut self, other: Self) {
2290
0
        self.bits |= other.bits;
2291
0
    }
2292
2293
    /// Removes the specified flags in-place.
2294
    #[inline]
2295
0
    pub fn remove(&mut self, other: Self) {
2296
0
        self.bits &= !other.bits;
2297
0
    }
2298
2299
    /// Toggles the specified flags in-place.
2300
    #[inline]
2301
0
    pub fn toggle(&mut self, other: Self) {
2302
0
        self.bits ^= other.bits;
2303
0
    }
2304
2305
    /// Returns the intersection between the flags in `self` and
2306
    /// `other`.
2307
    ///
2308
    /// Specifically, the returned set contains only the flags which are
2309
    /// present in *both* `self` *and* `other`.
2310
    ///
2311
    /// This is equivalent to using the `&` operator (e.g.
2312
    /// [`ops::BitAnd`]), as in `flags & other`.
2313
    ///
2314
    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
2315
    #[inline]
2316
    #[must_use]
2317
0
    pub const fn intersection(self, other: Self) -> Self {
2318
0
        Self {
2319
0
            bits: self.bits & other.bits,
2320
0
        }
2321
0
    }
2322
2323
    /// Returns the union of between the flags in `self` and `other`.
2324
    ///
2325
    /// Specifically, the returned set contains all flags which are
2326
    /// present in *either* `self` *or* `other`, including any which are
2327
    /// present in both.
2328
    ///
2329
    /// This is equivalent to using the `|` operator (e.g.
2330
    /// [`ops::BitOr`]), as in `flags | other`.
2331
    ///
2332
    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
2333
    #[inline]
2334
    #[must_use]
2335
0
    pub const fn union(self, other: Self) -> Self {
2336
0
        Self {
2337
0
            bits: self.bits | other.bits,
2338
0
        }
2339
0
    }
2340
2341
    /// Returns the difference between the flags in `self` and `other`.
2342
    ///
2343
    /// Specifically, the returned set contains all flags present in
2344
    /// `self`, except for the ones present in `other`.
2345
    ///
2346
    /// It is also conceptually equivalent to the "bit-clear" operation:
2347
    /// `flags & !other` (and this syntax is also supported).
2348
    ///
2349
    /// This is equivalent to using the `-` operator (e.g.
2350
    /// [`ops::Sub`]), as in `flags - other`.
2351
    ///
2352
    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
2353
    #[inline]
2354
    #[must_use]
2355
0
    pub const fn difference(self, other: Self) -> Self {
2356
0
        Self {
2357
0
            bits: self.bits & !other.bits,
2358
0
        }
2359
0
    }
2360
}
2361
2362
impl std::ops::BitOr for PartFlags {
2363
    type Output = Self;
2364
2365
    /// Returns the union of the two sets of flags.
2366
    #[inline]
2367
0
    fn bitor(self, other: PartFlags) -> Self {
2368
0
        Self {
2369
0
            bits: self.bits | other.bits,
2370
0
        }
2371
0
    }
2372
}
2373
2374
impl std::ops::BitOrAssign for PartFlags {
2375
    /// Adds the set of flags.
2376
    #[inline]
2377
0
    fn bitor_assign(&mut self, other: Self) {
2378
0
        self.bits |= other.bits;
2379
0
    }
2380
}
2381
2382
impl std::ops::BitXor for PartFlags {
2383
    type Output = Self;
2384
2385
    /// Returns the left flags, but with all the right flags toggled.
2386
    #[inline]
2387
0
    fn bitxor(self, other: Self) -> Self {
2388
0
        Self {
2389
0
            bits: self.bits ^ other.bits,
2390
0
        }
2391
0
    }
2392
}
2393
2394
impl std::ops::BitXorAssign for PartFlags {
2395
    /// Toggles the set of flags.
2396
    #[inline]
2397
0
    fn bitxor_assign(&mut self, other: Self) {
2398
0
        self.bits ^= other.bits;
2399
0
    }
2400
}
2401
2402
impl std::ops::BitAnd for PartFlags {
2403
    type Output = Self;
2404
2405
    /// Returns the intersection between the two sets of flags.
2406
    #[inline]
2407
0
    fn bitand(self, other: Self) -> Self {
2408
0
        Self {
2409
0
            bits: self.bits & other.bits,
2410
0
        }
2411
0
    }
2412
}
2413
2414
impl std::ops::BitAndAssign for PartFlags {
2415
    /// Disables all flags disabled in the set.
2416
    #[inline]
2417
0
    fn bitand_assign(&mut self, other: Self) {
2418
0
        self.bits &= other.bits;
2419
0
    }
2420
}
2421
2422
impl std::ops::Sub for PartFlags {
2423
    type Output = Self;
2424
2425
    /// Returns the set difference of the two sets of flags.
2426
    #[inline]
2427
0
    fn sub(self, other: Self) -> Self {
2428
0
        Self {
2429
0
            bits: self.bits & !other.bits,
2430
0
        }
2431
0
    }
2432
}
2433
2434
impl std::ops::SubAssign for PartFlags {
2435
    /// Disables all flags enabled in the set.
2436
    #[inline]
2437
0
    fn sub_assign(&mut self, other: Self) {
2438
0
        self.bits &= !other.bits;
2439
0
    }
2440
}
2441
2442
impl std::ops::Not for PartFlags {
2443
    type Output = Self;
2444
2445
    /// Returns the complement of this set of flags.
2446
    #[inline]
2447
0
    fn not(self) -> Self {
2448
0
        Self { bits: !self.bits } & Self::all()
2449
0
    }
2450
}
2451
2452
impl std::fmt::Debug for PartFlags {
2453
0
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2454
0
        let members: &[(&str, Self)] = &[("EXTENDER_FLAG", Self::EXTENDER_FLAG)];
2455
0
        let mut first = true;
2456
0
        for (name, value) in members {
2457
0
            if self.contains(*value) {
2458
0
                if !first {
2459
0
                    f.write_str(" | ")?;
2460
0
                }
2461
0
                first = false;
2462
0
                f.write_str(name)?;
2463
0
            }
2464
        }
2465
0
        if first {
2466
0
            f.write_str("(empty)")?;
2467
0
        }
2468
0
        Ok(())
2469
0
    }
2470
}
2471
2472
impl std::fmt::Binary for PartFlags {
2473
0
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2474
0
        std::fmt::Binary::fmt(&self.bits, f)
2475
0
    }
2476
}
2477
2478
impl std::fmt::Octal for PartFlags {
2479
0
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2480
0
        std::fmt::Octal::fmt(&self.bits, f)
2481
0
    }
2482
}
2483
2484
impl std::fmt::LowerHex for PartFlags {
2485
0
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2486
0
        std::fmt::LowerHex::fmt(&self.bits, f)
2487
0
    }
2488
}
2489
2490
impl std::fmt::UpperHex for PartFlags {
2491
0
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2492
0
        std::fmt::UpperHex::fmt(&self.bits, f)
2493
0
    }
2494
}
2495
2496
impl font_types::Scalar for PartFlags {
2497
    type Raw = <u16 as font_types::Scalar>::Raw;
2498
0
    fn to_raw(self) -> Self::Raw {
2499
0
        self.bits().to_raw()
2500
0
    }
2501
0
    fn from_raw(raw: Self::Raw) -> Self {
2502
0
        let t = <u16>::from_raw(raw);
2503
0
        Self::from_bits_truncate(t)
2504
0
    }
2505
}