Skip to main content

read_fonts/generated/
generated_math.rs

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