Skip to main content

write_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
8pub use read_fonts::tables::math::PartFlags;
9
10/// The [MATH](https://learn.microsoft.com/en-us/typography/opentype/spec/math) table
11#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Math {
14    /// Offset to MathConstants table, from beginning of MATH table.
15    pub math_constants: OffsetMarker<MathConstants>,
16    /// Offset to MathGlyphInfo table, from beginning of MATH table.
17    pub math_glyph_info: OffsetMarker<MathGlyphInfo>,
18    /// Offset to MathVariants table, from beginning of MATH table.
19    pub math_variants: OffsetMarker<MathVariants>,
20}
21
22impl Math {
23    /// Construct a new `Math`
24    pub fn new(
25        math_constants: MathConstants,
26        math_glyph_info: MathGlyphInfo,
27        math_variants: MathVariants,
28    ) -> Self {
29        Self {
30            math_constants: math_constants.into(),
31            math_glyph_info: math_glyph_info.into(),
32            math_variants: math_variants.into(),
33        }
34    }
35}
36
37impl FontWrite for Math {
38    #[allow(clippy::unnecessary_cast)]
39    fn write_into(&self, writer: &mut TableWriter) {
40        let version = MajorMinor::VERSION_1_0 as MajorMinor;
41        version.write_into(writer);
42        self.math_constants.write_into(writer);
43        self.math_glyph_info.write_into(writer);
44        self.math_variants.write_into(writer);
45    }
46    fn table_type(&self) -> TableType {
47        TableType::TopLevel(Math::TAG)
48    }
49}
50
51impl Validate for Math {
52    fn validate_impl(&self, ctx: &mut ValidationCtx) {
53        ctx.in_table("Math", |ctx| {
54            ctx.in_field("math_constants", |ctx| {
55                self.math_constants.validate_impl(ctx);
56            });
57            ctx.in_field("math_glyph_info", |ctx| {
58                self.math_glyph_info.validate_impl(ctx);
59            });
60            ctx.in_field("math_variants", |ctx| {
61                self.math_variants.validate_impl(ctx);
62            });
63        })
64    }
65}
66
67impl TopLevelTable for Math {
68    const TAG: Tag = Tag::new(b"MATH");
69}
70
71impl<'a> FromObjRef<read_fonts::tables::math::Math<'a>> for Math {
72    fn from_obj_ref(obj: &read_fonts::tables::math::Math<'a>, _: FontData) -> Self {
73        Math {
74            math_constants: obj.math_constants().to_owned_table(),
75            math_glyph_info: obj.math_glyph_info().to_owned_table(),
76            math_variants: obj.math_variants().to_owned_table(),
77        }
78    }
79}
80
81#[allow(clippy::needless_lifetimes)]
82impl<'a> FromTableRef<read_fonts::tables::math::Math<'a>> for Math {}
83
84impl ReadArgs for Math {
85    type Args = ();
86}
87
88impl<'a> FontRead<'a> for Math {
89    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
90        <read_fonts::tables::math::Math as FontRead>::read(data).map(|x| x.to_owned_table())
91    }
92}
93
94/// [MathValueRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathvaluerecord)
95///
96/// The device offset is measured from the beginning of the table that contains
97/// the record, not from the record itself.
98#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
99#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
100pub struct MathValueRecord {
101    /// The X or Y value in design units.
102    pub value: FWord,
103    /// Offset to the Device table (non-variable font) / VariationIndex table
104    /// (variable font) for this value, from the beginning of the parent table.
105    /// May be NULL.
106    pub device: NullableOffsetMarker<DeviceOrVariationIndex>,
107}
108
109impl MathValueRecord {
110    /// Construct a new `MathValueRecord`
111    pub fn new(value: FWord, device: Option<DeviceOrVariationIndex>) -> Self {
112        Self {
113            value,
114            device: device.into(),
115        }
116    }
117}
118
119impl FontWrite for MathValueRecord {
120    fn write_into(&self, writer: &mut TableWriter) {
121        self.value.write_into(writer);
122        self.device.write_into(writer);
123    }
124    fn table_type(&self) -> TableType {
125        TableType::Named("MathValueRecord")
126    }
127}
128
129impl Validate for MathValueRecord {
130    fn validate_impl(&self, ctx: &mut ValidationCtx) {
131        ctx.in_table("MathValueRecord", |ctx| {
132            ctx.in_field("device", |ctx| {
133                self.device.validate_impl(ctx);
134            });
135        })
136    }
137}
138
139impl FromObjRef<read_fonts::tables::math::MathValueRecord> for MathValueRecord {
140    fn from_obj_ref(
141        obj: &read_fonts::tables::math::MathValueRecord,
142        offset_data: FontData,
143    ) -> Self {
144        MathValueRecord {
145            value: obj.value(),
146            device: obj.device(offset_data).to_owned_table(),
147        }
148    }
149}
150
151/// [MathConstants](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathconstants-table)
152#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
153#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
154pub struct MathConstants {
155    /// Percentage of scaling down for level 1 superscripts and subscripts.
156    pub script_percent_scale_down: i16,
157    /// Percentage of scaling down for level 2 (scriptScript) superscripts and
158    /// subscripts.
159    pub script_script_percent_scale_down: i16,
160    /// Minimum height required for a delimited expression (contained within
161    /// parentheses, etc.) to be treated as a sub-formula.
162    pub delimited_sub_formula_min_height: UfWord,
163    /// Minimum height of n-ary operators (such as integral and summation) for
164    /// formulas in display mode (that is, appearing as standalone page
165    /// elements, not embedded inline within text).
166    pub display_operator_min_height: UfWord,
167    /// White space to be left between math formulas to ensure proper line
168    /// spacing.
169    pub math_leading: MathValueRecord,
170    /// Axis height of the font.
171    pub axis_height: MathValueRecord,
172    /// Maximum (ink) height of accent base that does not require raising the
173    /// accents.
174    pub accent_base_height: MathValueRecord,
175    /// Maximum (ink) height of accent base that does not require flattening the
176    /// accents.
177    pub flattened_accent_base_height: MathValueRecord,
178    /// The standard shift down applied to subscript elements.
179    pub subscript_shift_down: MathValueRecord,
180    /// Maximum allowed height of the (ink) top of subscripts that does not
181    /// require moving subscripts further down.
182    pub subscript_top_max: MathValueRecord,
183    /// Minimum allowed drop of the baseline of subscripts relative to the (ink)
184    /// bottom of the base.
185    pub subscript_baseline_drop_min: MathValueRecord,
186    /// Standard shift up applied to superscript elements.
187    pub superscript_shift_up: MathValueRecord,
188    /// Standard shift of superscripts relative to the base, in cramped style.
189    pub superscript_shift_up_cramped: MathValueRecord,
190    /// Minimum allowed height of the (ink) bottom of superscripts that does not
191    /// require moving subscripts further up.
192    pub superscript_bottom_min: MathValueRecord,
193    /// Maximum allowed drop of the baseline of superscripts relative to the
194    /// (ink) top of the base.
195    pub superscript_baseline_drop_max: MathValueRecord,
196    /// Minimum gap between the superscript and subscript ink.
197    pub sub_superscript_gap_min: MathValueRecord,
198    /// The maximum level to which the (ink) bottom of superscript can be
199    /// pushed to increase the gap between superscript and subscript, before
200    /// subscript starts being moved down.
201    pub superscript_bottom_max_with_subscript: MathValueRecord,
202    /// Extra white space to be added after each subscript and superscript.
203    pub space_after_script: MathValueRecord,
204    /// Minimum gap between the (ink) bottom of the upper limit, and the (ink)
205    /// top of the base operator.
206    pub upper_limit_gap_min: MathValueRecord,
207    /// Minimum distance between baseline of upper limit and (ink) top of the
208    /// base operator.
209    pub upper_limit_baseline_rise_min: MathValueRecord,
210    /// Minimum gap between (ink) top of the lower limit, and (ink) bottom of
211    /// the base operator.
212    pub lower_limit_gap_min: MathValueRecord,
213    /// Minimum distance between baseline of the lower limit and (ink) bottom of
214    /// the base operator.
215    pub lower_limit_baseline_drop_min: MathValueRecord,
216    /// Standard shift up applied to the top element of a stack.
217    pub stack_top_shift_up: MathValueRecord,
218    /// Standard shift up applied to the top element of a stack in display
219    /// style.
220    pub stack_top_display_style_shift_up: MathValueRecord,
221    /// Standard shift down applied to the bottom element of a stack.
222    pub stack_bottom_shift_down: MathValueRecord,
223    /// Standard shift down applied to the bottom element of a stack in display
224    /// style.
225    pub stack_bottom_display_style_shift_down: MathValueRecord,
226    /// Minimum gap between (ink) bottom of the top element of a stack, and the
227    /// (ink) top of the bottom element.
228    pub stack_gap_min: MathValueRecord,
229    /// Minimum gap between (ink) bottom of the top element of a stack, and the
230    /// (ink) top of the bottom element in display style.
231    pub stack_display_style_gap_min: MathValueRecord,
232    /// Standard shift up applied to the top element of the stretch stack.
233    pub stretch_stack_top_shift_up: MathValueRecord,
234    /// Standard shift down applied to the bottom element of the stretch stack.
235    pub stretch_stack_bottom_shift_down: MathValueRecord,
236    /// Minimum gap between the ink of the stretched element, and the (ink)
237    /// bottom of the element above.
238    pub stretch_stack_gap_above_min: MathValueRecord,
239    /// Minimum gap between the ink of the stretched element, and the (ink) top
240    /// of the element below.
241    pub stretch_stack_gap_below_min: MathValueRecord,
242    /// Standard shift up applied to the numerator.
243    pub fraction_numerator_shift_up: MathValueRecord,
244    /// Standard shift up applied to the numerator in display style.
245    pub fraction_numerator_display_style_shift_up: MathValueRecord,
246    /// Standard shift down applied to the denominator.
247    pub fraction_denominator_shift_down: MathValueRecord,
248    /// Standard shift down applied to the denominator in display style.
249    pub fraction_denominator_display_style_shift_down: MathValueRecord,
250    /// Minimum tolerated gap between the (ink) bottom of the numerator and the
251    /// ink of the fraction bar.
252    pub fraction_numerator_gap_min: MathValueRecord,
253    /// Minimum tolerated gap between the (ink) bottom of the numerator and the
254    /// ink of the fraction bar in display style.
255    pub fraction_num_display_style_gap_min: MathValueRecord,
256    /// Thickness of the fraction bar.
257    pub fraction_rule_thickness: MathValueRecord,
258    /// Minimum tolerated gap between the ink of the fraction bar and the (ink)
259    /// top of the denominator.
260    pub fraction_denominator_gap_min: MathValueRecord,
261    /// Minimum tolerated gap between the ink of the fraction bar and the (ink)
262    /// top of the denominator in display style.
263    pub fraction_denom_display_style_gap_min: MathValueRecord,
264    /// Horizontal distance between the top and bottom elements of a skewed
265    /// fraction.
266    pub skewed_fraction_horizontal_gap: MathValueRecord,
267    /// Vertical distance between the ink of the top and bottom elements of a
268    /// skewed fraction.
269    pub skewed_fraction_vertical_gap: MathValueRecord,
270    /// Distance between the overbar and the (ink) top of he base.
271    pub overbar_vertical_gap: MathValueRecord,
272    /// Thickness of overbar.
273    pub overbar_rule_thickness: MathValueRecord,
274    /// Extra white space reserved above the overbar.
275    pub overbar_extra_ascender: MathValueRecord,
276    /// Distance between underbar and (ink) bottom of the base.
277    pub underbar_vertical_gap: MathValueRecord,
278    /// Thickness of underbar.
279    pub underbar_rule_thickness: MathValueRecord,
280    /// Extra white space reserved below the underbar.
281    pub underbar_extra_descender: MathValueRecord,
282    /// Space between the (ink) top of the expression and the bar over it.
283    pub radical_vertical_gap: MathValueRecord,
284    /// Space between the (ink) top of the expression and the bar over it in
285    /// display style.
286    pub radical_display_style_vertical_gap: MathValueRecord,
287    /// Thickness of the radical rule.
288    pub radical_rule_thickness: MathValueRecord,
289    /// Extra white space reserved above the radical.
290    pub radical_extra_ascender: MathValueRecord,
291    /// Extra horizontal kern before the degree of a radical, if such is
292    /// present.
293    pub radical_kern_before_degree: MathValueRecord,
294    /// Negative kern after the degree of a radical, if such is present.
295    pub radical_kern_after_degree: MathValueRecord,
296    /// Height of the bottom of the radical degree, if such is present, in
297    /// proportion to the ascender of the radical sign.
298    pub radical_degree_bottom_raise_percent: i16,
299}
300
301impl MathConstants {
302    /// Construct a new `MathConstants`
303    #[allow(clippy::too_many_arguments)]
304    pub fn new(
305        script_percent_scale_down: i16,
306        script_script_percent_scale_down: i16,
307        delimited_sub_formula_min_height: UfWord,
308        display_operator_min_height: UfWord,
309        math_leading: MathValueRecord,
310        axis_height: MathValueRecord,
311        accent_base_height: MathValueRecord,
312        flattened_accent_base_height: MathValueRecord,
313        subscript_shift_down: MathValueRecord,
314        subscript_top_max: MathValueRecord,
315        subscript_baseline_drop_min: MathValueRecord,
316        superscript_shift_up: MathValueRecord,
317        superscript_shift_up_cramped: MathValueRecord,
318        superscript_bottom_min: MathValueRecord,
319        superscript_baseline_drop_max: MathValueRecord,
320        sub_superscript_gap_min: MathValueRecord,
321        superscript_bottom_max_with_subscript: MathValueRecord,
322        space_after_script: MathValueRecord,
323        upper_limit_gap_min: MathValueRecord,
324        upper_limit_baseline_rise_min: MathValueRecord,
325        lower_limit_gap_min: MathValueRecord,
326        lower_limit_baseline_drop_min: MathValueRecord,
327        stack_top_shift_up: MathValueRecord,
328        stack_top_display_style_shift_up: MathValueRecord,
329        stack_bottom_shift_down: MathValueRecord,
330        stack_bottom_display_style_shift_down: MathValueRecord,
331        stack_gap_min: MathValueRecord,
332        stack_display_style_gap_min: MathValueRecord,
333        stretch_stack_top_shift_up: MathValueRecord,
334        stretch_stack_bottom_shift_down: MathValueRecord,
335        stretch_stack_gap_above_min: MathValueRecord,
336        stretch_stack_gap_below_min: MathValueRecord,
337        fraction_numerator_shift_up: MathValueRecord,
338        fraction_numerator_display_style_shift_up: MathValueRecord,
339        fraction_denominator_shift_down: MathValueRecord,
340        fraction_denominator_display_style_shift_down: MathValueRecord,
341        fraction_numerator_gap_min: MathValueRecord,
342        fraction_num_display_style_gap_min: MathValueRecord,
343        fraction_rule_thickness: MathValueRecord,
344        fraction_denominator_gap_min: MathValueRecord,
345        fraction_denom_display_style_gap_min: MathValueRecord,
346        skewed_fraction_horizontal_gap: MathValueRecord,
347        skewed_fraction_vertical_gap: MathValueRecord,
348        overbar_vertical_gap: MathValueRecord,
349        overbar_rule_thickness: MathValueRecord,
350        overbar_extra_ascender: MathValueRecord,
351        underbar_vertical_gap: MathValueRecord,
352        underbar_rule_thickness: MathValueRecord,
353        underbar_extra_descender: MathValueRecord,
354        radical_vertical_gap: MathValueRecord,
355        radical_display_style_vertical_gap: MathValueRecord,
356        radical_rule_thickness: MathValueRecord,
357        radical_extra_ascender: MathValueRecord,
358        radical_kern_before_degree: MathValueRecord,
359        radical_kern_after_degree: MathValueRecord,
360        radical_degree_bottom_raise_percent: i16,
361    ) -> Self {
362        Self {
363            script_percent_scale_down,
364            script_script_percent_scale_down,
365            delimited_sub_formula_min_height,
366            display_operator_min_height,
367            math_leading,
368            axis_height,
369            accent_base_height,
370            flattened_accent_base_height,
371            subscript_shift_down,
372            subscript_top_max,
373            subscript_baseline_drop_min,
374            superscript_shift_up,
375            superscript_shift_up_cramped,
376            superscript_bottom_min,
377            superscript_baseline_drop_max,
378            sub_superscript_gap_min,
379            superscript_bottom_max_with_subscript,
380            space_after_script,
381            upper_limit_gap_min,
382            upper_limit_baseline_rise_min,
383            lower_limit_gap_min,
384            lower_limit_baseline_drop_min,
385            stack_top_shift_up,
386            stack_top_display_style_shift_up,
387            stack_bottom_shift_down,
388            stack_bottom_display_style_shift_down,
389            stack_gap_min,
390            stack_display_style_gap_min,
391            stretch_stack_top_shift_up,
392            stretch_stack_bottom_shift_down,
393            stretch_stack_gap_above_min,
394            stretch_stack_gap_below_min,
395            fraction_numerator_shift_up,
396            fraction_numerator_display_style_shift_up,
397            fraction_denominator_shift_down,
398            fraction_denominator_display_style_shift_down,
399            fraction_numerator_gap_min,
400            fraction_num_display_style_gap_min,
401            fraction_rule_thickness,
402            fraction_denominator_gap_min,
403            fraction_denom_display_style_gap_min,
404            skewed_fraction_horizontal_gap,
405            skewed_fraction_vertical_gap,
406            overbar_vertical_gap,
407            overbar_rule_thickness,
408            overbar_extra_ascender,
409            underbar_vertical_gap,
410            underbar_rule_thickness,
411            underbar_extra_descender,
412            radical_vertical_gap,
413            radical_display_style_vertical_gap,
414            radical_rule_thickness,
415            radical_extra_ascender,
416            radical_kern_before_degree,
417            radical_kern_after_degree,
418            radical_degree_bottom_raise_percent,
419        }
420    }
421}
422
423impl FontWrite for MathConstants {
424    fn write_into(&self, writer: &mut TableWriter) {
425        self.script_percent_scale_down.write_into(writer);
426        self.script_script_percent_scale_down.write_into(writer);
427        self.delimited_sub_formula_min_height.write_into(writer);
428        self.display_operator_min_height.write_into(writer);
429        self.math_leading.write_into(writer);
430        self.axis_height.write_into(writer);
431        self.accent_base_height.write_into(writer);
432        self.flattened_accent_base_height.write_into(writer);
433        self.subscript_shift_down.write_into(writer);
434        self.subscript_top_max.write_into(writer);
435        self.subscript_baseline_drop_min.write_into(writer);
436        self.superscript_shift_up.write_into(writer);
437        self.superscript_shift_up_cramped.write_into(writer);
438        self.superscript_bottom_min.write_into(writer);
439        self.superscript_baseline_drop_max.write_into(writer);
440        self.sub_superscript_gap_min.write_into(writer);
441        self.superscript_bottom_max_with_subscript
442            .write_into(writer);
443        self.space_after_script.write_into(writer);
444        self.upper_limit_gap_min.write_into(writer);
445        self.upper_limit_baseline_rise_min.write_into(writer);
446        self.lower_limit_gap_min.write_into(writer);
447        self.lower_limit_baseline_drop_min.write_into(writer);
448        self.stack_top_shift_up.write_into(writer);
449        self.stack_top_display_style_shift_up.write_into(writer);
450        self.stack_bottom_shift_down.write_into(writer);
451        self.stack_bottom_display_style_shift_down
452            .write_into(writer);
453        self.stack_gap_min.write_into(writer);
454        self.stack_display_style_gap_min.write_into(writer);
455        self.stretch_stack_top_shift_up.write_into(writer);
456        self.stretch_stack_bottom_shift_down.write_into(writer);
457        self.stretch_stack_gap_above_min.write_into(writer);
458        self.stretch_stack_gap_below_min.write_into(writer);
459        self.fraction_numerator_shift_up.write_into(writer);
460        self.fraction_numerator_display_style_shift_up
461            .write_into(writer);
462        self.fraction_denominator_shift_down.write_into(writer);
463        self.fraction_denominator_display_style_shift_down
464            .write_into(writer);
465        self.fraction_numerator_gap_min.write_into(writer);
466        self.fraction_num_display_style_gap_min.write_into(writer);
467        self.fraction_rule_thickness.write_into(writer);
468        self.fraction_denominator_gap_min.write_into(writer);
469        self.fraction_denom_display_style_gap_min.write_into(writer);
470        self.skewed_fraction_horizontal_gap.write_into(writer);
471        self.skewed_fraction_vertical_gap.write_into(writer);
472        self.overbar_vertical_gap.write_into(writer);
473        self.overbar_rule_thickness.write_into(writer);
474        self.overbar_extra_ascender.write_into(writer);
475        self.underbar_vertical_gap.write_into(writer);
476        self.underbar_rule_thickness.write_into(writer);
477        self.underbar_extra_descender.write_into(writer);
478        self.radical_vertical_gap.write_into(writer);
479        self.radical_display_style_vertical_gap.write_into(writer);
480        self.radical_rule_thickness.write_into(writer);
481        self.radical_extra_ascender.write_into(writer);
482        self.radical_kern_before_degree.write_into(writer);
483        self.radical_kern_after_degree.write_into(writer);
484        self.radical_degree_bottom_raise_percent.write_into(writer);
485    }
486    fn table_type(&self) -> TableType {
487        TableType::Named("MathConstants")
488    }
489}
490
491impl Validate for MathConstants {
492    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
493}
494
495impl<'a> FromObjRef<read_fonts::tables::math::MathConstants<'a>> for MathConstants {
496    fn from_obj_ref(obj: &read_fonts::tables::math::MathConstants<'a>, _: FontData) -> Self {
497        let offset_data = obj.offset_data();
498        MathConstants {
499            script_percent_scale_down: obj.script_percent_scale_down(),
500            script_script_percent_scale_down: obj.script_script_percent_scale_down(),
501            delimited_sub_formula_min_height: obj.delimited_sub_formula_min_height(),
502            display_operator_min_height: obj.display_operator_min_height(),
503            math_leading: obj.math_leading().to_owned_obj(offset_data),
504            axis_height: obj.axis_height().to_owned_obj(offset_data),
505            accent_base_height: obj.accent_base_height().to_owned_obj(offset_data),
506            flattened_accent_base_height: obj
507                .flattened_accent_base_height()
508                .to_owned_obj(offset_data),
509            subscript_shift_down: obj.subscript_shift_down().to_owned_obj(offset_data),
510            subscript_top_max: obj.subscript_top_max().to_owned_obj(offset_data),
511            subscript_baseline_drop_min: obj
512                .subscript_baseline_drop_min()
513                .to_owned_obj(offset_data),
514            superscript_shift_up: obj.superscript_shift_up().to_owned_obj(offset_data),
515            superscript_shift_up_cramped: obj
516                .superscript_shift_up_cramped()
517                .to_owned_obj(offset_data),
518            superscript_bottom_min: obj.superscript_bottom_min().to_owned_obj(offset_data),
519            superscript_baseline_drop_max: obj
520                .superscript_baseline_drop_max()
521                .to_owned_obj(offset_data),
522            sub_superscript_gap_min: obj.sub_superscript_gap_min().to_owned_obj(offset_data),
523            superscript_bottom_max_with_subscript: obj
524                .superscript_bottom_max_with_subscript()
525                .to_owned_obj(offset_data),
526            space_after_script: obj.space_after_script().to_owned_obj(offset_data),
527            upper_limit_gap_min: obj.upper_limit_gap_min().to_owned_obj(offset_data),
528            upper_limit_baseline_rise_min: obj
529                .upper_limit_baseline_rise_min()
530                .to_owned_obj(offset_data),
531            lower_limit_gap_min: obj.lower_limit_gap_min().to_owned_obj(offset_data),
532            lower_limit_baseline_drop_min: obj
533                .lower_limit_baseline_drop_min()
534                .to_owned_obj(offset_data),
535            stack_top_shift_up: obj.stack_top_shift_up().to_owned_obj(offset_data),
536            stack_top_display_style_shift_up: obj
537                .stack_top_display_style_shift_up()
538                .to_owned_obj(offset_data),
539            stack_bottom_shift_down: obj.stack_bottom_shift_down().to_owned_obj(offset_data),
540            stack_bottom_display_style_shift_down: obj
541                .stack_bottom_display_style_shift_down()
542                .to_owned_obj(offset_data),
543            stack_gap_min: obj.stack_gap_min().to_owned_obj(offset_data),
544            stack_display_style_gap_min: obj
545                .stack_display_style_gap_min()
546                .to_owned_obj(offset_data),
547            stretch_stack_top_shift_up: obj.stretch_stack_top_shift_up().to_owned_obj(offset_data),
548            stretch_stack_bottom_shift_down: obj
549                .stretch_stack_bottom_shift_down()
550                .to_owned_obj(offset_data),
551            stretch_stack_gap_above_min: obj
552                .stretch_stack_gap_above_min()
553                .to_owned_obj(offset_data),
554            stretch_stack_gap_below_min: obj
555                .stretch_stack_gap_below_min()
556                .to_owned_obj(offset_data),
557            fraction_numerator_shift_up: obj
558                .fraction_numerator_shift_up()
559                .to_owned_obj(offset_data),
560            fraction_numerator_display_style_shift_up: obj
561                .fraction_numerator_display_style_shift_up()
562                .to_owned_obj(offset_data),
563            fraction_denominator_shift_down: obj
564                .fraction_denominator_shift_down()
565                .to_owned_obj(offset_data),
566            fraction_denominator_display_style_shift_down: obj
567                .fraction_denominator_display_style_shift_down()
568                .to_owned_obj(offset_data),
569            fraction_numerator_gap_min: obj.fraction_numerator_gap_min().to_owned_obj(offset_data),
570            fraction_num_display_style_gap_min: obj
571                .fraction_num_display_style_gap_min()
572                .to_owned_obj(offset_data),
573            fraction_rule_thickness: obj.fraction_rule_thickness().to_owned_obj(offset_data),
574            fraction_denominator_gap_min: obj
575                .fraction_denominator_gap_min()
576                .to_owned_obj(offset_data),
577            fraction_denom_display_style_gap_min: obj
578                .fraction_denom_display_style_gap_min()
579                .to_owned_obj(offset_data),
580            skewed_fraction_horizontal_gap: obj
581                .skewed_fraction_horizontal_gap()
582                .to_owned_obj(offset_data),
583            skewed_fraction_vertical_gap: obj
584                .skewed_fraction_vertical_gap()
585                .to_owned_obj(offset_data),
586            overbar_vertical_gap: obj.overbar_vertical_gap().to_owned_obj(offset_data),
587            overbar_rule_thickness: obj.overbar_rule_thickness().to_owned_obj(offset_data),
588            overbar_extra_ascender: obj.overbar_extra_ascender().to_owned_obj(offset_data),
589            underbar_vertical_gap: obj.underbar_vertical_gap().to_owned_obj(offset_data),
590            underbar_rule_thickness: obj.underbar_rule_thickness().to_owned_obj(offset_data),
591            underbar_extra_descender: obj.underbar_extra_descender().to_owned_obj(offset_data),
592            radical_vertical_gap: obj.radical_vertical_gap().to_owned_obj(offset_data),
593            radical_display_style_vertical_gap: obj
594                .radical_display_style_vertical_gap()
595                .to_owned_obj(offset_data),
596            radical_rule_thickness: obj.radical_rule_thickness().to_owned_obj(offset_data),
597            radical_extra_ascender: obj.radical_extra_ascender().to_owned_obj(offset_data),
598            radical_kern_before_degree: obj.radical_kern_before_degree().to_owned_obj(offset_data),
599            radical_kern_after_degree: obj.radical_kern_after_degree().to_owned_obj(offset_data),
600            radical_degree_bottom_raise_percent: obj.radical_degree_bottom_raise_percent(),
601        }
602    }
603}
604
605#[allow(clippy::needless_lifetimes)]
606impl<'a> FromTableRef<read_fonts::tables::math::MathConstants<'a>> for MathConstants {}
607
608impl ReadArgs for MathConstants {
609    type Args = ();
610}
611
612impl<'a> FontRead<'a> for MathConstants {
613    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
614        <read_fonts::tables::math::MathConstants as FontRead>::read(data)
615            .map(|x| x.to_owned_table())
616    }
617}
618
619/// [MathGlyphInfo](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathglyphinfo-table)
620#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
621#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
622pub struct MathGlyphInfo {
623    /// Offset to MathItalicsCorrectionInfo table, from the beginning of the
624    /// MathGlyphInfo table. May be NULL.
625    pub math_italics_correction_info: NullableOffsetMarker<MathItalicsCorrectionInfo>,
626    /// Offset to MathTopAccentAttachment table, from the beginning of the
627    /// MathGlyphInfo table. May be NULL.
628    pub math_top_accent_attachment: NullableOffsetMarker<MathTopAccentAttachment>,
629    /// Offset to the Coverage table for glyphs with extended shapes, from the
630    /// beginning of the MathGlyphInfo table. May be NULL.
631    pub extended_shape_coverage: NullableOffsetMarker<CoverageTable>,
632    /// Offset to the MathKernInfo table, from the beginning of the
633    /// MathGlyphInfo table. May be NULL.
634    pub math_kern_info: NullableOffsetMarker<MathKernInfo>,
635}
636
637impl MathGlyphInfo {
638    /// Construct a new `MathGlyphInfo`
639    pub fn new(
640        math_italics_correction_info: Option<MathItalicsCorrectionInfo>,
641        math_top_accent_attachment: Option<MathTopAccentAttachment>,
642        extended_shape_coverage: Option<CoverageTable>,
643        math_kern_info: Option<MathKernInfo>,
644    ) -> Self {
645        Self {
646            math_italics_correction_info: math_italics_correction_info.into(),
647            math_top_accent_attachment: math_top_accent_attachment.into(),
648            extended_shape_coverage: extended_shape_coverage.into(),
649            math_kern_info: math_kern_info.into(),
650        }
651    }
652}
653
654impl FontWrite for MathGlyphInfo {
655    fn write_into(&self, writer: &mut TableWriter) {
656        self.math_italics_correction_info.write_into(writer);
657        self.math_top_accent_attachment.write_into(writer);
658        self.extended_shape_coverage.write_into(writer);
659        self.math_kern_info.write_into(writer);
660    }
661    fn table_type(&self) -> TableType {
662        TableType::Named("MathGlyphInfo")
663    }
664}
665
666impl Validate for MathGlyphInfo {
667    fn validate_impl(&self, ctx: &mut ValidationCtx) {
668        ctx.in_table("MathGlyphInfo", |ctx| {
669            ctx.in_field("math_italics_correction_info", |ctx| {
670                self.math_italics_correction_info.validate_impl(ctx);
671            });
672            ctx.in_field("math_top_accent_attachment", |ctx| {
673                self.math_top_accent_attachment.validate_impl(ctx);
674            });
675            ctx.in_field("extended_shape_coverage", |ctx| {
676                self.extended_shape_coverage.validate_impl(ctx);
677            });
678            ctx.in_field("math_kern_info", |ctx| {
679                self.math_kern_info.validate_impl(ctx);
680            });
681        })
682    }
683}
684
685impl<'a> FromObjRef<read_fonts::tables::math::MathGlyphInfo<'a>> for MathGlyphInfo {
686    fn from_obj_ref(obj: &read_fonts::tables::math::MathGlyphInfo<'a>, _: FontData) -> Self {
687        MathGlyphInfo {
688            math_italics_correction_info: obj.math_italics_correction_info().to_owned_table(),
689            math_top_accent_attachment: obj.math_top_accent_attachment().to_owned_table(),
690            extended_shape_coverage: obj.extended_shape_coverage().to_owned_table(),
691            math_kern_info: obj.math_kern_info().to_owned_table(),
692        }
693    }
694}
695
696#[allow(clippy::needless_lifetimes)]
697impl<'a> FromTableRef<read_fonts::tables::math::MathGlyphInfo<'a>> for MathGlyphInfo {}
698
699impl ReadArgs for MathGlyphInfo {
700    type Args = ();
701}
702
703impl<'a> FontRead<'a> for MathGlyphInfo {
704    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
705        <read_fonts::tables::math::MathGlyphInfo as FontRead>::read(data)
706            .map(|x| x.to_owned_table())
707    }
708}
709
710/// [MathItalicsCorrectionInfo](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathitalicscorrectioninfo-table)
711#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
712#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
713pub struct MathItalicsCorrectionInfo {
714    /// Offset to the Coverage table, from the beginning of the
715    /// MathItalicsCorrectionInfo table.
716    pub coverage: OffsetMarker<CoverageTable>,
717    /// Array of MathValueRecords defining italics correction values for each
718    /// covered glyph.
719    pub italics_correction: Vec<MathValueRecord>,
720}
721
722impl MathItalicsCorrectionInfo {
723    /// Construct a new `MathItalicsCorrectionInfo`
724    pub fn new(coverage: CoverageTable, italics_correction: Vec<MathValueRecord>) -> Self {
725        Self {
726            coverage: coverage.into(),
727            italics_correction,
728        }
729    }
730}
731
732impl FontWrite for MathItalicsCorrectionInfo {
733    #[allow(clippy::unnecessary_cast)]
734    fn write_into(&self, writer: &mut TableWriter) {
735        self.coverage.write_into(writer);
736        (u16::try_from(array_len(&self.italics_correction)).unwrap()).write_into(writer);
737        self.italics_correction.write_into(writer);
738    }
739    fn table_type(&self) -> TableType {
740        TableType::Named("MathItalicsCorrectionInfo")
741    }
742}
743
744impl Validate for MathItalicsCorrectionInfo {
745    fn validate_impl(&self, ctx: &mut ValidationCtx) {
746        ctx.in_table("MathItalicsCorrectionInfo", |ctx| {
747            ctx.in_field("coverage", |ctx| {
748                self.coverage.validate_impl(ctx);
749            });
750            ctx.in_field("italics_correction", |ctx| {
751                if self.italics_correction.len() > to_usize(u16::MAX) {
752                    ctx.report("array exceeds max length");
753                }
754                self.italics_correction.validate_impl(ctx);
755            });
756        })
757    }
758}
759
760impl<'a> FromObjRef<read_fonts::tables::math::MathItalicsCorrectionInfo<'a>>
761    for MathItalicsCorrectionInfo
762{
763    fn from_obj_ref(
764        obj: &read_fonts::tables::math::MathItalicsCorrectionInfo<'a>,
765        _: FontData,
766    ) -> Self {
767        let offset_data = obj.offset_data();
768        MathItalicsCorrectionInfo {
769            coverage: obj.coverage().to_owned_table(),
770            italics_correction: obj.italics_correction().to_owned_obj(offset_data),
771        }
772    }
773}
774
775#[allow(clippy::needless_lifetimes)]
776impl<'a> FromTableRef<read_fonts::tables::math::MathItalicsCorrectionInfo<'a>>
777    for MathItalicsCorrectionInfo
778{
779}
780
781impl ReadArgs for MathItalicsCorrectionInfo {
782    type Args = ();
783}
784
785impl<'a> FontRead<'a> for MathItalicsCorrectionInfo {
786    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
787        <read_fonts::tables::math::MathItalicsCorrectionInfo as FontRead>::read(data)
788            .map(|x| x.to_owned_table())
789    }
790}
791
792/// [MathTopAccentAttachment](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathtopaccentattachment-table)
793#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
794#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
795pub struct MathTopAccentAttachment {
796    /// Offset to the Coverage table, from the beginning of the
797    /// MathTopAccentAttachment table.
798    pub top_accent_coverage: OffsetMarker<CoverageTable>,
799    /// Array of MathValueRecords defining top accent attachment points for each
800    /// covered glyph.
801    pub top_accent_attachment: Vec<MathValueRecord>,
802}
803
804impl MathTopAccentAttachment {
805    /// Construct a new `MathTopAccentAttachment`
806    pub fn new(
807        top_accent_coverage: CoverageTable,
808        top_accent_attachment: Vec<MathValueRecord>,
809    ) -> Self {
810        Self {
811            top_accent_coverage: top_accent_coverage.into(),
812            top_accent_attachment,
813        }
814    }
815}
816
817impl FontWrite for MathTopAccentAttachment {
818    #[allow(clippy::unnecessary_cast)]
819    fn write_into(&self, writer: &mut TableWriter) {
820        self.top_accent_coverage.write_into(writer);
821        (u16::try_from(array_len(&self.top_accent_attachment)).unwrap()).write_into(writer);
822        self.top_accent_attachment.write_into(writer);
823    }
824    fn table_type(&self) -> TableType {
825        TableType::Named("MathTopAccentAttachment")
826    }
827}
828
829impl Validate for MathTopAccentAttachment {
830    fn validate_impl(&self, ctx: &mut ValidationCtx) {
831        ctx.in_table("MathTopAccentAttachment", |ctx| {
832            ctx.in_field("top_accent_coverage", |ctx| {
833                self.top_accent_coverage.validate_impl(ctx);
834            });
835            ctx.in_field("top_accent_attachment", |ctx| {
836                if self.top_accent_attachment.len() > to_usize(u16::MAX) {
837                    ctx.report("array exceeds max length");
838                }
839                self.top_accent_attachment.validate_impl(ctx);
840            });
841        })
842    }
843}
844
845impl<'a> FromObjRef<read_fonts::tables::math::MathTopAccentAttachment<'a>>
846    for MathTopAccentAttachment
847{
848    fn from_obj_ref(
849        obj: &read_fonts::tables::math::MathTopAccentAttachment<'a>,
850        _: FontData,
851    ) -> Self {
852        let offset_data = obj.offset_data();
853        MathTopAccentAttachment {
854            top_accent_coverage: obj.top_accent_coverage().to_owned_table(),
855            top_accent_attachment: obj.top_accent_attachment().to_owned_obj(offset_data),
856        }
857    }
858}
859
860#[allow(clippy::needless_lifetimes)]
861impl<'a> FromTableRef<read_fonts::tables::math::MathTopAccentAttachment<'a>>
862    for MathTopAccentAttachment
863{
864}
865
866impl ReadArgs for MathTopAccentAttachment {
867    type Args = ();
868}
869
870impl<'a> FontRead<'a> for MathTopAccentAttachment {
871    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
872        <read_fonts::tables::math::MathTopAccentAttachment as FontRead>::read(data)
873            .map(|x| x.to_owned_table())
874    }
875}
876
877/// [MathKernInfo](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathkerninfo-table)
878#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
879#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
880pub struct MathKernInfo {
881    /// Offset to the Coverage table, from the beginning of the MathKernInfo
882    /// table.
883    pub math_kern_coverage: OffsetMarker<CoverageTable>,
884    /// Array of MathKernInfoRecords, one for each covered glyph.
885    pub math_kern_info_records: Vec<MathKernInfoRecord>,
886}
887
888impl MathKernInfo {
889    /// Construct a new `MathKernInfo`
890    pub fn new(
891        math_kern_coverage: CoverageTable,
892        math_kern_info_records: Vec<MathKernInfoRecord>,
893    ) -> Self {
894        Self {
895            math_kern_coverage: math_kern_coverage.into(),
896            math_kern_info_records,
897        }
898    }
899}
900
901impl FontWrite for MathKernInfo {
902    #[allow(clippy::unnecessary_cast)]
903    fn write_into(&self, writer: &mut TableWriter) {
904        self.math_kern_coverage.write_into(writer);
905        (u16::try_from(array_len(&self.math_kern_info_records)).unwrap()).write_into(writer);
906        self.math_kern_info_records.write_into(writer);
907    }
908    fn table_type(&self) -> TableType {
909        TableType::Named("MathKernInfo")
910    }
911}
912
913impl Validate for MathKernInfo {
914    fn validate_impl(&self, ctx: &mut ValidationCtx) {
915        ctx.in_table("MathKernInfo", |ctx| {
916            ctx.in_field("math_kern_coverage", |ctx| {
917                self.math_kern_coverage.validate_impl(ctx);
918            });
919            ctx.in_field("math_kern_info_records", |ctx| {
920                if self.math_kern_info_records.len() > to_usize(u16::MAX) {
921                    ctx.report("array exceeds max length");
922                }
923                self.math_kern_info_records.validate_impl(ctx);
924            });
925        })
926    }
927}
928
929impl<'a> FromObjRef<read_fonts::tables::math::MathKernInfo<'a>> for MathKernInfo {
930    fn from_obj_ref(obj: &read_fonts::tables::math::MathKernInfo<'a>, _: FontData) -> Self {
931        let offset_data = obj.offset_data();
932        MathKernInfo {
933            math_kern_coverage: obj.math_kern_coverage().to_owned_table(),
934            math_kern_info_records: obj.math_kern_info_records().to_owned_obj(offset_data),
935        }
936    }
937}
938
939#[allow(clippy::needless_lifetimes)]
940impl<'a> FromTableRef<read_fonts::tables::math::MathKernInfo<'a>> for MathKernInfo {}
941
942impl ReadArgs for MathKernInfo {
943    type Args = ();
944}
945
946impl<'a> FontRead<'a> for MathKernInfo {
947    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
948        <read_fonts::tables::math::MathKernInfo as FontRead>::read(data).map(|x| x.to_owned_table())
949    }
950}
951
952/// [MathKernInfoRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathkerninforecord)
953///
954/// The offsets are measured from the beginning of the MathKernInfo table.
955#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
956#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
957pub struct MathKernInfoRecord {
958    /// Offset to the MathKern table for the top right corner, from the
959    /// beginning of the MathKernInfo table. May be NULL.
960    pub top_right_math_kern: NullableOffsetMarker<MathKern>,
961    /// Offset to the MathKern table for the top left corner, from the beginning
962    /// of the MathKernInfo table. May be NULL.
963    pub top_left_math_kern: NullableOffsetMarker<MathKern>,
964    /// Offset to the MathKern table for the bottom right corner, from the
965    /// beginning of the MathKernInfo table. May be NULL.
966    pub bottom_right_math_kern: NullableOffsetMarker<MathKern>,
967    /// Offset to the MathKern table for the bottom left corner, from the
968    /// beginning of the MathKernInfo table. May be NULL.
969    pub bottom_left_math_kern: NullableOffsetMarker<MathKern>,
970}
971
972impl MathKernInfoRecord {
973    /// Construct a new `MathKernInfoRecord`
974    pub fn new(
975        top_right_math_kern: Option<MathKern>,
976        top_left_math_kern: Option<MathKern>,
977        bottom_right_math_kern: Option<MathKern>,
978        bottom_left_math_kern: Option<MathKern>,
979    ) -> Self {
980        Self {
981            top_right_math_kern: top_right_math_kern.into(),
982            top_left_math_kern: top_left_math_kern.into(),
983            bottom_right_math_kern: bottom_right_math_kern.into(),
984            bottom_left_math_kern: bottom_left_math_kern.into(),
985        }
986    }
987}
988
989impl FontWrite for MathKernInfoRecord {
990    fn write_into(&self, writer: &mut TableWriter) {
991        self.top_right_math_kern.write_into(writer);
992        self.top_left_math_kern.write_into(writer);
993        self.bottom_right_math_kern.write_into(writer);
994        self.bottom_left_math_kern.write_into(writer);
995    }
996    fn table_type(&self) -> TableType {
997        TableType::Named("MathKernInfoRecord")
998    }
999}
1000
1001impl Validate for MathKernInfoRecord {
1002    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1003        ctx.in_table("MathKernInfoRecord", |ctx| {
1004            ctx.in_field("top_right_math_kern", |ctx| {
1005                self.top_right_math_kern.validate_impl(ctx);
1006            });
1007            ctx.in_field("top_left_math_kern", |ctx| {
1008                self.top_left_math_kern.validate_impl(ctx);
1009            });
1010            ctx.in_field("bottom_right_math_kern", |ctx| {
1011                self.bottom_right_math_kern.validate_impl(ctx);
1012            });
1013            ctx.in_field("bottom_left_math_kern", |ctx| {
1014                self.bottom_left_math_kern.validate_impl(ctx);
1015            });
1016        })
1017    }
1018}
1019
1020impl FromObjRef<read_fonts::tables::math::MathKernInfoRecord> for MathKernInfoRecord {
1021    fn from_obj_ref(
1022        obj: &read_fonts::tables::math::MathKernInfoRecord,
1023        offset_data: FontData,
1024    ) -> Self {
1025        MathKernInfoRecord {
1026            top_right_math_kern: obj.top_right_math_kern(offset_data).to_owned_table(),
1027            top_left_math_kern: obj.top_left_math_kern(offset_data).to_owned_table(),
1028            bottom_right_math_kern: obj.bottom_right_math_kern(offset_data).to_owned_table(),
1029            bottom_left_math_kern: obj.bottom_left_math_kern(offset_data).to_owned_table(),
1030        }
1031    }
1032}
1033
1034/// [MathKern](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathkern-table)
1035#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1036#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1037pub struct MathKern {
1038    /// Array of correction heights, in design units, sorted from lowest to
1039    /// highest.
1040    pub correction_height: Vec<MathValueRecord>,
1041    /// Array of kerning values for different height ranges, in design units.
1042    ///
1043    /// There is one more of these than there are correction heights: the first
1044    /// applies below the first correction height, and the last above the last.
1045    pub kern_values: Vec<MathValueRecord>,
1046}
1047
1048impl MathKern {
1049    /// Construct a new `MathKern`
1050    pub fn new(correction_height: Vec<MathValueRecord>, kern_values: Vec<MathValueRecord>) -> Self {
1051        Self {
1052            correction_height,
1053            kern_values,
1054        }
1055    }
1056}
1057
1058impl FontWrite for MathKern {
1059    #[allow(clippy::unnecessary_cast)]
1060    fn write_into(&self, writer: &mut TableWriter) {
1061        (u16::try_from(array_len(&self.correction_height)).unwrap()).write_into(writer);
1062        self.correction_height.write_into(writer);
1063        self.kern_values.write_into(writer);
1064    }
1065    fn table_type(&self) -> TableType {
1066        TableType::Named("MathKern")
1067    }
1068}
1069
1070impl Validate for MathKern {
1071    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1072        ctx.in_table("MathKern", |ctx| {
1073            ctx.in_field("correction_height", |ctx| {
1074                if self.correction_height.len() > to_usize(u16::MAX) {
1075                    ctx.report("array exceeds max length");
1076                }
1077                self.correction_height.validate_impl(ctx);
1078            });
1079            ctx.in_field("kern_values", |ctx| {
1080                self.kern_values.validate_impl(ctx);
1081            });
1082        })
1083    }
1084}
1085
1086impl<'a> FromObjRef<read_fonts::tables::math::MathKern<'a>> for MathKern {
1087    fn from_obj_ref(obj: &read_fonts::tables::math::MathKern<'a>, _: FontData) -> Self {
1088        let offset_data = obj.offset_data();
1089        MathKern {
1090            correction_height: obj.correction_height().to_owned_obj(offset_data),
1091            kern_values: obj.kern_values().to_owned_obj(offset_data),
1092        }
1093    }
1094}
1095
1096#[allow(clippy::needless_lifetimes)]
1097impl<'a> FromTableRef<read_fonts::tables::math::MathKern<'a>> for MathKern {}
1098
1099impl ReadArgs for MathKern {
1100    type Args = ();
1101}
1102
1103impl<'a> FontRead<'a> for MathKern {
1104    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1105        <read_fonts::tables::math::MathKern as FontRead>::read(data).map(|x| x.to_owned_table())
1106    }
1107}
1108
1109/// [MathVariants](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathvariants-table)
1110#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1111#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1112pub struct MathVariants {
1113    /// Minimum overlap of connecting glyphs during glyph construction, in
1114    /// design units.
1115    pub min_connector_overlap: UfWord,
1116    /// Offset to the Coverage table for shapes growing in the vertical
1117    /// direction, from the beginning of the MathVariants table. May be NULL.
1118    pub vert_glyph_coverage: NullableOffsetMarker<CoverageTable>,
1119    /// Offset to the Coverage table for shapes growing in the horizontal
1120    /// direction, from the beginning of the MathVariants table. May be NULL.
1121    pub horiz_glyph_coverage: NullableOffsetMarker<CoverageTable>,
1122    /// Array of offsets to MathGlyphConstruction tables, from the beginning of
1123    /// the MathVariants table, for shapes growing in the vertical direction.
1124    pub vert_glyph_constructions: Vec<OffsetMarker<MathGlyphConstruction>>,
1125    /// Array of offsets to MathGlyphConstruction tables, from the beginning of
1126    /// the MathVariants table, for shapes growing in the horizontal direction.
1127    pub horiz_glyph_constructions: Vec<OffsetMarker<MathGlyphConstruction>>,
1128}
1129
1130impl MathVariants {
1131    /// Construct a new `MathVariants`
1132    pub fn new(
1133        min_connector_overlap: UfWord,
1134        vert_glyph_coverage: Option<CoverageTable>,
1135        horiz_glyph_coverage: Option<CoverageTable>,
1136        vert_glyph_constructions: Vec<MathGlyphConstruction>,
1137        horiz_glyph_constructions: Vec<MathGlyphConstruction>,
1138    ) -> Self {
1139        Self {
1140            min_connector_overlap,
1141            vert_glyph_coverage: vert_glyph_coverage.into(),
1142            horiz_glyph_coverage: horiz_glyph_coverage.into(),
1143            vert_glyph_constructions: vert_glyph_constructions
1144                .into_iter()
1145                .map(Into::into)
1146                .collect(),
1147            horiz_glyph_constructions: horiz_glyph_constructions
1148                .into_iter()
1149                .map(Into::into)
1150                .collect(),
1151        }
1152    }
1153}
1154
1155impl FontWrite for MathVariants {
1156    #[allow(clippy::unnecessary_cast)]
1157    fn write_into(&self, writer: &mut TableWriter) {
1158        self.min_connector_overlap.write_into(writer);
1159        self.vert_glyph_coverage.write_into(writer);
1160        self.horiz_glyph_coverage.write_into(writer);
1161        (u16::try_from(array_len(&self.vert_glyph_constructions)).unwrap()).write_into(writer);
1162        (u16::try_from(array_len(&self.horiz_glyph_constructions)).unwrap()).write_into(writer);
1163        self.vert_glyph_constructions.write_into(writer);
1164        self.horiz_glyph_constructions.write_into(writer);
1165    }
1166    fn table_type(&self) -> TableType {
1167        TableType::Named("MathVariants")
1168    }
1169}
1170
1171impl Validate for MathVariants {
1172    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1173        ctx.in_table("MathVariants", |ctx| {
1174            ctx.in_field("vert_glyph_coverage", |ctx| {
1175                self.vert_glyph_coverage.validate_impl(ctx);
1176            });
1177            ctx.in_field("horiz_glyph_coverage", |ctx| {
1178                self.horiz_glyph_coverage.validate_impl(ctx);
1179            });
1180            ctx.in_field("vert_glyph_constructions", |ctx| {
1181                if self.vert_glyph_constructions.len() > to_usize(u16::MAX) {
1182                    ctx.report("array exceeds max length");
1183                }
1184                self.vert_glyph_constructions.validate_impl(ctx);
1185            });
1186            ctx.in_field("horiz_glyph_constructions", |ctx| {
1187                if self.horiz_glyph_constructions.len() > to_usize(u16::MAX) {
1188                    ctx.report("array exceeds max length");
1189                }
1190                self.horiz_glyph_constructions.validate_impl(ctx);
1191            });
1192        })
1193    }
1194}
1195
1196impl<'a> FromObjRef<read_fonts::tables::math::MathVariants<'a>> for MathVariants {
1197    fn from_obj_ref(obj: &read_fonts::tables::math::MathVariants<'a>, _: FontData) -> Self {
1198        MathVariants {
1199            min_connector_overlap: obj.min_connector_overlap(),
1200            vert_glyph_coverage: obj.vert_glyph_coverage().to_owned_table(),
1201            horiz_glyph_coverage: obj.horiz_glyph_coverage().to_owned_table(),
1202            vert_glyph_constructions: obj.vert_glyph_constructions().to_owned_table(),
1203            horiz_glyph_constructions: obj.horiz_glyph_constructions().to_owned_table(),
1204        }
1205    }
1206}
1207
1208#[allow(clippy::needless_lifetimes)]
1209impl<'a> FromTableRef<read_fonts::tables::math::MathVariants<'a>> for MathVariants {}
1210
1211impl ReadArgs for MathVariants {
1212    type Args = ();
1213}
1214
1215impl<'a> FontRead<'a> for MathVariants {
1216    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1217        <read_fonts::tables::math::MathVariants as FontRead>::read(data).map(|x| x.to_owned_table())
1218    }
1219}
1220
1221/// [MathGlyphConstruction](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathglyphconstruction-table)
1222#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1223#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1224pub struct MathGlyphConstruction {
1225    /// Offset to the GlyphAssembly table for this shape, from the beginning of
1226    /// the MathGlyphConstruction table. May be NULL.
1227    pub glyph_assembly: NullableOffsetMarker<GlyphAssembly>,
1228    /// MathGlyphVariantRecords for alternative variants of the base glyph.
1229    pub math_glyph_variant_records: Vec<MathGlyphVariantRecord>,
1230}
1231
1232impl MathGlyphConstruction {
1233    /// Construct a new `MathGlyphConstruction`
1234    pub fn new(
1235        glyph_assembly: Option<GlyphAssembly>,
1236        math_glyph_variant_records: Vec<MathGlyphVariantRecord>,
1237    ) -> Self {
1238        Self {
1239            glyph_assembly: glyph_assembly.into(),
1240            math_glyph_variant_records,
1241        }
1242    }
1243}
1244
1245impl FontWrite for MathGlyphConstruction {
1246    #[allow(clippy::unnecessary_cast)]
1247    fn write_into(&self, writer: &mut TableWriter) {
1248        self.glyph_assembly.write_into(writer);
1249        (u16::try_from(array_len(&self.math_glyph_variant_records)).unwrap()).write_into(writer);
1250        self.math_glyph_variant_records.write_into(writer);
1251    }
1252    fn table_type(&self) -> TableType {
1253        TableType::Named("MathGlyphConstruction")
1254    }
1255}
1256
1257impl Validate for MathGlyphConstruction {
1258    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1259        ctx.in_table("MathGlyphConstruction", |ctx| {
1260            ctx.in_field("glyph_assembly", |ctx| {
1261                self.glyph_assembly.validate_impl(ctx);
1262            });
1263            ctx.in_field("math_glyph_variant_records", |ctx| {
1264                if self.math_glyph_variant_records.len() > to_usize(u16::MAX) {
1265                    ctx.report("array exceeds max length");
1266                }
1267                self.math_glyph_variant_records.validate_impl(ctx);
1268            });
1269        })
1270    }
1271}
1272
1273impl<'a> FromObjRef<read_fonts::tables::math::MathGlyphConstruction<'a>> for MathGlyphConstruction {
1274    fn from_obj_ref(
1275        obj: &read_fonts::tables::math::MathGlyphConstruction<'a>,
1276        _: FontData,
1277    ) -> Self {
1278        let offset_data = obj.offset_data();
1279        MathGlyphConstruction {
1280            glyph_assembly: obj.glyph_assembly().to_owned_table(),
1281            math_glyph_variant_records: obj.math_glyph_variant_records().to_owned_obj(offset_data),
1282        }
1283    }
1284}
1285
1286#[allow(clippy::needless_lifetimes)]
1287impl<'a> FromTableRef<read_fonts::tables::math::MathGlyphConstruction<'a>>
1288    for MathGlyphConstruction
1289{
1290}
1291
1292impl ReadArgs for MathGlyphConstruction {
1293    type Args = ();
1294}
1295
1296impl<'a> FontRead<'a> for MathGlyphConstruction {
1297    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1298        <read_fonts::tables::math::MathGlyphConstruction as FontRead>::read(data)
1299            .map(|x| x.to_owned_table())
1300    }
1301}
1302
1303/// [MathGlyphVariantRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/math#mathglyphvariantrecord)
1304#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1305#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1306pub struct MathGlyphVariantRecord {
1307    /// Glyph ID for the variant.
1308    pub variant_glyph: GlyphId16,
1309    /// Advance width/height, in design units, of the variant, in the direction
1310    /// of requested glyph extension.
1311    pub advance_measurement: UfWord,
1312}
1313
1314impl MathGlyphVariantRecord {
1315    /// Construct a new `MathGlyphVariantRecord`
1316    pub fn new(variant_glyph: GlyphId16, advance_measurement: UfWord) -> Self {
1317        Self {
1318            variant_glyph,
1319            advance_measurement,
1320        }
1321    }
1322}
1323
1324impl FontWrite for MathGlyphVariantRecord {
1325    fn write_into(&self, writer: &mut TableWriter) {
1326        self.variant_glyph.write_into(writer);
1327        self.advance_measurement.write_into(writer);
1328    }
1329    fn table_type(&self) -> TableType {
1330        TableType::Named("MathGlyphVariantRecord")
1331    }
1332}
1333
1334impl Validate for MathGlyphVariantRecord {
1335    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1336}
1337
1338impl FromObjRef<read_fonts::tables::math::MathGlyphVariantRecord> for MathGlyphVariantRecord {
1339    fn from_obj_ref(obj: &read_fonts::tables::math::MathGlyphVariantRecord, _: FontData) -> Self {
1340        MathGlyphVariantRecord {
1341            variant_glyph: obj.variant_glyph(),
1342            advance_measurement: obj.advance_measurement(),
1343        }
1344    }
1345}
1346
1347/// [GlyphAssembly](https://learn.microsoft.com/en-us/typography/opentype/spec/math#glyphassembly-table)
1348#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1349#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1350pub struct GlyphAssembly {
1351    /// Italics correction of this GlyphAssembly. Should not depend on the
1352    /// assembly size.
1353    pub italics_correction: MathValueRecord,
1354    /// Array of part records, from left to right (for assemblies that extend
1355    /// horizontally) or bottom to top (for assemblies that extend vertically).
1356    pub part_records: Vec<GlyphPartRecord>,
1357}
1358
1359impl GlyphAssembly {
1360    /// Construct a new `GlyphAssembly`
1361    pub fn new(italics_correction: MathValueRecord, part_records: Vec<GlyphPartRecord>) -> Self {
1362        Self {
1363            italics_correction,
1364            part_records,
1365        }
1366    }
1367}
1368
1369impl FontWrite for GlyphAssembly {
1370    #[allow(clippy::unnecessary_cast)]
1371    fn write_into(&self, writer: &mut TableWriter) {
1372        self.italics_correction.write_into(writer);
1373        (u16::try_from(array_len(&self.part_records)).unwrap()).write_into(writer);
1374        self.part_records.write_into(writer);
1375    }
1376    fn table_type(&self) -> TableType {
1377        TableType::Named("GlyphAssembly")
1378    }
1379}
1380
1381impl Validate for GlyphAssembly {
1382    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1383        ctx.in_table("GlyphAssembly", |ctx| {
1384            ctx.in_field("part_records", |ctx| {
1385                if self.part_records.len() > to_usize(u16::MAX) {
1386                    ctx.report("array exceeds max length");
1387                }
1388                self.part_records.validate_impl(ctx);
1389            });
1390        })
1391    }
1392}
1393
1394impl<'a> FromObjRef<read_fonts::tables::math::GlyphAssembly<'a>> for GlyphAssembly {
1395    fn from_obj_ref(obj: &read_fonts::tables::math::GlyphAssembly<'a>, _: FontData) -> Self {
1396        let offset_data = obj.offset_data();
1397        GlyphAssembly {
1398            italics_correction: obj.italics_correction().to_owned_obj(offset_data),
1399            part_records: obj.part_records().to_owned_obj(offset_data),
1400        }
1401    }
1402}
1403
1404#[allow(clippy::needless_lifetimes)]
1405impl<'a> FromTableRef<read_fonts::tables::math::GlyphAssembly<'a>> for GlyphAssembly {}
1406
1407impl ReadArgs for GlyphAssembly {
1408    type Args = ();
1409}
1410
1411impl<'a> FontRead<'a> for GlyphAssembly {
1412    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1413        <read_fonts::tables::math::GlyphAssembly as FontRead>::read(data)
1414            .map(|x| x.to_owned_table())
1415    }
1416}
1417
1418/// [GlyphPartRecord](https://learn.microsoft.com/en-us/typography/opentype/spec/math#glyphpartrecord)
1419#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1420#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1421pub struct GlyphPartRecord {
1422    /// Glyph ID for the part.
1423    pub glyph_id: GlyphId16,
1424    /// Advance width/ height, in design units, of the straight bar connector
1425    /// material at the start of the glyph in the direction of the extension.
1426    pub start_connector_length: UfWord,
1427    /// Advance width/ height, in design units, of the straight bar connector
1428    /// material at the end of the glyph in the direction of the extension.
1429    pub end_connector_length: UfWord,
1430    /// Full advance width/height for this part in the direction of the
1431    /// extension, in design units.
1432    pub full_advance: UfWord,
1433    /// Part qualifiers.
1434    pub part_flags: PartFlags,
1435}
1436
1437impl GlyphPartRecord {
1438    /// Construct a new `GlyphPartRecord`
1439    pub fn new(
1440        glyph_id: GlyphId16,
1441        start_connector_length: UfWord,
1442        end_connector_length: UfWord,
1443        full_advance: UfWord,
1444        part_flags: PartFlags,
1445    ) -> Self {
1446        Self {
1447            glyph_id,
1448            start_connector_length,
1449            end_connector_length,
1450            full_advance,
1451            part_flags,
1452        }
1453    }
1454}
1455
1456impl FontWrite for GlyphPartRecord {
1457    fn write_into(&self, writer: &mut TableWriter) {
1458        self.glyph_id.write_into(writer);
1459        self.start_connector_length.write_into(writer);
1460        self.end_connector_length.write_into(writer);
1461        self.full_advance.write_into(writer);
1462        self.part_flags.write_into(writer);
1463    }
1464    fn table_type(&self) -> TableType {
1465        TableType::Named("GlyphPartRecord")
1466    }
1467}
1468
1469impl Validate for GlyphPartRecord {
1470    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1471}
1472
1473impl FromObjRef<read_fonts::tables::math::GlyphPartRecord> for GlyphPartRecord {
1474    fn from_obj_ref(obj: &read_fonts::tables::math::GlyphPartRecord, _: FontData) -> Self {
1475        GlyphPartRecord {
1476            glyph_id: obj.glyph_id(),
1477            start_connector_length: obj.start_connector_length(),
1478            end_connector_length: obj.end_connector_length(),
1479            full_advance: obj.full_advance(),
1480            part_flags: obj.part_flags(),
1481        }
1482    }
1483}
1484
1485impl FontWrite for PartFlags {
1486    fn write_into(&self, writer: &mut TableWriter) {
1487        writer.write_slice(&self.bits().to_be_bytes())
1488    }
1489}