1 // THIS FILE IS AUTOGENERATED.
2 // Any changes to this file will be overwritten.
3 // For more information about how codegen works, see font-codegen/README.md
4 
5 #[allow(unused_imports)]
6 use crate::codegen_prelude::*;
7 
8 /// [BitmapSize](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#bitmapsize-record) record.
9 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
10 #[repr(C)]
11 #[repr(packed)]
12 pub struct BitmapSize {
13     /// Offset to index subtable from beginning of EBLC/CBLC.
14     pub index_subtable_array_offset: BigEndian<u32>,
15     /// Number of bytes in corresponding index subtables and array.
16     pub index_tables_size: BigEndian<u32>,
17     /// There is an index subtable for each range or format change.
18     pub number_of_index_subtables: BigEndian<u32>,
19     /// Not used; set to 0.
20     pub color_ref: BigEndian<u32>,
21     /// Line metrics for text rendered horizontally.
22     pub hori: SbitLineMetrics,
23     /// Line metrics for text rendered vertically.
24     pub vert: SbitLineMetrics,
25     /// Lowest glyph index for this size.
26     pub start_glyph_index: BigEndian<GlyphId>,
27     /// Highest glyph index for this size.
28     pub end_glyph_index: BigEndian<GlyphId>,
29     /// Horizontal pixels per em.
30     pub ppem_x: u8,
31     /// Vertical pixels per em.
32     pub ppem_y: u8,
33     /// The Microsoft rasterizer v.1.7 or greater supports the following
34     /// bitDepth values, as described below: 1, 2, 4, and 8 (and 32 for CBLC).
35     pub bit_depth: u8,
36     /// Vertical or horizontal.
37     pub flags: BigEndian<BitmapFlags>,
38 }
39 
40 impl BitmapSize {
41     /// Offset to index subtable from beginning of EBLC/CBLC.
index_subtable_array_offset(&self) -> u3242     pub fn index_subtable_array_offset(&self) -> u32 {
43         self.index_subtable_array_offset.get()
44     }
45 
46     /// Number of bytes in corresponding index subtables and array.
index_tables_size(&self) -> u3247     pub fn index_tables_size(&self) -> u32 {
48         self.index_tables_size.get()
49     }
50 
51     /// There is an index subtable for each range or format change.
number_of_index_subtables(&self) -> u3252     pub fn number_of_index_subtables(&self) -> u32 {
53         self.number_of_index_subtables.get()
54     }
55 
56     /// Not used; set to 0.
color_ref(&self) -> u3257     pub fn color_ref(&self) -> u32 {
58         self.color_ref.get()
59     }
60 
61     /// Line metrics for text rendered horizontally.
hori(&self) -> &SbitLineMetrics62     pub fn hori(&self) -> &SbitLineMetrics {
63         &self.hori
64     }
65 
66     /// Line metrics for text rendered vertically.
vert(&self) -> &SbitLineMetrics67     pub fn vert(&self) -> &SbitLineMetrics {
68         &self.vert
69     }
70 
71     /// Lowest glyph index for this size.
start_glyph_index(&self) -> GlyphId72     pub fn start_glyph_index(&self) -> GlyphId {
73         self.start_glyph_index.get()
74     }
75 
76     /// Highest glyph index for this size.
end_glyph_index(&self) -> GlyphId77     pub fn end_glyph_index(&self) -> GlyphId {
78         self.end_glyph_index.get()
79     }
80 
81     /// Horizontal pixels per em.
ppem_x(&self) -> u882     pub fn ppem_x(&self) -> u8 {
83         self.ppem_x
84     }
85 
86     /// Vertical pixels per em.
ppem_y(&self) -> u887     pub fn ppem_y(&self) -> u8 {
88         self.ppem_y
89     }
90 
91     /// The Microsoft rasterizer v.1.7 or greater supports the following
92     /// bitDepth values, as described below: 1, 2, 4, and 8 (and 32 for CBLC).
bit_depth(&self) -> u893     pub fn bit_depth(&self) -> u8 {
94         self.bit_depth
95     }
96 
97     /// Vertical or horizontal.
flags(&self) -> BitmapFlags98     pub fn flags(&self) -> BitmapFlags {
99         self.flags.get()
100     }
101 }
102 
103 impl FixedSize for BitmapSize {
104     const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN
105         + u32::RAW_BYTE_LEN
106         + u32::RAW_BYTE_LEN
107         + u32::RAW_BYTE_LEN
108         + SbitLineMetrics::RAW_BYTE_LEN
109         + SbitLineMetrics::RAW_BYTE_LEN
110         + GlyphId::RAW_BYTE_LEN
111         + GlyphId::RAW_BYTE_LEN
112         + u8::RAW_BYTE_LEN
113         + u8::RAW_BYTE_LEN
114         + u8::RAW_BYTE_LEN
115         + BitmapFlags::RAW_BYTE_LEN;
116 }
117 
118 impl sealed::Sealed for BitmapSize {}
119 
120 /// SAFETY: see the [`FromBytes`] trait documentation.
121 unsafe impl FromBytes for BitmapSize {
this_trait_should_only_be_implemented_in_generated_code()122     fn this_trait_should_only_be_implemented_in_generated_code() {}
123 }
124 
125 #[cfg(feature = "traversal")]
126 impl<'a> SomeRecord<'a> for BitmapSize {
traverse(self, data: FontData<'a>) -> RecordResolver<'a>127     fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
128         RecordResolver {
129             name: "BitmapSize",
130             get_field: Box::new(move |idx, _data| match idx {
131                 0usize => Some(Field::new(
132                     "index_subtable_array_offset",
133                     self.index_subtable_array_offset(),
134                 )),
135                 1usize => Some(Field::new("index_tables_size", self.index_tables_size())),
136                 2usize => Some(Field::new(
137                     "number_of_index_subtables",
138                     self.number_of_index_subtables(),
139                 )),
140                 3usize => Some(Field::new("color_ref", self.color_ref())),
141                 4usize => Some(Field::new("hori", self.hori().traversal_type(_data))),
142                 5usize => Some(Field::new("vert", self.vert().traversal_type(_data))),
143                 6usize => Some(Field::new("start_glyph_index", self.start_glyph_index())),
144                 7usize => Some(Field::new("end_glyph_index", self.end_glyph_index())),
145                 8usize => Some(Field::new("ppem_x", self.ppem_x())),
146                 9usize => Some(Field::new("ppem_y", self.ppem_y())),
147                 10usize => Some(Field::new("bit_depth", self.bit_depth())),
148                 11usize => Some(Field::new("flags", self.flags())),
149                 _ => None,
150             }),
151             data,
152         }
153     }
154 }
155 
156 /// [SbitLineMetrics](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#sbitlinemetrics-record) record.
157 #[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
158 #[repr(C)]
159 #[repr(packed)]
160 pub struct SbitLineMetrics {
161     pub ascender: BigEndian<i8>,
162     pub descender: BigEndian<i8>,
163     pub width_max: u8,
164     pub caret_slope_numerator: BigEndian<i8>,
165     pub caret_slope_denominator: u8,
166     pub caret_offset: BigEndian<i8>,
167     pub min_origin_sb: BigEndian<i8>,
168     pub min_advance_sb: BigEndian<i8>,
169     pub max_before_bl: BigEndian<i8>,
170     pub min_after_bl: BigEndian<i8>,
171     pub pad1: BigEndian<i8>,
172     pub pad2: BigEndian<i8>,
173 }
174 
175 impl SbitLineMetrics {
ascender(&self) -> i8176     pub fn ascender(&self) -> i8 {
177         self.ascender.get()
178     }
179 
descender(&self) -> i8180     pub fn descender(&self) -> i8 {
181         self.descender.get()
182     }
183 
width_max(&self) -> u8184     pub fn width_max(&self) -> u8 {
185         self.width_max
186     }
187 
caret_slope_numerator(&self) -> i8188     pub fn caret_slope_numerator(&self) -> i8 {
189         self.caret_slope_numerator.get()
190     }
191 
caret_slope_denominator(&self) -> u8192     pub fn caret_slope_denominator(&self) -> u8 {
193         self.caret_slope_denominator
194     }
195 
caret_offset(&self) -> i8196     pub fn caret_offset(&self) -> i8 {
197         self.caret_offset.get()
198     }
199 
min_origin_sb(&self) -> i8200     pub fn min_origin_sb(&self) -> i8 {
201         self.min_origin_sb.get()
202     }
203 
min_advance_sb(&self) -> i8204     pub fn min_advance_sb(&self) -> i8 {
205         self.min_advance_sb.get()
206     }
207 
max_before_bl(&self) -> i8208     pub fn max_before_bl(&self) -> i8 {
209         self.max_before_bl.get()
210     }
211 
min_after_bl(&self) -> i8212     pub fn min_after_bl(&self) -> i8 {
213         self.min_after_bl.get()
214     }
215 
pad1(&self) -> i8216     pub fn pad1(&self) -> i8 {
217         self.pad1.get()
218     }
219 
pad2(&self) -> i8220     pub fn pad2(&self) -> i8 {
221         self.pad2.get()
222     }
223 }
224 
225 impl FixedSize for SbitLineMetrics {
226     const RAW_BYTE_LEN: usize = i8::RAW_BYTE_LEN
227         + i8::RAW_BYTE_LEN
228         + u8::RAW_BYTE_LEN
229         + i8::RAW_BYTE_LEN
230         + u8::RAW_BYTE_LEN
231         + i8::RAW_BYTE_LEN
232         + i8::RAW_BYTE_LEN
233         + i8::RAW_BYTE_LEN
234         + i8::RAW_BYTE_LEN
235         + i8::RAW_BYTE_LEN
236         + i8::RAW_BYTE_LEN
237         + i8::RAW_BYTE_LEN;
238 }
239 
240 impl sealed::Sealed for SbitLineMetrics {}
241 
242 /// SAFETY: see the [`FromBytes`] trait documentation.
243 unsafe impl FromBytes for SbitLineMetrics {
this_trait_should_only_be_implemented_in_generated_code()244     fn this_trait_should_only_be_implemented_in_generated_code() {}
245 }
246 
247 #[cfg(feature = "traversal")]
248 impl<'a> SomeRecord<'a> for SbitLineMetrics {
traverse(self, data: FontData<'a>) -> RecordResolver<'a>249     fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
250         RecordResolver {
251             name: "SbitLineMetrics",
252             get_field: Box::new(move |idx, _data| match idx {
253                 0usize => Some(Field::new("ascender", self.ascender())),
254                 1usize => Some(Field::new("descender", self.descender())),
255                 2usize => Some(Field::new("width_max", self.width_max())),
256                 3usize => Some(Field::new(
257                     "caret_slope_numerator",
258                     self.caret_slope_numerator(),
259                 )),
260                 4usize => Some(Field::new(
261                     "caret_slope_denominator",
262                     self.caret_slope_denominator(),
263                 )),
264                 5usize => Some(Field::new("caret_offset", self.caret_offset())),
265                 6usize => Some(Field::new("min_origin_sb", self.min_origin_sb())),
266                 7usize => Some(Field::new("min_advance_sb", self.min_advance_sb())),
267                 8usize => Some(Field::new("max_before_bl", self.max_before_bl())),
268                 9usize => Some(Field::new("min_after_bl", self.min_after_bl())),
269                 10usize => Some(Field::new("pad1", self.pad1())),
270                 11usize => Some(Field::new("pad2", self.pad2())),
271                 _ => None,
272             }),
273             data,
274         }
275     }
276 }
277 
278 /// [Bitmap flags](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#bitmap-flags).
279 #[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
280 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
281 pub struct BitmapFlags {
282     bits: u8,
283 }
284 
285 impl BitmapFlags {
286     /// Horizontal
287     pub const HORIZONTAL_METRICS: Self = Self { bits: 0x01 };
288 
289     /// Vertical
290     pub const VERTICAL_METRICS: Self = Self { bits: 0x02 };
291 }
292 
293 impl BitmapFlags {
294     ///  Returns an empty set of flags.
295     #[inline]
empty() -> Self296     pub const fn empty() -> Self {
297         Self { bits: 0 }
298     }
299 
300     /// Returns the set containing all flags.
301     #[inline]
all() -> Self302     pub const fn all() -> Self {
303         Self {
304             bits: Self::HORIZONTAL_METRICS.bits | Self::VERTICAL_METRICS.bits,
305         }
306     }
307 
308     /// Returns the raw value of the flags currently stored.
309     #[inline]
bits(&self) -> u8310     pub const fn bits(&self) -> u8 {
311         self.bits
312     }
313 
314     /// Convert from underlying bit representation, unless that
315     /// representation contains bits that do not correspond to a flag.
316     #[inline]
from_bits(bits: u8) -> Option<Self>317     pub const fn from_bits(bits: u8) -> Option<Self> {
318         if (bits & !Self::all().bits()) == 0 {
319             Some(Self { bits })
320         } else {
321             None
322         }
323     }
324 
325     /// Convert from underlying bit representation, dropping any bits
326     /// that do not correspond to flags.
327     #[inline]
from_bits_truncate(bits: u8) -> Self328     pub const fn from_bits_truncate(bits: u8) -> Self {
329         Self {
330             bits: bits & Self::all().bits,
331         }
332     }
333 
334     /// Returns `true` if no flags are currently stored.
335     #[inline]
is_empty(&self) -> bool336     pub const fn is_empty(&self) -> bool {
337         self.bits() == Self::empty().bits()
338     }
339 
340     /// Returns `true` if there are flags common to both `self` and `other`.
341     #[inline]
intersects(&self, other: Self) -> bool342     pub const fn intersects(&self, other: Self) -> bool {
343         !(Self {
344             bits: self.bits & other.bits,
345         })
346         .is_empty()
347     }
348 
349     /// Returns `true` if all of the flags in `other` are contained within `self`.
350     #[inline]
contains(&self, other: Self) -> bool351     pub const fn contains(&self, other: Self) -> bool {
352         (self.bits & other.bits) == other.bits
353     }
354 
355     /// Inserts the specified flags in-place.
356     #[inline]
insert(&mut self, other: Self)357     pub fn insert(&mut self, other: Self) {
358         self.bits |= other.bits;
359     }
360 
361     /// Removes the specified flags in-place.
362     #[inline]
remove(&mut self, other: Self)363     pub fn remove(&mut self, other: Self) {
364         self.bits &= !other.bits;
365     }
366 
367     /// Toggles the specified flags in-place.
368     #[inline]
toggle(&mut self, other: Self)369     pub fn toggle(&mut self, other: Self) {
370         self.bits ^= other.bits;
371     }
372 
373     /// Returns the intersection between the flags in `self` and
374     /// `other`.
375     ///
376     /// Specifically, the returned set contains only the flags which are
377     /// present in *both* `self` *and* `other`.
378     ///
379     /// This is equivalent to using the `&` operator (e.g.
380     /// [`ops::BitAnd`]), as in `flags & other`.
381     ///
382     /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
383     #[inline]
384     #[must_use]
intersection(self, other: Self) -> Self385     pub const fn intersection(self, other: Self) -> Self {
386         Self {
387             bits: self.bits & other.bits,
388         }
389     }
390 
391     /// Returns the union of between the flags in `self` and `other`.
392     ///
393     /// Specifically, the returned set contains all flags which are
394     /// present in *either* `self` *or* `other`, including any which are
395     /// present in both.
396     ///
397     /// This is equivalent to using the `|` operator (e.g.
398     /// [`ops::BitOr`]), as in `flags | other`.
399     ///
400     /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
401     #[inline]
402     #[must_use]
union(self, other: Self) -> Self403     pub const fn union(self, other: Self) -> Self {
404         Self {
405             bits: self.bits | other.bits,
406         }
407     }
408 
409     /// Returns the difference between the flags in `self` and `other`.
410     ///
411     /// Specifically, the returned set contains all flags present in
412     /// `self`, except for the ones present in `other`.
413     ///
414     /// It is also conceptually equivalent to the "bit-clear" operation:
415     /// `flags & !other` (and this syntax is also supported).
416     ///
417     /// This is equivalent to using the `-` operator (e.g.
418     /// [`ops::Sub`]), as in `flags - other`.
419     ///
420     /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
421     #[inline]
422     #[must_use]
difference(self, other: Self) -> Self423     pub const fn difference(self, other: Self) -> Self {
424         Self {
425             bits: self.bits & !other.bits,
426         }
427     }
428 }
429 
430 impl std::ops::BitOr for BitmapFlags {
431     type Output = Self;
432 
433     /// Returns the union of the two sets of flags.
434     #[inline]
bitor(self, other: BitmapFlags) -> Self435     fn bitor(self, other: BitmapFlags) -> Self {
436         Self {
437             bits: self.bits | other.bits,
438         }
439     }
440 }
441 
442 impl std::ops::BitOrAssign for BitmapFlags {
443     /// Adds the set of flags.
444     #[inline]
bitor_assign(&mut self, other: Self)445     fn bitor_assign(&mut self, other: Self) {
446         self.bits |= other.bits;
447     }
448 }
449 
450 impl std::ops::BitXor for BitmapFlags {
451     type Output = Self;
452 
453     /// Returns the left flags, but with all the right flags toggled.
454     #[inline]
bitxor(self, other: Self) -> Self455     fn bitxor(self, other: Self) -> Self {
456         Self {
457             bits: self.bits ^ other.bits,
458         }
459     }
460 }
461 
462 impl std::ops::BitXorAssign for BitmapFlags {
463     /// Toggles the set of flags.
464     #[inline]
bitxor_assign(&mut self, other: Self)465     fn bitxor_assign(&mut self, other: Self) {
466         self.bits ^= other.bits;
467     }
468 }
469 
470 impl std::ops::BitAnd for BitmapFlags {
471     type Output = Self;
472 
473     /// Returns the intersection between the two sets of flags.
474     #[inline]
bitand(self, other: Self) -> Self475     fn bitand(self, other: Self) -> Self {
476         Self {
477             bits: self.bits & other.bits,
478         }
479     }
480 }
481 
482 impl std::ops::BitAndAssign for BitmapFlags {
483     /// Disables all flags disabled in the set.
484     #[inline]
bitand_assign(&mut self, other: Self)485     fn bitand_assign(&mut self, other: Self) {
486         self.bits &= other.bits;
487     }
488 }
489 
490 impl std::ops::Sub for BitmapFlags {
491     type Output = Self;
492 
493     /// Returns the set difference of the two sets of flags.
494     #[inline]
sub(self, other: Self) -> Self495     fn sub(self, other: Self) -> Self {
496         Self {
497             bits: self.bits & !other.bits,
498         }
499     }
500 }
501 
502 impl std::ops::SubAssign for BitmapFlags {
503     /// Disables all flags enabled in the set.
504     #[inline]
sub_assign(&mut self, other: Self)505     fn sub_assign(&mut self, other: Self) {
506         self.bits &= !other.bits;
507     }
508 }
509 
510 impl std::ops::Not for BitmapFlags {
511     type Output = Self;
512 
513     /// Returns the complement of this set of flags.
514     #[inline]
not(self) -> Self515     fn not(self) -> Self {
516         Self { bits: !self.bits } & Self::all()
517     }
518 }
519 
520 impl std::fmt::Debug for BitmapFlags {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result521     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
522         let members: &[(&str, Self)] = &[
523             ("HORIZONTAL_METRICS", Self::HORIZONTAL_METRICS),
524             ("VERTICAL_METRICS", Self::VERTICAL_METRICS),
525         ];
526         let mut first = true;
527         for (name, value) in members {
528             if self.contains(*value) {
529                 if !first {
530                     f.write_str(" | ")?;
531                 }
532                 first = false;
533                 f.write_str(name)?;
534             }
535         }
536         if first {
537             f.write_str("(empty)")?;
538         }
539         Ok(())
540     }
541 }
542 
543 impl std::fmt::Binary for BitmapFlags {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result544     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
545         std::fmt::Binary::fmt(&self.bits, f)
546     }
547 }
548 
549 impl std::fmt::Octal for BitmapFlags {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result550     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
551         std::fmt::Octal::fmt(&self.bits, f)
552     }
553 }
554 
555 impl std::fmt::LowerHex for BitmapFlags {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result556     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
557         std::fmt::LowerHex::fmt(&self.bits, f)
558     }
559 }
560 
561 impl std::fmt::UpperHex for BitmapFlags {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result562     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
563         std::fmt::UpperHex::fmt(&self.bits, f)
564     }
565 }
566 
567 impl font_types::Scalar for BitmapFlags {
568     type Raw = <u8 as font_types::Scalar>::Raw;
to_raw(self) -> Self::Raw569     fn to_raw(self) -> Self::Raw {
570         self.bits().to_raw()
571     }
from_raw(raw: Self::Raw) -> Self572     fn from_raw(raw: Self::Raw) -> Self {
573         let t = <u8>::from_raw(raw);
574         Self::from_bits_truncate(t)
575     }
576 }
577 
578 #[cfg(feature = "traversal")]
579 impl<'a> From<BitmapFlags> for FieldType<'a> {
from(src: BitmapFlags) -> FieldType<'a>580     fn from(src: BitmapFlags) -> FieldType<'a> {
581         src.bits().into()
582     }
583 }
584 
585 /// [BigGlyphMetrics](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#bigglyphmetrics) record.
586 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
587 #[repr(C)]
588 #[repr(packed)]
589 pub struct BigGlyphMetrics {
590     /// Number of rows of data.
591     pub height: u8,
592     /// Number of columns of data.
593     pub width: u8,
594     /// Distance in pixels from the horizontal origin to the left edge of the bitmap.
595     pub hori_bearing_x: BigEndian<i8>,
596     /// Distance in pixels from the horizontal origin to the top edge of the bitmap.
597     pub hori_bearing_y: BigEndian<i8>,
598     /// Horizontal advance width in pixels.
599     pub hori_advance: u8,
600     /// Distance in pixels from the vertical origin to the left edge of the bitmap.
601     pub vert_bearing_x: BigEndian<i8>,
602     /// Distance in pixels from the vertical origin to the top edge of the bitmap.
603     pub vert_bearing_y: BigEndian<i8>,
604     /// Vertical advance width in pixels.
605     pub vert_advance: u8,
606 }
607 
608 impl BigGlyphMetrics {
609     /// Number of rows of data.
height(&self) -> u8610     pub fn height(&self) -> u8 {
611         self.height
612     }
613 
614     /// Number of columns of data.
width(&self) -> u8615     pub fn width(&self) -> u8 {
616         self.width
617     }
618 
619     /// Distance in pixels from the horizontal origin to the left edge of the bitmap.
hori_bearing_x(&self) -> i8620     pub fn hori_bearing_x(&self) -> i8 {
621         self.hori_bearing_x.get()
622     }
623 
624     /// Distance in pixels from the horizontal origin to the top edge of the bitmap.
hori_bearing_y(&self) -> i8625     pub fn hori_bearing_y(&self) -> i8 {
626         self.hori_bearing_y.get()
627     }
628 
629     /// Horizontal advance width in pixels.
hori_advance(&self) -> u8630     pub fn hori_advance(&self) -> u8 {
631         self.hori_advance
632     }
633 
634     /// Distance in pixels from the vertical origin to the left edge of the bitmap.
vert_bearing_x(&self) -> i8635     pub fn vert_bearing_x(&self) -> i8 {
636         self.vert_bearing_x.get()
637     }
638 
639     /// Distance in pixels from the vertical origin to the top edge of the bitmap.
vert_bearing_y(&self) -> i8640     pub fn vert_bearing_y(&self) -> i8 {
641         self.vert_bearing_y.get()
642     }
643 
644     /// Vertical advance width in pixels.
vert_advance(&self) -> u8645     pub fn vert_advance(&self) -> u8 {
646         self.vert_advance
647     }
648 }
649 
650 impl FixedSize for BigGlyphMetrics {
651     const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN
652         + u8::RAW_BYTE_LEN
653         + i8::RAW_BYTE_LEN
654         + i8::RAW_BYTE_LEN
655         + u8::RAW_BYTE_LEN
656         + i8::RAW_BYTE_LEN
657         + i8::RAW_BYTE_LEN
658         + u8::RAW_BYTE_LEN;
659 }
660 
661 impl sealed::Sealed for BigGlyphMetrics {}
662 
663 /// SAFETY: see the [`FromBytes`] trait documentation.
664 unsafe impl FromBytes for BigGlyphMetrics {
this_trait_should_only_be_implemented_in_generated_code()665     fn this_trait_should_only_be_implemented_in_generated_code() {}
666 }
667 
668 #[cfg(feature = "traversal")]
669 impl<'a> SomeRecord<'a> for BigGlyphMetrics {
traverse(self, data: FontData<'a>) -> RecordResolver<'a>670     fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
671         RecordResolver {
672             name: "BigGlyphMetrics",
673             get_field: Box::new(move |idx, _data| match idx {
674                 0usize => Some(Field::new("height", self.height())),
675                 1usize => Some(Field::new("width", self.width())),
676                 2usize => Some(Field::new("hori_bearing_x", self.hori_bearing_x())),
677                 3usize => Some(Field::new("hori_bearing_y", self.hori_bearing_y())),
678                 4usize => Some(Field::new("hori_advance", self.hori_advance())),
679                 5usize => Some(Field::new("vert_bearing_x", self.vert_bearing_x())),
680                 6usize => Some(Field::new("vert_bearing_y", self.vert_bearing_y())),
681                 7usize => Some(Field::new("vert_advance", self.vert_advance())),
682                 _ => None,
683             }),
684             data,
685         }
686     }
687 }
688 
689 /// [SmallGlyphMetrics](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#smallglyphmetrics) record.
690 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
691 #[repr(C)]
692 #[repr(packed)]
693 pub struct SmallGlyphMetrics {
694     /// Number of rows of data.
695     pub height: u8,
696     /// Number of columns of data.
697     pub width: u8,
698     /// Distance in pixels from the horizontal origin to the left edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the top edge of the bitmap (for vertical text).
699     pub bearing_x: BigEndian<i8>,
700     /// Distance in pixels from the horizontal origin to the top edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the left edge of the bitmap (for vertical text).
701     pub bearing_y: BigEndian<i8>,
702     /// Horizontal or vertical advance width in pixels.
703     pub advance: u8,
704 }
705 
706 impl SmallGlyphMetrics {
707     /// Number of rows of data.
height(&self) -> u8708     pub fn height(&self) -> u8 {
709         self.height
710     }
711 
712     /// Number of columns of data.
width(&self) -> u8713     pub fn width(&self) -> u8 {
714         self.width
715     }
716 
717     /// Distance in pixels from the horizontal origin to the left edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the top edge of the bitmap (for vertical text).
bearing_x(&self) -> i8718     pub fn bearing_x(&self) -> i8 {
719         self.bearing_x.get()
720     }
721 
722     /// Distance in pixels from the horizontal origin to the top edge of the bitmap (for horizontal text); or distance in pixels from the vertical origin to the left edge of the bitmap (for vertical text).
bearing_y(&self) -> i8723     pub fn bearing_y(&self) -> i8 {
724         self.bearing_y.get()
725     }
726 
727     /// Horizontal or vertical advance width in pixels.
advance(&self) -> u8728     pub fn advance(&self) -> u8 {
729         self.advance
730     }
731 }
732 
733 impl FixedSize for SmallGlyphMetrics {
734     const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN
735         + u8::RAW_BYTE_LEN
736         + i8::RAW_BYTE_LEN
737         + i8::RAW_BYTE_LEN
738         + u8::RAW_BYTE_LEN;
739 }
740 
741 impl sealed::Sealed for SmallGlyphMetrics {}
742 
743 /// SAFETY: see the [`FromBytes`] trait documentation.
744 unsafe impl FromBytes for SmallGlyphMetrics {
this_trait_should_only_be_implemented_in_generated_code()745     fn this_trait_should_only_be_implemented_in_generated_code() {}
746 }
747 
748 #[cfg(feature = "traversal")]
749 impl<'a> SomeRecord<'a> for SmallGlyphMetrics {
traverse(self, data: FontData<'a>) -> RecordResolver<'a>750     fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
751         RecordResolver {
752             name: "SmallGlyphMetrics",
753             get_field: Box::new(move |idx, _data| match idx {
754                 0usize => Some(Field::new("height", self.height())),
755                 1usize => Some(Field::new("width", self.width())),
756                 2usize => Some(Field::new("bearing_x", self.bearing_x())),
757                 3usize => Some(Field::new("bearing_y", self.bearing_y())),
758                 4usize => Some(Field::new("advance", self.advance())),
759                 _ => None,
760             }),
761             data,
762         }
763     }
764 }
765 
766 /// [IndexSubtableArray](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtablearray) table.
767 #[derive(Debug, Clone, Copy)]
768 #[doc(hidden)]
769 pub struct IndexSubtableArrayMarker {}
770 
771 impl IndexSubtableArrayMarker {
first_glyph_index_byte_range(&self) -> Range<usize>772     fn first_glyph_index_byte_range(&self) -> Range<usize> {
773         let start = 0;
774         start..start + GlyphId::RAW_BYTE_LEN
775     }
last_glyph_index_byte_range(&self) -> Range<usize>776     fn last_glyph_index_byte_range(&self) -> Range<usize> {
777         let start = self.first_glyph_index_byte_range().end;
778         start..start + GlyphId::RAW_BYTE_LEN
779     }
additional_offset_to_index_subtable_byte_range(&self) -> Range<usize>780     fn additional_offset_to_index_subtable_byte_range(&self) -> Range<usize> {
781         let start = self.last_glyph_index_byte_range().end;
782         start..start + u32::RAW_BYTE_LEN
783     }
784 }
785 
786 impl<'a> FontRead<'a> for IndexSubtableArray<'a> {
read(data: FontData<'a>) -> Result<Self, ReadError>787     fn read(data: FontData<'a>) -> Result<Self, ReadError> {
788         let mut cursor = data.cursor();
789         cursor.advance::<GlyphId>();
790         cursor.advance::<GlyphId>();
791         cursor.advance::<u32>();
792         cursor.finish(IndexSubtableArrayMarker {})
793     }
794 }
795 
796 /// [IndexSubtableArray](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtablearray) table.
797 pub type IndexSubtableArray<'a> = TableRef<'a, IndexSubtableArrayMarker>;
798 
799 impl<'a> IndexSubtableArray<'a> {
800     /// First glyph ID of this range.
first_glyph_index(&self) -> GlyphId801     pub fn first_glyph_index(&self) -> GlyphId {
802         let range = self.shape.first_glyph_index_byte_range();
803         self.data.read_at(range.start).unwrap()
804     }
805 
806     /// Last glyph ID of this range (inclusive).
last_glyph_index(&self) -> GlyphId807     pub fn last_glyph_index(&self) -> GlyphId {
808         let range = self.shape.last_glyph_index_byte_range();
809         self.data.read_at(range.start).unwrap()
810     }
811 
812     /// Add to indexSubTableArrayOffset to get offset from beginning of EBLC.
additional_offset_to_index_subtable(&self) -> u32813     pub fn additional_offset_to_index_subtable(&self) -> u32 {
814         let range = self.shape.additional_offset_to_index_subtable_byte_range();
815         self.data.read_at(range.start).unwrap()
816     }
817 }
818 
819 #[cfg(feature = "traversal")]
820 impl<'a> SomeTable<'a> for IndexSubtableArray<'a> {
type_name(&self) -> &str821     fn type_name(&self) -> &str {
822         "IndexSubtableArray"
823     }
get_field(&self, idx: usize) -> Option<Field<'a>>824     fn get_field(&self, idx: usize) -> Option<Field<'a>> {
825         match idx {
826             0usize => Some(Field::new("first_glyph_index", self.first_glyph_index())),
827             1usize => Some(Field::new("last_glyph_index", self.last_glyph_index())),
828             2usize => Some(Field::new(
829                 "additional_offset_to_index_subtable",
830                 self.additional_offset_to_index_subtable(),
831             )),
832             _ => None,
833         }
834     }
835 }
836 
837 #[cfg(feature = "traversal")]
838 impl<'a> std::fmt::Debug for IndexSubtableArray<'a> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result839     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
840         (self as &dyn SomeTable<'a>).fmt(f)
841     }
842 }
843 
844 /// [IndexSubtables](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtables) format type.
845 #[derive(Clone)]
846 pub enum IndexSubtable<'a> {
847     Format1(IndexSubtable1<'a>),
848     Format2(IndexSubtable2<'a>),
849     Format3(IndexSubtable3<'a>),
850     Format4(IndexSubtable4<'a>),
851     Format5(IndexSubtable5<'a>),
852 }
853 
854 impl<'a> IndexSubtable<'a> {
855     /// Format of this IndexSubTable.
index_format(&self) -> u16856     pub fn index_format(&self) -> u16 {
857         match self {
858             Self::Format1(item) => item.index_format(),
859             Self::Format2(item) => item.index_format(),
860             Self::Format3(item) => item.index_format(),
861             Self::Format4(item) => item.index_format(),
862             Self::Format5(item) => item.index_format(),
863         }
864     }
865 
866     /// Format of EBDT image data.
image_format(&self) -> u16867     pub fn image_format(&self) -> u16 {
868         match self {
869             Self::Format1(item) => item.image_format(),
870             Self::Format2(item) => item.image_format(),
871             Self::Format3(item) => item.image_format(),
872             Self::Format4(item) => item.image_format(),
873             Self::Format5(item) => item.image_format(),
874         }
875     }
876 
877     /// Offset to image data in EBDT table.
image_data_offset(&self) -> u32878     pub fn image_data_offset(&self) -> u32 {
879         match self {
880             Self::Format1(item) => item.image_data_offset(),
881             Self::Format2(item) => item.image_data_offset(),
882             Self::Format3(item) => item.image_data_offset(),
883             Self::Format4(item) => item.image_data_offset(),
884             Self::Format5(item) => item.image_data_offset(),
885         }
886     }
887 }
888 
889 impl<'a> FontRead<'a> for IndexSubtable<'a> {
read(data: FontData<'a>) -> Result<Self, ReadError>890     fn read(data: FontData<'a>) -> Result<Self, ReadError> {
891         let format: u16 = data.read_at(0usize)?;
892         match format {
893             IndexSubtable1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
894             IndexSubtable2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
895             IndexSubtable3Marker::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
896             IndexSubtable4Marker::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
897             IndexSubtable5Marker::FORMAT => Ok(Self::Format5(FontRead::read(data)?)),
898             other => Err(ReadError::InvalidFormat(other.into())),
899         }
900     }
901 }
902 
903 #[cfg(feature = "traversal")]
904 impl<'a> IndexSubtable<'a> {
dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a>905     fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
906         match self {
907             Self::Format1(table) => table,
908             Self::Format2(table) => table,
909             Self::Format3(table) => table,
910             Self::Format4(table) => table,
911             Self::Format5(table) => table,
912         }
913     }
914 }
915 
916 #[cfg(feature = "traversal")]
917 impl<'a> std::fmt::Debug for IndexSubtable<'a> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result918     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
919         self.dyn_inner().fmt(f)
920     }
921 }
922 
923 #[cfg(feature = "traversal")]
924 impl<'a> SomeTable<'a> for IndexSubtable<'a> {
type_name(&self) -> &str925     fn type_name(&self) -> &str {
926         self.dyn_inner().type_name()
927     }
get_field(&self, idx: usize) -> Option<Field<'a>>928     fn get_field(&self, idx: usize) -> Option<Field<'a>> {
929         self.dyn_inner().get_field(idx)
930     }
931 }
932 
933 impl Format<u16> for IndexSubtable1Marker {
934     const FORMAT: u16 = 1;
935 }
936 
937 /// [IndexSubTable1](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable1-variable-metrics-glyphs-with-4-byte-offsets): variable-metrics glyphs with 4-byte offsets.
938 #[derive(Debug, Clone, Copy)]
939 #[doc(hidden)]
940 pub struct IndexSubtable1Marker {
941     sbit_offsets_byte_len: usize,
942 }
943 
944 impl IndexSubtable1Marker {
index_format_byte_range(&self) -> Range<usize>945     fn index_format_byte_range(&self) -> Range<usize> {
946         let start = 0;
947         start..start + u16::RAW_BYTE_LEN
948     }
image_format_byte_range(&self) -> Range<usize>949     fn image_format_byte_range(&self) -> Range<usize> {
950         let start = self.index_format_byte_range().end;
951         start..start + u16::RAW_BYTE_LEN
952     }
image_data_offset_byte_range(&self) -> Range<usize>953     fn image_data_offset_byte_range(&self) -> Range<usize> {
954         let start = self.image_format_byte_range().end;
955         start..start + u32::RAW_BYTE_LEN
956     }
sbit_offsets_byte_range(&self) -> Range<usize>957     fn sbit_offsets_byte_range(&self) -> Range<usize> {
958         let start = self.image_data_offset_byte_range().end;
959         start..start + self.sbit_offsets_byte_len
960     }
961 }
962 
963 impl<'a> FontRead<'a> for IndexSubtable1<'a> {
read(data: FontData<'a>) -> Result<Self, ReadError>964     fn read(data: FontData<'a>) -> Result<Self, ReadError> {
965         let mut cursor = data.cursor();
966         cursor.advance::<u16>();
967         cursor.advance::<u16>();
968         cursor.advance::<u32>();
969         let sbit_offsets_byte_len =
970             cursor.remaining_bytes() / u32::RAW_BYTE_LEN * u32::RAW_BYTE_LEN;
971         cursor.advance_by(sbit_offsets_byte_len);
972         cursor.finish(IndexSubtable1Marker {
973             sbit_offsets_byte_len,
974         })
975     }
976 }
977 
978 /// [IndexSubTable1](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable1-variable-metrics-glyphs-with-4-byte-offsets): variable-metrics glyphs with 4-byte offsets.
979 pub type IndexSubtable1<'a> = TableRef<'a, IndexSubtable1Marker>;
980 
981 impl<'a> IndexSubtable1<'a> {
982     /// Format of this IndexSubTable.
index_format(&self) -> u16983     pub fn index_format(&self) -> u16 {
984         let range = self.shape.index_format_byte_range();
985         self.data.read_at(range.start).unwrap()
986     }
987 
988     /// Format of EBDT image data.
image_format(&self) -> u16989     pub fn image_format(&self) -> u16 {
990         let range = self.shape.image_format_byte_range();
991         self.data.read_at(range.start).unwrap()
992     }
993 
994     /// Offset to image data in EBDT table.
image_data_offset(&self) -> u32995     pub fn image_data_offset(&self) -> u32 {
996         let range = self.shape.image_data_offset_byte_range();
997         self.data.read_at(range.start).unwrap()
998     }
999 
sbit_offsets(&self) -> &'a [BigEndian<u32>]1000     pub fn sbit_offsets(&self) -> &'a [BigEndian<u32>] {
1001         let range = self.shape.sbit_offsets_byte_range();
1002         self.data.read_array(range).unwrap()
1003     }
1004 }
1005 
1006 #[cfg(feature = "traversal")]
1007 impl<'a> SomeTable<'a> for IndexSubtable1<'a> {
type_name(&self) -> &str1008     fn type_name(&self) -> &str {
1009         "IndexSubtable1"
1010     }
get_field(&self, idx: usize) -> Option<Field<'a>>1011     fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1012         match idx {
1013             0usize => Some(Field::new("index_format", self.index_format())),
1014             1usize => Some(Field::new("image_format", self.image_format())),
1015             2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
1016             3usize => Some(Field::new("sbit_offsets", self.sbit_offsets())),
1017             _ => None,
1018         }
1019     }
1020 }
1021 
1022 #[cfg(feature = "traversal")]
1023 impl<'a> std::fmt::Debug for IndexSubtable1<'a> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result1024     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1025         (self as &dyn SomeTable<'a>).fmt(f)
1026     }
1027 }
1028 
1029 impl Format<u16> for IndexSubtable2Marker {
1030     const FORMAT: u16 = 2;
1031 }
1032 
1033 /// [IndexSubTable2](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable2-all-glyphs-have-identical-metrics): all glyphs have identical metrics.
1034 #[derive(Debug, Clone, Copy)]
1035 #[doc(hidden)]
1036 pub struct IndexSubtable2Marker {
1037     big_metrics_byte_len: usize,
1038 }
1039 
1040 impl IndexSubtable2Marker {
index_format_byte_range(&self) -> Range<usize>1041     fn index_format_byte_range(&self) -> Range<usize> {
1042         let start = 0;
1043         start..start + u16::RAW_BYTE_LEN
1044     }
image_format_byte_range(&self) -> Range<usize>1045     fn image_format_byte_range(&self) -> Range<usize> {
1046         let start = self.index_format_byte_range().end;
1047         start..start + u16::RAW_BYTE_LEN
1048     }
image_data_offset_byte_range(&self) -> Range<usize>1049     fn image_data_offset_byte_range(&self) -> Range<usize> {
1050         let start = self.image_format_byte_range().end;
1051         start..start + u32::RAW_BYTE_LEN
1052     }
image_size_byte_range(&self) -> Range<usize>1053     fn image_size_byte_range(&self) -> Range<usize> {
1054         let start = self.image_data_offset_byte_range().end;
1055         start..start + u32::RAW_BYTE_LEN
1056     }
big_metrics_byte_range(&self) -> Range<usize>1057     fn big_metrics_byte_range(&self) -> Range<usize> {
1058         let start = self.image_size_byte_range().end;
1059         start..start + self.big_metrics_byte_len
1060     }
1061 }
1062 
1063 impl<'a> FontRead<'a> for IndexSubtable2<'a> {
read(data: FontData<'a>) -> Result<Self, ReadError>1064     fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1065         let mut cursor = data.cursor();
1066         cursor.advance::<u16>();
1067         cursor.advance::<u16>();
1068         cursor.advance::<u32>();
1069         cursor.advance::<u32>();
1070         let big_metrics_byte_len = BigGlyphMetrics::RAW_BYTE_LEN;
1071         cursor.advance_by(big_metrics_byte_len);
1072         cursor.finish(IndexSubtable2Marker {
1073             big_metrics_byte_len,
1074         })
1075     }
1076 }
1077 
1078 /// [IndexSubTable2](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable2-all-glyphs-have-identical-metrics): all glyphs have identical metrics.
1079 pub type IndexSubtable2<'a> = TableRef<'a, IndexSubtable2Marker>;
1080 
1081 impl<'a> IndexSubtable2<'a> {
1082     /// Format of this IndexSubTable.
index_format(&self) -> u161083     pub fn index_format(&self) -> u16 {
1084         let range = self.shape.index_format_byte_range();
1085         self.data.read_at(range.start).unwrap()
1086     }
1087 
1088     /// Format of EBDT image data.
image_format(&self) -> u161089     pub fn image_format(&self) -> u16 {
1090         let range = self.shape.image_format_byte_range();
1091         self.data.read_at(range.start).unwrap()
1092     }
1093 
1094     /// Offset to image data in EBDT table.
image_data_offset(&self) -> u321095     pub fn image_data_offset(&self) -> u32 {
1096         let range = self.shape.image_data_offset_byte_range();
1097         self.data.read_at(range.start).unwrap()
1098     }
1099 
1100     /// All the glyphs are of the same size.
image_size(&self) -> u321101     pub fn image_size(&self) -> u32 {
1102         let range = self.shape.image_size_byte_range();
1103         self.data.read_at(range.start).unwrap()
1104     }
1105 
1106     /// All glyphs have the same metrics; glyph data may be compressed, byte-aligned, or bit-aligned.
big_metrics(&self) -> &'a [BigGlyphMetrics]1107     pub fn big_metrics(&self) -> &'a [BigGlyphMetrics] {
1108         let range = self.shape.big_metrics_byte_range();
1109         self.data.read_array(range).unwrap()
1110     }
1111 }
1112 
1113 #[cfg(feature = "traversal")]
1114 impl<'a> SomeTable<'a> for IndexSubtable2<'a> {
type_name(&self) -> &str1115     fn type_name(&self) -> &str {
1116         "IndexSubtable2"
1117     }
get_field(&self, idx: usize) -> Option<Field<'a>>1118     fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1119         match idx {
1120             0usize => Some(Field::new("index_format", self.index_format())),
1121             1usize => Some(Field::new("image_format", self.image_format())),
1122             2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
1123             3usize => Some(Field::new("image_size", self.image_size())),
1124             4usize => Some(Field::new(
1125                 "big_metrics",
1126                 traversal::FieldType::array_of_records(
1127                     stringify!(BigGlyphMetrics),
1128                     self.big_metrics(),
1129                     self.offset_data(),
1130                 ),
1131             )),
1132             _ => None,
1133         }
1134     }
1135 }
1136 
1137 #[cfg(feature = "traversal")]
1138 impl<'a> std::fmt::Debug for IndexSubtable2<'a> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result1139     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1140         (self as &dyn SomeTable<'a>).fmt(f)
1141     }
1142 }
1143 
1144 impl Format<u16> for IndexSubtable3Marker {
1145     const FORMAT: u16 = 3;
1146 }
1147 
1148 /// [IndexSubTable3](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with 2-byte offsets.
1149 #[derive(Debug, Clone, Copy)]
1150 #[doc(hidden)]
1151 pub struct IndexSubtable3Marker {
1152     sbit_offsets_byte_len: usize,
1153 }
1154 
1155 impl IndexSubtable3Marker {
index_format_byte_range(&self) -> Range<usize>1156     fn index_format_byte_range(&self) -> Range<usize> {
1157         let start = 0;
1158         start..start + u16::RAW_BYTE_LEN
1159     }
image_format_byte_range(&self) -> Range<usize>1160     fn image_format_byte_range(&self) -> Range<usize> {
1161         let start = self.index_format_byte_range().end;
1162         start..start + u16::RAW_BYTE_LEN
1163     }
image_data_offset_byte_range(&self) -> Range<usize>1164     fn image_data_offset_byte_range(&self) -> Range<usize> {
1165         let start = self.image_format_byte_range().end;
1166         start..start + u32::RAW_BYTE_LEN
1167     }
sbit_offsets_byte_range(&self) -> Range<usize>1168     fn sbit_offsets_byte_range(&self) -> Range<usize> {
1169         let start = self.image_data_offset_byte_range().end;
1170         start..start + self.sbit_offsets_byte_len
1171     }
1172 }
1173 
1174 impl<'a> FontRead<'a> for IndexSubtable3<'a> {
read(data: FontData<'a>) -> Result<Self, ReadError>1175     fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1176         let mut cursor = data.cursor();
1177         cursor.advance::<u16>();
1178         cursor.advance::<u16>();
1179         cursor.advance::<u32>();
1180         let sbit_offsets_byte_len =
1181             cursor.remaining_bytes() / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN;
1182         cursor.advance_by(sbit_offsets_byte_len);
1183         cursor.finish(IndexSubtable3Marker {
1184             sbit_offsets_byte_len,
1185         })
1186     }
1187 }
1188 
1189 /// [IndexSubTable3](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with 2-byte offsets.
1190 pub type IndexSubtable3<'a> = TableRef<'a, IndexSubtable3Marker>;
1191 
1192 impl<'a> IndexSubtable3<'a> {
1193     /// Format of this IndexSubTable.
index_format(&self) -> u161194     pub fn index_format(&self) -> u16 {
1195         let range = self.shape.index_format_byte_range();
1196         self.data.read_at(range.start).unwrap()
1197     }
1198 
1199     /// Format of EBDT image data.
image_format(&self) -> u161200     pub fn image_format(&self) -> u16 {
1201         let range = self.shape.image_format_byte_range();
1202         self.data.read_at(range.start).unwrap()
1203     }
1204 
1205     /// Offset to image data in EBDT table.
image_data_offset(&self) -> u321206     pub fn image_data_offset(&self) -> u32 {
1207         let range = self.shape.image_data_offset_byte_range();
1208         self.data.read_at(range.start).unwrap()
1209     }
1210 
sbit_offsets(&self) -> &'a [BigEndian<u16>]1211     pub fn sbit_offsets(&self) -> &'a [BigEndian<u16>] {
1212         let range = self.shape.sbit_offsets_byte_range();
1213         self.data.read_array(range).unwrap()
1214     }
1215 }
1216 
1217 #[cfg(feature = "traversal")]
1218 impl<'a> SomeTable<'a> for IndexSubtable3<'a> {
type_name(&self) -> &str1219     fn type_name(&self) -> &str {
1220         "IndexSubtable3"
1221     }
get_field(&self, idx: usize) -> Option<Field<'a>>1222     fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1223         match idx {
1224             0usize => Some(Field::new("index_format", self.index_format())),
1225             1usize => Some(Field::new("image_format", self.image_format())),
1226             2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
1227             3usize => Some(Field::new("sbit_offsets", self.sbit_offsets())),
1228             _ => None,
1229         }
1230     }
1231 }
1232 
1233 #[cfg(feature = "traversal")]
1234 impl<'a> std::fmt::Debug for IndexSubtable3<'a> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result1235     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1236         (self as &dyn SomeTable<'a>).fmt(f)
1237     }
1238 }
1239 
1240 impl Format<u16> for IndexSubtable4Marker {
1241     const FORMAT: u16 = 4;
1242 }
1243 
1244 /// [IndexSubTable4](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with sparse glyph codes.
1245 #[derive(Debug, Clone, Copy)]
1246 #[doc(hidden)]
1247 pub struct IndexSubtable4Marker {
1248     glyph_array_byte_len: usize,
1249 }
1250 
1251 impl IndexSubtable4Marker {
index_format_byte_range(&self) -> Range<usize>1252     fn index_format_byte_range(&self) -> Range<usize> {
1253         let start = 0;
1254         start..start + u16::RAW_BYTE_LEN
1255     }
image_format_byte_range(&self) -> Range<usize>1256     fn image_format_byte_range(&self) -> Range<usize> {
1257         let start = self.index_format_byte_range().end;
1258         start..start + u16::RAW_BYTE_LEN
1259     }
image_data_offset_byte_range(&self) -> Range<usize>1260     fn image_data_offset_byte_range(&self) -> Range<usize> {
1261         let start = self.image_format_byte_range().end;
1262         start..start + u32::RAW_BYTE_LEN
1263     }
num_glyphs_byte_range(&self) -> Range<usize>1264     fn num_glyphs_byte_range(&self) -> Range<usize> {
1265         let start = self.image_data_offset_byte_range().end;
1266         start..start + u32::RAW_BYTE_LEN
1267     }
glyph_array_byte_range(&self) -> Range<usize>1268     fn glyph_array_byte_range(&self) -> Range<usize> {
1269         let start = self.num_glyphs_byte_range().end;
1270         start..start + self.glyph_array_byte_len
1271     }
1272 }
1273 
1274 impl<'a> FontRead<'a> for IndexSubtable4<'a> {
read(data: FontData<'a>) -> Result<Self, ReadError>1275     fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1276         let mut cursor = data.cursor();
1277         cursor.advance::<u16>();
1278         cursor.advance::<u16>();
1279         cursor.advance::<u32>();
1280         let num_glyphs: u32 = cursor.read()?;
1281         let glyph_array_byte_len =
1282             transforms::add(num_glyphs, 1_usize) * GlyphIdOffsetPair::RAW_BYTE_LEN;
1283         cursor.advance_by(glyph_array_byte_len);
1284         cursor.finish(IndexSubtable4Marker {
1285             glyph_array_byte_len,
1286         })
1287     }
1288 }
1289 
1290 /// [IndexSubTable4](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable3-variable-metrics-glyphs-with-2-byte-offsets): variable-metrics glyphs with sparse glyph codes.
1291 pub type IndexSubtable4<'a> = TableRef<'a, IndexSubtable4Marker>;
1292 
1293 impl<'a> IndexSubtable4<'a> {
1294     /// Format of this IndexSubTable.
index_format(&self) -> u161295     pub fn index_format(&self) -> u16 {
1296         let range = self.shape.index_format_byte_range();
1297         self.data.read_at(range.start).unwrap()
1298     }
1299 
1300     /// Format of EBDT image data.
image_format(&self) -> u161301     pub fn image_format(&self) -> u16 {
1302         let range = self.shape.image_format_byte_range();
1303         self.data.read_at(range.start).unwrap()
1304     }
1305 
1306     /// Offset to image data in EBDT table.
image_data_offset(&self) -> u321307     pub fn image_data_offset(&self) -> u32 {
1308         let range = self.shape.image_data_offset_byte_range();
1309         self.data.read_at(range.start).unwrap()
1310     }
1311 
1312     /// Array length.
num_glyphs(&self) -> u321313     pub fn num_glyphs(&self) -> u32 {
1314         let range = self.shape.num_glyphs_byte_range();
1315         self.data.read_at(range.start).unwrap()
1316     }
1317 
1318     /// One per glyph.
glyph_array(&self) -> &'a [GlyphIdOffsetPair]1319     pub fn glyph_array(&self) -> &'a [GlyphIdOffsetPair] {
1320         let range = self.shape.glyph_array_byte_range();
1321         self.data.read_array(range).unwrap()
1322     }
1323 }
1324 
1325 #[cfg(feature = "traversal")]
1326 impl<'a> SomeTable<'a> for IndexSubtable4<'a> {
type_name(&self) -> &str1327     fn type_name(&self) -> &str {
1328         "IndexSubtable4"
1329     }
get_field(&self, idx: usize) -> Option<Field<'a>>1330     fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1331         match idx {
1332             0usize => Some(Field::new("index_format", self.index_format())),
1333             1usize => Some(Field::new("image_format", self.image_format())),
1334             2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
1335             3usize => Some(Field::new("num_glyphs", self.num_glyphs())),
1336             4usize => Some(Field::new(
1337                 "glyph_array",
1338                 traversal::FieldType::array_of_records(
1339                     stringify!(GlyphIdOffsetPair),
1340                     self.glyph_array(),
1341                     self.offset_data(),
1342                 ),
1343             )),
1344             _ => None,
1345         }
1346     }
1347 }
1348 
1349 #[cfg(feature = "traversal")]
1350 impl<'a> std::fmt::Debug for IndexSubtable4<'a> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result1351     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1352         (self as &dyn SomeTable<'a>).fmt(f)
1353     }
1354 }
1355 
1356 /// [GlyphIdOffsetPair](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#glyphidoffsetpair-record) record.
1357 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1358 #[repr(C)]
1359 #[repr(packed)]
1360 pub struct GlyphIdOffsetPair {
1361     /// Glyph ID of glyph present.
1362     pub glyph_id: BigEndian<GlyphId>,
1363     /// Location in EBDT.
1364     pub sbit_offset: BigEndian<u16>,
1365 }
1366 
1367 impl GlyphIdOffsetPair {
1368     /// Glyph ID of glyph present.
glyph_id(&self) -> GlyphId1369     pub fn glyph_id(&self) -> GlyphId {
1370         self.glyph_id.get()
1371     }
1372 
1373     /// Location in EBDT.
sbit_offset(&self) -> u161374     pub fn sbit_offset(&self) -> u16 {
1375         self.sbit_offset.get()
1376     }
1377 }
1378 
1379 impl FixedSize for GlyphIdOffsetPair {
1380     const RAW_BYTE_LEN: usize = GlyphId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1381 }
1382 
1383 impl sealed::Sealed for GlyphIdOffsetPair {}
1384 
1385 /// SAFETY: see the [`FromBytes`] trait documentation.
1386 unsafe impl FromBytes for GlyphIdOffsetPair {
this_trait_should_only_be_implemented_in_generated_code()1387     fn this_trait_should_only_be_implemented_in_generated_code() {}
1388 }
1389 
1390 #[cfg(feature = "traversal")]
1391 impl<'a> SomeRecord<'a> for GlyphIdOffsetPair {
traverse(self, data: FontData<'a>) -> RecordResolver<'a>1392     fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1393         RecordResolver {
1394             name: "GlyphIdOffsetPair",
1395             get_field: Box::new(move |idx, _data| match idx {
1396                 0usize => Some(Field::new("glyph_id", self.glyph_id())),
1397                 1usize => Some(Field::new("sbit_offset", self.sbit_offset())),
1398                 _ => None,
1399             }),
1400             data,
1401         }
1402     }
1403 }
1404 
1405 impl Format<u16> for IndexSubtable5Marker {
1406     const FORMAT: u16 = 5;
1407 }
1408 
1409 /// [IndexSubTable5](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable5-constant-metrics-glyphs-with-sparse-glyph-codes): constant-metrics glyphs with sparse glyph codes
1410 #[derive(Debug, Clone, Copy)]
1411 #[doc(hidden)]
1412 pub struct IndexSubtable5Marker {
1413     big_metrics_byte_len: usize,
1414     glyph_array_byte_len: usize,
1415 }
1416 
1417 impl IndexSubtable5Marker {
index_format_byte_range(&self) -> Range<usize>1418     fn index_format_byte_range(&self) -> Range<usize> {
1419         let start = 0;
1420         start..start + u16::RAW_BYTE_LEN
1421     }
image_format_byte_range(&self) -> Range<usize>1422     fn image_format_byte_range(&self) -> Range<usize> {
1423         let start = self.index_format_byte_range().end;
1424         start..start + u16::RAW_BYTE_LEN
1425     }
image_data_offset_byte_range(&self) -> Range<usize>1426     fn image_data_offset_byte_range(&self) -> Range<usize> {
1427         let start = self.image_format_byte_range().end;
1428         start..start + u32::RAW_BYTE_LEN
1429     }
image_size_byte_range(&self) -> Range<usize>1430     fn image_size_byte_range(&self) -> Range<usize> {
1431         let start = self.image_data_offset_byte_range().end;
1432         start..start + u32::RAW_BYTE_LEN
1433     }
big_metrics_byte_range(&self) -> Range<usize>1434     fn big_metrics_byte_range(&self) -> Range<usize> {
1435         let start = self.image_size_byte_range().end;
1436         start..start + self.big_metrics_byte_len
1437     }
num_glyphs_byte_range(&self) -> Range<usize>1438     fn num_glyphs_byte_range(&self) -> Range<usize> {
1439         let start = self.big_metrics_byte_range().end;
1440         start..start + u32::RAW_BYTE_LEN
1441     }
glyph_array_byte_range(&self) -> Range<usize>1442     fn glyph_array_byte_range(&self) -> Range<usize> {
1443         let start = self.num_glyphs_byte_range().end;
1444         start..start + self.glyph_array_byte_len
1445     }
1446 }
1447 
1448 impl<'a> FontRead<'a> for IndexSubtable5<'a> {
read(data: FontData<'a>) -> Result<Self, ReadError>1449     fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1450         let mut cursor = data.cursor();
1451         cursor.advance::<u16>();
1452         cursor.advance::<u16>();
1453         cursor.advance::<u32>();
1454         cursor.advance::<u32>();
1455         let big_metrics_byte_len = BigGlyphMetrics::RAW_BYTE_LEN;
1456         cursor.advance_by(big_metrics_byte_len);
1457         let num_glyphs: u32 = cursor.read()?;
1458         let glyph_array_byte_len = num_glyphs as usize * GlyphId::RAW_BYTE_LEN;
1459         cursor.advance_by(glyph_array_byte_len);
1460         cursor.finish(IndexSubtable5Marker {
1461             big_metrics_byte_len,
1462             glyph_array_byte_len,
1463         })
1464     }
1465 }
1466 
1467 /// [IndexSubTable5](https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable5-constant-metrics-glyphs-with-sparse-glyph-codes): constant-metrics glyphs with sparse glyph codes
1468 pub type IndexSubtable5<'a> = TableRef<'a, IndexSubtable5Marker>;
1469 
1470 impl<'a> IndexSubtable5<'a> {
1471     /// Format of this IndexSubTable.
index_format(&self) -> u161472     pub fn index_format(&self) -> u16 {
1473         let range = self.shape.index_format_byte_range();
1474         self.data.read_at(range.start).unwrap()
1475     }
1476 
1477     /// Format of EBDT image data.
image_format(&self) -> u161478     pub fn image_format(&self) -> u16 {
1479         let range = self.shape.image_format_byte_range();
1480         self.data.read_at(range.start).unwrap()
1481     }
1482 
1483     /// Offset to image data in EBDT table.
image_data_offset(&self) -> u321484     pub fn image_data_offset(&self) -> u32 {
1485         let range = self.shape.image_data_offset_byte_range();
1486         self.data.read_at(range.start).unwrap()
1487     }
1488 
1489     /// All glyphs have the same data size.
image_size(&self) -> u321490     pub fn image_size(&self) -> u32 {
1491         let range = self.shape.image_size_byte_range();
1492         self.data.read_at(range.start).unwrap()
1493     }
1494 
1495     /// All glyphs have the same metrics.
big_metrics(&self) -> &'a [BigGlyphMetrics]1496     pub fn big_metrics(&self) -> &'a [BigGlyphMetrics] {
1497         let range = self.shape.big_metrics_byte_range();
1498         self.data.read_array(range).unwrap()
1499     }
1500 
1501     /// Array length.
num_glyphs(&self) -> u321502     pub fn num_glyphs(&self) -> u32 {
1503         let range = self.shape.num_glyphs_byte_range();
1504         self.data.read_at(range.start).unwrap()
1505     }
1506 
1507     /// One per glyph, sorted by glyhph ID.
glyph_array(&self) -> &'a [BigEndian<GlyphId>]1508     pub fn glyph_array(&self) -> &'a [BigEndian<GlyphId>] {
1509         let range = self.shape.glyph_array_byte_range();
1510         self.data.read_array(range).unwrap()
1511     }
1512 }
1513 
1514 #[cfg(feature = "traversal")]
1515 impl<'a> SomeTable<'a> for IndexSubtable5<'a> {
type_name(&self) -> &str1516     fn type_name(&self) -> &str {
1517         "IndexSubtable5"
1518     }
get_field(&self, idx: usize) -> Option<Field<'a>>1519     fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1520         match idx {
1521             0usize => Some(Field::new("index_format", self.index_format())),
1522             1usize => Some(Field::new("image_format", self.image_format())),
1523             2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
1524             3usize => Some(Field::new("image_size", self.image_size())),
1525             4usize => Some(Field::new(
1526                 "big_metrics",
1527                 traversal::FieldType::array_of_records(
1528                     stringify!(BigGlyphMetrics),
1529                     self.big_metrics(),
1530                     self.offset_data(),
1531                 ),
1532             )),
1533             5usize => Some(Field::new("num_glyphs", self.num_glyphs())),
1534             6usize => Some(Field::new("glyph_array", self.glyph_array())),
1535             _ => None,
1536         }
1537     }
1538 }
1539 
1540 #[cfg(feature = "traversal")]
1541 impl<'a> std::fmt::Debug for IndexSubtable5<'a> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result1542     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1543         (self as &dyn SomeTable<'a>).fmt(f)
1544     }
1545 }
1546 
1547 /// [EbdtComponent](https://learn.microsoft.com/en-us/typography/opentype/spec/ebdt#ebdtcomponent-record) record.
1548 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1549 #[repr(C)]
1550 #[repr(packed)]
1551 pub struct BdtComponent {
1552     /// Component glyph ID.
1553     pub glyph_id: BigEndian<GlyphId>,
1554     /// Position of component left.
1555     pub x_offset: BigEndian<i8>,
1556     /// Position of component top.
1557     pub y_offset: BigEndian<i8>,
1558 }
1559 
1560 impl BdtComponent {
1561     /// Component glyph ID.
glyph_id(&self) -> GlyphId1562     pub fn glyph_id(&self) -> GlyphId {
1563         self.glyph_id.get()
1564     }
1565 
1566     /// Position of component left.
x_offset(&self) -> i81567     pub fn x_offset(&self) -> i8 {
1568         self.x_offset.get()
1569     }
1570 
1571     /// Position of component top.
y_offset(&self) -> i81572     pub fn y_offset(&self) -> i8 {
1573         self.y_offset.get()
1574     }
1575 }
1576 
1577 impl FixedSize for BdtComponent {
1578     const RAW_BYTE_LEN: usize = GlyphId::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN;
1579 }
1580 
1581 impl sealed::Sealed for BdtComponent {}
1582 
1583 /// SAFETY: see the [`FromBytes`] trait documentation.
1584 unsafe impl FromBytes for BdtComponent {
this_trait_should_only_be_implemented_in_generated_code()1585     fn this_trait_should_only_be_implemented_in_generated_code() {}
1586 }
1587 
1588 #[cfg(feature = "traversal")]
1589 impl<'a> SomeRecord<'a> for BdtComponent {
traverse(self, data: FontData<'a>) -> RecordResolver<'a>1590     fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1591         RecordResolver {
1592             name: "BdtComponent",
1593             get_field: Box::new(move |idx, _data| match idx {
1594                 0usize => Some(Field::new("glyph_id", self.glyph_id())),
1595                 1usize => Some(Field::new("x_offset", self.x_offset())),
1596                 2usize => Some(Field::new("y_offset", self.y_offset())),
1597                 _ => None,
1598             }),
1599             data,
1600         }
1601     }
1602 }
1603