1#[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.offset_data().as_bytes().get(range).unwrap_or_default()
15 }
16}
17
18impl TopLevelTable for Math<'_> {
19 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 let Some(data) = TableDataRef::new(data.as_bytes()) else {
34 return Err(ReadError::OutOfBounds);
35 };
36 Ok(Self { data })
37 }
38}
39
40#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
42#[repr(C, packed)]
43#[doc(hidden)]
44pub struct MathFixedHeader {
45 pub version: BigEndian<MajorMinor>,
46 pub math_constants_offset: BigEndian<Offset16>,
47 pub math_glyph_info_offset: BigEndian<Offset16>,
48 pub math_variants_offset: BigEndian<Offset16>,
49}
50
51#[allow(clippy::absurd_extreme_comparisons)]
52const _: () = assert!(std::mem::size_of::<MathFixedHeader>() <= Math::MIN_SIZE);
53
54#[derive(Clone)]
56pub struct Math<'a> {
57 data: TableDataRef<'a, MathFixedHeader>,
58}
59
60#[allow(clippy::needless_lifetimes)]
61impl<'a> Math<'a> {
62 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
63 + Offset16::RAW_BYTE_LEN
64 + Offset16::RAW_BYTE_LEN
65 + Offset16::RAW_BYTE_LEN);
66 basic_table_impls!(impl_the_methods);
67
68 pub fn version(&self) -> MajorMinor {
70 self.data.header().version.get()
71 }
72
73 pub fn math_constants_offset(&self) -> Offset16 {
75 self.data.header().math_constants_offset.get()
76 }
77
78 pub fn math_constants(&self) -> Result<MathConstants<'a>, ReadError> {
80 let data = self.offset_data();
81 self.math_constants_offset().resolve(data)
82 }
83
84 pub fn math_glyph_info_offset(&self) -> Offset16 {
86 self.data.header().math_glyph_info_offset.get()
87 }
88
89 pub fn math_glyph_info(&self) -> Result<MathGlyphInfo<'a>, ReadError> {
91 let data = self.offset_data();
92 self.math_glyph_info_offset().resolve(data)
93 }
94
95 pub fn math_variants_offset(&self) -> Offset16 {
97 self.data.header().math_variants_offset.get()
98 }
99
100 pub fn math_variants(&self) -> Result<MathVariants<'a>, ReadError> {
102 let data = self.offset_data();
103 self.math_variants_offset().resolve(data)
104 }
105
106 pub fn version_byte_range(&self) -> Range<usize> {
107 let start = 0;
108 let end = start + MajorMinor::RAW_BYTE_LEN;
109 start..end
110 }
111
112 pub fn math_constants_offset_byte_range(&self) -> Range<usize> {
113 let start = self.version_byte_range().end;
114 let end = start + Offset16::RAW_BYTE_LEN;
115 start..end
116 }
117
118 pub fn math_glyph_info_offset_byte_range(&self) -> Range<usize> {
119 let start = self.math_constants_offset_byte_range().end;
120 let end = start + Offset16::RAW_BYTE_LEN;
121 start..end
122 }
123
124 pub fn math_variants_offset_byte_range(&self) -> Range<usize> {
125 let start = self.math_glyph_info_offset_byte_range().end;
126 let end = start + Offset16::RAW_BYTE_LEN;
127 start..end
128 }
129}
130
131const _: () = assert!(FontData::default_data_long_enough(Math::MIN_SIZE));
132
133impl Default for Math<'_> {
134 fn default() -> Self {
135 Self {
136 data: TableDataRef::new(FontData::default_table_data().as_bytes())
137 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
138 }
139 }
140}
141
142#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
147#[repr(C)]
148#[repr(packed)]
149pub struct MathValueRecord {
150 pub value: BigEndian<FWord>,
152 pub device_offset: BigEndian<Nullable<Offset16>>,
156}
157
158impl MathValueRecord {
159 pub fn value(&self) -> FWord {
161 self.value.get()
162 }
163
164 pub fn device_offset(&self) -> Nullable<Offset16> {
168 self.device_offset.get()
169 }
170
171 pub fn device<'a>(
178 &self,
179 data: FontData<'a>,
180 ) -> Option<Result<DeviceOrVariationIndex<'a>, ReadError>> {
181 self.device_offset().resolve(data)
182 }
183}
184
185impl FixedSize for MathValueRecord {
186 const RAW_BYTE_LEN: usize = FWord::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
187}
188
189impl<'a> MinByteRange<'a> for MathConstants<'a> {
190 fn min_byte_range(&self) -> Range<usize> {
191 0..self.radical_degree_bottom_raise_percent_byte_range().end
192 }
193 fn min_table_bytes(&self) -> &'a [u8] {
194 let range = self.min_byte_range();
195 self.offset_data().as_bytes().get(range).unwrap_or_default()
196 }
197}
198
199impl ReadArgs for MathConstants<'_> {
200 type Args = ();
201}
202
203impl<'a> FontRead<'a> for MathConstants<'a> {
204 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
205 #[allow(clippy::absurd_extreme_comparisons)]
206 if data.len() < Self::MIN_SIZE {
207 return Err(ReadError::OutOfBounds);
208 }
209 let Some(data) = TableDataRef::new(data.as_bytes()) else {
210 return Err(ReadError::OutOfBounds);
211 };
212 Ok(Self { data })
213 }
214}
215
216#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
218#[repr(C, packed)]
219#[doc(hidden)]
220pub struct MathConstantsFixedHeader {
221 pub script_percent_scale_down: BigEndian<i16>,
222 pub script_script_percent_scale_down: BigEndian<i16>,
223 pub delimited_sub_formula_min_height: BigEndian<UfWord>,
224 pub display_operator_min_height: BigEndian<UfWord>,
225 pub math_leading: MathValueRecord,
226 pub axis_height: MathValueRecord,
227 pub accent_base_height: MathValueRecord,
228 pub flattened_accent_base_height: MathValueRecord,
229 pub subscript_shift_down: MathValueRecord,
230 pub subscript_top_max: MathValueRecord,
231 pub subscript_baseline_drop_min: MathValueRecord,
232 pub superscript_shift_up: MathValueRecord,
233 pub superscript_shift_up_cramped: MathValueRecord,
234 pub superscript_bottom_min: MathValueRecord,
235 pub superscript_baseline_drop_max: MathValueRecord,
236 pub sub_superscript_gap_min: MathValueRecord,
237 pub superscript_bottom_max_with_subscript: MathValueRecord,
238 pub space_after_script: MathValueRecord,
239 pub upper_limit_gap_min: MathValueRecord,
240 pub upper_limit_baseline_rise_min: MathValueRecord,
241 pub lower_limit_gap_min: MathValueRecord,
242 pub lower_limit_baseline_drop_min: MathValueRecord,
243 pub stack_top_shift_up: MathValueRecord,
244 pub stack_top_display_style_shift_up: MathValueRecord,
245 pub stack_bottom_shift_down: MathValueRecord,
246 pub stack_bottom_display_style_shift_down: MathValueRecord,
247 pub stack_gap_min: MathValueRecord,
248 pub stack_display_style_gap_min: MathValueRecord,
249 pub stretch_stack_top_shift_up: MathValueRecord,
250 pub stretch_stack_bottom_shift_down: MathValueRecord,
251 pub stretch_stack_gap_above_min: MathValueRecord,
252 pub stretch_stack_gap_below_min: MathValueRecord,
253 pub fraction_numerator_shift_up: MathValueRecord,
254 pub fraction_numerator_display_style_shift_up: MathValueRecord,
255 pub fraction_denominator_shift_down: MathValueRecord,
256 pub fraction_denominator_display_style_shift_down: MathValueRecord,
257 pub fraction_numerator_gap_min: MathValueRecord,
258 pub fraction_num_display_style_gap_min: MathValueRecord,
259 pub fraction_rule_thickness: MathValueRecord,
260 pub fraction_denominator_gap_min: MathValueRecord,
261 pub fraction_denom_display_style_gap_min: MathValueRecord,
262 pub skewed_fraction_horizontal_gap: MathValueRecord,
263 pub skewed_fraction_vertical_gap: MathValueRecord,
264 pub overbar_vertical_gap: MathValueRecord,
265 pub overbar_rule_thickness: MathValueRecord,
266 pub overbar_extra_ascender: MathValueRecord,
267 pub underbar_vertical_gap: MathValueRecord,
268 pub underbar_rule_thickness: MathValueRecord,
269 pub underbar_extra_descender: MathValueRecord,
270 pub radical_vertical_gap: MathValueRecord,
271 pub radical_display_style_vertical_gap: MathValueRecord,
272 pub radical_rule_thickness: MathValueRecord,
273 pub radical_extra_ascender: MathValueRecord,
274 pub radical_kern_before_degree: MathValueRecord,
275 pub radical_kern_after_degree: MathValueRecord,
276 pub radical_degree_bottom_raise_percent: BigEndian<i16>,
277}
278
279#[allow(clippy::absurd_extreme_comparisons)]
280const _: () = assert!(std::mem::size_of::<MathConstantsFixedHeader>() <= MathConstants::MIN_SIZE);
281
282#[derive(Clone)]
284pub struct MathConstants<'a> {
285 data: TableDataRef<'a, MathConstantsFixedHeader>,
286}
287
288#[allow(clippy::needless_lifetimes)]
289impl<'a> MathConstants<'a> {
290 pub const MIN_SIZE: usize = (i16::RAW_BYTE_LEN
291 + i16::RAW_BYTE_LEN
292 + UfWord::RAW_BYTE_LEN
293 + UfWord::RAW_BYTE_LEN
294 + MathValueRecord::RAW_BYTE_LEN
295 + MathValueRecord::RAW_BYTE_LEN
296 + MathValueRecord::RAW_BYTE_LEN
297 + MathValueRecord::RAW_BYTE_LEN
298 + MathValueRecord::RAW_BYTE_LEN
299 + MathValueRecord::RAW_BYTE_LEN
300 + MathValueRecord::RAW_BYTE_LEN
301 + MathValueRecord::RAW_BYTE_LEN
302 + MathValueRecord::RAW_BYTE_LEN
303 + MathValueRecord::RAW_BYTE_LEN
304 + MathValueRecord::RAW_BYTE_LEN
305 + MathValueRecord::RAW_BYTE_LEN
306 + MathValueRecord::RAW_BYTE_LEN
307 + MathValueRecord::RAW_BYTE_LEN
308 + MathValueRecord::RAW_BYTE_LEN
309 + MathValueRecord::RAW_BYTE_LEN
310 + MathValueRecord::RAW_BYTE_LEN
311 + MathValueRecord::RAW_BYTE_LEN
312 + MathValueRecord::RAW_BYTE_LEN
313 + MathValueRecord::RAW_BYTE_LEN
314 + MathValueRecord::RAW_BYTE_LEN
315 + MathValueRecord::RAW_BYTE_LEN
316 + MathValueRecord::RAW_BYTE_LEN
317 + MathValueRecord::RAW_BYTE_LEN
318 + MathValueRecord::RAW_BYTE_LEN
319 + MathValueRecord::RAW_BYTE_LEN
320 + MathValueRecord::RAW_BYTE_LEN
321 + MathValueRecord::RAW_BYTE_LEN
322 + MathValueRecord::RAW_BYTE_LEN
323 + MathValueRecord::RAW_BYTE_LEN
324 + MathValueRecord::RAW_BYTE_LEN
325 + MathValueRecord::RAW_BYTE_LEN
326 + MathValueRecord::RAW_BYTE_LEN
327 + MathValueRecord::RAW_BYTE_LEN
328 + MathValueRecord::RAW_BYTE_LEN
329 + MathValueRecord::RAW_BYTE_LEN
330 + MathValueRecord::RAW_BYTE_LEN
331 + MathValueRecord::RAW_BYTE_LEN
332 + MathValueRecord::RAW_BYTE_LEN
333 + MathValueRecord::RAW_BYTE_LEN
334 + MathValueRecord::RAW_BYTE_LEN
335 + MathValueRecord::RAW_BYTE_LEN
336 + MathValueRecord::RAW_BYTE_LEN
337 + MathValueRecord::RAW_BYTE_LEN
338 + MathValueRecord::RAW_BYTE_LEN
339 + MathValueRecord::RAW_BYTE_LEN
340 + MathValueRecord::RAW_BYTE_LEN
341 + MathValueRecord::RAW_BYTE_LEN
342 + MathValueRecord::RAW_BYTE_LEN
343 + MathValueRecord::RAW_BYTE_LEN
344 + MathValueRecord::RAW_BYTE_LEN
345 + i16::RAW_BYTE_LEN);
346 basic_table_impls!(impl_the_methods);
347
348 pub fn script_percent_scale_down(&self) -> i16 {
350 self.data.header().script_percent_scale_down.get()
351 }
352
353 pub fn script_script_percent_scale_down(&self) -> i16 {
356 self.data.header().script_script_percent_scale_down.get()
357 }
358
359 pub fn delimited_sub_formula_min_height(&self) -> UfWord {
362 self.data.header().delimited_sub_formula_min_height.get()
363 }
364
365 pub fn display_operator_min_height(&self) -> UfWord {
369 self.data.header().display_operator_min_height.get()
370 }
371
372 pub fn math_leading(&self) -> &'a MathValueRecord {
375 &self.data.header().math_leading
376 }
377
378 pub fn axis_height(&self) -> &'a MathValueRecord {
380 &self.data.header().axis_height
381 }
382
383 pub fn accent_base_height(&self) -> &'a MathValueRecord {
386 &self.data.header().accent_base_height
387 }
388
389 pub fn flattened_accent_base_height(&self) -> &'a MathValueRecord {
392 &self.data.header().flattened_accent_base_height
393 }
394
395 pub fn subscript_shift_down(&self) -> &'a MathValueRecord {
397 &self.data.header().subscript_shift_down
398 }
399
400 pub fn subscript_top_max(&self) -> &'a MathValueRecord {
403 &self.data.header().subscript_top_max
404 }
405
406 pub fn subscript_baseline_drop_min(&self) -> &'a MathValueRecord {
409 &self.data.header().subscript_baseline_drop_min
410 }
411
412 pub fn superscript_shift_up(&self) -> &'a MathValueRecord {
414 &self.data.header().superscript_shift_up
415 }
416
417 pub fn superscript_shift_up_cramped(&self) -> &'a MathValueRecord {
419 &self.data.header().superscript_shift_up_cramped
420 }
421
422 pub fn superscript_bottom_min(&self) -> &'a MathValueRecord {
425 &self.data.header().superscript_bottom_min
426 }
427
428 pub fn superscript_baseline_drop_max(&self) -> &'a MathValueRecord {
431 &self.data.header().superscript_baseline_drop_max
432 }
433
434 pub fn sub_superscript_gap_min(&self) -> &'a MathValueRecord {
436 &self.data.header().sub_superscript_gap_min
437 }
438
439 pub fn superscript_bottom_max_with_subscript(&self) -> &'a MathValueRecord {
443 &self.data.header().superscript_bottom_max_with_subscript
444 }
445
446 pub fn space_after_script(&self) -> &'a MathValueRecord {
448 &self.data.header().space_after_script
449 }
450
451 pub fn upper_limit_gap_min(&self) -> &'a MathValueRecord {
454 &self.data.header().upper_limit_gap_min
455 }
456
457 pub fn upper_limit_baseline_rise_min(&self) -> &'a MathValueRecord {
460 &self.data.header().upper_limit_baseline_rise_min
461 }
462
463 pub fn lower_limit_gap_min(&self) -> &'a MathValueRecord {
466 &self.data.header().lower_limit_gap_min
467 }
468
469 pub fn lower_limit_baseline_drop_min(&self) -> &'a MathValueRecord {
472 &self.data.header().lower_limit_baseline_drop_min
473 }
474
475 pub fn stack_top_shift_up(&self) -> &'a MathValueRecord {
477 &self.data.header().stack_top_shift_up
478 }
479
480 pub fn stack_top_display_style_shift_up(&self) -> &'a MathValueRecord {
483 &self.data.header().stack_top_display_style_shift_up
484 }
485
486 pub fn stack_bottom_shift_down(&self) -> &'a MathValueRecord {
488 &self.data.header().stack_bottom_shift_down
489 }
490
491 pub fn stack_bottom_display_style_shift_down(&self) -> &'a MathValueRecord {
494 &self.data.header().stack_bottom_display_style_shift_down
495 }
496
497 pub fn stack_gap_min(&self) -> &'a MathValueRecord {
500 &self.data.header().stack_gap_min
501 }
502
503 pub fn stack_display_style_gap_min(&self) -> &'a MathValueRecord {
506 &self.data.header().stack_display_style_gap_min
507 }
508
509 pub fn stretch_stack_top_shift_up(&self) -> &'a MathValueRecord {
511 &self.data.header().stretch_stack_top_shift_up
512 }
513
514 pub fn stretch_stack_bottom_shift_down(&self) -> &'a MathValueRecord {
516 &self.data.header().stretch_stack_bottom_shift_down
517 }
518
519 pub fn stretch_stack_gap_above_min(&self) -> &'a MathValueRecord {
522 &self.data.header().stretch_stack_gap_above_min
523 }
524
525 pub fn stretch_stack_gap_below_min(&self) -> &'a MathValueRecord {
528 &self.data.header().stretch_stack_gap_below_min
529 }
530
531 pub fn fraction_numerator_shift_up(&self) -> &'a MathValueRecord {
533 &self.data.header().fraction_numerator_shift_up
534 }
535
536 pub fn fraction_numerator_display_style_shift_up(&self) -> &'a MathValueRecord {
538 &self.data.header().fraction_numerator_display_style_shift_up
539 }
540
541 pub fn fraction_denominator_shift_down(&self) -> &'a MathValueRecord {
543 &self.data.header().fraction_denominator_shift_down
544 }
545
546 pub fn fraction_denominator_display_style_shift_down(&self) -> &'a MathValueRecord {
548 &self
549 .data
550 .header()
551 .fraction_denominator_display_style_shift_down
552 }
553
554 pub fn fraction_numerator_gap_min(&self) -> &'a MathValueRecord {
557 &self.data.header().fraction_numerator_gap_min
558 }
559
560 pub fn fraction_num_display_style_gap_min(&self) -> &'a MathValueRecord {
563 &self.data.header().fraction_num_display_style_gap_min
564 }
565
566 pub fn fraction_rule_thickness(&self) -> &'a MathValueRecord {
568 &self.data.header().fraction_rule_thickness
569 }
570
571 pub fn fraction_denominator_gap_min(&self) -> &'a MathValueRecord {
574 &self.data.header().fraction_denominator_gap_min
575 }
576
577 pub fn fraction_denom_display_style_gap_min(&self) -> &'a MathValueRecord {
580 &self.data.header().fraction_denom_display_style_gap_min
581 }
582
583 pub fn skewed_fraction_horizontal_gap(&self) -> &'a MathValueRecord {
586 &self.data.header().skewed_fraction_horizontal_gap
587 }
588
589 pub fn skewed_fraction_vertical_gap(&self) -> &'a MathValueRecord {
592 &self.data.header().skewed_fraction_vertical_gap
593 }
594
595 pub fn overbar_vertical_gap(&self) -> &'a MathValueRecord {
597 &self.data.header().overbar_vertical_gap
598 }
599
600 pub fn overbar_rule_thickness(&self) -> &'a MathValueRecord {
602 &self.data.header().overbar_rule_thickness
603 }
604
605 pub fn overbar_extra_ascender(&self) -> &'a MathValueRecord {
607 &self.data.header().overbar_extra_ascender
608 }
609
610 pub fn underbar_vertical_gap(&self) -> &'a MathValueRecord {
612 &self.data.header().underbar_vertical_gap
613 }
614
615 pub fn underbar_rule_thickness(&self) -> &'a MathValueRecord {
617 &self.data.header().underbar_rule_thickness
618 }
619
620 pub fn underbar_extra_descender(&self) -> &'a MathValueRecord {
622 &self.data.header().underbar_extra_descender
623 }
624
625 pub fn radical_vertical_gap(&self) -> &'a MathValueRecord {
627 &self.data.header().radical_vertical_gap
628 }
629
630 pub fn radical_display_style_vertical_gap(&self) -> &'a MathValueRecord {
633 &self.data.header().radical_display_style_vertical_gap
634 }
635
636 pub fn radical_rule_thickness(&self) -> &'a MathValueRecord {
638 &self.data.header().radical_rule_thickness
639 }
640
641 pub fn radical_extra_ascender(&self) -> &'a MathValueRecord {
643 &self.data.header().radical_extra_ascender
644 }
645
646 pub fn radical_kern_before_degree(&self) -> &'a MathValueRecord {
649 &self.data.header().radical_kern_before_degree
650 }
651
652 pub fn radical_kern_after_degree(&self) -> &'a MathValueRecord {
654 &self.data.header().radical_kern_after_degree
655 }
656
657 pub fn radical_degree_bottom_raise_percent(&self) -> i16 {
660 self.data.header().radical_degree_bottom_raise_percent.get()
661 }
662
663 pub fn script_percent_scale_down_byte_range(&self) -> Range<usize> {
664 let start = 0;
665 let end = start + i16::RAW_BYTE_LEN;
666 start..end
667 }
668
669 pub fn script_script_percent_scale_down_byte_range(&self) -> Range<usize> {
670 let start = self.script_percent_scale_down_byte_range().end;
671 let end = start + i16::RAW_BYTE_LEN;
672 start..end
673 }
674
675 pub fn delimited_sub_formula_min_height_byte_range(&self) -> Range<usize> {
676 let start = self.script_script_percent_scale_down_byte_range().end;
677 let end = start + UfWord::RAW_BYTE_LEN;
678 start..end
679 }
680
681 pub fn display_operator_min_height_byte_range(&self) -> Range<usize> {
682 let start = self.delimited_sub_formula_min_height_byte_range().end;
683 let end = start + UfWord::RAW_BYTE_LEN;
684 start..end
685 }
686
687 pub fn math_leading_byte_range(&self) -> Range<usize> {
688 let start = self.display_operator_min_height_byte_range().end;
689 let end = start + MathValueRecord::RAW_BYTE_LEN;
690 start..end
691 }
692
693 pub fn axis_height_byte_range(&self) -> Range<usize> {
694 let start = self.math_leading_byte_range().end;
695 let end = start + MathValueRecord::RAW_BYTE_LEN;
696 start..end
697 }
698
699 pub fn accent_base_height_byte_range(&self) -> Range<usize> {
700 let start = self.axis_height_byte_range().end;
701 let end = start + MathValueRecord::RAW_BYTE_LEN;
702 start..end
703 }
704
705 pub fn flattened_accent_base_height_byte_range(&self) -> Range<usize> {
706 let start = self.accent_base_height_byte_range().end;
707 let end = start + MathValueRecord::RAW_BYTE_LEN;
708 start..end
709 }
710
711 pub fn subscript_shift_down_byte_range(&self) -> Range<usize> {
712 let start = self.flattened_accent_base_height_byte_range().end;
713 let end = start + MathValueRecord::RAW_BYTE_LEN;
714 start..end
715 }
716
717 pub fn subscript_top_max_byte_range(&self) -> Range<usize> {
718 let start = self.subscript_shift_down_byte_range().end;
719 let end = start + MathValueRecord::RAW_BYTE_LEN;
720 start..end
721 }
722
723 pub fn subscript_baseline_drop_min_byte_range(&self) -> Range<usize> {
724 let start = self.subscript_top_max_byte_range().end;
725 let end = start + MathValueRecord::RAW_BYTE_LEN;
726 start..end
727 }
728
729 pub fn superscript_shift_up_byte_range(&self) -> Range<usize> {
730 let start = self.subscript_baseline_drop_min_byte_range().end;
731 let end = start + MathValueRecord::RAW_BYTE_LEN;
732 start..end
733 }
734
735 pub fn superscript_shift_up_cramped_byte_range(&self) -> Range<usize> {
736 let start = self.superscript_shift_up_byte_range().end;
737 let end = start + MathValueRecord::RAW_BYTE_LEN;
738 start..end
739 }
740
741 pub fn superscript_bottom_min_byte_range(&self) -> Range<usize> {
742 let start = self.superscript_shift_up_cramped_byte_range().end;
743 let end = start + MathValueRecord::RAW_BYTE_LEN;
744 start..end
745 }
746
747 pub fn superscript_baseline_drop_max_byte_range(&self) -> Range<usize> {
748 let start = self.superscript_bottom_min_byte_range().end;
749 let end = start + MathValueRecord::RAW_BYTE_LEN;
750 start..end
751 }
752
753 pub fn sub_superscript_gap_min_byte_range(&self) -> Range<usize> {
754 let start = self.superscript_baseline_drop_max_byte_range().end;
755 let end = start + MathValueRecord::RAW_BYTE_LEN;
756 start..end
757 }
758
759 pub fn superscript_bottom_max_with_subscript_byte_range(&self) -> Range<usize> {
760 let start = self.sub_superscript_gap_min_byte_range().end;
761 let end = start + MathValueRecord::RAW_BYTE_LEN;
762 start..end
763 }
764
765 pub fn space_after_script_byte_range(&self) -> Range<usize> {
766 let start = self.superscript_bottom_max_with_subscript_byte_range().end;
767 let end = start + MathValueRecord::RAW_BYTE_LEN;
768 start..end
769 }
770
771 pub fn upper_limit_gap_min_byte_range(&self) -> Range<usize> {
772 let start = self.space_after_script_byte_range().end;
773 let end = start + MathValueRecord::RAW_BYTE_LEN;
774 start..end
775 }
776
777 pub fn upper_limit_baseline_rise_min_byte_range(&self) -> Range<usize> {
778 let start = self.upper_limit_gap_min_byte_range().end;
779 let end = start + MathValueRecord::RAW_BYTE_LEN;
780 start..end
781 }
782
783 pub fn lower_limit_gap_min_byte_range(&self) -> Range<usize> {
784 let start = self.upper_limit_baseline_rise_min_byte_range().end;
785 let end = start + MathValueRecord::RAW_BYTE_LEN;
786 start..end
787 }
788
789 pub fn lower_limit_baseline_drop_min_byte_range(&self) -> Range<usize> {
790 let start = self.lower_limit_gap_min_byte_range().end;
791 let end = start + MathValueRecord::RAW_BYTE_LEN;
792 start..end
793 }
794
795 pub fn stack_top_shift_up_byte_range(&self) -> Range<usize> {
796 let start = self.lower_limit_baseline_drop_min_byte_range().end;
797 let end = start + MathValueRecord::RAW_BYTE_LEN;
798 start..end
799 }
800
801 pub fn stack_top_display_style_shift_up_byte_range(&self) -> Range<usize> {
802 let start = self.stack_top_shift_up_byte_range().end;
803 let end = start + MathValueRecord::RAW_BYTE_LEN;
804 start..end
805 }
806
807 pub fn stack_bottom_shift_down_byte_range(&self) -> Range<usize> {
808 let start = self.stack_top_display_style_shift_up_byte_range().end;
809 let end = start + MathValueRecord::RAW_BYTE_LEN;
810 start..end
811 }
812
813 pub fn stack_bottom_display_style_shift_down_byte_range(&self) -> Range<usize> {
814 let start = self.stack_bottom_shift_down_byte_range().end;
815 let end = start + MathValueRecord::RAW_BYTE_LEN;
816 start..end
817 }
818
819 pub fn stack_gap_min_byte_range(&self) -> Range<usize> {
820 let start = self.stack_bottom_display_style_shift_down_byte_range().end;
821 let end = start + MathValueRecord::RAW_BYTE_LEN;
822 start..end
823 }
824
825 pub fn stack_display_style_gap_min_byte_range(&self) -> Range<usize> {
826 let start = self.stack_gap_min_byte_range().end;
827 let end = start + MathValueRecord::RAW_BYTE_LEN;
828 start..end
829 }
830
831 pub fn stretch_stack_top_shift_up_byte_range(&self) -> Range<usize> {
832 let start = self.stack_display_style_gap_min_byte_range().end;
833 let end = start + MathValueRecord::RAW_BYTE_LEN;
834 start..end
835 }
836
837 pub fn stretch_stack_bottom_shift_down_byte_range(&self) -> Range<usize> {
838 let start = self.stretch_stack_top_shift_up_byte_range().end;
839 let end = start + MathValueRecord::RAW_BYTE_LEN;
840 start..end
841 }
842
843 pub fn stretch_stack_gap_above_min_byte_range(&self) -> Range<usize> {
844 let start = self.stretch_stack_bottom_shift_down_byte_range().end;
845 let end = start + MathValueRecord::RAW_BYTE_LEN;
846 start..end
847 }
848
849 pub fn stretch_stack_gap_below_min_byte_range(&self) -> Range<usize> {
850 let start = self.stretch_stack_gap_above_min_byte_range().end;
851 let end = start + MathValueRecord::RAW_BYTE_LEN;
852 start..end
853 }
854
855 pub fn fraction_numerator_shift_up_byte_range(&self) -> Range<usize> {
856 let start = self.stretch_stack_gap_below_min_byte_range().end;
857 let end = start + MathValueRecord::RAW_BYTE_LEN;
858 start..end
859 }
860
861 pub fn fraction_numerator_display_style_shift_up_byte_range(&self) -> Range<usize> {
862 let start = self.fraction_numerator_shift_up_byte_range().end;
863 let end = start + MathValueRecord::RAW_BYTE_LEN;
864 start..end
865 }
866
867 pub fn fraction_denominator_shift_down_byte_range(&self) -> Range<usize> {
868 let start = self
869 .fraction_numerator_display_style_shift_up_byte_range()
870 .end;
871 let end = start + MathValueRecord::RAW_BYTE_LEN;
872 start..end
873 }
874
875 pub fn fraction_denominator_display_style_shift_down_byte_range(&self) -> Range<usize> {
876 let start = self.fraction_denominator_shift_down_byte_range().end;
877 let end = start + MathValueRecord::RAW_BYTE_LEN;
878 start..end
879 }
880
881 pub fn fraction_numerator_gap_min_byte_range(&self) -> Range<usize> {
882 let start = self
883 .fraction_denominator_display_style_shift_down_byte_range()
884 .end;
885 let end = start + MathValueRecord::RAW_BYTE_LEN;
886 start..end
887 }
888
889 pub fn fraction_num_display_style_gap_min_byte_range(&self) -> Range<usize> {
890 let start = self.fraction_numerator_gap_min_byte_range().end;
891 let end = start + MathValueRecord::RAW_BYTE_LEN;
892 start..end
893 }
894
895 pub fn fraction_rule_thickness_byte_range(&self) -> Range<usize> {
896 let start = self.fraction_num_display_style_gap_min_byte_range().end;
897 let end = start + MathValueRecord::RAW_BYTE_LEN;
898 start..end
899 }
900
901 pub fn fraction_denominator_gap_min_byte_range(&self) -> Range<usize> {
902 let start = self.fraction_rule_thickness_byte_range().end;
903 let end = start + MathValueRecord::RAW_BYTE_LEN;
904 start..end
905 }
906
907 pub fn fraction_denom_display_style_gap_min_byte_range(&self) -> Range<usize> {
908 let start = self.fraction_denominator_gap_min_byte_range().end;
909 let end = start + MathValueRecord::RAW_BYTE_LEN;
910 start..end
911 }
912
913 pub fn skewed_fraction_horizontal_gap_byte_range(&self) -> Range<usize> {
914 let start = self.fraction_denom_display_style_gap_min_byte_range().end;
915 let end = start + MathValueRecord::RAW_BYTE_LEN;
916 start..end
917 }
918
919 pub fn skewed_fraction_vertical_gap_byte_range(&self) -> Range<usize> {
920 let start = self.skewed_fraction_horizontal_gap_byte_range().end;
921 let end = start + MathValueRecord::RAW_BYTE_LEN;
922 start..end
923 }
924
925 pub fn overbar_vertical_gap_byte_range(&self) -> Range<usize> {
926 let start = self.skewed_fraction_vertical_gap_byte_range().end;
927 let end = start + MathValueRecord::RAW_BYTE_LEN;
928 start..end
929 }
930
931 pub fn overbar_rule_thickness_byte_range(&self) -> Range<usize> {
932 let start = self.overbar_vertical_gap_byte_range().end;
933 let end = start + MathValueRecord::RAW_BYTE_LEN;
934 start..end
935 }
936
937 pub fn overbar_extra_ascender_byte_range(&self) -> Range<usize> {
938 let start = self.overbar_rule_thickness_byte_range().end;
939 let end = start + MathValueRecord::RAW_BYTE_LEN;
940 start..end
941 }
942
943 pub fn underbar_vertical_gap_byte_range(&self) -> Range<usize> {
944 let start = self.overbar_extra_ascender_byte_range().end;
945 let end = start + MathValueRecord::RAW_BYTE_LEN;
946 start..end
947 }
948
949 pub fn underbar_rule_thickness_byte_range(&self) -> Range<usize> {
950 let start = self.underbar_vertical_gap_byte_range().end;
951 let end = start + MathValueRecord::RAW_BYTE_LEN;
952 start..end
953 }
954
955 pub fn underbar_extra_descender_byte_range(&self) -> Range<usize> {
956 let start = self.underbar_rule_thickness_byte_range().end;
957 let end = start + MathValueRecord::RAW_BYTE_LEN;
958 start..end
959 }
960
961 pub fn radical_vertical_gap_byte_range(&self) -> Range<usize> {
962 let start = self.underbar_extra_descender_byte_range().end;
963 let end = start + MathValueRecord::RAW_BYTE_LEN;
964 start..end
965 }
966
967 pub fn radical_display_style_vertical_gap_byte_range(&self) -> Range<usize> {
968 let start = self.radical_vertical_gap_byte_range().end;
969 let end = start + MathValueRecord::RAW_BYTE_LEN;
970 start..end
971 }
972
973 pub fn radical_rule_thickness_byte_range(&self) -> Range<usize> {
974 let start = self.radical_display_style_vertical_gap_byte_range().end;
975 let end = start + MathValueRecord::RAW_BYTE_LEN;
976 start..end
977 }
978
979 pub fn radical_extra_ascender_byte_range(&self) -> Range<usize> {
980 let start = self.radical_rule_thickness_byte_range().end;
981 let end = start + MathValueRecord::RAW_BYTE_LEN;
982 start..end
983 }
984
985 pub fn radical_kern_before_degree_byte_range(&self) -> Range<usize> {
986 let start = self.radical_extra_ascender_byte_range().end;
987 let end = start + MathValueRecord::RAW_BYTE_LEN;
988 start..end
989 }
990
991 pub fn radical_kern_after_degree_byte_range(&self) -> Range<usize> {
992 let start = self.radical_kern_before_degree_byte_range().end;
993 let end = start + MathValueRecord::RAW_BYTE_LEN;
994 start..end
995 }
996
997 pub fn radical_degree_bottom_raise_percent_byte_range(&self) -> Range<usize> {
998 let start = self.radical_kern_after_degree_byte_range().end;
999 let end = start + i16::RAW_BYTE_LEN;
1000 start..end
1001 }
1002}
1003
1004const _: () = assert!(FontData::default_data_long_enough(MathConstants::MIN_SIZE));
1005
1006impl Default for MathConstants<'_> {
1007 fn default() -> Self {
1008 Self {
1009 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1010 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1011 }
1012 }
1013}
1014
1015impl<'a> MinByteRange<'a> for MathGlyphInfo<'a> {
1016 fn min_byte_range(&self) -> Range<usize> {
1017 0..self.math_kern_info_offset_byte_range().end
1018 }
1019 fn min_table_bytes(&self) -> &'a [u8] {
1020 let range = self.min_byte_range();
1021 self.offset_data().as_bytes().get(range).unwrap_or_default()
1022 }
1023}
1024
1025impl ReadArgs for MathGlyphInfo<'_> {
1026 type Args = ();
1027}
1028
1029impl<'a> FontRead<'a> for MathGlyphInfo<'a> {
1030 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1031 #[allow(clippy::absurd_extreme_comparisons)]
1032 if data.len() < Self::MIN_SIZE {
1033 return Err(ReadError::OutOfBounds);
1034 }
1035 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1036 return Err(ReadError::OutOfBounds);
1037 };
1038 Ok(Self { data })
1039 }
1040}
1041
1042#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1044#[repr(C, packed)]
1045#[doc(hidden)]
1046pub struct MathGlyphInfoFixedHeader {
1047 pub math_italics_correction_info_offset: BigEndian<Nullable<Offset16>>,
1048 pub math_top_accent_attachment_offset: BigEndian<Nullable<Offset16>>,
1049 pub extended_shape_coverage_offset: BigEndian<Nullable<Offset16>>,
1050 pub math_kern_info_offset: BigEndian<Nullable<Offset16>>,
1051}
1052
1053#[allow(clippy::absurd_extreme_comparisons)]
1054const _: () = assert!(std::mem::size_of::<MathGlyphInfoFixedHeader>() <= MathGlyphInfo::MIN_SIZE);
1055
1056#[derive(Clone)]
1058pub struct MathGlyphInfo<'a> {
1059 data: TableDataRef<'a, MathGlyphInfoFixedHeader>,
1060}
1061
1062#[allow(clippy::needless_lifetimes)]
1063impl<'a> MathGlyphInfo<'a> {
1064 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN
1065 + Offset16::RAW_BYTE_LEN
1066 + Offset16::RAW_BYTE_LEN
1067 + Offset16::RAW_BYTE_LEN);
1068 basic_table_impls!(impl_the_methods);
1069
1070 pub fn math_italics_correction_info_offset(&self) -> Nullable<Offset16> {
1073 self.data.header().math_italics_correction_info_offset.get()
1074 }
1075
1076 pub fn math_italics_correction_info(
1078 &self,
1079 ) -> Option<Result<MathItalicsCorrectionInfo<'a>, ReadError>> {
1080 let data = self.offset_data();
1081 self.math_italics_correction_info_offset().resolve(data)
1082 }
1083
1084 pub fn math_top_accent_attachment_offset(&self) -> Nullable<Offset16> {
1087 self.data.header().math_top_accent_attachment_offset.get()
1088 }
1089
1090 pub fn math_top_accent_attachment(
1092 &self,
1093 ) -> Option<Result<MathTopAccentAttachment<'a>, ReadError>> {
1094 let data = self.offset_data();
1095 self.math_top_accent_attachment_offset().resolve(data)
1096 }
1097
1098 pub fn extended_shape_coverage_offset(&self) -> Nullable<Offset16> {
1101 self.data.header().extended_shape_coverage_offset.get()
1102 }
1103
1104 pub fn extended_shape_coverage(&self) -> Option<Result<CoverageTable<'a>, ReadError>> {
1106 let data = self.offset_data();
1107 self.extended_shape_coverage_offset().resolve(data)
1108 }
1109
1110 pub fn math_kern_info_offset(&self) -> Nullable<Offset16> {
1113 self.data.header().math_kern_info_offset.get()
1114 }
1115
1116 pub fn math_kern_info(&self) -> Option<Result<MathKernInfo<'a>, ReadError>> {
1118 let data = self.offset_data();
1119 self.math_kern_info_offset().resolve(data)
1120 }
1121
1122 pub fn math_italics_correction_info_offset_byte_range(&self) -> Range<usize> {
1123 let start = 0;
1124 let end = start + Offset16::RAW_BYTE_LEN;
1125 start..end
1126 }
1127
1128 pub fn math_top_accent_attachment_offset_byte_range(&self) -> Range<usize> {
1129 let start = self.math_italics_correction_info_offset_byte_range().end;
1130 let end = start + Offset16::RAW_BYTE_LEN;
1131 start..end
1132 }
1133
1134 pub fn extended_shape_coverage_offset_byte_range(&self) -> Range<usize> {
1135 let start = self.math_top_accent_attachment_offset_byte_range().end;
1136 let end = start + Offset16::RAW_BYTE_LEN;
1137 start..end
1138 }
1139
1140 pub fn math_kern_info_offset_byte_range(&self) -> Range<usize> {
1141 let start = self.extended_shape_coverage_offset_byte_range().end;
1142 let end = start + Offset16::RAW_BYTE_LEN;
1143 start..end
1144 }
1145}
1146
1147const _: () = assert!(FontData::default_data_long_enough(MathGlyphInfo::MIN_SIZE));
1148
1149impl Default for MathGlyphInfo<'_> {
1150 fn default() -> Self {
1151 Self {
1152 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1153 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1154 }
1155 }
1156}
1157
1158impl<'a> MinByteRange<'a> for MathItalicsCorrectionInfo<'a> {
1159 fn min_byte_range(&self) -> Range<usize> {
1160 0..self.italics_correction_byte_range().end
1161 }
1162 fn min_table_bytes(&self) -> &'a [u8] {
1163 let range = self.min_byte_range();
1164 self.offset_data().as_bytes().get(range).unwrap_or_default()
1165 }
1166}
1167
1168impl ReadArgs for MathItalicsCorrectionInfo<'_> {
1169 type Args = ();
1170}
1171
1172impl<'a> FontRead<'a> for MathItalicsCorrectionInfo<'a> {
1173 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1174 #[allow(clippy::absurd_extreme_comparisons)]
1175 if data.len() < Self::MIN_SIZE {
1176 return Err(ReadError::OutOfBounds);
1177 }
1178 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1179 return Err(ReadError::OutOfBounds);
1180 };
1181 Ok(Self { data })
1182 }
1183}
1184
1185#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1187#[repr(C, packed)]
1188#[doc(hidden)]
1189pub struct MathItalicsCorrectionInfoFixedHeader {
1190 pub coverage_offset: BigEndian<Offset16>,
1191 pub italics_correction_count: BigEndian<u16>,
1192}
1193
1194#[allow(clippy::absurd_extreme_comparisons)]
1195const _: () = assert!(
1196 std::mem::size_of::<MathItalicsCorrectionInfoFixedHeader>()
1197 <= MathItalicsCorrectionInfo::MIN_SIZE
1198);
1199
1200#[derive(Clone)]
1202pub struct MathItalicsCorrectionInfo<'a> {
1203 data: TableDataRef<'a, MathItalicsCorrectionInfoFixedHeader>,
1204}
1205
1206#[allow(clippy::needless_lifetimes)]
1207impl<'a> MathItalicsCorrectionInfo<'a> {
1208 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1209 basic_table_impls!(impl_the_methods);
1210
1211 pub fn coverage_offset(&self) -> Offset16 {
1214 self.data.header().coverage_offset.get()
1215 }
1216
1217 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1219 let data = self.offset_data();
1220 self.coverage_offset().resolve(data)
1221 }
1222
1223 pub fn italics_correction_count(&self) -> u16 {
1226 self.data.header().italics_correction_count.get()
1227 }
1228
1229 pub fn italics_correction(&self) -> &'a [MathValueRecord] {
1232 let range = self.italics_correction_byte_range();
1233 self.offset_data()
1234 .read_array(range)
1235 .ok()
1236 .unwrap_or_default()
1237 }
1238
1239 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1240 let start = 0;
1241 let end = start + Offset16::RAW_BYTE_LEN;
1242 start..end
1243 }
1244
1245 pub fn italics_correction_count_byte_range(&self) -> Range<usize> {
1246 let start = self.coverage_offset_byte_range().end;
1247 let end = start + u16::RAW_BYTE_LEN;
1248 start..end
1249 }
1250
1251 pub fn italics_correction_byte_range(&self) -> Range<usize> {
1252 let italics_correction_count = self.italics_correction_count();
1253 let start = self.italics_correction_count_byte_range().end;
1254 let end = start
1255 + (transforms::to_usize(italics_correction_count))
1256 .saturating_mul(MathValueRecord::RAW_BYTE_LEN);
1257 start..end
1258 }
1259}
1260
1261const _: () = assert!(FontData::default_data_long_enough(
1262 MathItalicsCorrectionInfo::MIN_SIZE
1263));
1264
1265impl Default for MathItalicsCorrectionInfo<'_> {
1266 fn default() -> Self {
1267 Self {
1268 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1269 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1270 }
1271 }
1272}
1273
1274impl<'a> MinByteRange<'a> for MathTopAccentAttachment<'a> {
1275 fn min_byte_range(&self) -> Range<usize> {
1276 0..self.top_accent_attachment_byte_range().end
1277 }
1278 fn min_table_bytes(&self) -> &'a [u8] {
1279 let range = self.min_byte_range();
1280 self.offset_data().as_bytes().get(range).unwrap_or_default()
1281 }
1282}
1283
1284impl ReadArgs for MathTopAccentAttachment<'_> {
1285 type Args = ();
1286}
1287
1288impl<'a> FontRead<'a> for MathTopAccentAttachment<'a> {
1289 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1290 #[allow(clippy::absurd_extreme_comparisons)]
1291 if data.len() < Self::MIN_SIZE {
1292 return Err(ReadError::OutOfBounds);
1293 }
1294 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1295 return Err(ReadError::OutOfBounds);
1296 };
1297 Ok(Self { data })
1298 }
1299}
1300
1301#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1303#[repr(C, packed)]
1304#[doc(hidden)]
1305pub struct MathTopAccentAttachmentFixedHeader {
1306 pub top_accent_coverage_offset: BigEndian<Offset16>,
1307 pub top_accent_attachment_count: BigEndian<u16>,
1308}
1309
1310#[allow(clippy::absurd_extreme_comparisons)]
1311const _: () = assert!(
1312 std::mem::size_of::<MathTopAccentAttachmentFixedHeader>() <= MathTopAccentAttachment::MIN_SIZE
1313);
1314
1315#[derive(Clone)]
1317pub struct MathTopAccentAttachment<'a> {
1318 data: TableDataRef<'a, MathTopAccentAttachmentFixedHeader>,
1319}
1320
1321#[allow(clippy::needless_lifetimes)]
1322impl<'a> MathTopAccentAttachment<'a> {
1323 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1324 basic_table_impls!(impl_the_methods);
1325
1326 pub fn top_accent_coverage_offset(&self) -> Offset16 {
1329 self.data.header().top_accent_coverage_offset.get()
1330 }
1331
1332 pub fn top_accent_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1334 let data = self.offset_data();
1335 self.top_accent_coverage_offset().resolve(data)
1336 }
1337
1338 pub fn top_accent_attachment_count(&self) -> u16 {
1341 self.data.header().top_accent_attachment_count.get()
1342 }
1343
1344 pub fn top_accent_attachment(&self) -> &'a [MathValueRecord] {
1347 let range = self.top_accent_attachment_byte_range();
1348 self.offset_data()
1349 .read_array(range)
1350 .ok()
1351 .unwrap_or_default()
1352 }
1353
1354 pub fn top_accent_coverage_offset_byte_range(&self) -> Range<usize> {
1355 let start = 0;
1356 let end = start + Offset16::RAW_BYTE_LEN;
1357 start..end
1358 }
1359
1360 pub fn top_accent_attachment_count_byte_range(&self) -> Range<usize> {
1361 let start = self.top_accent_coverage_offset_byte_range().end;
1362 let end = start + u16::RAW_BYTE_LEN;
1363 start..end
1364 }
1365
1366 pub fn top_accent_attachment_byte_range(&self) -> Range<usize> {
1367 let top_accent_attachment_count = self.top_accent_attachment_count();
1368 let start = self.top_accent_attachment_count_byte_range().end;
1369 let end = start
1370 + (transforms::to_usize(top_accent_attachment_count))
1371 .saturating_mul(MathValueRecord::RAW_BYTE_LEN);
1372 start..end
1373 }
1374}
1375
1376const _: () = assert!(FontData::default_data_long_enough(
1377 MathTopAccentAttachment::MIN_SIZE
1378));
1379
1380impl Default for MathTopAccentAttachment<'_> {
1381 fn default() -> Self {
1382 Self {
1383 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1384 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1385 }
1386 }
1387}
1388
1389impl<'a> MinByteRange<'a> for MathKernInfo<'a> {
1390 fn min_byte_range(&self) -> Range<usize> {
1391 0..self.math_kern_info_records_byte_range().end
1392 }
1393 fn min_table_bytes(&self) -> &'a [u8] {
1394 let range = self.min_byte_range();
1395 self.offset_data().as_bytes().get(range).unwrap_or_default()
1396 }
1397}
1398
1399impl ReadArgs for MathKernInfo<'_> {
1400 type Args = ();
1401}
1402
1403impl<'a> FontRead<'a> for MathKernInfo<'a> {
1404 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1405 #[allow(clippy::absurd_extreme_comparisons)]
1406 if data.len() < Self::MIN_SIZE {
1407 return Err(ReadError::OutOfBounds);
1408 }
1409 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1410 return Err(ReadError::OutOfBounds);
1411 };
1412 Ok(Self { data })
1413 }
1414}
1415
1416#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1418#[repr(C, packed)]
1419#[doc(hidden)]
1420pub struct MathKernInfoFixedHeader {
1421 pub math_kern_coverage_offset: BigEndian<Offset16>,
1422 pub math_kern_count: BigEndian<u16>,
1423}
1424
1425#[allow(clippy::absurd_extreme_comparisons)]
1426const _: () = assert!(std::mem::size_of::<MathKernInfoFixedHeader>() <= MathKernInfo::MIN_SIZE);
1427
1428#[derive(Clone)]
1430pub struct MathKernInfo<'a> {
1431 data: TableDataRef<'a, MathKernInfoFixedHeader>,
1432}
1433
1434#[allow(clippy::needless_lifetimes)]
1435impl<'a> MathKernInfo<'a> {
1436 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1437 basic_table_impls!(impl_the_methods);
1438
1439 pub fn math_kern_coverage_offset(&self) -> Offset16 {
1442 self.data.header().math_kern_coverage_offset.get()
1443 }
1444
1445 pub fn math_kern_coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1447 let data = self.offset_data();
1448 self.math_kern_coverage_offset().resolve(data)
1449 }
1450
1451 pub fn math_kern_count(&self) -> u16 {
1454 self.data.header().math_kern_count.get()
1455 }
1456
1457 pub fn math_kern_info_records(&self) -> &'a [MathKernInfoRecord] {
1459 let range = self.math_kern_info_records_byte_range();
1460 self.offset_data()
1461 .read_array(range)
1462 .ok()
1463 .unwrap_or_default()
1464 }
1465
1466 pub fn math_kern_coverage_offset_byte_range(&self) -> Range<usize> {
1467 let start = 0;
1468 let end = start + Offset16::RAW_BYTE_LEN;
1469 start..end
1470 }
1471
1472 pub fn math_kern_count_byte_range(&self) -> Range<usize> {
1473 let start = self.math_kern_coverage_offset_byte_range().end;
1474 let end = start + u16::RAW_BYTE_LEN;
1475 start..end
1476 }
1477
1478 pub fn math_kern_info_records_byte_range(&self) -> Range<usize> {
1479 let math_kern_count = self.math_kern_count();
1480 let start = self.math_kern_count_byte_range().end;
1481 let end = start
1482 + (transforms::to_usize(math_kern_count))
1483 .saturating_mul(MathKernInfoRecord::RAW_BYTE_LEN);
1484 start..end
1485 }
1486}
1487
1488const _: () = assert!(FontData::default_data_long_enough(MathKernInfo::MIN_SIZE));
1489
1490impl Default for MathKernInfo<'_> {
1491 fn default() -> Self {
1492 Self {
1493 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1494 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1495 }
1496 }
1497}
1498
1499#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
1503#[repr(C)]
1504#[repr(packed)]
1505pub struct MathKernInfoRecord {
1506 pub top_right_math_kern_offset: BigEndian<Nullable<Offset16>>,
1509 pub top_left_math_kern_offset: BigEndian<Nullable<Offset16>>,
1512 pub bottom_right_math_kern_offset: BigEndian<Nullable<Offset16>>,
1515 pub bottom_left_math_kern_offset: BigEndian<Nullable<Offset16>>,
1518}
1519
1520impl MathKernInfoRecord {
1521 pub fn top_right_math_kern_offset(&self) -> Nullable<Offset16> {
1524 self.top_right_math_kern_offset.get()
1525 }
1526
1527 pub fn top_right_math_kern<'a>(
1533 &self,
1534 data: FontData<'a>,
1535 ) -> Option<Result<MathKern<'a>, ReadError>> {
1536 self.top_right_math_kern_offset().resolve(data)
1537 }
1538
1539 pub fn top_left_math_kern_offset(&self) -> Nullable<Offset16> {
1542 self.top_left_math_kern_offset.get()
1543 }
1544
1545 pub fn top_left_math_kern<'a>(
1551 &self,
1552 data: FontData<'a>,
1553 ) -> Option<Result<MathKern<'a>, ReadError>> {
1554 self.top_left_math_kern_offset().resolve(data)
1555 }
1556
1557 pub fn bottom_right_math_kern_offset(&self) -> Nullable<Offset16> {
1560 self.bottom_right_math_kern_offset.get()
1561 }
1562
1563 pub fn bottom_right_math_kern<'a>(
1569 &self,
1570 data: FontData<'a>,
1571 ) -> Option<Result<MathKern<'a>, ReadError>> {
1572 self.bottom_right_math_kern_offset().resolve(data)
1573 }
1574
1575 pub fn bottom_left_math_kern_offset(&self) -> Nullable<Offset16> {
1578 self.bottom_left_math_kern_offset.get()
1579 }
1580
1581 pub fn bottom_left_math_kern<'a>(
1587 &self,
1588 data: FontData<'a>,
1589 ) -> Option<Result<MathKern<'a>, ReadError>> {
1590 self.bottom_left_math_kern_offset().resolve(data)
1591 }
1592}
1593
1594impl FixedSize for MathKernInfoRecord {
1595 const RAW_BYTE_LEN: usize = Offset16::RAW_BYTE_LEN
1596 + Offset16::RAW_BYTE_LEN
1597 + Offset16::RAW_BYTE_LEN
1598 + Offset16::RAW_BYTE_LEN;
1599}
1600
1601impl<'a> MinByteRange<'a> for MathKern<'a> {
1602 fn min_byte_range(&self) -> Range<usize> {
1603 0..self.kern_values_byte_range().end
1604 }
1605 fn min_table_bytes(&self) -> &'a [u8] {
1606 let range = self.min_byte_range();
1607 self.offset_data().as_bytes().get(range).unwrap_or_default()
1608 }
1609}
1610
1611impl ReadArgs for MathKern<'_> {
1612 type Args = ();
1613}
1614
1615impl<'a> FontRead<'a> for MathKern<'a> {
1616 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1617 #[allow(clippy::absurd_extreme_comparisons)]
1618 if data.len() < Self::MIN_SIZE {
1619 return Err(ReadError::OutOfBounds);
1620 }
1621 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1622 return Err(ReadError::OutOfBounds);
1623 };
1624 Ok(Self { data })
1625 }
1626}
1627
1628#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1630#[repr(C, packed)]
1631#[doc(hidden)]
1632pub struct MathKernFixedHeader {
1633 pub height_count: BigEndian<u16>,
1634}
1635
1636#[allow(clippy::absurd_extreme_comparisons)]
1637const _: () = assert!(std::mem::size_of::<MathKernFixedHeader>() <= MathKern::MIN_SIZE);
1638
1639#[derive(Clone)]
1641pub struct MathKern<'a> {
1642 data: TableDataRef<'a, MathKernFixedHeader>,
1643}
1644
1645#[allow(clippy::needless_lifetimes)]
1646impl<'a> MathKern<'a> {
1647 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
1648 basic_table_impls!(impl_the_methods);
1649
1650 pub fn height_count(&self) -> u16 {
1652 self.data.header().height_count.get()
1653 }
1654
1655 pub fn correction_height(&self) -> &'a [MathValueRecord] {
1658 let range = self.correction_height_byte_range();
1659 self.offset_data()
1660 .read_array(range)
1661 .ok()
1662 .unwrap_or_default()
1663 }
1664
1665 pub fn kern_values(&self) -> &'a [MathValueRecord] {
1670 let range = self.kern_values_byte_range();
1671 self.offset_data()
1672 .read_array(range)
1673 .ok()
1674 .unwrap_or_default()
1675 }
1676
1677 pub fn height_count_byte_range(&self) -> Range<usize> {
1678 let start = 0;
1679 let end = start + u16::RAW_BYTE_LEN;
1680 start..end
1681 }
1682
1683 pub fn correction_height_byte_range(&self) -> Range<usize> {
1684 let height_count = self.height_count();
1685 let start = self.height_count_byte_range().end;
1686 let end = start
1687 + (transforms::to_usize(height_count)).saturating_mul(MathValueRecord::RAW_BYTE_LEN);
1688 start..end
1689 }
1690
1691 pub fn kern_values_byte_range(&self) -> Range<usize> {
1692 let height_count = self.height_count();
1693 let start = self.correction_height_byte_range().end;
1694 let end = start
1695 + (transforms::add(height_count, 1_usize))
1696 .saturating_mul(MathValueRecord::RAW_BYTE_LEN);
1697 start..end
1698 }
1699}
1700
1701const _: () = assert!(FontData::default_data_long_enough(MathKern::MIN_SIZE));
1702
1703impl Default for MathKern<'_> {
1704 fn default() -> Self {
1705 Self {
1706 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1707 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1708 }
1709 }
1710}
1711
1712impl<'a> MinByteRange<'a> for MathVariants<'a> {
1713 fn min_byte_range(&self) -> Range<usize> {
1714 0..self.horiz_glyph_construction_offsets_byte_range().end
1715 }
1716 fn min_table_bytes(&self) -> &'a [u8] {
1717 let range = self.min_byte_range();
1718 self.offset_data().as_bytes().get(range).unwrap_or_default()
1719 }
1720}
1721
1722impl ReadArgs for MathVariants<'_> {
1723 type Args = ();
1724}
1725
1726impl<'a> FontRead<'a> for MathVariants<'a> {
1727 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1728 #[allow(clippy::absurd_extreme_comparisons)]
1729 if data.len() < Self::MIN_SIZE {
1730 return Err(ReadError::OutOfBounds);
1731 }
1732 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1733 return Err(ReadError::OutOfBounds);
1734 };
1735 Ok(Self { data })
1736 }
1737}
1738
1739#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1741#[repr(C, packed)]
1742#[doc(hidden)]
1743pub struct MathVariantsFixedHeader {
1744 pub min_connector_overlap: BigEndian<UfWord>,
1745 pub vert_glyph_coverage_offset: BigEndian<Nullable<Offset16>>,
1746 pub horiz_glyph_coverage_offset: BigEndian<Nullable<Offset16>>,
1747 pub vert_glyph_count: BigEndian<u16>,
1748 pub horiz_glyph_count: BigEndian<u16>,
1749}
1750
1751#[allow(clippy::absurd_extreme_comparisons)]
1752const _: () = assert!(std::mem::size_of::<MathVariantsFixedHeader>() <= MathVariants::MIN_SIZE);
1753
1754#[derive(Clone)]
1756pub struct MathVariants<'a> {
1757 data: TableDataRef<'a, MathVariantsFixedHeader>,
1758}
1759
1760#[allow(clippy::needless_lifetimes)]
1761impl<'a> MathVariants<'a> {
1762 pub const MIN_SIZE: usize = (UfWord::RAW_BYTE_LEN
1763 + Offset16::RAW_BYTE_LEN
1764 + Offset16::RAW_BYTE_LEN
1765 + u16::RAW_BYTE_LEN
1766 + u16::RAW_BYTE_LEN);
1767 basic_table_impls!(impl_the_methods);
1768
1769 pub fn min_connector_overlap(&self) -> UfWord {
1772 self.data.header().min_connector_overlap.get()
1773 }
1774
1775 pub fn vert_glyph_coverage_offset(&self) -> Nullable<Offset16> {
1778 self.data.header().vert_glyph_coverage_offset.get()
1779 }
1780
1781 pub fn vert_glyph_coverage(&self) -> Option<Result<CoverageTable<'a>, ReadError>> {
1783 let data = self.offset_data();
1784 self.vert_glyph_coverage_offset().resolve(data)
1785 }
1786
1787 pub fn horiz_glyph_coverage_offset(&self) -> Nullable<Offset16> {
1790 self.data.header().horiz_glyph_coverage_offset.get()
1791 }
1792
1793 pub fn horiz_glyph_coverage(&self) -> Option<Result<CoverageTable<'a>, ReadError>> {
1795 let data = self.offset_data();
1796 self.horiz_glyph_coverage_offset().resolve(data)
1797 }
1798
1799 pub fn vert_glyph_count(&self) -> u16 {
1803 self.data.header().vert_glyph_count.get()
1804 }
1805
1806 pub fn horiz_glyph_count(&self) -> u16 {
1810 self.data.header().horiz_glyph_count.get()
1811 }
1812
1813 pub fn vert_glyph_construction_offsets(&self) -> &'a [BigEndian<Offset16>] {
1816 let range = self.vert_glyph_construction_offsets_byte_range();
1817 self.offset_data()
1818 .read_array(range)
1819 .ok()
1820 .unwrap_or_default()
1821 }
1822
1823 pub fn vert_glyph_constructions(
1825 &self,
1826 ) -> ArrayOfOffsets<'a, MathGlyphConstruction<'a>, Offset16> {
1827 let data = self.offset_data();
1828 let offsets = self.vert_glyph_construction_offsets();
1829 ArrayOfOffsets::new(offsets, data, ())
1830 }
1831
1832 pub fn horiz_glyph_construction_offsets(&self) -> &'a [BigEndian<Offset16>] {
1835 let range = self.horiz_glyph_construction_offsets_byte_range();
1836 self.offset_data()
1837 .read_array(range)
1838 .ok()
1839 .unwrap_or_default()
1840 }
1841
1842 pub fn horiz_glyph_constructions(
1844 &self,
1845 ) -> ArrayOfOffsets<'a, MathGlyphConstruction<'a>, Offset16> {
1846 let data = self.offset_data();
1847 let offsets = self.horiz_glyph_construction_offsets();
1848 ArrayOfOffsets::new(offsets, data, ())
1849 }
1850
1851 pub fn min_connector_overlap_byte_range(&self) -> Range<usize> {
1852 let start = 0;
1853 let end = start + UfWord::RAW_BYTE_LEN;
1854 start..end
1855 }
1856
1857 pub fn vert_glyph_coverage_offset_byte_range(&self) -> Range<usize> {
1858 let start = self.min_connector_overlap_byte_range().end;
1859 let end = start + Offset16::RAW_BYTE_LEN;
1860 start..end
1861 }
1862
1863 pub fn horiz_glyph_coverage_offset_byte_range(&self) -> Range<usize> {
1864 let start = self.vert_glyph_coverage_offset_byte_range().end;
1865 let end = start + Offset16::RAW_BYTE_LEN;
1866 start..end
1867 }
1868
1869 pub fn vert_glyph_count_byte_range(&self) -> Range<usize> {
1870 let start = self.horiz_glyph_coverage_offset_byte_range().end;
1871 let end = start + u16::RAW_BYTE_LEN;
1872 start..end
1873 }
1874
1875 pub fn horiz_glyph_count_byte_range(&self) -> Range<usize> {
1876 let start = self.vert_glyph_count_byte_range().end;
1877 let end = start + u16::RAW_BYTE_LEN;
1878 start..end
1879 }
1880
1881 pub fn vert_glyph_construction_offsets_byte_range(&self) -> Range<usize> {
1882 let vert_glyph_count = self.vert_glyph_count();
1883 let start = self.horiz_glyph_count_byte_range().end;
1884 let end =
1885 start + (transforms::to_usize(vert_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1886 start..end
1887 }
1888
1889 pub fn horiz_glyph_construction_offsets_byte_range(&self) -> Range<usize> {
1890 let horiz_glyph_count = self.horiz_glyph_count();
1891 let start = self.vert_glyph_construction_offsets_byte_range().end;
1892 let end = start
1893 + (transforms::to_usize(horiz_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1894 start..end
1895 }
1896}
1897
1898const _: () = assert!(FontData::default_data_long_enough(MathVariants::MIN_SIZE));
1899
1900impl Default for MathVariants<'_> {
1901 fn default() -> Self {
1902 Self {
1903 data: TableDataRef::new(FontData::default_table_data().as_bytes())
1904 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
1905 }
1906 }
1907}
1908
1909impl<'a> MinByteRange<'a> for MathGlyphConstruction<'a> {
1910 fn min_byte_range(&self) -> Range<usize> {
1911 0..self.math_glyph_variant_records_byte_range().end
1912 }
1913 fn min_table_bytes(&self) -> &'a [u8] {
1914 let range = self.min_byte_range();
1915 self.offset_data().as_bytes().get(range).unwrap_or_default()
1916 }
1917}
1918
1919impl ReadArgs for MathGlyphConstruction<'_> {
1920 type Args = ();
1921}
1922
1923impl<'a> FontRead<'a> for MathGlyphConstruction<'a> {
1924 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1925 #[allow(clippy::absurd_extreme_comparisons)]
1926 if data.len() < Self::MIN_SIZE {
1927 return Err(ReadError::OutOfBounds);
1928 }
1929 let Some(data) = TableDataRef::new(data.as_bytes()) else {
1930 return Err(ReadError::OutOfBounds);
1931 };
1932 Ok(Self { data })
1933 }
1934}
1935
1936#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
1938#[repr(C, packed)]
1939#[doc(hidden)]
1940pub struct MathGlyphConstructionFixedHeader {
1941 pub glyph_assembly_offset: BigEndian<Nullable<Offset16>>,
1942 pub variant_count: BigEndian<u16>,
1943}
1944
1945#[allow(clippy::absurd_extreme_comparisons)]
1946const _: () = assert!(
1947 std::mem::size_of::<MathGlyphConstructionFixedHeader>() <= MathGlyphConstruction::MIN_SIZE
1948);
1949
1950#[derive(Clone)]
1952pub struct MathGlyphConstruction<'a> {
1953 data: TableDataRef<'a, MathGlyphConstructionFixedHeader>,
1954}
1955
1956#[allow(clippy::needless_lifetimes)]
1957impl<'a> MathGlyphConstruction<'a> {
1958 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1959 basic_table_impls!(impl_the_methods);
1960
1961 pub fn glyph_assembly_offset(&self) -> Nullable<Offset16> {
1964 self.data.header().glyph_assembly_offset.get()
1965 }
1966
1967 pub fn glyph_assembly(&self) -> Option<Result<GlyphAssembly<'a>, ReadError>> {
1969 let data = self.offset_data();
1970 self.glyph_assembly_offset().resolve(data)
1971 }
1972
1973 pub fn variant_count(&self) -> u16 {
1975 self.data.header().variant_count.get()
1976 }
1977
1978 pub fn math_glyph_variant_records(&self) -> &'a [MathGlyphVariantRecord] {
1980 let range = self.math_glyph_variant_records_byte_range();
1981 self.offset_data()
1982 .read_array(range)
1983 .ok()
1984 .unwrap_or_default()
1985 }
1986
1987 pub fn glyph_assembly_offset_byte_range(&self) -> Range<usize> {
1988 let start = 0;
1989 let end = start + Offset16::RAW_BYTE_LEN;
1990 start..end
1991 }
1992
1993 pub fn variant_count_byte_range(&self) -> Range<usize> {
1994 let start = self.glyph_assembly_offset_byte_range().end;
1995 let end = start + u16::RAW_BYTE_LEN;
1996 start..end
1997 }
1998
1999 pub fn math_glyph_variant_records_byte_range(&self) -> Range<usize> {
2000 let variant_count = self.variant_count();
2001 let start = self.variant_count_byte_range().end;
2002 let end = start
2003 + (transforms::to_usize(variant_count))
2004 .saturating_mul(MathGlyphVariantRecord::RAW_BYTE_LEN);
2005 start..end
2006 }
2007}
2008
2009const _: () = assert!(FontData::default_data_long_enough(
2010 MathGlyphConstruction::MIN_SIZE
2011));
2012
2013impl Default for MathGlyphConstruction<'_> {
2014 fn default() -> Self {
2015 Self {
2016 data: TableDataRef::new(FontData::default_table_data().as_bytes())
2017 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2018 }
2019 }
2020}
2021
2022#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
2024#[repr(C)]
2025#[repr(packed)]
2026pub struct MathGlyphVariantRecord {
2027 pub variant_glyph: BigEndian<GlyphId16>,
2029 pub advance_measurement: BigEndian<UfWord>,
2032}
2033
2034impl MathGlyphVariantRecord {
2035 pub fn variant_glyph(&self) -> GlyphId16 {
2037 self.variant_glyph.get()
2038 }
2039
2040 pub fn advance_measurement(&self) -> UfWord {
2043 self.advance_measurement.get()
2044 }
2045}
2046
2047impl FixedSize for MathGlyphVariantRecord {
2048 const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + UfWord::RAW_BYTE_LEN;
2049}
2050
2051impl<'a> MinByteRange<'a> for GlyphAssembly<'a> {
2052 fn min_byte_range(&self) -> Range<usize> {
2053 0..self.part_records_byte_range().end
2054 }
2055 fn min_table_bytes(&self) -> &'a [u8] {
2056 let range = self.min_byte_range();
2057 self.offset_data().as_bytes().get(range).unwrap_or_default()
2058 }
2059}
2060
2061impl ReadArgs for GlyphAssembly<'_> {
2062 type Args = ();
2063}
2064
2065impl<'a> FontRead<'a> for GlyphAssembly<'a> {
2066 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2067 #[allow(clippy::absurd_extreme_comparisons)]
2068 if data.len() < Self::MIN_SIZE {
2069 return Err(ReadError::OutOfBounds);
2070 }
2071 let Some(data) = TableDataRef::new(data.as_bytes()) else {
2072 return Err(ReadError::OutOfBounds);
2073 };
2074 Ok(Self { data })
2075 }
2076}
2077
2078#[derive(Clone, Copy, bytemuck :: AnyBitPattern)]
2080#[repr(C, packed)]
2081#[doc(hidden)]
2082pub struct GlyphAssemblyFixedHeader {
2083 pub italics_correction: MathValueRecord,
2084 pub part_count: BigEndian<u16>,
2085}
2086
2087#[allow(clippy::absurd_extreme_comparisons)]
2088const _: () = assert!(std::mem::size_of::<GlyphAssemblyFixedHeader>() <= GlyphAssembly::MIN_SIZE);
2089
2090#[derive(Clone)]
2092pub struct GlyphAssembly<'a> {
2093 data: TableDataRef<'a, GlyphAssemblyFixedHeader>,
2094}
2095
2096#[allow(clippy::needless_lifetimes)]
2097impl<'a> GlyphAssembly<'a> {
2098 pub const MIN_SIZE: usize = (MathValueRecord::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2099 basic_table_impls!(impl_the_methods);
2100
2101 pub fn italics_correction(&self) -> &'a MathValueRecord {
2104 &self.data.header().italics_correction
2105 }
2106
2107 pub fn part_count(&self) -> u16 {
2109 self.data.header().part_count.get()
2110 }
2111
2112 pub fn part_records(&self) -> &'a [GlyphPartRecord] {
2115 let range = self.part_records_byte_range();
2116 self.offset_data()
2117 .read_array(range)
2118 .ok()
2119 .unwrap_or_default()
2120 }
2121
2122 pub fn italics_correction_byte_range(&self) -> Range<usize> {
2123 let start = 0;
2124 let end = start + MathValueRecord::RAW_BYTE_LEN;
2125 start..end
2126 }
2127
2128 pub fn part_count_byte_range(&self) -> Range<usize> {
2129 let start = self.italics_correction_byte_range().end;
2130 let end = start + u16::RAW_BYTE_LEN;
2131 start..end
2132 }
2133
2134 pub fn part_records_byte_range(&self) -> Range<usize> {
2135 let part_count = self.part_count();
2136 let start = self.part_count_byte_range().end;
2137 let end = start
2138 + (transforms::to_usize(part_count)).saturating_mul(GlyphPartRecord::RAW_BYTE_LEN);
2139 start..end
2140 }
2141}
2142
2143const _: () = assert!(FontData::default_data_long_enough(GlyphAssembly::MIN_SIZE));
2144
2145impl Default for GlyphAssembly<'_> {
2146 fn default() -> Self {
2147 Self {
2148 data: TableDataRef::new(FontData::default_table_data().as_bytes())
2149 .unwrap_or_else(|| unreachable!("the default data covers MIN_SIZE")),
2150 }
2151 }
2152}
2153
2154#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
2156#[repr(C)]
2157#[repr(packed)]
2158pub struct GlyphPartRecord {
2159 pub glyph_id: BigEndian<GlyphId16>,
2161 pub start_connector_length: BigEndian<UfWord>,
2164 pub end_connector_length: BigEndian<UfWord>,
2167 pub full_advance: BigEndian<UfWord>,
2170 pub part_flags: BigEndian<PartFlags>,
2172}
2173
2174impl GlyphPartRecord {
2175 pub fn glyph_id(&self) -> GlyphId16 {
2177 self.glyph_id.get()
2178 }
2179
2180 pub fn start_connector_length(&self) -> UfWord {
2183 self.start_connector_length.get()
2184 }
2185
2186 pub fn end_connector_length(&self) -> UfWord {
2189 self.end_connector_length.get()
2190 }
2191
2192 pub fn full_advance(&self) -> UfWord {
2195 self.full_advance.get()
2196 }
2197
2198 pub fn part_flags(&self) -> PartFlags {
2200 self.part_flags.get()
2201 }
2202}
2203
2204impl FixedSize for GlyphPartRecord {
2205 const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN
2206 + UfWord::RAW_BYTE_LEN
2207 + UfWord::RAW_BYTE_LEN
2208 + UfWord::RAW_BYTE_LEN
2209 + PartFlags::RAW_BYTE_LEN;
2210}
2211
2212#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
2214#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2215#[repr(transparent)]
2216pub struct PartFlags {
2217 bits: u16,
2218}
2219
2220impl PartFlags {
2221 pub const EXTENDER_FLAG: Self = Self { bits: 0x0001 };
2223}
2224
2225impl PartFlags {
2226 #[inline]
2228 pub const fn empty() -> Self {
2229 Self { bits: 0 }
2230 }
2231
2232 #[inline]
2234 pub const fn all() -> Self {
2235 Self {
2236 bits: Self::EXTENDER_FLAG.bits,
2237 }
2238 }
2239
2240 #[inline]
2242 pub const fn bits(&self) -> u16 {
2243 self.bits
2244 }
2245
2246 #[inline]
2249 pub const fn from_bits(bits: u16) -> Option<Self> {
2250 if (bits & !Self::all().bits()) == 0 {
2251 Some(Self { bits })
2252 } else {
2253 None
2254 }
2255 }
2256
2257 #[inline]
2260 pub const fn from_bits_truncate(bits: u16) -> Self {
2261 Self {
2262 bits: bits & Self::all().bits,
2263 }
2264 }
2265
2266 #[inline]
2268 pub const fn is_empty(&self) -> bool {
2269 self.bits() == Self::empty().bits()
2270 }
2271
2272 #[inline]
2274 pub const fn intersects(&self, other: Self) -> bool {
2275 !(Self {
2276 bits: self.bits & other.bits,
2277 })
2278 .is_empty()
2279 }
2280
2281 #[inline]
2283 pub const fn contains(&self, other: Self) -> bool {
2284 (self.bits & other.bits) == other.bits
2285 }
2286
2287 #[inline]
2289 pub fn insert(&mut self, other: Self) {
2290 self.bits |= other.bits;
2291 }
2292
2293 #[inline]
2295 pub fn remove(&mut self, other: Self) {
2296 self.bits &= !other.bits;
2297 }
2298
2299 #[inline]
2301 pub fn toggle(&mut self, other: Self) {
2302 self.bits ^= other.bits;
2303 }
2304
2305 #[inline]
2316 #[must_use]
2317 pub const fn intersection(self, other: Self) -> Self {
2318 Self {
2319 bits: self.bits & other.bits,
2320 }
2321 }
2322
2323 #[inline]
2334 #[must_use]
2335 pub const fn union(self, other: Self) -> Self {
2336 Self {
2337 bits: self.bits | other.bits,
2338 }
2339 }
2340
2341 #[inline]
2354 #[must_use]
2355 pub const fn difference(self, other: Self) -> Self {
2356 Self {
2357 bits: self.bits & !other.bits,
2358 }
2359 }
2360}
2361
2362impl std::ops::BitOr for PartFlags {
2363 type Output = Self;
2364
2365 #[inline]
2367 fn bitor(self, other: PartFlags) -> Self {
2368 Self {
2369 bits: self.bits | other.bits,
2370 }
2371 }
2372}
2373
2374impl std::ops::BitOrAssign for PartFlags {
2375 #[inline]
2377 fn bitor_assign(&mut self, other: Self) {
2378 self.bits |= other.bits;
2379 }
2380}
2381
2382impl std::ops::BitXor for PartFlags {
2383 type Output = Self;
2384
2385 #[inline]
2387 fn bitxor(self, other: Self) -> Self {
2388 Self {
2389 bits: self.bits ^ other.bits,
2390 }
2391 }
2392}
2393
2394impl std::ops::BitXorAssign for PartFlags {
2395 #[inline]
2397 fn bitxor_assign(&mut self, other: Self) {
2398 self.bits ^= other.bits;
2399 }
2400}
2401
2402impl std::ops::BitAnd for PartFlags {
2403 type Output = Self;
2404
2405 #[inline]
2407 fn bitand(self, other: Self) -> Self {
2408 Self {
2409 bits: self.bits & other.bits,
2410 }
2411 }
2412}
2413
2414impl std::ops::BitAndAssign for PartFlags {
2415 #[inline]
2417 fn bitand_assign(&mut self, other: Self) {
2418 self.bits &= other.bits;
2419 }
2420}
2421
2422impl std::ops::Sub for PartFlags {
2423 type Output = Self;
2424
2425 #[inline]
2427 fn sub(self, other: Self) -> Self {
2428 Self {
2429 bits: self.bits & !other.bits,
2430 }
2431 }
2432}
2433
2434impl std::ops::SubAssign for PartFlags {
2435 #[inline]
2437 fn sub_assign(&mut self, other: Self) {
2438 self.bits &= !other.bits;
2439 }
2440}
2441
2442impl std::ops::Not for PartFlags {
2443 type Output = Self;
2444
2445 #[inline]
2447 fn not(self) -> Self {
2448 Self { bits: !self.bits } & Self::all()
2449 }
2450}
2451
2452impl std::fmt::Debug for PartFlags {
2453 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2454 let members: &[(&str, Self)] = &[("EXTENDER_FLAG", Self::EXTENDER_FLAG)];
2455 let mut first = true;
2456 for (name, value) in members {
2457 if self.contains(*value) {
2458 if !first {
2459 f.write_str(" | ")?;
2460 }
2461 first = false;
2462 f.write_str(name)?;
2463 }
2464 }
2465 if first {
2466 f.write_str("(empty)")?;
2467 }
2468 Ok(())
2469 }
2470}
2471
2472impl std::fmt::Binary for PartFlags {
2473 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2474 std::fmt::Binary::fmt(&self.bits, f)
2475 }
2476}
2477
2478impl std::fmt::Octal for PartFlags {
2479 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2480 std::fmt::Octal::fmt(&self.bits, f)
2481 }
2482}
2483
2484impl std::fmt::LowerHex for PartFlags {
2485 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2486 std::fmt::LowerHex::fmt(&self.bits, f)
2487 }
2488}
2489
2490impl std::fmt::UpperHex for PartFlags {
2491 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2492 std::fmt::UpperHex::fmt(&self.bits, f)
2493 }
2494}
2495
2496impl font_types::Scalar for PartFlags {
2497 type Raw = <u16 as font_types::Scalar>::Raw;
2498 fn to_raw(self) -> Self::Raw {
2499 self.bits().to_raw()
2500 }
2501 fn from_raw(raw: Self::Raw) -> Self {
2502 let t = <u16>::from_raw(raw);
2503 Self::from_bits_truncate(t)
2504 }
2505}