1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
10#[repr(C)]
11#[repr(packed)]
12pub struct BitmapSize {
13 pub index_subtable_list_offset: BigEndian<u32>,
15 pub index_subtable_list_size: BigEndian<u32>,
17 pub number_of_index_subtables: BigEndian<u32>,
19 pub color_ref: BigEndian<u32>,
21 pub hori: SbitLineMetrics,
23 pub vert: SbitLineMetrics,
25 pub start_glyph_index: BigEndian<GlyphId16>,
27 pub end_glyph_index: BigEndian<GlyphId16>,
29 pub ppem_x: u8,
31 pub ppem_y: u8,
33 pub bit_depth: u8,
36 pub flags: BigEndian<BitmapFlags>,
38}
39
40impl BitmapSize {
41 pub fn index_subtable_list_offset(&self) -> u32 {
43 self.index_subtable_list_offset.get()
44 }
45
46 pub fn index_subtable_list_size(&self) -> u32 {
48 self.index_subtable_list_size.get()
49 }
50
51 pub fn number_of_index_subtables(&self) -> u32 {
53 self.number_of_index_subtables.get()
54 }
55
56 pub fn color_ref(&self) -> u32 {
58 self.color_ref.get()
59 }
60
61 pub fn hori(&self) -> &SbitLineMetrics {
63 &self.hori
64 }
65
66 pub fn vert(&self) -> &SbitLineMetrics {
68 &self.vert
69 }
70
71 pub fn start_glyph_index(&self) -> GlyphId16 {
73 self.start_glyph_index.get()
74 }
75
76 pub fn end_glyph_index(&self) -> GlyphId16 {
78 self.end_glyph_index.get()
79 }
80
81 pub fn ppem_x(&self) -> u8 {
83 self.ppem_x
84 }
85
86 pub fn ppem_y(&self) -> u8 {
88 self.ppem_y
89 }
90
91 pub fn bit_depth(&self) -> u8 {
94 self.bit_depth
95 }
96
97 pub fn flags(&self) -> BitmapFlags {
99 self.flags.get()
100 }
101}
102
103impl 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 + GlyphId16::RAW_BYTE_LEN
111 + GlyphId16::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#[cfg(feature = "experimental_traverse")]
119impl<'a> SomeRecord<'a> for BitmapSize {
120 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
121 RecordResolver {
122 name: "BitmapSize",
123 get_field: Box::new(move |idx, _data| match idx {
124 0usize => Some(Field::new(
125 "index_subtable_list_offset",
126 self.index_subtable_list_offset(),
127 )),
128 1usize => Some(Field::new(
129 "index_subtable_list_size",
130 self.index_subtable_list_size(),
131 )),
132 2usize => Some(Field::new(
133 "number_of_index_subtables",
134 self.number_of_index_subtables(),
135 )),
136 3usize => Some(Field::new("color_ref", self.color_ref())),
137 4usize => Some(Field::new("hori", self.hori().traversal_type(_data))),
138 5usize => Some(Field::new("vert", self.vert().traversal_type(_data))),
139 6usize => Some(Field::new("start_glyph_index", self.start_glyph_index())),
140 7usize => Some(Field::new("end_glyph_index", self.end_glyph_index())),
141 8usize => Some(Field::new("ppem_x", self.ppem_x())),
142 9usize => Some(Field::new("ppem_y", self.ppem_y())),
143 10usize => Some(Field::new("bit_depth", self.bit_depth())),
144 11usize => Some(Field::new("flags", self.flags())),
145 _ => None,
146 }),
147 data,
148 }
149 }
150}
151
152#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
154#[repr(C)]
155#[repr(packed)]
156pub struct SbitLineMetrics {
157 pub ascender: BigEndian<i8>,
158 pub descender: BigEndian<i8>,
159 pub width_max: u8,
160 pub caret_slope_numerator: BigEndian<i8>,
161 pub caret_slope_denominator: u8,
162 pub caret_offset: BigEndian<i8>,
163 pub min_origin_sb: BigEndian<i8>,
164 pub min_advance_sb: BigEndian<i8>,
165 pub max_before_bl: BigEndian<i8>,
166 pub min_after_bl: BigEndian<i8>,
167 pub pad1: BigEndian<i8>,
168 pub pad2: BigEndian<i8>,
169}
170
171impl SbitLineMetrics {
172 pub fn ascender(&self) -> i8 {
173 self.ascender.get()
174 }
175
176 pub fn descender(&self) -> i8 {
177 self.descender.get()
178 }
179
180 pub fn width_max(&self) -> u8 {
181 self.width_max
182 }
183
184 pub fn caret_slope_numerator(&self) -> i8 {
185 self.caret_slope_numerator.get()
186 }
187
188 pub fn caret_slope_denominator(&self) -> u8 {
189 self.caret_slope_denominator
190 }
191
192 pub fn caret_offset(&self) -> i8 {
193 self.caret_offset.get()
194 }
195
196 pub fn min_origin_sb(&self) -> i8 {
197 self.min_origin_sb.get()
198 }
199
200 pub fn min_advance_sb(&self) -> i8 {
201 self.min_advance_sb.get()
202 }
203
204 pub fn max_before_bl(&self) -> i8 {
205 self.max_before_bl.get()
206 }
207
208 pub fn min_after_bl(&self) -> i8 {
209 self.min_after_bl.get()
210 }
211
212 pub fn pad1(&self) -> i8 {
213 self.pad1.get()
214 }
215
216 pub fn pad2(&self) -> i8 {
217 self.pad2.get()
218 }
219}
220
221impl FixedSize for SbitLineMetrics {
222 const RAW_BYTE_LEN: usize = i8::RAW_BYTE_LEN
223 + i8::RAW_BYTE_LEN
224 + u8::RAW_BYTE_LEN
225 + i8::RAW_BYTE_LEN
226 + u8::RAW_BYTE_LEN
227 + i8::RAW_BYTE_LEN
228 + i8::RAW_BYTE_LEN
229 + i8::RAW_BYTE_LEN
230 + i8::RAW_BYTE_LEN
231 + i8::RAW_BYTE_LEN
232 + i8::RAW_BYTE_LEN
233 + i8::RAW_BYTE_LEN;
234}
235
236#[cfg(feature = "experimental_traverse")]
237impl<'a> SomeRecord<'a> for SbitLineMetrics {
238 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
239 RecordResolver {
240 name: "SbitLineMetrics",
241 get_field: Box::new(move |idx, _data| match idx {
242 0usize => Some(Field::new("ascender", self.ascender())),
243 1usize => Some(Field::new("descender", self.descender())),
244 2usize => Some(Field::new("width_max", self.width_max())),
245 3usize => Some(Field::new(
246 "caret_slope_numerator",
247 self.caret_slope_numerator(),
248 )),
249 4usize => Some(Field::new(
250 "caret_slope_denominator",
251 self.caret_slope_denominator(),
252 )),
253 5usize => Some(Field::new("caret_offset", self.caret_offset())),
254 6usize => Some(Field::new("min_origin_sb", self.min_origin_sb())),
255 7usize => Some(Field::new("min_advance_sb", self.min_advance_sb())),
256 8usize => Some(Field::new("max_before_bl", self.max_before_bl())),
257 9usize => Some(Field::new("min_after_bl", self.min_after_bl())),
258 10usize => Some(Field::new("pad1", self.pad1())),
259 11usize => Some(Field::new("pad2", self.pad2())),
260 _ => None,
261 }),
262 data,
263 }
264 }
265}
266
267#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
269#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
270#[repr(transparent)]
271pub struct BitmapFlags {
272 bits: u8,
273}
274
275impl BitmapFlags {
276 pub const HORIZONTAL_METRICS: Self = Self { bits: 0x01 };
278
279 pub const VERTICAL_METRICS: Self = Self { bits: 0x02 };
281}
282
283impl BitmapFlags {
284 #[inline]
286 pub const fn empty() -> Self {
287 Self { bits: 0 }
288 }
289
290 #[inline]
292 pub const fn all() -> Self {
293 Self {
294 bits: Self::HORIZONTAL_METRICS.bits | Self::VERTICAL_METRICS.bits,
295 }
296 }
297
298 #[inline]
300 pub const fn bits(&self) -> u8 {
301 self.bits
302 }
303
304 #[inline]
307 pub const fn from_bits(bits: u8) -> Option<Self> {
308 if (bits & !Self::all().bits()) == 0 {
309 Some(Self { bits })
310 } else {
311 None
312 }
313 }
314
315 #[inline]
318 pub const fn from_bits_truncate(bits: u8) -> Self {
319 Self {
320 bits: bits & Self::all().bits,
321 }
322 }
323
324 #[inline]
326 pub const fn is_empty(&self) -> bool {
327 self.bits() == Self::empty().bits()
328 }
329
330 #[inline]
332 pub const fn intersects(&self, other: Self) -> bool {
333 !(Self {
334 bits: self.bits & other.bits,
335 })
336 .is_empty()
337 }
338
339 #[inline]
341 pub const fn contains(&self, other: Self) -> bool {
342 (self.bits & other.bits) == other.bits
343 }
344
345 #[inline]
347 pub fn insert(&mut self, other: Self) {
348 self.bits |= other.bits;
349 }
350
351 #[inline]
353 pub fn remove(&mut self, other: Self) {
354 self.bits &= !other.bits;
355 }
356
357 #[inline]
359 pub fn toggle(&mut self, other: Self) {
360 self.bits ^= other.bits;
361 }
362
363 #[inline]
374 #[must_use]
375 pub const fn intersection(self, other: Self) -> Self {
376 Self {
377 bits: self.bits & other.bits,
378 }
379 }
380
381 #[inline]
392 #[must_use]
393 pub const fn union(self, other: Self) -> Self {
394 Self {
395 bits: self.bits | other.bits,
396 }
397 }
398
399 #[inline]
412 #[must_use]
413 pub const fn difference(self, other: Self) -> Self {
414 Self {
415 bits: self.bits & !other.bits,
416 }
417 }
418}
419
420impl std::ops::BitOr for BitmapFlags {
421 type Output = Self;
422
423 #[inline]
425 fn bitor(self, other: BitmapFlags) -> Self {
426 Self {
427 bits: self.bits | other.bits,
428 }
429 }
430}
431
432impl std::ops::BitOrAssign for BitmapFlags {
433 #[inline]
435 fn bitor_assign(&mut self, other: Self) {
436 self.bits |= other.bits;
437 }
438}
439
440impl std::ops::BitXor for BitmapFlags {
441 type Output = Self;
442
443 #[inline]
445 fn bitxor(self, other: Self) -> Self {
446 Self {
447 bits: self.bits ^ other.bits,
448 }
449 }
450}
451
452impl std::ops::BitXorAssign for BitmapFlags {
453 #[inline]
455 fn bitxor_assign(&mut self, other: Self) {
456 self.bits ^= other.bits;
457 }
458}
459
460impl std::ops::BitAnd for BitmapFlags {
461 type Output = Self;
462
463 #[inline]
465 fn bitand(self, other: Self) -> Self {
466 Self {
467 bits: self.bits & other.bits,
468 }
469 }
470}
471
472impl std::ops::BitAndAssign for BitmapFlags {
473 #[inline]
475 fn bitand_assign(&mut self, other: Self) {
476 self.bits &= other.bits;
477 }
478}
479
480impl std::ops::Sub for BitmapFlags {
481 type Output = Self;
482
483 #[inline]
485 fn sub(self, other: Self) -> Self {
486 Self {
487 bits: self.bits & !other.bits,
488 }
489 }
490}
491
492impl std::ops::SubAssign for BitmapFlags {
493 #[inline]
495 fn sub_assign(&mut self, other: Self) {
496 self.bits &= !other.bits;
497 }
498}
499
500impl std::ops::Not for BitmapFlags {
501 type Output = Self;
502
503 #[inline]
505 fn not(self) -> Self {
506 Self { bits: !self.bits } & Self::all()
507 }
508}
509
510impl std::fmt::Debug for BitmapFlags {
511 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
512 let members: &[(&str, Self)] = &[
513 ("HORIZONTAL_METRICS", Self::HORIZONTAL_METRICS),
514 ("VERTICAL_METRICS", Self::VERTICAL_METRICS),
515 ];
516 let mut first = true;
517 for (name, value) in members {
518 if self.contains(*value) {
519 if !first {
520 f.write_str(" | ")?;
521 }
522 first = false;
523 f.write_str(name)?;
524 }
525 }
526 if first {
527 f.write_str("(empty)")?;
528 }
529 Ok(())
530 }
531}
532
533impl std::fmt::Binary for BitmapFlags {
534 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
535 std::fmt::Binary::fmt(&self.bits, f)
536 }
537}
538
539impl std::fmt::Octal for BitmapFlags {
540 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
541 std::fmt::Octal::fmt(&self.bits, f)
542 }
543}
544
545impl std::fmt::LowerHex for BitmapFlags {
546 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
547 std::fmt::LowerHex::fmt(&self.bits, f)
548 }
549}
550
551impl std::fmt::UpperHex for BitmapFlags {
552 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
553 std::fmt::UpperHex::fmt(&self.bits, f)
554 }
555}
556
557impl font_types::Scalar for BitmapFlags {
558 type Raw = <u8 as font_types::Scalar>::Raw;
559 fn to_raw(self) -> Self::Raw {
560 self.bits().to_raw()
561 }
562 fn from_raw(raw: Self::Raw) -> Self {
563 let t = <u8>::from_raw(raw);
564 Self::from_bits_truncate(t)
565 }
566}
567
568#[cfg(feature = "experimental_traverse")]
569impl<'a> From<BitmapFlags> for FieldType<'a> {
570 fn from(src: BitmapFlags) -> FieldType<'a> {
571 src.bits().into()
572 }
573}
574
575#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
577#[repr(C)]
578#[repr(packed)]
579pub struct BigGlyphMetrics {
580 pub height: u8,
582 pub width: u8,
584 pub hori_bearing_x: BigEndian<i8>,
586 pub hori_bearing_y: BigEndian<i8>,
588 pub hori_advance: u8,
590 pub vert_bearing_x: BigEndian<i8>,
592 pub vert_bearing_y: BigEndian<i8>,
594 pub vert_advance: u8,
596}
597
598impl BigGlyphMetrics {
599 pub fn height(&self) -> u8 {
601 self.height
602 }
603
604 pub fn width(&self) -> u8 {
606 self.width
607 }
608
609 pub fn hori_bearing_x(&self) -> i8 {
611 self.hori_bearing_x.get()
612 }
613
614 pub fn hori_bearing_y(&self) -> i8 {
616 self.hori_bearing_y.get()
617 }
618
619 pub fn hori_advance(&self) -> u8 {
621 self.hori_advance
622 }
623
624 pub fn vert_bearing_x(&self) -> i8 {
626 self.vert_bearing_x.get()
627 }
628
629 pub fn vert_bearing_y(&self) -> i8 {
631 self.vert_bearing_y.get()
632 }
633
634 pub fn vert_advance(&self) -> u8 {
636 self.vert_advance
637 }
638}
639
640impl FixedSize for BigGlyphMetrics {
641 const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN
642 + u8::RAW_BYTE_LEN
643 + i8::RAW_BYTE_LEN
644 + i8::RAW_BYTE_LEN
645 + u8::RAW_BYTE_LEN
646 + i8::RAW_BYTE_LEN
647 + i8::RAW_BYTE_LEN
648 + u8::RAW_BYTE_LEN;
649}
650
651#[cfg(feature = "experimental_traverse")]
652impl<'a> SomeRecord<'a> for BigGlyphMetrics {
653 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
654 RecordResolver {
655 name: "BigGlyphMetrics",
656 get_field: Box::new(move |idx, _data| match idx {
657 0usize => Some(Field::new("height", self.height())),
658 1usize => Some(Field::new("width", self.width())),
659 2usize => Some(Field::new("hori_bearing_x", self.hori_bearing_x())),
660 3usize => Some(Field::new("hori_bearing_y", self.hori_bearing_y())),
661 4usize => Some(Field::new("hori_advance", self.hori_advance())),
662 5usize => Some(Field::new("vert_bearing_x", self.vert_bearing_x())),
663 6usize => Some(Field::new("vert_bearing_y", self.vert_bearing_y())),
664 7usize => Some(Field::new("vert_advance", self.vert_advance())),
665 _ => None,
666 }),
667 data,
668 }
669 }
670}
671
672#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
674#[repr(C)]
675#[repr(packed)]
676pub struct SmallGlyphMetrics {
677 pub height: u8,
679 pub width: u8,
681 pub bearing_x: BigEndian<i8>,
683 pub bearing_y: BigEndian<i8>,
685 pub advance: u8,
687}
688
689impl SmallGlyphMetrics {
690 pub fn height(&self) -> u8 {
692 self.height
693 }
694
695 pub fn width(&self) -> u8 {
697 self.width
698 }
699
700 pub fn bearing_x(&self) -> i8 {
702 self.bearing_x.get()
703 }
704
705 pub fn bearing_y(&self) -> i8 {
707 self.bearing_y.get()
708 }
709
710 pub fn advance(&self) -> u8 {
712 self.advance
713 }
714}
715
716impl FixedSize for SmallGlyphMetrics {
717 const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN
718 + u8::RAW_BYTE_LEN
719 + i8::RAW_BYTE_LEN
720 + i8::RAW_BYTE_LEN
721 + u8::RAW_BYTE_LEN;
722}
723
724#[cfg(feature = "experimental_traverse")]
725impl<'a> SomeRecord<'a> for SmallGlyphMetrics {
726 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
727 RecordResolver {
728 name: "SmallGlyphMetrics",
729 get_field: Box::new(move |idx, _data| match idx {
730 0usize => Some(Field::new("height", self.height())),
731 1usize => Some(Field::new("width", self.width())),
732 2usize => Some(Field::new("bearing_x", self.bearing_x())),
733 3usize => Some(Field::new("bearing_y", self.bearing_y())),
734 4usize => Some(Field::new("advance", self.advance())),
735 _ => None,
736 }),
737 data,
738 }
739 }
740}
741
742#[derive(Debug, Clone, Copy)]
744#[doc(hidden)]
745pub struct IndexSubtableListMarker {
746 index_subtable_records_byte_len: usize,
747}
748
749impl IndexSubtableListMarker {
750 pub fn index_subtable_records_byte_range(&self) -> Range<usize> {
751 let start = 0;
752 start..start + self.index_subtable_records_byte_len
753 }
754}
755
756impl MinByteRange for IndexSubtableListMarker {
757 fn min_byte_range(&self) -> Range<usize> {
758 0..self.index_subtable_records_byte_range().end
759 }
760}
761
762impl ReadArgs for IndexSubtableList<'_> {
763 type Args = u32;
764}
765
766impl<'a> FontReadWithArgs<'a> for IndexSubtableList<'a> {
767 fn read_with_args(data: FontData<'a>, args: &u32) -> Result<Self, ReadError> {
768 let number_of_index_subtables = *args;
769 let mut cursor = data.cursor();
770 let index_subtable_records_byte_len = (number_of_index_subtables as usize)
771 .checked_mul(IndexSubtableRecord::RAW_BYTE_LEN)
772 .ok_or(ReadError::OutOfBounds)?;
773 cursor.advance_by(index_subtable_records_byte_len);
774 cursor.finish(IndexSubtableListMarker {
775 index_subtable_records_byte_len,
776 })
777 }
778}
779
780impl<'a> IndexSubtableList<'a> {
781 pub fn read(data: FontData<'a>, number_of_index_subtables: u32) -> Result<Self, ReadError> {
786 let args = number_of_index_subtables;
787 Self::read_with_args(data, &args)
788 }
789}
790
791pub type IndexSubtableList<'a> = TableRef<'a, IndexSubtableListMarker>;
793
794#[allow(clippy::needless_lifetimes)]
795impl<'a> IndexSubtableList<'a> {
796 pub fn index_subtable_records(&self) -> &'a [IndexSubtableRecord] {
798 let range = self.shape.index_subtable_records_byte_range();
799 self.data.read_array(range).unwrap()
800 }
801}
802
803#[cfg(feature = "experimental_traverse")]
804impl<'a> SomeTable<'a> for IndexSubtableList<'a> {
805 fn type_name(&self) -> &str {
806 "IndexSubtableList"
807 }
808 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
809 match idx {
810 0usize => Some(Field::new(
811 "index_subtable_records",
812 traversal::FieldType::array_of_records(
813 stringify!(IndexSubtableRecord),
814 self.index_subtable_records(),
815 self.offset_data(),
816 ),
817 )),
818 _ => None,
819 }
820 }
821}
822
823#[cfg(feature = "experimental_traverse")]
824#[allow(clippy::needless_lifetimes)]
825impl<'a> std::fmt::Debug for IndexSubtableList<'a> {
826 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
827 (self as &dyn SomeTable<'a>).fmt(f)
828 }
829}
830
831#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
832#[repr(C)]
833#[repr(packed)]
834pub struct IndexSubtableRecord {
835 pub first_glyph_index: BigEndian<GlyphId16>,
837 pub last_glyph_index: BigEndian<GlyphId16>,
839 pub index_subtable_offset: BigEndian<Offset32>,
841}
842
843impl IndexSubtableRecord {
844 pub fn first_glyph_index(&self) -> GlyphId16 {
846 self.first_glyph_index.get()
847 }
848
849 pub fn last_glyph_index(&self) -> GlyphId16 {
851 self.last_glyph_index.get()
852 }
853
854 pub fn index_subtable_offset(&self) -> Offset32 {
856 self.index_subtable_offset.get()
857 }
858
859 pub fn index_subtable<'a>(&self, data: FontData<'a>) -> Result<IndexSubtable<'a>, ReadError> {
864 let args = (self.last_glyph_index(), self.first_glyph_index());
865 self.index_subtable_offset().resolve_with_args(data, &args)
866 }
867}
868
869impl FixedSize for IndexSubtableRecord {
870 const RAW_BYTE_LEN: usize =
871 GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
872}
873
874#[cfg(feature = "experimental_traverse")]
875impl<'a> SomeRecord<'a> for IndexSubtableRecord {
876 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
877 RecordResolver {
878 name: "IndexSubtableRecord",
879 get_field: Box::new(move |idx, _data| match idx {
880 0usize => Some(Field::new("first_glyph_index", self.first_glyph_index())),
881 1usize => Some(Field::new("last_glyph_index", self.last_glyph_index())),
882 2usize => Some(Field::new(
883 "index_subtable_offset",
884 FieldType::offset(self.index_subtable_offset(), self.index_subtable(_data)),
885 )),
886 _ => None,
887 }),
888 data,
889 }
890 }
891}
892
893impl Format<u16> for IndexSubtable1Marker {
894 const FORMAT: u16 = 1;
895}
896
897#[derive(Debug, Clone, Copy)]
899#[doc(hidden)]
900pub struct IndexSubtable1Marker {
901 sbit_offsets_byte_len: usize,
902}
903
904impl IndexSubtable1Marker {
905 pub fn index_format_byte_range(&self) -> Range<usize> {
906 let start = 0;
907 start..start + u16::RAW_BYTE_LEN
908 }
909
910 pub fn image_format_byte_range(&self) -> Range<usize> {
911 let start = self.index_format_byte_range().end;
912 start..start + u16::RAW_BYTE_LEN
913 }
914
915 pub fn image_data_offset_byte_range(&self) -> Range<usize> {
916 let start = self.image_format_byte_range().end;
917 start..start + u32::RAW_BYTE_LEN
918 }
919
920 pub fn sbit_offsets_byte_range(&self) -> Range<usize> {
921 let start = self.image_data_offset_byte_range().end;
922 start..start + self.sbit_offsets_byte_len
923 }
924}
925
926impl MinByteRange for IndexSubtable1Marker {
927 fn min_byte_range(&self) -> Range<usize> {
928 0..self.sbit_offsets_byte_range().end
929 }
930}
931
932impl ReadArgs for IndexSubtable1<'_> {
933 type Args = (GlyphId16, GlyphId16);
934}
935
936impl<'a> FontReadWithArgs<'a> for IndexSubtable1<'a> {
937 fn read_with_args(
938 data: FontData<'a>,
939 args: &(GlyphId16, GlyphId16),
940 ) -> Result<Self, ReadError> {
941 let (last_glyph_index, first_glyph_index) = *args;
942 let mut cursor = data.cursor();
943 cursor.advance::<u16>();
944 cursor.advance::<u16>();
945 cursor.advance::<u32>();
946 let sbit_offsets_byte_len =
947 (transforms::subtract_add_two(last_glyph_index, first_glyph_index))
948 .checked_mul(u32::RAW_BYTE_LEN)
949 .ok_or(ReadError::OutOfBounds)?;
950 cursor.advance_by(sbit_offsets_byte_len);
951 cursor.finish(IndexSubtable1Marker {
952 sbit_offsets_byte_len,
953 })
954 }
955}
956
957impl<'a> IndexSubtable1<'a> {
958 pub fn read(
963 data: FontData<'a>,
964 last_glyph_index: GlyphId16,
965 first_glyph_index: GlyphId16,
966 ) -> Result<Self, ReadError> {
967 let args = (last_glyph_index, first_glyph_index);
968 Self::read_with_args(data, &args)
969 }
970}
971
972pub type IndexSubtable1<'a> = TableRef<'a, IndexSubtable1Marker>;
974
975#[allow(clippy::needless_lifetimes)]
976impl<'a> IndexSubtable1<'a> {
977 pub fn index_format(&self) -> u16 {
979 let range = self.shape.index_format_byte_range();
980 self.data.read_at(range.start).unwrap()
981 }
982
983 pub fn image_format(&self) -> u16 {
985 let range = self.shape.image_format_byte_range();
986 self.data.read_at(range.start).unwrap()
987 }
988
989 pub fn image_data_offset(&self) -> u32 {
991 let range = self.shape.image_data_offset_byte_range();
992 self.data.read_at(range.start).unwrap()
993 }
994
995 pub fn sbit_offsets(&self) -> &'a [BigEndian<u32>] {
996 let range = self.shape.sbit_offsets_byte_range();
997 self.data.read_array(range).unwrap()
998 }
999}
1000
1001#[cfg(feature = "experimental_traverse")]
1002impl<'a> SomeTable<'a> for IndexSubtable1<'a> {
1003 fn type_name(&self) -> &str {
1004 "IndexSubtable1"
1005 }
1006 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1007 match idx {
1008 0usize => Some(Field::new("index_format", self.index_format())),
1009 1usize => Some(Field::new("image_format", self.image_format())),
1010 2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
1011 3usize => Some(Field::new("sbit_offsets", self.sbit_offsets())),
1012 _ => None,
1013 }
1014 }
1015}
1016
1017#[cfg(feature = "experimental_traverse")]
1018#[allow(clippy::needless_lifetimes)]
1019impl<'a> std::fmt::Debug for IndexSubtable1<'a> {
1020 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1021 (self as &dyn SomeTable<'a>).fmt(f)
1022 }
1023}
1024
1025impl Format<u16> for IndexSubtable2Marker {
1026 const FORMAT: u16 = 2;
1027}
1028
1029#[derive(Debug, Clone, Copy)]
1031#[doc(hidden)]
1032pub struct IndexSubtable2Marker {
1033 big_metrics_byte_len: usize,
1034}
1035
1036impl IndexSubtable2Marker {
1037 pub fn index_format_byte_range(&self) -> Range<usize> {
1038 let start = 0;
1039 start..start + u16::RAW_BYTE_LEN
1040 }
1041
1042 pub fn image_format_byte_range(&self) -> Range<usize> {
1043 let start = self.index_format_byte_range().end;
1044 start..start + u16::RAW_BYTE_LEN
1045 }
1046
1047 pub fn image_data_offset_byte_range(&self) -> Range<usize> {
1048 let start = self.image_format_byte_range().end;
1049 start..start + u32::RAW_BYTE_LEN
1050 }
1051
1052 pub fn image_size_byte_range(&self) -> Range<usize> {
1053 let start = self.image_data_offset_byte_range().end;
1054 start..start + u32::RAW_BYTE_LEN
1055 }
1056
1057 pub 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
1063impl MinByteRange for IndexSubtable2Marker {
1064 fn min_byte_range(&self) -> Range<usize> {
1065 0..self.big_metrics_byte_range().end
1066 }
1067}
1068
1069impl<'a> FontRead<'a> for IndexSubtable2<'a> {
1070 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1071 let mut cursor = data.cursor();
1072 cursor.advance::<u16>();
1073 cursor.advance::<u16>();
1074 cursor.advance::<u32>();
1075 cursor.advance::<u32>();
1076 let big_metrics_byte_len = BigGlyphMetrics::RAW_BYTE_LEN;
1077 cursor.advance_by(big_metrics_byte_len);
1078 cursor.finish(IndexSubtable2Marker {
1079 big_metrics_byte_len,
1080 })
1081 }
1082}
1083
1084pub type IndexSubtable2<'a> = TableRef<'a, IndexSubtable2Marker>;
1086
1087#[allow(clippy::needless_lifetimes)]
1088impl<'a> IndexSubtable2<'a> {
1089 pub fn index_format(&self) -> u16 {
1091 let range = self.shape.index_format_byte_range();
1092 self.data.read_at(range.start).unwrap()
1093 }
1094
1095 pub fn image_format(&self) -> u16 {
1097 let range = self.shape.image_format_byte_range();
1098 self.data.read_at(range.start).unwrap()
1099 }
1100
1101 pub fn image_data_offset(&self) -> u32 {
1103 let range = self.shape.image_data_offset_byte_range();
1104 self.data.read_at(range.start).unwrap()
1105 }
1106
1107 pub fn image_size(&self) -> u32 {
1109 let range = self.shape.image_size_byte_range();
1110 self.data.read_at(range.start).unwrap()
1111 }
1112
1113 pub fn big_metrics(&self) -> &'a [BigGlyphMetrics] {
1115 let range = self.shape.big_metrics_byte_range();
1116 self.data.read_array(range).unwrap()
1117 }
1118}
1119
1120#[cfg(feature = "experimental_traverse")]
1121impl<'a> SomeTable<'a> for IndexSubtable2<'a> {
1122 fn type_name(&self) -> &str {
1123 "IndexSubtable2"
1124 }
1125 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1126 match idx {
1127 0usize => Some(Field::new("index_format", self.index_format())),
1128 1usize => Some(Field::new("image_format", self.image_format())),
1129 2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
1130 3usize => Some(Field::new("image_size", self.image_size())),
1131 4usize => Some(Field::new(
1132 "big_metrics",
1133 traversal::FieldType::array_of_records(
1134 stringify!(BigGlyphMetrics),
1135 self.big_metrics(),
1136 self.offset_data(),
1137 ),
1138 )),
1139 _ => None,
1140 }
1141 }
1142}
1143
1144#[cfg(feature = "experimental_traverse")]
1145#[allow(clippy::needless_lifetimes)]
1146impl<'a> std::fmt::Debug for IndexSubtable2<'a> {
1147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1148 (self as &dyn SomeTable<'a>).fmt(f)
1149 }
1150}
1151
1152impl Format<u16> for IndexSubtable3Marker {
1153 const FORMAT: u16 = 3;
1154}
1155
1156#[derive(Debug, Clone, Copy)]
1158#[doc(hidden)]
1159pub struct IndexSubtable3Marker {
1160 sbit_offsets_byte_len: usize,
1161}
1162
1163impl IndexSubtable3Marker {
1164 pub fn index_format_byte_range(&self) -> Range<usize> {
1165 let start = 0;
1166 start..start + u16::RAW_BYTE_LEN
1167 }
1168
1169 pub fn image_format_byte_range(&self) -> Range<usize> {
1170 let start = self.index_format_byte_range().end;
1171 start..start + u16::RAW_BYTE_LEN
1172 }
1173
1174 pub fn image_data_offset_byte_range(&self) -> Range<usize> {
1175 let start = self.image_format_byte_range().end;
1176 start..start + u32::RAW_BYTE_LEN
1177 }
1178
1179 pub fn sbit_offsets_byte_range(&self) -> Range<usize> {
1180 let start = self.image_data_offset_byte_range().end;
1181 start..start + self.sbit_offsets_byte_len
1182 }
1183}
1184
1185impl MinByteRange for IndexSubtable3Marker {
1186 fn min_byte_range(&self) -> Range<usize> {
1187 0..self.sbit_offsets_byte_range().end
1188 }
1189}
1190
1191impl ReadArgs for IndexSubtable3<'_> {
1192 type Args = (GlyphId16, GlyphId16);
1193}
1194
1195impl<'a> FontReadWithArgs<'a> for IndexSubtable3<'a> {
1196 fn read_with_args(
1197 data: FontData<'a>,
1198 args: &(GlyphId16, GlyphId16),
1199 ) -> Result<Self, ReadError> {
1200 let (last_glyph_index, first_glyph_index) = *args;
1201 let mut cursor = data.cursor();
1202 cursor.advance::<u16>();
1203 cursor.advance::<u16>();
1204 cursor.advance::<u32>();
1205 let sbit_offsets_byte_len =
1206 (transforms::subtract_add_two(last_glyph_index, first_glyph_index))
1207 .checked_mul(u16::RAW_BYTE_LEN)
1208 .ok_or(ReadError::OutOfBounds)?;
1209 cursor.advance_by(sbit_offsets_byte_len);
1210 cursor.finish(IndexSubtable3Marker {
1211 sbit_offsets_byte_len,
1212 })
1213 }
1214}
1215
1216impl<'a> IndexSubtable3<'a> {
1217 pub fn read(
1222 data: FontData<'a>,
1223 last_glyph_index: GlyphId16,
1224 first_glyph_index: GlyphId16,
1225 ) -> Result<Self, ReadError> {
1226 let args = (last_glyph_index, first_glyph_index);
1227 Self::read_with_args(data, &args)
1228 }
1229}
1230
1231pub type IndexSubtable3<'a> = TableRef<'a, IndexSubtable3Marker>;
1233
1234#[allow(clippy::needless_lifetimes)]
1235impl<'a> IndexSubtable3<'a> {
1236 pub fn index_format(&self) -> u16 {
1238 let range = self.shape.index_format_byte_range();
1239 self.data.read_at(range.start).unwrap()
1240 }
1241
1242 pub fn image_format(&self) -> u16 {
1244 let range = self.shape.image_format_byte_range();
1245 self.data.read_at(range.start).unwrap()
1246 }
1247
1248 pub fn image_data_offset(&self) -> u32 {
1250 let range = self.shape.image_data_offset_byte_range();
1251 self.data.read_at(range.start).unwrap()
1252 }
1253
1254 pub fn sbit_offsets(&self) -> &'a [BigEndian<u16>] {
1255 let range = self.shape.sbit_offsets_byte_range();
1256 self.data.read_array(range).unwrap()
1257 }
1258}
1259
1260#[cfg(feature = "experimental_traverse")]
1261impl<'a> SomeTable<'a> for IndexSubtable3<'a> {
1262 fn type_name(&self) -> &str {
1263 "IndexSubtable3"
1264 }
1265 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1266 match idx {
1267 0usize => Some(Field::new("index_format", self.index_format())),
1268 1usize => Some(Field::new("image_format", self.image_format())),
1269 2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
1270 3usize => Some(Field::new("sbit_offsets", self.sbit_offsets())),
1271 _ => None,
1272 }
1273 }
1274}
1275
1276#[cfg(feature = "experimental_traverse")]
1277#[allow(clippy::needless_lifetimes)]
1278impl<'a> std::fmt::Debug for IndexSubtable3<'a> {
1279 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1280 (self as &dyn SomeTable<'a>).fmt(f)
1281 }
1282}
1283
1284impl Format<u16> for IndexSubtable4Marker {
1285 const FORMAT: u16 = 4;
1286}
1287
1288#[derive(Debug, Clone, Copy)]
1290#[doc(hidden)]
1291pub struct IndexSubtable4Marker {
1292 glyph_array_byte_len: usize,
1293}
1294
1295impl IndexSubtable4Marker {
1296 pub fn index_format_byte_range(&self) -> Range<usize> {
1297 let start = 0;
1298 start..start + u16::RAW_BYTE_LEN
1299 }
1300
1301 pub fn image_format_byte_range(&self) -> Range<usize> {
1302 let start = self.index_format_byte_range().end;
1303 start..start + u16::RAW_BYTE_LEN
1304 }
1305
1306 pub fn image_data_offset_byte_range(&self) -> Range<usize> {
1307 let start = self.image_format_byte_range().end;
1308 start..start + u32::RAW_BYTE_LEN
1309 }
1310
1311 pub fn num_glyphs_byte_range(&self) -> Range<usize> {
1312 let start = self.image_data_offset_byte_range().end;
1313 start..start + u32::RAW_BYTE_LEN
1314 }
1315
1316 pub fn glyph_array_byte_range(&self) -> Range<usize> {
1317 let start = self.num_glyphs_byte_range().end;
1318 start..start + self.glyph_array_byte_len
1319 }
1320}
1321
1322impl MinByteRange for IndexSubtable4Marker {
1323 fn min_byte_range(&self) -> Range<usize> {
1324 0..self.glyph_array_byte_range().end
1325 }
1326}
1327
1328impl<'a> FontRead<'a> for IndexSubtable4<'a> {
1329 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1330 let mut cursor = data.cursor();
1331 cursor.advance::<u16>();
1332 cursor.advance::<u16>();
1333 cursor.advance::<u32>();
1334 let num_glyphs: u32 = cursor.read()?;
1335 let glyph_array_byte_len = (transforms::add(num_glyphs, 1_usize))
1336 .checked_mul(GlyphIdOffsetPair::RAW_BYTE_LEN)
1337 .ok_or(ReadError::OutOfBounds)?;
1338 cursor.advance_by(glyph_array_byte_len);
1339 cursor.finish(IndexSubtable4Marker {
1340 glyph_array_byte_len,
1341 })
1342 }
1343}
1344
1345pub type IndexSubtable4<'a> = TableRef<'a, IndexSubtable4Marker>;
1347
1348#[allow(clippy::needless_lifetimes)]
1349impl<'a> IndexSubtable4<'a> {
1350 pub fn index_format(&self) -> u16 {
1352 let range = self.shape.index_format_byte_range();
1353 self.data.read_at(range.start).unwrap()
1354 }
1355
1356 pub fn image_format(&self) -> u16 {
1358 let range = self.shape.image_format_byte_range();
1359 self.data.read_at(range.start).unwrap()
1360 }
1361
1362 pub fn image_data_offset(&self) -> u32 {
1364 let range = self.shape.image_data_offset_byte_range();
1365 self.data.read_at(range.start).unwrap()
1366 }
1367
1368 pub fn num_glyphs(&self) -> u32 {
1370 let range = self.shape.num_glyphs_byte_range();
1371 self.data.read_at(range.start).unwrap()
1372 }
1373
1374 pub fn glyph_array(&self) -> &'a [GlyphIdOffsetPair] {
1376 let range = self.shape.glyph_array_byte_range();
1377 self.data.read_array(range).unwrap()
1378 }
1379}
1380
1381#[cfg(feature = "experimental_traverse")]
1382impl<'a> SomeTable<'a> for IndexSubtable4<'a> {
1383 fn type_name(&self) -> &str {
1384 "IndexSubtable4"
1385 }
1386 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1387 match idx {
1388 0usize => Some(Field::new("index_format", self.index_format())),
1389 1usize => Some(Field::new("image_format", self.image_format())),
1390 2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
1391 3usize => Some(Field::new("num_glyphs", self.num_glyphs())),
1392 4usize => Some(Field::new(
1393 "glyph_array",
1394 traversal::FieldType::array_of_records(
1395 stringify!(GlyphIdOffsetPair),
1396 self.glyph_array(),
1397 self.offset_data(),
1398 ),
1399 )),
1400 _ => None,
1401 }
1402 }
1403}
1404
1405#[cfg(feature = "experimental_traverse")]
1406#[allow(clippy::needless_lifetimes)]
1407impl<'a> std::fmt::Debug for IndexSubtable4<'a> {
1408 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1409 (self as &dyn SomeTable<'a>).fmt(f)
1410 }
1411}
1412
1413#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1415#[repr(C)]
1416#[repr(packed)]
1417pub struct GlyphIdOffsetPair {
1418 pub glyph_id: BigEndian<GlyphId16>,
1420 pub sbit_offset: BigEndian<u16>,
1422}
1423
1424impl GlyphIdOffsetPair {
1425 pub fn glyph_id(&self) -> GlyphId16 {
1427 self.glyph_id.get()
1428 }
1429
1430 pub fn sbit_offset(&self) -> u16 {
1432 self.sbit_offset.get()
1433 }
1434}
1435
1436impl FixedSize for GlyphIdOffsetPair {
1437 const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1438}
1439
1440#[cfg(feature = "experimental_traverse")]
1441impl<'a> SomeRecord<'a> for GlyphIdOffsetPair {
1442 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1443 RecordResolver {
1444 name: "GlyphIdOffsetPair",
1445 get_field: Box::new(move |idx, _data| match idx {
1446 0usize => Some(Field::new("glyph_id", self.glyph_id())),
1447 1usize => Some(Field::new("sbit_offset", self.sbit_offset())),
1448 _ => None,
1449 }),
1450 data,
1451 }
1452 }
1453}
1454
1455impl Format<u16> for IndexSubtable5Marker {
1456 const FORMAT: u16 = 5;
1457}
1458
1459#[derive(Debug, Clone, Copy)]
1461#[doc(hidden)]
1462pub struct IndexSubtable5Marker {
1463 big_metrics_byte_len: usize,
1464 glyph_array_byte_len: usize,
1465}
1466
1467impl IndexSubtable5Marker {
1468 pub fn index_format_byte_range(&self) -> Range<usize> {
1469 let start = 0;
1470 start..start + u16::RAW_BYTE_LEN
1471 }
1472
1473 pub fn image_format_byte_range(&self) -> Range<usize> {
1474 let start = self.index_format_byte_range().end;
1475 start..start + u16::RAW_BYTE_LEN
1476 }
1477
1478 pub fn image_data_offset_byte_range(&self) -> Range<usize> {
1479 let start = self.image_format_byte_range().end;
1480 start..start + u32::RAW_BYTE_LEN
1481 }
1482
1483 pub fn image_size_byte_range(&self) -> Range<usize> {
1484 let start = self.image_data_offset_byte_range().end;
1485 start..start + u32::RAW_BYTE_LEN
1486 }
1487
1488 pub fn big_metrics_byte_range(&self) -> Range<usize> {
1489 let start = self.image_size_byte_range().end;
1490 start..start + self.big_metrics_byte_len
1491 }
1492
1493 pub fn num_glyphs_byte_range(&self) -> Range<usize> {
1494 let start = self.big_metrics_byte_range().end;
1495 start..start + u32::RAW_BYTE_LEN
1496 }
1497
1498 pub fn glyph_array_byte_range(&self) -> Range<usize> {
1499 let start = self.num_glyphs_byte_range().end;
1500 start..start + self.glyph_array_byte_len
1501 }
1502}
1503
1504impl MinByteRange for IndexSubtable5Marker {
1505 fn min_byte_range(&self) -> Range<usize> {
1506 0..self.glyph_array_byte_range().end
1507 }
1508}
1509
1510impl<'a> FontRead<'a> for IndexSubtable5<'a> {
1511 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1512 let mut cursor = data.cursor();
1513 cursor.advance::<u16>();
1514 cursor.advance::<u16>();
1515 cursor.advance::<u32>();
1516 cursor.advance::<u32>();
1517 let big_metrics_byte_len = BigGlyphMetrics::RAW_BYTE_LEN;
1518 cursor.advance_by(big_metrics_byte_len);
1519 let num_glyphs: u32 = cursor.read()?;
1520 let glyph_array_byte_len = (num_glyphs as usize)
1521 .checked_mul(GlyphId16::RAW_BYTE_LEN)
1522 .ok_or(ReadError::OutOfBounds)?;
1523 cursor.advance_by(glyph_array_byte_len);
1524 cursor.finish(IndexSubtable5Marker {
1525 big_metrics_byte_len,
1526 glyph_array_byte_len,
1527 })
1528 }
1529}
1530
1531pub type IndexSubtable5<'a> = TableRef<'a, IndexSubtable5Marker>;
1533
1534#[allow(clippy::needless_lifetimes)]
1535impl<'a> IndexSubtable5<'a> {
1536 pub fn index_format(&self) -> u16 {
1538 let range = self.shape.index_format_byte_range();
1539 self.data.read_at(range.start).unwrap()
1540 }
1541
1542 pub fn image_format(&self) -> u16 {
1544 let range = self.shape.image_format_byte_range();
1545 self.data.read_at(range.start).unwrap()
1546 }
1547
1548 pub fn image_data_offset(&self) -> u32 {
1550 let range = self.shape.image_data_offset_byte_range();
1551 self.data.read_at(range.start).unwrap()
1552 }
1553
1554 pub fn image_size(&self) -> u32 {
1556 let range = self.shape.image_size_byte_range();
1557 self.data.read_at(range.start).unwrap()
1558 }
1559
1560 pub fn big_metrics(&self) -> &'a [BigGlyphMetrics] {
1562 let range = self.shape.big_metrics_byte_range();
1563 self.data.read_array(range).unwrap()
1564 }
1565
1566 pub fn num_glyphs(&self) -> u32 {
1568 let range = self.shape.num_glyphs_byte_range();
1569 self.data.read_at(range.start).unwrap()
1570 }
1571
1572 pub fn glyph_array(&self) -> &'a [BigEndian<GlyphId16>] {
1574 let range = self.shape.glyph_array_byte_range();
1575 self.data.read_array(range).unwrap()
1576 }
1577}
1578
1579#[cfg(feature = "experimental_traverse")]
1580impl<'a> SomeTable<'a> for IndexSubtable5<'a> {
1581 fn type_name(&self) -> &str {
1582 "IndexSubtable5"
1583 }
1584 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1585 match idx {
1586 0usize => Some(Field::new("index_format", self.index_format())),
1587 1usize => Some(Field::new("image_format", self.image_format())),
1588 2usize => Some(Field::new("image_data_offset", self.image_data_offset())),
1589 3usize => Some(Field::new("image_size", self.image_size())),
1590 4usize => Some(Field::new(
1591 "big_metrics",
1592 traversal::FieldType::array_of_records(
1593 stringify!(BigGlyphMetrics),
1594 self.big_metrics(),
1595 self.offset_data(),
1596 ),
1597 )),
1598 5usize => Some(Field::new("num_glyphs", self.num_glyphs())),
1599 6usize => Some(Field::new("glyph_array", self.glyph_array())),
1600 _ => None,
1601 }
1602 }
1603}
1604
1605#[cfg(feature = "experimental_traverse")]
1606#[allow(clippy::needless_lifetimes)]
1607impl<'a> std::fmt::Debug for IndexSubtable5<'a> {
1608 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1609 (self as &dyn SomeTable<'a>).fmt(f)
1610 }
1611}
1612
1613#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1615#[repr(C)]
1616#[repr(packed)]
1617pub struct BdtComponent {
1618 pub glyph_id: BigEndian<GlyphId16>,
1620 pub x_offset: BigEndian<i8>,
1622 pub y_offset: BigEndian<i8>,
1624}
1625
1626impl BdtComponent {
1627 pub fn glyph_id(&self) -> GlyphId16 {
1629 self.glyph_id.get()
1630 }
1631
1632 pub fn x_offset(&self) -> i8 {
1634 self.x_offset.get()
1635 }
1636
1637 pub fn y_offset(&self) -> i8 {
1639 self.y_offset.get()
1640 }
1641}
1642
1643impl FixedSize for BdtComponent {
1644 const RAW_BYTE_LEN: usize = GlyphId16::RAW_BYTE_LEN + i8::RAW_BYTE_LEN + i8::RAW_BYTE_LEN;
1645}
1646
1647#[cfg(feature = "experimental_traverse")]
1648impl<'a> SomeRecord<'a> for BdtComponent {
1649 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1650 RecordResolver {
1651 name: "BdtComponent",
1652 get_field: Box::new(move |idx, _data| match idx {
1653 0usize => Some(Field::new("glyph_id", self.glyph_id())),
1654 1usize => Some(Field::new("x_offset", self.x_offset())),
1655 2usize => Some(Field::new("y_offset", self.y_offset())),
1656 _ => None,
1657 }),
1658 data,
1659 }
1660 }
1661}