1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8#[derive(Debug, Clone, Copy)]
10#[doc(hidden)]
11pub struct ScriptListMarker {
12 script_records_byte_len: usize,
13}
14
15impl ScriptListMarker {
16 pub fn script_count_byte_range(&self) -> Range<usize> {
17 let start = 0;
18 start..start + u16::RAW_BYTE_LEN
19 }
20
21 pub fn script_records_byte_range(&self) -> Range<usize> {
22 let start = self.script_count_byte_range().end;
23 start..start + self.script_records_byte_len
24 }
25}
26
27impl MinByteRange for ScriptListMarker {
28 fn min_byte_range(&self) -> Range<usize> {
29 0..self.script_records_byte_range().end
30 }
31}
32
33impl<'a> FontRead<'a> for ScriptList<'a> {
34 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
35 let mut cursor = data.cursor();
36 let script_count: u16 = cursor.read()?;
37 let script_records_byte_len = (script_count as usize)
38 .checked_mul(ScriptRecord::RAW_BYTE_LEN)
39 .ok_or(ReadError::OutOfBounds)?;
40 cursor.advance_by(script_records_byte_len);
41 cursor.finish(ScriptListMarker {
42 script_records_byte_len,
43 })
44 }
45}
46
47pub type ScriptList<'a> = TableRef<'a, ScriptListMarker>;
49
50#[allow(clippy::needless_lifetimes)]
51impl<'a> ScriptList<'a> {
52 pub fn script_count(&self) -> u16 {
54 let range = self.shape.script_count_byte_range();
55 self.data.read_at(range.start).unwrap()
56 }
57
58 pub fn script_records(&self) -> &'a [ScriptRecord] {
60 let range = self.shape.script_records_byte_range();
61 self.data.read_array(range).unwrap()
62 }
63}
64
65#[cfg(feature = "experimental_traverse")]
66impl<'a> SomeTable<'a> for ScriptList<'a> {
67 fn type_name(&self) -> &str {
68 "ScriptList"
69 }
70 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
71 match idx {
72 0usize => Some(Field::new("script_count", self.script_count())),
73 1usize => Some(Field::new(
74 "script_records",
75 traversal::FieldType::array_of_records(
76 stringify!(ScriptRecord),
77 self.script_records(),
78 self.offset_data(),
79 ),
80 )),
81 _ => None,
82 }
83 }
84}
85
86#[cfg(feature = "experimental_traverse")]
87#[allow(clippy::needless_lifetimes)]
88impl<'a> std::fmt::Debug for ScriptList<'a> {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 (self as &dyn SomeTable<'a>).fmt(f)
91 }
92}
93
94#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
96#[repr(C)]
97#[repr(packed)]
98pub struct ScriptRecord {
99 pub script_tag: BigEndian<Tag>,
101 pub script_offset: BigEndian<Offset16>,
103}
104
105impl ScriptRecord {
106 pub fn script_tag(&self) -> Tag {
108 self.script_tag.get()
109 }
110
111 pub fn script_offset(&self) -> Offset16 {
113 self.script_offset.get()
114 }
115
116 pub fn script<'a>(&self, data: FontData<'a>) -> Result<Script<'a>, ReadError> {
121 self.script_offset().resolve(data)
122 }
123}
124
125impl FixedSize for ScriptRecord {
126 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
127}
128
129#[cfg(feature = "experimental_traverse")]
130impl<'a> SomeRecord<'a> for ScriptRecord {
131 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
132 RecordResolver {
133 name: "ScriptRecord",
134 get_field: Box::new(move |idx, _data| match idx {
135 0usize => Some(Field::new("script_tag", self.script_tag())),
136 1usize => Some(Field::new(
137 "script_offset",
138 FieldType::offset(self.script_offset(), self.script(_data)),
139 )),
140 _ => None,
141 }),
142 data,
143 }
144 }
145}
146
147#[derive(Debug, Clone, Copy)]
149#[doc(hidden)]
150pub struct ScriptMarker {
151 lang_sys_records_byte_len: usize,
152}
153
154impl ScriptMarker {
155 pub fn default_lang_sys_offset_byte_range(&self) -> Range<usize> {
156 let start = 0;
157 start..start + Offset16::RAW_BYTE_LEN
158 }
159
160 pub fn lang_sys_count_byte_range(&self) -> Range<usize> {
161 let start = self.default_lang_sys_offset_byte_range().end;
162 start..start + u16::RAW_BYTE_LEN
163 }
164
165 pub fn lang_sys_records_byte_range(&self) -> Range<usize> {
166 let start = self.lang_sys_count_byte_range().end;
167 start..start + self.lang_sys_records_byte_len
168 }
169}
170
171impl MinByteRange for ScriptMarker {
172 fn min_byte_range(&self) -> Range<usize> {
173 0..self.lang_sys_records_byte_range().end
174 }
175}
176
177impl<'a> FontRead<'a> for Script<'a> {
178 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
179 let mut cursor = data.cursor();
180 cursor.advance::<Offset16>();
181 let lang_sys_count: u16 = cursor.read()?;
182 let lang_sys_records_byte_len = (lang_sys_count as usize)
183 .checked_mul(LangSysRecord::RAW_BYTE_LEN)
184 .ok_or(ReadError::OutOfBounds)?;
185 cursor.advance_by(lang_sys_records_byte_len);
186 cursor.finish(ScriptMarker {
187 lang_sys_records_byte_len,
188 })
189 }
190}
191
192pub type Script<'a> = TableRef<'a, ScriptMarker>;
194
195#[allow(clippy::needless_lifetimes)]
196impl<'a> Script<'a> {
197 pub fn default_lang_sys_offset(&self) -> Nullable<Offset16> {
200 let range = self.shape.default_lang_sys_offset_byte_range();
201 self.data.read_at(range.start).unwrap()
202 }
203
204 pub fn default_lang_sys(&self) -> Option<Result<LangSys<'a>, ReadError>> {
206 let data = self.data;
207 self.default_lang_sys_offset().resolve(data)
208 }
209
210 pub fn lang_sys_count(&self) -> u16 {
213 let range = self.shape.lang_sys_count_byte_range();
214 self.data.read_at(range.start).unwrap()
215 }
216
217 pub fn lang_sys_records(&self) -> &'a [LangSysRecord] {
219 let range = self.shape.lang_sys_records_byte_range();
220 self.data.read_array(range).unwrap()
221 }
222}
223
224#[cfg(feature = "experimental_traverse")]
225impl<'a> SomeTable<'a> for Script<'a> {
226 fn type_name(&self) -> &str {
227 "Script"
228 }
229 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
230 match idx {
231 0usize => Some(Field::new(
232 "default_lang_sys_offset",
233 FieldType::offset(self.default_lang_sys_offset(), self.default_lang_sys()),
234 )),
235 1usize => Some(Field::new("lang_sys_count", self.lang_sys_count())),
236 2usize => Some(Field::new(
237 "lang_sys_records",
238 traversal::FieldType::array_of_records(
239 stringify!(LangSysRecord),
240 self.lang_sys_records(),
241 self.offset_data(),
242 ),
243 )),
244 _ => None,
245 }
246 }
247}
248
249#[cfg(feature = "experimental_traverse")]
250#[allow(clippy::needless_lifetimes)]
251impl<'a> std::fmt::Debug for Script<'a> {
252 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
253 (self as &dyn SomeTable<'a>).fmt(f)
254 }
255}
256
257#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
258#[repr(C)]
259#[repr(packed)]
260pub struct LangSysRecord {
261 pub lang_sys_tag: BigEndian<Tag>,
263 pub lang_sys_offset: BigEndian<Offset16>,
265}
266
267impl LangSysRecord {
268 pub fn lang_sys_tag(&self) -> Tag {
270 self.lang_sys_tag.get()
271 }
272
273 pub fn lang_sys_offset(&self) -> Offset16 {
275 self.lang_sys_offset.get()
276 }
277
278 pub fn lang_sys<'a>(&self, data: FontData<'a>) -> Result<LangSys<'a>, ReadError> {
283 self.lang_sys_offset().resolve(data)
284 }
285}
286
287impl FixedSize for LangSysRecord {
288 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
289}
290
291#[cfg(feature = "experimental_traverse")]
292impl<'a> SomeRecord<'a> for LangSysRecord {
293 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
294 RecordResolver {
295 name: "LangSysRecord",
296 get_field: Box::new(move |idx, _data| match idx {
297 0usize => Some(Field::new("lang_sys_tag", self.lang_sys_tag())),
298 1usize => Some(Field::new(
299 "lang_sys_offset",
300 FieldType::offset(self.lang_sys_offset(), self.lang_sys(_data)),
301 )),
302 _ => None,
303 }),
304 data,
305 }
306 }
307}
308
309#[derive(Debug, Clone, Copy)]
311#[doc(hidden)]
312pub struct LangSysMarker {
313 feature_indices_byte_len: usize,
314}
315
316impl LangSysMarker {
317 pub fn lookup_order_offset_byte_range(&self) -> Range<usize> {
318 let start = 0;
319 start..start + u16::RAW_BYTE_LEN
320 }
321
322 pub fn required_feature_index_byte_range(&self) -> Range<usize> {
323 let start = self.lookup_order_offset_byte_range().end;
324 start..start + u16::RAW_BYTE_LEN
325 }
326
327 pub fn feature_index_count_byte_range(&self) -> Range<usize> {
328 let start = self.required_feature_index_byte_range().end;
329 start..start + u16::RAW_BYTE_LEN
330 }
331
332 pub fn feature_indices_byte_range(&self) -> Range<usize> {
333 let start = self.feature_index_count_byte_range().end;
334 start..start + self.feature_indices_byte_len
335 }
336}
337
338impl MinByteRange for LangSysMarker {
339 fn min_byte_range(&self) -> Range<usize> {
340 0..self.feature_indices_byte_range().end
341 }
342}
343
344impl<'a> FontRead<'a> for LangSys<'a> {
345 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
346 let mut cursor = data.cursor();
347 cursor.advance::<u16>();
348 cursor.advance::<u16>();
349 let feature_index_count: u16 = cursor.read()?;
350 let feature_indices_byte_len = (feature_index_count as usize)
351 .checked_mul(u16::RAW_BYTE_LEN)
352 .ok_or(ReadError::OutOfBounds)?;
353 cursor.advance_by(feature_indices_byte_len);
354 cursor.finish(LangSysMarker {
355 feature_indices_byte_len,
356 })
357 }
358}
359
360pub type LangSys<'a> = TableRef<'a, LangSysMarker>;
362
363#[allow(clippy::needless_lifetimes)]
364impl<'a> LangSys<'a> {
365 pub fn required_feature_index(&self) -> u16 {
368 let range = self.shape.required_feature_index_byte_range();
369 self.data.read_at(range.start).unwrap()
370 }
371
372 pub fn feature_index_count(&self) -> u16 {
375 let range = self.shape.feature_index_count_byte_range();
376 self.data.read_at(range.start).unwrap()
377 }
378
379 pub fn feature_indices(&self) -> &'a [BigEndian<u16>] {
381 let range = self.shape.feature_indices_byte_range();
382 self.data.read_array(range).unwrap()
383 }
384}
385
386#[cfg(feature = "experimental_traverse")]
387impl<'a> SomeTable<'a> for LangSys<'a> {
388 fn type_name(&self) -> &str {
389 "LangSys"
390 }
391 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
392 match idx {
393 0usize => Some(Field::new(
394 "required_feature_index",
395 self.required_feature_index(),
396 )),
397 1usize => Some(Field::new(
398 "feature_index_count",
399 self.feature_index_count(),
400 )),
401 2usize => Some(Field::new("feature_indices", self.feature_indices())),
402 _ => None,
403 }
404 }
405}
406
407#[cfg(feature = "experimental_traverse")]
408#[allow(clippy::needless_lifetimes)]
409impl<'a> std::fmt::Debug for LangSys<'a> {
410 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
411 (self as &dyn SomeTable<'a>).fmt(f)
412 }
413}
414
415#[derive(Debug, Clone, Copy)]
417#[doc(hidden)]
418pub struct FeatureListMarker {
419 feature_records_byte_len: usize,
420}
421
422impl FeatureListMarker {
423 pub fn feature_count_byte_range(&self) -> Range<usize> {
424 let start = 0;
425 start..start + u16::RAW_BYTE_LEN
426 }
427
428 pub fn feature_records_byte_range(&self) -> Range<usize> {
429 let start = self.feature_count_byte_range().end;
430 start..start + self.feature_records_byte_len
431 }
432}
433
434impl MinByteRange for FeatureListMarker {
435 fn min_byte_range(&self) -> Range<usize> {
436 0..self.feature_records_byte_range().end
437 }
438}
439
440impl<'a> FontRead<'a> for FeatureList<'a> {
441 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
442 let mut cursor = data.cursor();
443 let feature_count: u16 = cursor.read()?;
444 let feature_records_byte_len = (feature_count as usize)
445 .checked_mul(FeatureRecord::RAW_BYTE_LEN)
446 .ok_or(ReadError::OutOfBounds)?;
447 cursor.advance_by(feature_records_byte_len);
448 cursor.finish(FeatureListMarker {
449 feature_records_byte_len,
450 })
451 }
452}
453
454pub type FeatureList<'a> = TableRef<'a, FeatureListMarker>;
456
457#[allow(clippy::needless_lifetimes)]
458impl<'a> FeatureList<'a> {
459 pub fn feature_count(&self) -> u16 {
461 let range = self.shape.feature_count_byte_range();
462 self.data.read_at(range.start).unwrap()
463 }
464
465 pub fn feature_records(&self) -> &'a [FeatureRecord] {
468 let range = self.shape.feature_records_byte_range();
469 self.data.read_array(range).unwrap()
470 }
471}
472
473#[cfg(feature = "experimental_traverse")]
474impl<'a> SomeTable<'a> for FeatureList<'a> {
475 fn type_name(&self) -> &str {
476 "FeatureList"
477 }
478 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
479 match idx {
480 0usize => Some(Field::new("feature_count", self.feature_count())),
481 1usize => Some(Field::new(
482 "feature_records",
483 traversal::FieldType::array_of_records(
484 stringify!(FeatureRecord),
485 self.feature_records(),
486 self.offset_data(),
487 ),
488 )),
489 _ => None,
490 }
491 }
492}
493
494#[cfg(feature = "experimental_traverse")]
495#[allow(clippy::needless_lifetimes)]
496impl<'a> std::fmt::Debug for FeatureList<'a> {
497 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
498 (self as &dyn SomeTable<'a>).fmt(f)
499 }
500}
501
502#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
504#[repr(C)]
505#[repr(packed)]
506pub struct FeatureRecord {
507 pub feature_tag: BigEndian<Tag>,
509 pub feature_offset: BigEndian<Offset16>,
511}
512
513impl FeatureRecord {
514 pub fn feature_tag(&self) -> Tag {
516 self.feature_tag.get()
517 }
518
519 pub fn feature_offset(&self) -> Offset16 {
521 self.feature_offset.get()
522 }
523
524 pub fn feature<'a>(&self, data: FontData<'a>) -> Result<Feature<'a>, ReadError> {
529 let args = self.feature_tag();
530 self.feature_offset().resolve_with_args(data, &args)
531 }
532}
533
534impl FixedSize for FeatureRecord {
535 const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN;
536}
537
538#[cfg(feature = "experimental_traverse")]
539impl<'a> SomeRecord<'a> for FeatureRecord {
540 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
541 RecordResolver {
542 name: "FeatureRecord",
543 get_field: Box::new(move |idx, _data| match idx {
544 0usize => Some(Field::new("feature_tag", self.feature_tag())),
545 1usize => Some(Field::new(
546 "feature_offset",
547 FieldType::offset(self.feature_offset(), self.feature(_data)),
548 )),
549 _ => None,
550 }),
551 data,
552 }
553 }
554}
555
556#[derive(Debug, Clone, Copy)]
558#[doc(hidden)]
559pub struct FeatureMarker {
560 feature_tag: Tag,
561 lookup_list_indices_byte_len: usize,
562}
563
564impl FeatureMarker {
565 pub fn feature_params_offset_byte_range(&self) -> Range<usize> {
566 let start = 0;
567 start..start + Offset16::RAW_BYTE_LEN
568 }
569
570 pub fn lookup_index_count_byte_range(&self) -> Range<usize> {
571 let start = self.feature_params_offset_byte_range().end;
572 start..start + u16::RAW_BYTE_LEN
573 }
574
575 pub fn lookup_list_indices_byte_range(&self) -> Range<usize> {
576 let start = self.lookup_index_count_byte_range().end;
577 start..start + self.lookup_list_indices_byte_len
578 }
579}
580
581impl MinByteRange for FeatureMarker {
582 fn min_byte_range(&self) -> Range<usize> {
583 0..self.lookup_list_indices_byte_range().end
584 }
585}
586
587impl ReadArgs for Feature<'_> {
588 type Args = Tag;
589}
590
591impl<'a> FontReadWithArgs<'a> for Feature<'a> {
592 fn read_with_args(data: FontData<'a>, args: &Tag) -> Result<Self, ReadError> {
593 let feature_tag = *args;
594 let mut cursor = data.cursor();
595 cursor.advance::<Offset16>();
596 let lookup_index_count: u16 = cursor.read()?;
597 let lookup_list_indices_byte_len = (lookup_index_count as usize)
598 .checked_mul(u16::RAW_BYTE_LEN)
599 .ok_or(ReadError::OutOfBounds)?;
600 cursor.advance_by(lookup_list_indices_byte_len);
601 cursor.finish(FeatureMarker {
602 feature_tag,
603 lookup_list_indices_byte_len,
604 })
605 }
606}
607
608impl<'a> Feature<'a> {
609 pub fn read(data: FontData<'a>, feature_tag: Tag) -> Result<Self, ReadError> {
614 let args = feature_tag;
615 Self::read_with_args(data, &args)
616 }
617}
618
619pub type Feature<'a> = TableRef<'a, FeatureMarker>;
621
622#[allow(clippy::needless_lifetimes)]
623impl<'a> Feature<'a> {
624 pub fn feature_params_offset(&self) -> Nullable<Offset16> {
626 let range = self.shape.feature_params_offset_byte_range();
627 self.data.read_at(range.start).unwrap()
628 }
629
630 pub fn feature_params(&self) -> Option<Result<FeatureParams<'a>, ReadError>> {
632 let data = self.data;
633 let args = self.feature_tag();
634 self.feature_params_offset().resolve_with_args(data, &args)
635 }
636
637 pub fn lookup_index_count(&self) -> u16 {
639 let range = self.shape.lookup_index_count_byte_range();
640 self.data.read_at(range.start).unwrap()
641 }
642
643 pub fn lookup_list_indices(&self) -> &'a [BigEndian<u16>] {
646 let range = self.shape.lookup_list_indices_byte_range();
647 self.data.read_array(range).unwrap()
648 }
649
650 pub(crate) fn feature_tag(&self) -> Tag {
651 self.shape.feature_tag
652 }
653}
654
655#[cfg(feature = "experimental_traverse")]
656impl<'a> SomeTable<'a> for Feature<'a> {
657 fn type_name(&self) -> &str {
658 "Feature"
659 }
660 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
661 match idx {
662 0usize => Some(Field::new(
663 "feature_params_offset",
664 FieldType::offset(self.feature_params_offset(), self.feature_params()),
665 )),
666 1usize => Some(Field::new("lookup_index_count", self.lookup_index_count())),
667 2usize => Some(Field::new(
668 "lookup_list_indices",
669 self.lookup_list_indices(),
670 )),
671 _ => None,
672 }
673 }
674}
675
676#[cfg(feature = "experimental_traverse")]
677#[allow(clippy::needless_lifetimes)]
678impl<'a> std::fmt::Debug for Feature<'a> {
679 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
680 (self as &dyn SomeTable<'a>).fmt(f)
681 }
682}
683
684#[derive(Debug)]
686#[doc(hidden)]
687pub struct LookupListMarker<T = ()> {
688 lookup_offsets_byte_len: usize,
689 offset_type: std::marker::PhantomData<*const T>,
690}
691
692impl<T> LookupListMarker<T> {
693 pub fn lookup_count_byte_range(&self) -> Range<usize> {
694 let start = 0;
695 start..start + u16::RAW_BYTE_LEN
696 }
697
698 pub fn lookup_offsets_byte_range(&self) -> Range<usize> {
699 let start = self.lookup_count_byte_range().end;
700 start..start + self.lookup_offsets_byte_len
701 }
702}
703
704impl MinByteRange for LookupListMarker {
705 fn min_byte_range(&self) -> Range<usize> {
706 0..self.lookup_offsets_byte_range().end
707 }
708}
709
710impl<T> Clone for LookupListMarker<T> {
711 fn clone(&self) -> Self {
712 *self
713 }
714}
715
716impl<T> Copy for LookupListMarker<T> {}
717
718impl<'a, T> FontRead<'a> for LookupList<'a, T> {
719 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
720 let mut cursor = data.cursor();
721 let lookup_count: u16 = cursor.read()?;
722 let lookup_offsets_byte_len = (lookup_count as usize)
723 .checked_mul(Offset16::RAW_BYTE_LEN)
724 .ok_or(ReadError::OutOfBounds)?;
725 cursor.advance_by(lookup_offsets_byte_len);
726 cursor.finish(LookupListMarker {
727 lookup_offsets_byte_len,
728 offset_type: std::marker::PhantomData,
729 })
730 }
731}
732
733impl<'a> LookupList<'a, ()> {
734 #[allow(dead_code)]
735 pub(crate) fn into_concrete<T>(self) -> LookupList<'a, T> {
736 let TableRef { data, shape } = self;
737 TableRef {
738 shape: LookupListMarker {
739 lookup_offsets_byte_len: shape.lookup_offsets_byte_len,
740 offset_type: std::marker::PhantomData,
741 },
742 data,
743 }
744 }
745}
746
747impl<'a, T> LookupList<'a, T> {
748 #[allow(dead_code)]
749 pub(crate) fn of_unit_type(&self) -> LookupList<'a, ()> {
751 let TableRef { data, shape } = self;
752 TableRef {
753 shape: LookupListMarker {
754 lookup_offsets_byte_len: shape.lookup_offsets_byte_len,
755 offset_type: std::marker::PhantomData,
756 },
757 data: *data,
758 }
759 }
760}
761
762pub type LookupList<'a, T> = TableRef<'a, LookupListMarker<T>>;
764
765#[allow(clippy::needless_lifetimes)]
766impl<'a, T> LookupList<'a, T> {
767 pub fn lookup_count(&self) -> u16 {
769 let range = self.shape.lookup_count_byte_range();
770 self.data.read_at(range.start).unwrap()
771 }
772
773 pub fn lookup_offsets(&self) -> &'a [BigEndian<Offset16>] {
776 let range = self.shape.lookup_offsets_byte_range();
777 self.data.read_array(range).unwrap()
778 }
779
780 pub fn lookups(&self) -> ArrayOfOffsets<'a, T, Offset16>
782 where
783 T: FontRead<'a>,
784 {
785 let data = self.data;
786 let offsets = self.lookup_offsets();
787 ArrayOfOffsets::new(offsets, data, ())
788 }
789}
790
791#[cfg(feature = "experimental_traverse")]
792impl<'a, T: FontRead<'a> + SomeTable<'a> + 'a> SomeTable<'a> for LookupList<'a, T> {
793 fn type_name(&self) -> &str {
794 "LookupList"
795 }
796 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
797 match idx {
798 0usize => Some(Field::new("lookup_count", self.lookup_count())),
799 1usize => Some({
800 let data = self.data;
801 Field::new(
802 "lookup_offsets",
803 FieldType::array_of_offsets(
804 better_type_name::<T>(),
805 self.lookup_offsets(),
806 move |off| {
807 let target = off.get().resolve::<T>(data);
808 FieldType::offset(off.get(), target)
809 },
810 ),
811 )
812 }),
813 _ => None,
814 }
815 }
816}
817
818#[cfg(feature = "experimental_traverse")]
819#[allow(clippy::needless_lifetimes)]
820impl<'a, T: FontRead<'a> + SomeTable<'a> + 'a> std::fmt::Debug for LookupList<'a, T> {
821 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
822 (self as &dyn SomeTable<'a>).fmt(f)
823 }
824}
825
826#[derive(Debug)]
828#[doc(hidden)]
829pub struct LookupMarker<T = ()> {
830 subtable_offsets_byte_len: usize,
831 mark_filtering_set_byte_start: Option<usize>,
832 offset_type: std::marker::PhantomData<*const T>,
833}
834
835impl<T> LookupMarker<T> {
836 pub fn lookup_type_byte_range(&self) -> Range<usize> {
837 let start = 0;
838 start..start + u16::RAW_BYTE_LEN
839 }
840
841 pub fn lookup_flag_byte_range(&self) -> Range<usize> {
842 let start = self.lookup_type_byte_range().end;
843 start..start + LookupFlag::RAW_BYTE_LEN
844 }
845
846 pub fn sub_table_count_byte_range(&self) -> Range<usize> {
847 let start = self.lookup_flag_byte_range().end;
848 start..start + u16::RAW_BYTE_LEN
849 }
850
851 pub fn subtable_offsets_byte_range(&self) -> Range<usize> {
852 let start = self.sub_table_count_byte_range().end;
853 start..start + self.subtable_offsets_byte_len
854 }
855
856 pub fn mark_filtering_set_byte_range(&self) -> Option<Range<usize>> {
857 let start = self.mark_filtering_set_byte_start?;
858 Some(start..start + u16::RAW_BYTE_LEN)
859 }
860}
861
862impl MinByteRange for LookupMarker {
863 fn min_byte_range(&self) -> Range<usize> {
864 0..self.subtable_offsets_byte_range().end
865 }
866}
867
868impl<T> Clone for LookupMarker<T> {
869 fn clone(&self) -> Self {
870 *self
871 }
872}
873
874impl<T> Copy for LookupMarker<T> {}
875
876impl<'a, T> FontRead<'a> for Lookup<'a, T> {
877 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
878 let mut cursor = data.cursor();
879 cursor.advance::<u16>();
880 let lookup_flag: LookupFlag = cursor.read()?;
881 let sub_table_count: u16 = cursor.read()?;
882 let subtable_offsets_byte_len = (sub_table_count as usize)
883 .checked_mul(Offset16::RAW_BYTE_LEN)
884 .ok_or(ReadError::OutOfBounds)?;
885 cursor.advance_by(subtable_offsets_byte_len);
886 let mark_filtering_set_byte_start = lookup_flag
887 .contains(LookupFlag::USE_MARK_FILTERING_SET)
888 .then(|| cursor.position())
889 .transpose()?;
890 lookup_flag
891 .contains(LookupFlag::USE_MARK_FILTERING_SET)
892 .then(|| cursor.advance::<u16>());
893 cursor.finish(LookupMarker {
894 subtable_offsets_byte_len,
895 mark_filtering_set_byte_start,
896 offset_type: std::marker::PhantomData,
897 })
898 }
899}
900
901impl<'a> Lookup<'a, ()> {
902 #[allow(dead_code)]
903 pub(crate) fn into_concrete<T>(self) -> Lookup<'a, T> {
904 let TableRef { data, shape } = self;
905 TableRef {
906 shape: LookupMarker {
907 subtable_offsets_byte_len: shape.subtable_offsets_byte_len,
908 mark_filtering_set_byte_start: shape.mark_filtering_set_byte_start,
909 offset_type: std::marker::PhantomData,
910 },
911 data,
912 }
913 }
914}
915
916impl<'a, T> Lookup<'a, T> {
917 #[allow(dead_code)]
918 pub(crate) fn of_unit_type(&self) -> Lookup<'a, ()> {
920 let TableRef { data, shape } = self;
921 TableRef {
922 shape: LookupMarker {
923 subtable_offsets_byte_len: shape.subtable_offsets_byte_len,
924 mark_filtering_set_byte_start: shape.mark_filtering_set_byte_start,
925 offset_type: std::marker::PhantomData,
926 },
927 data: *data,
928 }
929 }
930}
931
932pub type Lookup<'a, T> = TableRef<'a, LookupMarker<T>>;
934
935#[allow(clippy::needless_lifetimes)]
936impl<'a, T> Lookup<'a, T> {
937 pub fn lookup_type(&self) -> u16 {
939 let range = self.shape.lookup_type_byte_range();
940 self.data.read_at(range.start).unwrap()
941 }
942
943 pub fn lookup_flag(&self) -> LookupFlag {
945 let range = self.shape.lookup_flag_byte_range();
946 self.data.read_at(range.start).unwrap()
947 }
948
949 pub fn sub_table_count(&self) -> u16 {
951 let range = self.shape.sub_table_count_byte_range();
952 self.data.read_at(range.start).unwrap()
953 }
954
955 pub fn subtable_offsets(&self) -> &'a [BigEndian<Offset16>] {
958 let range = self.shape.subtable_offsets_byte_range();
959 self.data.read_array(range).unwrap()
960 }
961
962 pub fn subtables(&self) -> ArrayOfOffsets<'a, T, Offset16>
964 where
965 T: FontRead<'a>,
966 {
967 let data = self.data;
968 let offsets = self.subtable_offsets();
969 ArrayOfOffsets::new(offsets, data, ())
970 }
971
972 pub fn mark_filtering_set(&self) -> Option<u16> {
976 let range = self.shape.mark_filtering_set_byte_range()?;
977 Some(self.data.read_at(range.start).unwrap())
978 }
979}
980
981#[cfg(feature = "experimental_traverse")]
982impl<'a, T: FontRead<'a> + SomeTable<'a> + 'a> SomeTable<'a> for Lookup<'a, T> {
983 fn type_name(&self) -> &str {
984 "Lookup"
985 }
986 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
987 let lookup_flag = self.lookup_flag();
988 match idx {
989 0usize => Some(Field::new("lookup_type", self.lookup_type())),
990 1usize => Some(Field::new("lookup_flag", self.traverse_lookup_flag())),
991 2usize => Some(Field::new("sub_table_count", self.sub_table_count())),
992 3usize => Some({
993 let data = self.data;
994 Field::new(
995 "subtable_offsets",
996 FieldType::array_of_offsets(
997 better_type_name::<T>(),
998 self.subtable_offsets(),
999 move |off| {
1000 let target = off.get().resolve::<T>(data);
1001 FieldType::offset(off.get(), target)
1002 },
1003 ),
1004 )
1005 }),
1006 4usize if lookup_flag.contains(LookupFlag::USE_MARK_FILTERING_SET) => Some(Field::new(
1007 "mark_filtering_set",
1008 self.mark_filtering_set().unwrap(),
1009 )),
1010 _ => None,
1011 }
1012 }
1013}
1014
1015#[cfg(feature = "experimental_traverse")]
1016#[allow(clippy::needless_lifetimes)]
1017impl<'a, T: FontRead<'a> + SomeTable<'a> + 'a> std::fmt::Debug for Lookup<'a, T> {
1018 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1019 (self as &dyn SomeTable<'a>).fmt(f)
1020 }
1021}
1022
1023impl Format<u16> for CoverageFormat1Marker {
1024 const FORMAT: u16 = 1;
1025}
1026
1027#[derive(Debug, Clone, Copy)]
1029#[doc(hidden)]
1030pub struct CoverageFormat1Marker {
1031 glyph_array_byte_len: usize,
1032}
1033
1034impl CoverageFormat1Marker {
1035 pub fn coverage_format_byte_range(&self) -> Range<usize> {
1036 let start = 0;
1037 start..start + u16::RAW_BYTE_LEN
1038 }
1039
1040 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1041 let start = self.coverage_format_byte_range().end;
1042 start..start + u16::RAW_BYTE_LEN
1043 }
1044
1045 pub fn glyph_array_byte_range(&self) -> Range<usize> {
1046 let start = self.glyph_count_byte_range().end;
1047 start..start + self.glyph_array_byte_len
1048 }
1049}
1050
1051impl MinByteRange for CoverageFormat1Marker {
1052 fn min_byte_range(&self) -> Range<usize> {
1053 0..self.glyph_array_byte_range().end
1054 }
1055}
1056
1057impl<'a> FontRead<'a> for CoverageFormat1<'a> {
1058 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1059 let mut cursor = data.cursor();
1060 cursor.advance::<u16>();
1061 let glyph_count: u16 = cursor.read()?;
1062 let glyph_array_byte_len = (glyph_count as usize)
1063 .checked_mul(GlyphId16::RAW_BYTE_LEN)
1064 .ok_or(ReadError::OutOfBounds)?;
1065 cursor.advance_by(glyph_array_byte_len);
1066 cursor.finish(CoverageFormat1Marker {
1067 glyph_array_byte_len,
1068 })
1069 }
1070}
1071
1072pub type CoverageFormat1<'a> = TableRef<'a, CoverageFormat1Marker>;
1074
1075#[allow(clippy::needless_lifetimes)]
1076impl<'a> CoverageFormat1<'a> {
1077 pub fn coverage_format(&self) -> u16 {
1079 let range = self.shape.coverage_format_byte_range();
1080 self.data.read_at(range.start).unwrap()
1081 }
1082
1083 pub fn glyph_count(&self) -> u16 {
1085 let range = self.shape.glyph_count_byte_range();
1086 self.data.read_at(range.start).unwrap()
1087 }
1088
1089 pub fn glyph_array(&self) -> &'a [BigEndian<GlyphId16>] {
1091 let range = self.shape.glyph_array_byte_range();
1092 self.data.read_array(range).unwrap()
1093 }
1094}
1095
1096#[cfg(feature = "experimental_traverse")]
1097impl<'a> SomeTable<'a> for CoverageFormat1<'a> {
1098 fn type_name(&self) -> &str {
1099 "CoverageFormat1"
1100 }
1101 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1102 match idx {
1103 0usize => Some(Field::new("coverage_format", self.coverage_format())),
1104 1usize => Some(Field::new("glyph_count", self.glyph_count())),
1105 2usize => Some(Field::new("glyph_array", self.glyph_array())),
1106 _ => None,
1107 }
1108 }
1109}
1110
1111#[cfg(feature = "experimental_traverse")]
1112#[allow(clippy::needless_lifetimes)]
1113impl<'a> std::fmt::Debug for CoverageFormat1<'a> {
1114 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1115 (self as &dyn SomeTable<'a>).fmt(f)
1116 }
1117}
1118
1119impl Format<u16> for CoverageFormat2Marker {
1120 const FORMAT: u16 = 2;
1121}
1122
1123#[derive(Debug, Clone, Copy)]
1125#[doc(hidden)]
1126pub struct CoverageFormat2Marker {
1127 range_records_byte_len: usize,
1128}
1129
1130impl CoverageFormat2Marker {
1131 pub fn coverage_format_byte_range(&self) -> Range<usize> {
1132 let start = 0;
1133 start..start + u16::RAW_BYTE_LEN
1134 }
1135
1136 pub fn range_count_byte_range(&self) -> Range<usize> {
1137 let start = self.coverage_format_byte_range().end;
1138 start..start + u16::RAW_BYTE_LEN
1139 }
1140
1141 pub fn range_records_byte_range(&self) -> Range<usize> {
1142 let start = self.range_count_byte_range().end;
1143 start..start + self.range_records_byte_len
1144 }
1145}
1146
1147impl MinByteRange for CoverageFormat2Marker {
1148 fn min_byte_range(&self) -> Range<usize> {
1149 0..self.range_records_byte_range().end
1150 }
1151}
1152
1153impl<'a> FontRead<'a> for CoverageFormat2<'a> {
1154 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1155 let mut cursor = data.cursor();
1156 cursor.advance::<u16>();
1157 let range_count: u16 = cursor.read()?;
1158 let range_records_byte_len = (range_count as usize)
1159 .checked_mul(RangeRecord::RAW_BYTE_LEN)
1160 .ok_or(ReadError::OutOfBounds)?;
1161 cursor.advance_by(range_records_byte_len);
1162 cursor.finish(CoverageFormat2Marker {
1163 range_records_byte_len,
1164 })
1165 }
1166}
1167
1168pub type CoverageFormat2<'a> = TableRef<'a, CoverageFormat2Marker>;
1170
1171#[allow(clippy::needless_lifetimes)]
1172impl<'a> CoverageFormat2<'a> {
1173 pub fn coverage_format(&self) -> u16 {
1175 let range = self.shape.coverage_format_byte_range();
1176 self.data.read_at(range.start).unwrap()
1177 }
1178
1179 pub fn range_count(&self) -> u16 {
1181 let range = self.shape.range_count_byte_range();
1182 self.data.read_at(range.start).unwrap()
1183 }
1184
1185 pub fn range_records(&self) -> &'a [RangeRecord] {
1187 let range = self.shape.range_records_byte_range();
1188 self.data.read_array(range).unwrap()
1189 }
1190}
1191
1192#[cfg(feature = "experimental_traverse")]
1193impl<'a> SomeTable<'a> for CoverageFormat2<'a> {
1194 fn type_name(&self) -> &str {
1195 "CoverageFormat2"
1196 }
1197 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1198 match idx {
1199 0usize => Some(Field::new("coverage_format", self.coverage_format())),
1200 1usize => Some(Field::new("range_count", self.range_count())),
1201 2usize => Some(Field::new(
1202 "range_records",
1203 traversal::FieldType::array_of_records(
1204 stringify!(RangeRecord),
1205 self.range_records(),
1206 self.offset_data(),
1207 ),
1208 )),
1209 _ => None,
1210 }
1211 }
1212}
1213
1214#[cfg(feature = "experimental_traverse")]
1215#[allow(clippy::needless_lifetimes)]
1216impl<'a> std::fmt::Debug for CoverageFormat2<'a> {
1217 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1218 (self as &dyn SomeTable<'a>).fmt(f)
1219 }
1220}
1221
1222#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1224#[repr(C)]
1225#[repr(packed)]
1226pub struct RangeRecord {
1227 pub start_glyph_id: BigEndian<GlyphId16>,
1229 pub end_glyph_id: BigEndian<GlyphId16>,
1231 pub start_coverage_index: BigEndian<u16>,
1233}
1234
1235impl RangeRecord {
1236 pub fn start_glyph_id(&self) -> GlyphId16 {
1238 self.start_glyph_id.get()
1239 }
1240
1241 pub fn end_glyph_id(&self) -> GlyphId16 {
1243 self.end_glyph_id.get()
1244 }
1245
1246 pub fn start_coverage_index(&self) -> u16 {
1248 self.start_coverage_index.get()
1249 }
1250}
1251
1252impl FixedSize for RangeRecord {
1253 const RAW_BYTE_LEN: usize =
1254 GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1255}
1256
1257#[cfg(feature = "experimental_traverse")]
1258impl<'a> SomeRecord<'a> for RangeRecord {
1259 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1260 RecordResolver {
1261 name: "RangeRecord",
1262 get_field: Box::new(move |idx, _data| match idx {
1263 0usize => Some(Field::new("start_glyph_id", self.start_glyph_id())),
1264 1usize => Some(Field::new("end_glyph_id", self.end_glyph_id())),
1265 2usize => Some(Field::new(
1266 "start_coverage_index",
1267 self.start_coverage_index(),
1268 )),
1269 _ => None,
1270 }),
1271 data,
1272 }
1273 }
1274}
1275
1276#[derive(Clone)]
1278pub enum CoverageTable<'a> {
1279 Format1(CoverageFormat1<'a>),
1280 Format2(CoverageFormat2<'a>),
1281}
1282
1283impl<'a> CoverageTable<'a> {
1284 pub fn offset_data(&self) -> FontData<'a> {
1286 match self {
1287 Self::Format1(item) => item.offset_data(),
1288 Self::Format2(item) => item.offset_data(),
1289 }
1290 }
1291
1292 pub fn coverage_format(&self) -> u16 {
1294 match self {
1295 Self::Format1(item) => item.coverage_format(),
1296 Self::Format2(item) => item.coverage_format(),
1297 }
1298 }
1299}
1300
1301impl<'a> FontRead<'a> for CoverageTable<'a> {
1302 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1303 let format: u16 = data.read_at(0usize)?;
1304 match format {
1305 CoverageFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1306 CoverageFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1307 other => Err(ReadError::InvalidFormat(other.into())),
1308 }
1309 }
1310}
1311
1312impl MinByteRange for CoverageTable<'_> {
1313 fn min_byte_range(&self) -> Range<usize> {
1314 match self {
1315 Self::Format1(item) => item.min_byte_range(),
1316 Self::Format2(item) => item.min_byte_range(),
1317 }
1318 }
1319}
1320
1321#[cfg(feature = "experimental_traverse")]
1322impl<'a> CoverageTable<'a> {
1323 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
1324 match self {
1325 Self::Format1(table) => table,
1326 Self::Format2(table) => table,
1327 }
1328 }
1329}
1330
1331#[cfg(feature = "experimental_traverse")]
1332impl std::fmt::Debug for CoverageTable<'_> {
1333 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1334 self.dyn_inner().fmt(f)
1335 }
1336}
1337
1338#[cfg(feature = "experimental_traverse")]
1339impl<'a> SomeTable<'a> for CoverageTable<'a> {
1340 fn type_name(&self) -> &str {
1341 self.dyn_inner().type_name()
1342 }
1343 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1344 self.dyn_inner().get_field(idx)
1345 }
1346}
1347
1348impl Format<u16> for ClassDefFormat1Marker {
1349 const FORMAT: u16 = 1;
1350}
1351
1352#[derive(Debug, Clone, Copy)]
1354#[doc(hidden)]
1355pub struct ClassDefFormat1Marker {
1356 class_value_array_byte_len: usize,
1357}
1358
1359impl ClassDefFormat1Marker {
1360 pub fn class_format_byte_range(&self) -> Range<usize> {
1361 let start = 0;
1362 start..start + u16::RAW_BYTE_LEN
1363 }
1364
1365 pub fn start_glyph_id_byte_range(&self) -> Range<usize> {
1366 let start = self.class_format_byte_range().end;
1367 start..start + GlyphId16::RAW_BYTE_LEN
1368 }
1369
1370 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1371 let start = self.start_glyph_id_byte_range().end;
1372 start..start + u16::RAW_BYTE_LEN
1373 }
1374
1375 pub fn class_value_array_byte_range(&self) -> Range<usize> {
1376 let start = self.glyph_count_byte_range().end;
1377 start..start + self.class_value_array_byte_len
1378 }
1379}
1380
1381impl MinByteRange for ClassDefFormat1Marker {
1382 fn min_byte_range(&self) -> Range<usize> {
1383 0..self.class_value_array_byte_range().end
1384 }
1385}
1386
1387impl<'a> FontRead<'a> for ClassDefFormat1<'a> {
1388 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1389 let mut cursor = data.cursor();
1390 cursor.advance::<u16>();
1391 cursor.advance::<GlyphId16>();
1392 let glyph_count: u16 = cursor.read()?;
1393 let class_value_array_byte_len = (glyph_count as usize)
1394 .checked_mul(u16::RAW_BYTE_LEN)
1395 .ok_or(ReadError::OutOfBounds)?;
1396 cursor.advance_by(class_value_array_byte_len);
1397 cursor.finish(ClassDefFormat1Marker {
1398 class_value_array_byte_len,
1399 })
1400 }
1401}
1402
1403pub type ClassDefFormat1<'a> = TableRef<'a, ClassDefFormat1Marker>;
1405
1406#[allow(clippy::needless_lifetimes)]
1407impl<'a> ClassDefFormat1<'a> {
1408 pub fn class_format(&self) -> u16 {
1410 let range = self.shape.class_format_byte_range();
1411 self.data.read_at(range.start).unwrap()
1412 }
1413
1414 pub fn start_glyph_id(&self) -> GlyphId16 {
1416 let range = self.shape.start_glyph_id_byte_range();
1417 self.data.read_at(range.start).unwrap()
1418 }
1419
1420 pub fn glyph_count(&self) -> u16 {
1422 let range = self.shape.glyph_count_byte_range();
1423 self.data.read_at(range.start).unwrap()
1424 }
1425
1426 pub fn class_value_array(&self) -> &'a [BigEndian<u16>] {
1428 let range = self.shape.class_value_array_byte_range();
1429 self.data.read_array(range).unwrap()
1430 }
1431}
1432
1433#[cfg(feature = "experimental_traverse")]
1434impl<'a> SomeTable<'a> for ClassDefFormat1<'a> {
1435 fn type_name(&self) -> &str {
1436 "ClassDefFormat1"
1437 }
1438 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1439 match idx {
1440 0usize => Some(Field::new("class_format", self.class_format())),
1441 1usize => Some(Field::new("start_glyph_id", self.start_glyph_id())),
1442 2usize => Some(Field::new("glyph_count", self.glyph_count())),
1443 3usize => Some(Field::new("class_value_array", self.class_value_array())),
1444 _ => None,
1445 }
1446 }
1447}
1448
1449#[cfg(feature = "experimental_traverse")]
1450#[allow(clippy::needless_lifetimes)]
1451impl<'a> std::fmt::Debug for ClassDefFormat1<'a> {
1452 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1453 (self as &dyn SomeTable<'a>).fmt(f)
1454 }
1455}
1456
1457impl Format<u16> for ClassDefFormat2Marker {
1458 const FORMAT: u16 = 2;
1459}
1460
1461#[derive(Debug, Clone, Copy)]
1463#[doc(hidden)]
1464pub struct ClassDefFormat2Marker {
1465 class_range_records_byte_len: usize,
1466}
1467
1468impl ClassDefFormat2Marker {
1469 pub fn class_format_byte_range(&self) -> Range<usize> {
1470 let start = 0;
1471 start..start + u16::RAW_BYTE_LEN
1472 }
1473
1474 pub fn class_range_count_byte_range(&self) -> Range<usize> {
1475 let start = self.class_format_byte_range().end;
1476 start..start + u16::RAW_BYTE_LEN
1477 }
1478
1479 pub fn class_range_records_byte_range(&self) -> Range<usize> {
1480 let start = self.class_range_count_byte_range().end;
1481 start..start + self.class_range_records_byte_len
1482 }
1483}
1484
1485impl MinByteRange for ClassDefFormat2Marker {
1486 fn min_byte_range(&self) -> Range<usize> {
1487 0..self.class_range_records_byte_range().end
1488 }
1489}
1490
1491impl<'a> FontRead<'a> for ClassDefFormat2<'a> {
1492 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1493 let mut cursor = data.cursor();
1494 cursor.advance::<u16>();
1495 let class_range_count: u16 = cursor.read()?;
1496 let class_range_records_byte_len = (class_range_count as usize)
1497 .checked_mul(ClassRangeRecord::RAW_BYTE_LEN)
1498 .ok_or(ReadError::OutOfBounds)?;
1499 cursor.advance_by(class_range_records_byte_len);
1500 cursor.finish(ClassDefFormat2Marker {
1501 class_range_records_byte_len,
1502 })
1503 }
1504}
1505
1506pub type ClassDefFormat2<'a> = TableRef<'a, ClassDefFormat2Marker>;
1508
1509#[allow(clippy::needless_lifetimes)]
1510impl<'a> ClassDefFormat2<'a> {
1511 pub fn class_format(&self) -> u16 {
1513 let range = self.shape.class_format_byte_range();
1514 self.data.read_at(range.start).unwrap()
1515 }
1516
1517 pub fn class_range_count(&self) -> u16 {
1519 let range = self.shape.class_range_count_byte_range();
1520 self.data.read_at(range.start).unwrap()
1521 }
1522
1523 pub fn class_range_records(&self) -> &'a [ClassRangeRecord] {
1525 let range = self.shape.class_range_records_byte_range();
1526 self.data.read_array(range).unwrap()
1527 }
1528}
1529
1530#[cfg(feature = "experimental_traverse")]
1531impl<'a> SomeTable<'a> for ClassDefFormat2<'a> {
1532 fn type_name(&self) -> &str {
1533 "ClassDefFormat2"
1534 }
1535 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1536 match idx {
1537 0usize => Some(Field::new("class_format", self.class_format())),
1538 1usize => Some(Field::new("class_range_count", self.class_range_count())),
1539 2usize => Some(Field::new(
1540 "class_range_records",
1541 traversal::FieldType::array_of_records(
1542 stringify!(ClassRangeRecord),
1543 self.class_range_records(),
1544 self.offset_data(),
1545 ),
1546 )),
1547 _ => None,
1548 }
1549 }
1550}
1551
1552#[cfg(feature = "experimental_traverse")]
1553#[allow(clippy::needless_lifetimes)]
1554impl<'a> std::fmt::Debug for ClassDefFormat2<'a> {
1555 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1556 (self as &dyn SomeTable<'a>).fmt(f)
1557 }
1558}
1559
1560#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1562#[repr(C)]
1563#[repr(packed)]
1564pub struct ClassRangeRecord {
1565 pub start_glyph_id: BigEndian<GlyphId16>,
1567 pub end_glyph_id: BigEndian<GlyphId16>,
1569 pub class: BigEndian<u16>,
1571}
1572
1573impl ClassRangeRecord {
1574 pub fn start_glyph_id(&self) -> GlyphId16 {
1576 self.start_glyph_id.get()
1577 }
1578
1579 pub fn end_glyph_id(&self) -> GlyphId16 {
1581 self.end_glyph_id.get()
1582 }
1583
1584 pub fn class(&self) -> u16 {
1586 self.class.get()
1587 }
1588}
1589
1590impl FixedSize for ClassRangeRecord {
1591 const RAW_BYTE_LEN: usize =
1592 GlyphId16::RAW_BYTE_LEN + GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1593}
1594
1595#[cfg(feature = "experimental_traverse")]
1596impl<'a> SomeRecord<'a> for ClassRangeRecord {
1597 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1598 RecordResolver {
1599 name: "ClassRangeRecord",
1600 get_field: Box::new(move |idx, _data| match idx {
1601 0usize => Some(Field::new("start_glyph_id", self.start_glyph_id())),
1602 1usize => Some(Field::new("end_glyph_id", self.end_glyph_id())),
1603 2usize => Some(Field::new("class", self.class())),
1604 _ => None,
1605 }),
1606 data,
1607 }
1608 }
1609}
1610
1611#[derive(Clone)]
1613pub enum ClassDef<'a> {
1614 Format1(ClassDefFormat1<'a>),
1615 Format2(ClassDefFormat2<'a>),
1616}
1617
1618impl<'a> ClassDef<'a> {
1619 pub fn offset_data(&self) -> FontData<'a> {
1621 match self {
1622 Self::Format1(item) => item.offset_data(),
1623 Self::Format2(item) => item.offset_data(),
1624 }
1625 }
1626
1627 pub fn class_format(&self) -> u16 {
1629 match self {
1630 Self::Format1(item) => item.class_format(),
1631 Self::Format2(item) => item.class_format(),
1632 }
1633 }
1634}
1635
1636impl<'a> FontRead<'a> for ClassDef<'a> {
1637 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1638 let format: u16 = data.read_at(0usize)?;
1639 match format {
1640 ClassDefFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
1641 ClassDefFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
1642 other => Err(ReadError::InvalidFormat(other.into())),
1643 }
1644 }
1645}
1646
1647impl MinByteRange for ClassDef<'_> {
1648 fn min_byte_range(&self) -> Range<usize> {
1649 match self {
1650 Self::Format1(item) => item.min_byte_range(),
1651 Self::Format2(item) => item.min_byte_range(),
1652 }
1653 }
1654}
1655
1656#[cfg(feature = "experimental_traverse")]
1657impl<'a> ClassDef<'a> {
1658 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
1659 match self {
1660 Self::Format1(table) => table,
1661 Self::Format2(table) => table,
1662 }
1663 }
1664}
1665
1666#[cfg(feature = "experimental_traverse")]
1667impl std::fmt::Debug for ClassDef<'_> {
1668 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1669 self.dyn_inner().fmt(f)
1670 }
1671}
1672
1673#[cfg(feature = "experimental_traverse")]
1674impl<'a> SomeTable<'a> for ClassDef<'a> {
1675 fn type_name(&self) -> &str {
1676 self.dyn_inner().type_name()
1677 }
1678 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1679 self.dyn_inner().get_field(idx)
1680 }
1681}
1682
1683#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1685#[repr(C)]
1686#[repr(packed)]
1687pub struct SequenceLookupRecord {
1688 pub sequence_index: BigEndian<u16>,
1690 pub lookup_list_index: BigEndian<u16>,
1692}
1693
1694impl SequenceLookupRecord {
1695 pub fn sequence_index(&self) -> u16 {
1697 self.sequence_index.get()
1698 }
1699
1700 pub fn lookup_list_index(&self) -> u16 {
1702 self.lookup_list_index.get()
1703 }
1704}
1705
1706impl FixedSize for SequenceLookupRecord {
1707 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1708}
1709
1710#[cfg(feature = "experimental_traverse")]
1711impl<'a> SomeRecord<'a> for SequenceLookupRecord {
1712 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1713 RecordResolver {
1714 name: "SequenceLookupRecord",
1715 get_field: Box::new(move |idx, _data| match idx {
1716 0usize => Some(Field::new("sequence_index", self.sequence_index())),
1717 1usize => Some(Field::new("lookup_list_index", self.lookup_list_index())),
1718 _ => None,
1719 }),
1720 data,
1721 }
1722 }
1723}
1724
1725impl Format<u16> for SequenceContextFormat1Marker {
1726 const FORMAT: u16 = 1;
1727}
1728
1729#[derive(Debug, Clone, Copy)]
1731#[doc(hidden)]
1732pub struct SequenceContextFormat1Marker {
1733 seq_rule_set_offsets_byte_len: usize,
1734}
1735
1736impl SequenceContextFormat1Marker {
1737 pub fn format_byte_range(&self) -> Range<usize> {
1738 let start = 0;
1739 start..start + u16::RAW_BYTE_LEN
1740 }
1741
1742 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1743 let start = self.format_byte_range().end;
1744 start..start + Offset16::RAW_BYTE_LEN
1745 }
1746
1747 pub fn seq_rule_set_count_byte_range(&self) -> Range<usize> {
1748 let start = self.coverage_offset_byte_range().end;
1749 start..start + u16::RAW_BYTE_LEN
1750 }
1751
1752 pub fn seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
1753 let start = self.seq_rule_set_count_byte_range().end;
1754 start..start + self.seq_rule_set_offsets_byte_len
1755 }
1756}
1757
1758impl MinByteRange for SequenceContextFormat1Marker {
1759 fn min_byte_range(&self) -> Range<usize> {
1760 0..self.seq_rule_set_offsets_byte_range().end
1761 }
1762}
1763
1764impl<'a> FontRead<'a> for SequenceContextFormat1<'a> {
1765 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1766 let mut cursor = data.cursor();
1767 cursor.advance::<u16>();
1768 cursor.advance::<Offset16>();
1769 let seq_rule_set_count: u16 = cursor.read()?;
1770 let seq_rule_set_offsets_byte_len = (seq_rule_set_count as usize)
1771 .checked_mul(Offset16::RAW_BYTE_LEN)
1772 .ok_or(ReadError::OutOfBounds)?;
1773 cursor.advance_by(seq_rule_set_offsets_byte_len);
1774 cursor.finish(SequenceContextFormat1Marker {
1775 seq_rule_set_offsets_byte_len,
1776 })
1777 }
1778}
1779
1780pub type SequenceContextFormat1<'a> = TableRef<'a, SequenceContextFormat1Marker>;
1782
1783#[allow(clippy::needless_lifetimes)]
1784impl<'a> SequenceContextFormat1<'a> {
1785 pub fn format(&self) -> u16 {
1787 let range = self.shape.format_byte_range();
1788 self.data.read_at(range.start).unwrap()
1789 }
1790
1791 pub fn coverage_offset(&self) -> Offset16 {
1794 let range = self.shape.coverage_offset_byte_range();
1795 self.data.read_at(range.start).unwrap()
1796 }
1797
1798 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1800 let data = self.data;
1801 self.coverage_offset().resolve(data)
1802 }
1803
1804 pub fn seq_rule_set_count(&self) -> u16 {
1806 let range = self.shape.seq_rule_set_count_byte_range();
1807 self.data.read_at(range.start).unwrap()
1808 }
1809
1810 pub fn seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
1813 let range = self.shape.seq_rule_set_offsets_byte_range();
1814 self.data.read_array(range).unwrap()
1815 }
1816
1817 pub fn seq_rule_sets(&self) -> ArrayOfNullableOffsets<'a, SequenceRuleSet<'a>, Offset16> {
1819 let data = self.data;
1820 let offsets = self.seq_rule_set_offsets();
1821 ArrayOfNullableOffsets::new(offsets, data, ())
1822 }
1823}
1824
1825#[cfg(feature = "experimental_traverse")]
1826impl<'a> SomeTable<'a> for SequenceContextFormat1<'a> {
1827 fn type_name(&self) -> &str {
1828 "SequenceContextFormat1"
1829 }
1830 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1831 match idx {
1832 0usize => Some(Field::new("format", self.format())),
1833 1usize => Some(Field::new(
1834 "coverage_offset",
1835 FieldType::offset(self.coverage_offset(), self.coverage()),
1836 )),
1837 2usize => Some(Field::new("seq_rule_set_count", self.seq_rule_set_count())),
1838 3usize => Some({
1839 let data = self.data;
1840 Field::new(
1841 "seq_rule_set_offsets",
1842 FieldType::array_of_offsets(
1843 better_type_name::<SequenceRuleSet>(),
1844 self.seq_rule_set_offsets(),
1845 move |off| {
1846 let target = off.get().resolve::<SequenceRuleSet>(data);
1847 FieldType::offset(off.get(), target)
1848 },
1849 ),
1850 )
1851 }),
1852 _ => None,
1853 }
1854 }
1855}
1856
1857#[cfg(feature = "experimental_traverse")]
1858#[allow(clippy::needless_lifetimes)]
1859impl<'a> std::fmt::Debug for SequenceContextFormat1<'a> {
1860 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1861 (self as &dyn SomeTable<'a>).fmt(f)
1862 }
1863}
1864
1865#[derive(Debug, Clone, Copy)]
1867#[doc(hidden)]
1868pub struct SequenceRuleSetMarker {
1869 seq_rule_offsets_byte_len: usize,
1870}
1871
1872impl SequenceRuleSetMarker {
1873 pub fn seq_rule_count_byte_range(&self) -> Range<usize> {
1874 let start = 0;
1875 start..start + u16::RAW_BYTE_LEN
1876 }
1877
1878 pub fn seq_rule_offsets_byte_range(&self) -> Range<usize> {
1879 let start = self.seq_rule_count_byte_range().end;
1880 start..start + self.seq_rule_offsets_byte_len
1881 }
1882}
1883
1884impl MinByteRange for SequenceRuleSetMarker {
1885 fn min_byte_range(&self) -> Range<usize> {
1886 0..self.seq_rule_offsets_byte_range().end
1887 }
1888}
1889
1890impl<'a> FontRead<'a> for SequenceRuleSet<'a> {
1891 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1892 let mut cursor = data.cursor();
1893 let seq_rule_count: u16 = cursor.read()?;
1894 let seq_rule_offsets_byte_len = (seq_rule_count as usize)
1895 .checked_mul(Offset16::RAW_BYTE_LEN)
1896 .ok_or(ReadError::OutOfBounds)?;
1897 cursor.advance_by(seq_rule_offsets_byte_len);
1898 cursor.finish(SequenceRuleSetMarker {
1899 seq_rule_offsets_byte_len,
1900 })
1901 }
1902}
1903
1904pub type SequenceRuleSet<'a> = TableRef<'a, SequenceRuleSetMarker>;
1906
1907#[allow(clippy::needless_lifetimes)]
1908impl<'a> SequenceRuleSet<'a> {
1909 pub fn seq_rule_count(&self) -> u16 {
1911 let range = self.shape.seq_rule_count_byte_range();
1912 self.data.read_at(range.start).unwrap()
1913 }
1914
1915 pub fn seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
1918 let range = self.shape.seq_rule_offsets_byte_range();
1919 self.data.read_array(range).unwrap()
1920 }
1921
1922 pub fn seq_rules(&self) -> ArrayOfOffsets<'a, SequenceRule<'a>, Offset16> {
1924 let data = self.data;
1925 let offsets = self.seq_rule_offsets();
1926 ArrayOfOffsets::new(offsets, data, ())
1927 }
1928}
1929
1930#[cfg(feature = "experimental_traverse")]
1931impl<'a> SomeTable<'a> for SequenceRuleSet<'a> {
1932 fn type_name(&self) -> &str {
1933 "SequenceRuleSet"
1934 }
1935 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1936 match idx {
1937 0usize => Some(Field::new("seq_rule_count", self.seq_rule_count())),
1938 1usize => Some({
1939 let data = self.data;
1940 Field::new(
1941 "seq_rule_offsets",
1942 FieldType::array_of_offsets(
1943 better_type_name::<SequenceRule>(),
1944 self.seq_rule_offsets(),
1945 move |off| {
1946 let target = off.get().resolve::<SequenceRule>(data);
1947 FieldType::offset(off.get(), target)
1948 },
1949 ),
1950 )
1951 }),
1952 _ => None,
1953 }
1954 }
1955}
1956
1957#[cfg(feature = "experimental_traverse")]
1958#[allow(clippy::needless_lifetimes)]
1959impl<'a> std::fmt::Debug for SequenceRuleSet<'a> {
1960 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1961 (self as &dyn SomeTable<'a>).fmt(f)
1962 }
1963}
1964
1965#[derive(Debug, Clone, Copy)]
1967#[doc(hidden)]
1968pub struct SequenceRuleMarker {
1969 input_sequence_byte_len: usize,
1970 seq_lookup_records_byte_len: usize,
1971}
1972
1973impl SequenceRuleMarker {
1974 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1975 let start = 0;
1976 start..start + u16::RAW_BYTE_LEN
1977 }
1978
1979 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
1980 let start = self.glyph_count_byte_range().end;
1981 start..start + u16::RAW_BYTE_LEN
1982 }
1983
1984 pub fn input_sequence_byte_range(&self) -> Range<usize> {
1985 let start = self.seq_lookup_count_byte_range().end;
1986 start..start + self.input_sequence_byte_len
1987 }
1988
1989 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
1990 let start = self.input_sequence_byte_range().end;
1991 start..start + self.seq_lookup_records_byte_len
1992 }
1993}
1994
1995impl MinByteRange for SequenceRuleMarker {
1996 fn min_byte_range(&self) -> Range<usize> {
1997 0..self.seq_lookup_records_byte_range().end
1998 }
1999}
2000
2001impl<'a> FontRead<'a> for SequenceRule<'a> {
2002 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
2003 let mut cursor = data.cursor();
2004 let glyph_count: u16 = cursor.read()?;
2005 let seq_lookup_count: u16 = cursor.read()?;
2006 let input_sequence_byte_len = (transforms::subtract(glyph_count, 1_usize))
2007 .checked_mul(GlyphId16::RAW_BYTE_LEN)
2008 .ok_or(ReadError::OutOfBounds)?;
2009 cursor.advance_by(input_sequence_byte_len);
2010 let seq_lookup_records_byte_len = (seq_lookup_count as usize)
2011 .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN)
2012 .ok_or(ReadError::OutOfBounds)?;
2013 cursor.advance_by(seq_lookup_records_byte_len);
2014 cursor.finish(SequenceRuleMarker {
2015 input_sequence_byte_len,
2016 seq_lookup_records_byte_len,
2017 })
2018 }
2019}
2020
2021pub type SequenceRule<'a> = TableRef<'a, SequenceRuleMarker>;
2023
2024#[allow(clippy::needless_lifetimes)]
2025impl<'a> SequenceRule<'a> {
2026 pub fn glyph_count(&self) -> u16 {
2028 let range = self.shape.glyph_count_byte_range();
2029 self.data.read_at(range.start).unwrap()
2030 }
2031
2032 pub fn seq_lookup_count(&self) -> u16 {
2034 let range = self.shape.seq_lookup_count_byte_range();
2035 self.data.read_at(range.start).unwrap()
2036 }
2037
2038 pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
2040 let range = self.shape.input_sequence_byte_range();
2041 self.data.read_array(range).unwrap()
2042 }
2043
2044 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2046 let range = self.shape.seq_lookup_records_byte_range();
2047 self.data.read_array(range).unwrap()
2048 }
2049}
2050
2051#[cfg(feature = "experimental_traverse")]
2052impl<'a> SomeTable<'a> for SequenceRule<'a> {
2053 fn type_name(&self) -> &str {
2054 "SequenceRule"
2055 }
2056 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2057 match idx {
2058 0usize => Some(Field::new("glyph_count", self.glyph_count())),
2059 1usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
2060 2usize => Some(Field::new("input_sequence", self.input_sequence())),
2061 3usize => Some(Field::new(
2062 "seq_lookup_records",
2063 traversal::FieldType::array_of_records(
2064 stringify!(SequenceLookupRecord),
2065 self.seq_lookup_records(),
2066 self.offset_data(),
2067 ),
2068 )),
2069 _ => None,
2070 }
2071 }
2072}
2073
2074#[cfg(feature = "experimental_traverse")]
2075#[allow(clippy::needless_lifetimes)]
2076impl<'a> std::fmt::Debug for SequenceRule<'a> {
2077 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2078 (self as &dyn SomeTable<'a>).fmt(f)
2079 }
2080}
2081
2082impl Format<u16> for SequenceContextFormat2Marker {
2083 const FORMAT: u16 = 2;
2084}
2085
2086#[derive(Debug, Clone, Copy)]
2088#[doc(hidden)]
2089pub struct SequenceContextFormat2Marker {
2090 class_seq_rule_set_offsets_byte_len: usize,
2091}
2092
2093impl SequenceContextFormat2Marker {
2094 pub fn format_byte_range(&self) -> Range<usize> {
2095 let start = 0;
2096 start..start + u16::RAW_BYTE_LEN
2097 }
2098
2099 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2100 let start = self.format_byte_range().end;
2101 start..start + Offset16::RAW_BYTE_LEN
2102 }
2103
2104 pub fn class_def_offset_byte_range(&self) -> Range<usize> {
2105 let start = self.coverage_offset_byte_range().end;
2106 start..start + Offset16::RAW_BYTE_LEN
2107 }
2108
2109 pub fn class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
2110 let start = self.class_def_offset_byte_range().end;
2111 start..start + u16::RAW_BYTE_LEN
2112 }
2113
2114 pub fn class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
2115 let start = self.class_seq_rule_set_count_byte_range().end;
2116 start..start + self.class_seq_rule_set_offsets_byte_len
2117 }
2118}
2119
2120impl MinByteRange for SequenceContextFormat2Marker {
2121 fn min_byte_range(&self) -> Range<usize> {
2122 0..self.class_seq_rule_set_offsets_byte_range().end
2123 }
2124}
2125
2126impl<'a> FontRead<'a> for SequenceContextFormat2<'a> {
2127 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
2128 let mut cursor = data.cursor();
2129 cursor.advance::<u16>();
2130 cursor.advance::<Offset16>();
2131 cursor.advance::<Offset16>();
2132 let class_seq_rule_set_count: u16 = cursor.read()?;
2133 let class_seq_rule_set_offsets_byte_len = (class_seq_rule_set_count as usize)
2134 .checked_mul(Offset16::RAW_BYTE_LEN)
2135 .ok_or(ReadError::OutOfBounds)?;
2136 cursor.advance_by(class_seq_rule_set_offsets_byte_len);
2137 cursor.finish(SequenceContextFormat2Marker {
2138 class_seq_rule_set_offsets_byte_len,
2139 })
2140 }
2141}
2142
2143pub type SequenceContextFormat2<'a> = TableRef<'a, SequenceContextFormat2Marker>;
2145
2146#[allow(clippy::needless_lifetimes)]
2147impl<'a> SequenceContextFormat2<'a> {
2148 pub fn format(&self) -> u16 {
2150 let range = self.shape.format_byte_range();
2151 self.data.read_at(range.start).unwrap()
2152 }
2153
2154 pub fn coverage_offset(&self) -> Offset16 {
2157 let range = self.shape.coverage_offset_byte_range();
2158 self.data.read_at(range.start).unwrap()
2159 }
2160
2161 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2163 let data = self.data;
2164 self.coverage_offset().resolve(data)
2165 }
2166
2167 pub fn class_def_offset(&self) -> Offset16 {
2170 let range = self.shape.class_def_offset_byte_range();
2171 self.data.read_at(range.start).unwrap()
2172 }
2173
2174 pub fn class_def(&self) -> Result<ClassDef<'a>, ReadError> {
2176 let data = self.data;
2177 self.class_def_offset().resolve(data)
2178 }
2179
2180 pub fn class_seq_rule_set_count(&self) -> u16 {
2182 let range = self.shape.class_seq_rule_set_count_byte_range();
2183 self.data.read_at(range.start).unwrap()
2184 }
2185
2186 pub fn class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2189 let range = self.shape.class_seq_rule_set_offsets_byte_range();
2190 self.data.read_array(range).unwrap()
2191 }
2192
2193 pub fn class_seq_rule_sets(
2195 &self,
2196 ) -> ArrayOfNullableOffsets<'a, ClassSequenceRuleSet<'a>, Offset16> {
2197 let data = self.data;
2198 let offsets = self.class_seq_rule_set_offsets();
2199 ArrayOfNullableOffsets::new(offsets, data, ())
2200 }
2201}
2202
2203#[cfg(feature = "experimental_traverse")]
2204impl<'a> SomeTable<'a> for SequenceContextFormat2<'a> {
2205 fn type_name(&self) -> &str {
2206 "SequenceContextFormat2"
2207 }
2208 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2209 match idx {
2210 0usize => Some(Field::new("format", self.format())),
2211 1usize => Some(Field::new(
2212 "coverage_offset",
2213 FieldType::offset(self.coverage_offset(), self.coverage()),
2214 )),
2215 2usize => Some(Field::new(
2216 "class_def_offset",
2217 FieldType::offset(self.class_def_offset(), self.class_def()),
2218 )),
2219 3usize => Some(Field::new(
2220 "class_seq_rule_set_count",
2221 self.class_seq_rule_set_count(),
2222 )),
2223 4usize => Some({
2224 let data = self.data;
2225 Field::new(
2226 "class_seq_rule_set_offsets",
2227 FieldType::array_of_offsets(
2228 better_type_name::<ClassSequenceRuleSet>(),
2229 self.class_seq_rule_set_offsets(),
2230 move |off| {
2231 let target = off.get().resolve::<ClassSequenceRuleSet>(data);
2232 FieldType::offset(off.get(), target)
2233 },
2234 ),
2235 )
2236 }),
2237 _ => None,
2238 }
2239 }
2240}
2241
2242#[cfg(feature = "experimental_traverse")]
2243#[allow(clippy::needless_lifetimes)]
2244impl<'a> std::fmt::Debug for SequenceContextFormat2<'a> {
2245 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2246 (self as &dyn SomeTable<'a>).fmt(f)
2247 }
2248}
2249
2250#[derive(Debug, Clone, Copy)]
2252#[doc(hidden)]
2253pub struct ClassSequenceRuleSetMarker {
2254 class_seq_rule_offsets_byte_len: usize,
2255}
2256
2257impl ClassSequenceRuleSetMarker {
2258 pub fn class_seq_rule_count_byte_range(&self) -> Range<usize> {
2259 let start = 0;
2260 start..start + u16::RAW_BYTE_LEN
2261 }
2262
2263 pub fn class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
2264 let start = self.class_seq_rule_count_byte_range().end;
2265 start..start + self.class_seq_rule_offsets_byte_len
2266 }
2267}
2268
2269impl MinByteRange for ClassSequenceRuleSetMarker {
2270 fn min_byte_range(&self) -> Range<usize> {
2271 0..self.class_seq_rule_offsets_byte_range().end
2272 }
2273}
2274
2275impl<'a> FontRead<'a> for ClassSequenceRuleSet<'a> {
2276 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
2277 let mut cursor = data.cursor();
2278 let class_seq_rule_count: u16 = cursor.read()?;
2279 let class_seq_rule_offsets_byte_len = (class_seq_rule_count as usize)
2280 .checked_mul(Offset16::RAW_BYTE_LEN)
2281 .ok_or(ReadError::OutOfBounds)?;
2282 cursor.advance_by(class_seq_rule_offsets_byte_len);
2283 cursor.finish(ClassSequenceRuleSetMarker {
2284 class_seq_rule_offsets_byte_len,
2285 })
2286 }
2287}
2288
2289pub type ClassSequenceRuleSet<'a> = TableRef<'a, ClassSequenceRuleSetMarker>;
2291
2292#[allow(clippy::needless_lifetimes)]
2293impl<'a> ClassSequenceRuleSet<'a> {
2294 pub fn class_seq_rule_count(&self) -> u16 {
2296 let range = self.shape.class_seq_rule_count_byte_range();
2297 self.data.read_at(range.start).unwrap()
2298 }
2299
2300 pub fn class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
2303 let range = self.shape.class_seq_rule_offsets_byte_range();
2304 self.data.read_array(range).unwrap()
2305 }
2306
2307 pub fn class_seq_rules(&self) -> ArrayOfOffsets<'a, ClassSequenceRule<'a>, Offset16> {
2309 let data = self.data;
2310 let offsets = self.class_seq_rule_offsets();
2311 ArrayOfOffsets::new(offsets, data, ())
2312 }
2313}
2314
2315#[cfg(feature = "experimental_traverse")]
2316impl<'a> SomeTable<'a> for ClassSequenceRuleSet<'a> {
2317 fn type_name(&self) -> &str {
2318 "ClassSequenceRuleSet"
2319 }
2320 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2321 match idx {
2322 0usize => Some(Field::new(
2323 "class_seq_rule_count",
2324 self.class_seq_rule_count(),
2325 )),
2326 1usize => Some({
2327 let data = self.data;
2328 Field::new(
2329 "class_seq_rule_offsets",
2330 FieldType::array_of_offsets(
2331 better_type_name::<ClassSequenceRule>(),
2332 self.class_seq_rule_offsets(),
2333 move |off| {
2334 let target = off.get().resolve::<ClassSequenceRule>(data);
2335 FieldType::offset(off.get(), target)
2336 },
2337 ),
2338 )
2339 }),
2340 _ => None,
2341 }
2342 }
2343}
2344
2345#[cfg(feature = "experimental_traverse")]
2346#[allow(clippy::needless_lifetimes)]
2347impl<'a> std::fmt::Debug for ClassSequenceRuleSet<'a> {
2348 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2349 (self as &dyn SomeTable<'a>).fmt(f)
2350 }
2351}
2352
2353#[derive(Debug, Clone, Copy)]
2355#[doc(hidden)]
2356pub struct ClassSequenceRuleMarker {
2357 input_sequence_byte_len: usize,
2358 seq_lookup_records_byte_len: usize,
2359}
2360
2361impl ClassSequenceRuleMarker {
2362 pub fn glyph_count_byte_range(&self) -> Range<usize> {
2363 let start = 0;
2364 start..start + u16::RAW_BYTE_LEN
2365 }
2366
2367 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2368 let start = self.glyph_count_byte_range().end;
2369 start..start + u16::RAW_BYTE_LEN
2370 }
2371
2372 pub fn input_sequence_byte_range(&self) -> Range<usize> {
2373 let start = self.seq_lookup_count_byte_range().end;
2374 start..start + self.input_sequence_byte_len
2375 }
2376
2377 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2378 let start = self.input_sequence_byte_range().end;
2379 start..start + self.seq_lookup_records_byte_len
2380 }
2381}
2382
2383impl MinByteRange for ClassSequenceRuleMarker {
2384 fn min_byte_range(&self) -> Range<usize> {
2385 0..self.seq_lookup_records_byte_range().end
2386 }
2387}
2388
2389impl<'a> FontRead<'a> for ClassSequenceRule<'a> {
2390 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
2391 let mut cursor = data.cursor();
2392 let glyph_count: u16 = cursor.read()?;
2393 let seq_lookup_count: u16 = cursor.read()?;
2394 let input_sequence_byte_len = (transforms::subtract(glyph_count, 1_usize))
2395 .checked_mul(u16::RAW_BYTE_LEN)
2396 .ok_or(ReadError::OutOfBounds)?;
2397 cursor.advance_by(input_sequence_byte_len);
2398 let seq_lookup_records_byte_len = (seq_lookup_count as usize)
2399 .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN)
2400 .ok_or(ReadError::OutOfBounds)?;
2401 cursor.advance_by(seq_lookup_records_byte_len);
2402 cursor.finish(ClassSequenceRuleMarker {
2403 input_sequence_byte_len,
2404 seq_lookup_records_byte_len,
2405 })
2406 }
2407}
2408
2409pub type ClassSequenceRule<'a> = TableRef<'a, ClassSequenceRuleMarker>;
2411
2412#[allow(clippy::needless_lifetimes)]
2413impl<'a> ClassSequenceRule<'a> {
2414 pub fn glyph_count(&self) -> u16 {
2416 let range = self.shape.glyph_count_byte_range();
2417 self.data.read_at(range.start).unwrap()
2418 }
2419
2420 pub fn seq_lookup_count(&self) -> u16 {
2422 let range = self.shape.seq_lookup_count_byte_range();
2423 self.data.read_at(range.start).unwrap()
2424 }
2425
2426 pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
2429 let range = self.shape.input_sequence_byte_range();
2430 self.data.read_array(range).unwrap()
2431 }
2432
2433 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2435 let range = self.shape.seq_lookup_records_byte_range();
2436 self.data.read_array(range).unwrap()
2437 }
2438}
2439
2440#[cfg(feature = "experimental_traverse")]
2441impl<'a> SomeTable<'a> for ClassSequenceRule<'a> {
2442 fn type_name(&self) -> &str {
2443 "ClassSequenceRule"
2444 }
2445 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2446 match idx {
2447 0usize => Some(Field::new("glyph_count", self.glyph_count())),
2448 1usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
2449 2usize => Some(Field::new("input_sequence", self.input_sequence())),
2450 3usize => Some(Field::new(
2451 "seq_lookup_records",
2452 traversal::FieldType::array_of_records(
2453 stringify!(SequenceLookupRecord),
2454 self.seq_lookup_records(),
2455 self.offset_data(),
2456 ),
2457 )),
2458 _ => None,
2459 }
2460 }
2461}
2462
2463#[cfg(feature = "experimental_traverse")]
2464#[allow(clippy::needless_lifetimes)]
2465impl<'a> std::fmt::Debug for ClassSequenceRule<'a> {
2466 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2467 (self as &dyn SomeTable<'a>).fmt(f)
2468 }
2469}
2470
2471impl Format<u16> for SequenceContextFormat3Marker {
2472 const FORMAT: u16 = 3;
2473}
2474
2475#[derive(Debug, Clone, Copy)]
2477#[doc(hidden)]
2478pub struct SequenceContextFormat3Marker {
2479 coverage_offsets_byte_len: usize,
2480 seq_lookup_records_byte_len: usize,
2481}
2482
2483impl SequenceContextFormat3Marker {
2484 pub fn format_byte_range(&self) -> Range<usize> {
2485 let start = 0;
2486 start..start + u16::RAW_BYTE_LEN
2487 }
2488
2489 pub fn glyph_count_byte_range(&self) -> Range<usize> {
2490 let start = self.format_byte_range().end;
2491 start..start + u16::RAW_BYTE_LEN
2492 }
2493
2494 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2495 let start = self.glyph_count_byte_range().end;
2496 start..start + u16::RAW_BYTE_LEN
2497 }
2498
2499 pub fn coverage_offsets_byte_range(&self) -> Range<usize> {
2500 let start = self.seq_lookup_count_byte_range().end;
2501 start..start + self.coverage_offsets_byte_len
2502 }
2503
2504 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2505 let start = self.coverage_offsets_byte_range().end;
2506 start..start + self.seq_lookup_records_byte_len
2507 }
2508}
2509
2510impl MinByteRange for SequenceContextFormat3Marker {
2511 fn min_byte_range(&self) -> Range<usize> {
2512 0..self.seq_lookup_records_byte_range().end
2513 }
2514}
2515
2516impl<'a> FontRead<'a> for SequenceContextFormat3<'a> {
2517 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
2518 let mut cursor = data.cursor();
2519 cursor.advance::<u16>();
2520 let glyph_count: u16 = cursor.read()?;
2521 let seq_lookup_count: u16 = cursor.read()?;
2522 let coverage_offsets_byte_len = (glyph_count as usize)
2523 .checked_mul(Offset16::RAW_BYTE_LEN)
2524 .ok_or(ReadError::OutOfBounds)?;
2525 cursor.advance_by(coverage_offsets_byte_len);
2526 let seq_lookup_records_byte_len = (seq_lookup_count as usize)
2527 .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN)
2528 .ok_or(ReadError::OutOfBounds)?;
2529 cursor.advance_by(seq_lookup_records_byte_len);
2530 cursor.finish(SequenceContextFormat3Marker {
2531 coverage_offsets_byte_len,
2532 seq_lookup_records_byte_len,
2533 })
2534 }
2535}
2536
2537pub type SequenceContextFormat3<'a> = TableRef<'a, SequenceContextFormat3Marker>;
2539
2540#[allow(clippy::needless_lifetimes)]
2541impl<'a> SequenceContextFormat3<'a> {
2542 pub fn format(&self) -> u16 {
2544 let range = self.shape.format_byte_range();
2545 self.data.read_at(range.start).unwrap()
2546 }
2547
2548 pub fn glyph_count(&self) -> u16 {
2550 let range = self.shape.glyph_count_byte_range();
2551 self.data.read_at(range.start).unwrap()
2552 }
2553
2554 pub fn seq_lookup_count(&self) -> u16 {
2556 let range = self.shape.seq_lookup_count_byte_range();
2557 self.data.read_at(range.start).unwrap()
2558 }
2559
2560 pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
2563 let range = self.shape.coverage_offsets_byte_range();
2564 self.data.read_array(range).unwrap()
2565 }
2566
2567 pub fn coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
2569 let data = self.data;
2570 let offsets = self.coverage_offsets();
2571 ArrayOfOffsets::new(offsets, data, ())
2572 }
2573
2574 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
2576 let range = self.shape.seq_lookup_records_byte_range();
2577 self.data.read_array(range).unwrap()
2578 }
2579}
2580
2581#[cfg(feature = "experimental_traverse")]
2582impl<'a> SomeTable<'a> for SequenceContextFormat3<'a> {
2583 fn type_name(&self) -> &str {
2584 "SequenceContextFormat3"
2585 }
2586 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2587 match idx {
2588 0usize => Some(Field::new("format", self.format())),
2589 1usize => Some(Field::new("glyph_count", self.glyph_count())),
2590 2usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
2591 3usize => Some({
2592 let data = self.data;
2593 Field::new(
2594 "coverage_offsets",
2595 FieldType::array_of_offsets(
2596 better_type_name::<CoverageTable>(),
2597 self.coverage_offsets(),
2598 move |off| {
2599 let target = off.get().resolve::<CoverageTable>(data);
2600 FieldType::offset(off.get(), target)
2601 },
2602 ),
2603 )
2604 }),
2605 4usize => Some(Field::new(
2606 "seq_lookup_records",
2607 traversal::FieldType::array_of_records(
2608 stringify!(SequenceLookupRecord),
2609 self.seq_lookup_records(),
2610 self.offset_data(),
2611 ),
2612 )),
2613 _ => None,
2614 }
2615 }
2616}
2617
2618#[cfg(feature = "experimental_traverse")]
2619#[allow(clippy::needless_lifetimes)]
2620impl<'a> std::fmt::Debug for SequenceContextFormat3<'a> {
2621 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2622 (self as &dyn SomeTable<'a>).fmt(f)
2623 }
2624}
2625
2626#[derive(Clone)]
2627pub enum SequenceContext<'a> {
2628 Format1(SequenceContextFormat1<'a>),
2629 Format2(SequenceContextFormat2<'a>),
2630 Format3(SequenceContextFormat3<'a>),
2631}
2632
2633impl<'a> SequenceContext<'a> {
2634 pub fn offset_data(&self) -> FontData<'a> {
2636 match self {
2637 Self::Format1(item) => item.offset_data(),
2638 Self::Format2(item) => item.offset_data(),
2639 Self::Format3(item) => item.offset_data(),
2640 }
2641 }
2642
2643 pub fn format(&self) -> u16 {
2645 match self {
2646 Self::Format1(item) => item.format(),
2647 Self::Format2(item) => item.format(),
2648 Self::Format3(item) => item.format(),
2649 }
2650 }
2651}
2652
2653impl<'a> FontRead<'a> for SequenceContext<'a> {
2654 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
2655 let format: u16 = data.read_at(0usize)?;
2656 match format {
2657 SequenceContextFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
2658 SequenceContextFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
2659 SequenceContextFormat3Marker::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
2660 other => Err(ReadError::InvalidFormat(other.into())),
2661 }
2662 }
2663}
2664
2665impl MinByteRange for SequenceContext<'_> {
2666 fn min_byte_range(&self) -> Range<usize> {
2667 match self {
2668 Self::Format1(item) => item.min_byte_range(),
2669 Self::Format2(item) => item.min_byte_range(),
2670 Self::Format3(item) => item.min_byte_range(),
2671 }
2672 }
2673}
2674
2675#[cfg(feature = "experimental_traverse")]
2676impl<'a> SequenceContext<'a> {
2677 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
2678 match self {
2679 Self::Format1(table) => table,
2680 Self::Format2(table) => table,
2681 Self::Format3(table) => table,
2682 }
2683 }
2684}
2685
2686#[cfg(feature = "experimental_traverse")]
2687impl std::fmt::Debug for SequenceContext<'_> {
2688 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2689 self.dyn_inner().fmt(f)
2690 }
2691}
2692
2693#[cfg(feature = "experimental_traverse")]
2694impl<'a> SomeTable<'a> for SequenceContext<'a> {
2695 fn type_name(&self) -> &str {
2696 self.dyn_inner().type_name()
2697 }
2698 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2699 self.dyn_inner().get_field(idx)
2700 }
2701}
2702
2703impl Format<u16> for ChainedSequenceContextFormat1Marker {
2704 const FORMAT: u16 = 1;
2705}
2706
2707#[derive(Debug, Clone, Copy)]
2709#[doc(hidden)]
2710pub struct ChainedSequenceContextFormat1Marker {
2711 chained_seq_rule_set_offsets_byte_len: usize,
2712}
2713
2714impl ChainedSequenceContextFormat1Marker {
2715 pub fn format_byte_range(&self) -> Range<usize> {
2716 let start = 0;
2717 start..start + u16::RAW_BYTE_LEN
2718 }
2719
2720 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
2721 let start = self.format_byte_range().end;
2722 start..start + Offset16::RAW_BYTE_LEN
2723 }
2724
2725 pub fn chained_seq_rule_set_count_byte_range(&self) -> Range<usize> {
2726 let start = self.coverage_offset_byte_range().end;
2727 start..start + u16::RAW_BYTE_LEN
2728 }
2729
2730 pub fn chained_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
2731 let start = self.chained_seq_rule_set_count_byte_range().end;
2732 start..start + self.chained_seq_rule_set_offsets_byte_len
2733 }
2734}
2735
2736impl MinByteRange for ChainedSequenceContextFormat1Marker {
2737 fn min_byte_range(&self) -> Range<usize> {
2738 0..self.chained_seq_rule_set_offsets_byte_range().end
2739 }
2740}
2741
2742impl<'a> FontRead<'a> for ChainedSequenceContextFormat1<'a> {
2743 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
2744 let mut cursor = data.cursor();
2745 cursor.advance::<u16>();
2746 cursor.advance::<Offset16>();
2747 let chained_seq_rule_set_count: u16 = cursor.read()?;
2748 let chained_seq_rule_set_offsets_byte_len = (chained_seq_rule_set_count as usize)
2749 .checked_mul(Offset16::RAW_BYTE_LEN)
2750 .ok_or(ReadError::OutOfBounds)?;
2751 cursor.advance_by(chained_seq_rule_set_offsets_byte_len);
2752 cursor.finish(ChainedSequenceContextFormat1Marker {
2753 chained_seq_rule_set_offsets_byte_len,
2754 })
2755 }
2756}
2757
2758pub type ChainedSequenceContextFormat1<'a> = TableRef<'a, ChainedSequenceContextFormat1Marker>;
2760
2761#[allow(clippy::needless_lifetimes)]
2762impl<'a> ChainedSequenceContextFormat1<'a> {
2763 pub fn format(&self) -> u16 {
2765 let range = self.shape.format_byte_range();
2766 self.data.read_at(range.start).unwrap()
2767 }
2768
2769 pub fn coverage_offset(&self) -> Offset16 {
2772 let range = self.shape.coverage_offset_byte_range();
2773 self.data.read_at(range.start).unwrap()
2774 }
2775
2776 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
2778 let data = self.data;
2779 self.coverage_offset().resolve(data)
2780 }
2781
2782 pub fn chained_seq_rule_set_count(&self) -> u16 {
2784 let range = self.shape.chained_seq_rule_set_count_byte_range();
2785 self.data.read_at(range.start).unwrap()
2786 }
2787
2788 pub fn chained_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
2791 let range = self.shape.chained_seq_rule_set_offsets_byte_range();
2792 self.data.read_array(range).unwrap()
2793 }
2794
2795 pub fn chained_seq_rule_sets(
2797 &self,
2798 ) -> ArrayOfNullableOffsets<'a, ChainedSequenceRuleSet<'a>, Offset16> {
2799 let data = self.data;
2800 let offsets = self.chained_seq_rule_set_offsets();
2801 ArrayOfNullableOffsets::new(offsets, data, ())
2802 }
2803}
2804
2805#[cfg(feature = "experimental_traverse")]
2806impl<'a> SomeTable<'a> for ChainedSequenceContextFormat1<'a> {
2807 fn type_name(&self) -> &str {
2808 "ChainedSequenceContextFormat1"
2809 }
2810 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2811 match idx {
2812 0usize => Some(Field::new("format", self.format())),
2813 1usize => Some(Field::new(
2814 "coverage_offset",
2815 FieldType::offset(self.coverage_offset(), self.coverage()),
2816 )),
2817 2usize => Some(Field::new(
2818 "chained_seq_rule_set_count",
2819 self.chained_seq_rule_set_count(),
2820 )),
2821 3usize => Some({
2822 let data = self.data;
2823 Field::new(
2824 "chained_seq_rule_set_offsets",
2825 FieldType::array_of_offsets(
2826 better_type_name::<ChainedSequenceRuleSet>(),
2827 self.chained_seq_rule_set_offsets(),
2828 move |off| {
2829 let target = off.get().resolve::<ChainedSequenceRuleSet>(data);
2830 FieldType::offset(off.get(), target)
2831 },
2832 ),
2833 )
2834 }),
2835 _ => None,
2836 }
2837 }
2838}
2839
2840#[cfg(feature = "experimental_traverse")]
2841#[allow(clippy::needless_lifetimes)]
2842impl<'a> std::fmt::Debug for ChainedSequenceContextFormat1<'a> {
2843 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2844 (self as &dyn SomeTable<'a>).fmt(f)
2845 }
2846}
2847
2848#[derive(Debug, Clone, Copy)]
2850#[doc(hidden)]
2851pub struct ChainedSequenceRuleSetMarker {
2852 chained_seq_rule_offsets_byte_len: usize,
2853}
2854
2855impl ChainedSequenceRuleSetMarker {
2856 pub fn chained_seq_rule_count_byte_range(&self) -> Range<usize> {
2857 let start = 0;
2858 start..start + u16::RAW_BYTE_LEN
2859 }
2860
2861 pub fn chained_seq_rule_offsets_byte_range(&self) -> Range<usize> {
2862 let start = self.chained_seq_rule_count_byte_range().end;
2863 start..start + self.chained_seq_rule_offsets_byte_len
2864 }
2865}
2866
2867impl MinByteRange for ChainedSequenceRuleSetMarker {
2868 fn min_byte_range(&self) -> Range<usize> {
2869 0..self.chained_seq_rule_offsets_byte_range().end
2870 }
2871}
2872
2873impl<'a> FontRead<'a> for ChainedSequenceRuleSet<'a> {
2874 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
2875 let mut cursor = data.cursor();
2876 let chained_seq_rule_count: u16 = cursor.read()?;
2877 let chained_seq_rule_offsets_byte_len = (chained_seq_rule_count as usize)
2878 .checked_mul(Offset16::RAW_BYTE_LEN)
2879 .ok_or(ReadError::OutOfBounds)?;
2880 cursor.advance_by(chained_seq_rule_offsets_byte_len);
2881 cursor.finish(ChainedSequenceRuleSetMarker {
2882 chained_seq_rule_offsets_byte_len,
2883 })
2884 }
2885}
2886
2887pub type ChainedSequenceRuleSet<'a> = TableRef<'a, ChainedSequenceRuleSetMarker>;
2889
2890#[allow(clippy::needless_lifetimes)]
2891impl<'a> ChainedSequenceRuleSet<'a> {
2892 pub fn chained_seq_rule_count(&self) -> u16 {
2894 let range = self.shape.chained_seq_rule_count_byte_range();
2895 self.data.read_at(range.start).unwrap()
2896 }
2897
2898 pub fn chained_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
2901 let range = self.shape.chained_seq_rule_offsets_byte_range();
2902 self.data.read_array(range).unwrap()
2903 }
2904
2905 pub fn chained_seq_rules(&self) -> ArrayOfOffsets<'a, ChainedSequenceRule<'a>, Offset16> {
2907 let data = self.data;
2908 let offsets = self.chained_seq_rule_offsets();
2909 ArrayOfOffsets::new(offsets, data, ())
2910 }
2911}
2912
2913#[cfg(feature = "experimental_traverse")]
2914impl<'a> SomeTable<'a> for ChainedSequenceRuleSet<'a> {
2915 fn type_name(&self) -> &str {
2916 "ChainedSequenceRuleSet"
2917 }
2918 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2919 match idx {
2920 0usize => Some(Field::new(
2921 "chained_seq_rule_count",
2922 self.chained_seq_rule_count(),
2923 )),
2924 1usize => Some({
2925 let data = self.data;
2926 Field::new(
2927 "chained_seq_rule_offsets",
2928 FieldType::array_of_offsets(
2929 better_type_name::<ChainedSequenceRule>(),
2930 self.chained_seq_rule_offsets(),
2931 move |off| {
2932 let target = off.get().resolve::<ChainedSequenceRule>(data);
2933 FieldType::offset(off.get(), target)
2934 },
2935 ),
2936 )
2937 }),
2938 _ => None,
2939 }
2940 }
2941}
2942
2943#[cfg(feature = "experimental_traverse")]
2944#[allow(clippy::needless_lifetimes)]
2945impl<'a> std::fmt::Debug for ChainedSequenceRuleSet<'a> {
2946 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2947 (self as &dyn SomeTable<'a>).fmt(f)
2948 }
2949}
2950
2951#[derive(Debug, Clone, Copy)]
2953#[doc(hidden)]
2954pub struct ChainedSequenceRuleMarker {
2955 backtrack_sequence_byte_len: usize,
2956 input_sequence_byte_len: usize,
2957 lookahead_sequence_byte_len: usize,
2958 seq_lookup_records_byte_len: usize,
2959}
2960
2961impl ChainedSequenceRuleMarker {
2962 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
2963 let start = 0;
2964 start..start + u16::RAW_BYTE_LEN
2965 }
2966
2967 pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
2968 let start = self.backtrack_glyph_count_byte_range().end;
2969 start..start + self.backtrack_sequence_byte_len
2970 }
2971
2972 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
2973 let start = self.backtrack_sequence_byte_range().end;
2974 start..start + u16::RAW_BYTE_LEN
2975 }
2976
2977 pub fn input_sequence_byte_range(&self) -> Range<usize> {
2978 let start = self.input_glyph_count_byte_range().end;
2979 start..start + self.input_sequence_byte_len
2980 }
2981
2982 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
2983 let start = self.input_sequence_byte_range().end;
2984 start..start + u16::RAW_BYTE_LEN
2985 }
2986
2987 pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
2988 let start = self.lookahead_glyph_count_byte_range().end;
2989 start..start + self.lookahead_sequence_byte_len
2990 }
2991
2992 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
2993 let start = self.lookahead_sequence_byte_range().end;
2994 start..start + u16::RAW_BYTE_LEN
2995 }
2996
2997 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
2998 let start = self.seq_lookup_count_byte_range().end;
2999 start..start + self.seq_lookup_records_byte_len
3000 }
3001}
3002
3003impl MinByteRange for ChainedSequenceRuleMarker {
3004 fn min_byte_range(&self) -> Range<usize> {
3005 0..self.seq_lookup_records_byte_range().end
3006 }
3007}
3008
3009impl<'a> FontRead<'a> for ChainedSequenceRule<'a> {
3010 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
3011 let mut cursor = data.cursor();
3012 let backtrack_glyph_count: u16 = cursor.read()?;
3013 let backtrack_sequence_byte_len = (backtrack_glyph_count as usize)
3014 .checked_mul(GlyphId16::RAW_BYTE_LEN)
3015 .ok_or(ReadError::OutOfBounds)?;
3016 cursor.advance_by(backtrack_sequence_byte_len);
3017 let input_glyph_count: u16 = cursor.read()?;
3018 let input_sequence_byte_len = (transforms::subtract(input_glyph_count, 1_usize))
3019 .checked_mul(GlyphId16::RAW_BYTE_LEN)
3020 .ok_or(ReadError::OutOfBounds)?;
3021 cursor.advance_by(input_sequence_byte_len);
3022 let lookahead_glyph_count: u16 = cursor.read()?;
3023 let lookahead_sequence_byte_len = (lookahead_glyph_count as usize)
3024 .checked_mul(GlyphId16::RAW_BYTE_LEN)
3025 .ok_or(ReadError::OutOfBounds)?;
3026 cursor.advance_by(lookahead_sequence_byte_len);
3027 let seq_lookup_count: u16 = cursor.read()?;
3028 let seq_lookup_records_byte_len = (seq_lookup_count as usize)
3029 .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN)
3030 .ok_or(ReadError::OutOfBounds)?;
3031 cursor.advance_by(seq_lookup_records_byte_len);
3032 cursor.finish(ChainedSequenceRuleMarker {
3033 backtrack_sequence_byte_len,
3034 input_sequence_byte_len,
3035 lookahead_sequence_byte_len,
3036 seq_lookup_records_byte_len,
3037 })
3038 }
3039}
3040
3041pub type ChainedSequenceRule<'a> = TableRef<'a, ChainedSequenceRuleMarker>;
3043
3044#[allow(clippy::needless_lifetimes)]
3045impl<'a> ChainedSequenceRule<'a> {
3046 pub fn backtrack_glyph_count(&self) -> u16 {
3048 let range = self.shape.backtrack_glyph_count_byte_range();
3049 self.data.read_at(range.start).unwrap()
3050 }
3051
3052 pub fn backtrack_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
3054 let range = self.shape.backtrack_sequence_byte_range();
3055 self.data.read_array(range).unwrap()
3056 }
3057
3058 pub fn input_glyph_count(&self) -> u16 {
3060 let range = self.shape.input_glyph_count_byte_range();
3061 self.data.read_at(range.start).unwrap()
3062 }
3063
3064 pub fn input_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
3066 let range = self.shape.input_sequence_byte_range();
3067 self.data.read_array(range).unwrap()
3068 }
3069
3070 pub fn lookahead_glyph_count(&self) -> u16 {
3072 let range = self.shape.lookahead_glyph_count_byte_range();
3073 self.data.read_at(range.start).unwrap()
3074 }
3075
3076 pub fn lookahead_sequence(&self) -> &'a [BigEndian<GlyphId16>] {
3078 let range = self.shape.lookahead_sequence_byte_range();
3079 self.data.read_array(range).unwrap()
3080 }
3081
3082 pub fn seq_lookup_count(&self) -> u16 {
3084 let range = self.shape.seq_lookup_count_byte_range();
3085 self.data.read_at(range.start).unwrap()
3086 }
3087
3088 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
3090 let range = self.shape.seq_lookup_records_byte_range();
3091 self.data.read_array(range).unwrap()
3092 }
3093}
3094
3095#[cfg(feature = "experimental_traverse")]
3096impl<'a> SomeTable<'a> for ChainedSequenceRule<'a> {
3097 fn type_name(&self) -> &str {
3098 "ChainedSequenceRule"
3099 }
3100 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3101 match idx {
3102 0usize => Some(Field::new(
3103 "backtrack_glyph_count",
3104 self.backtrack_glyph_count(),
3105 )),
3106 1usize => Some(Field::new("backtrack_sequence", self.backtrack_sequence())),
3107 2usize => Some(Field::new("input_glyph_count", self.input_glyph_count())),
3108 3usize => Some(Field::new("input_sequence", self.input_sequence())),
3109 4usize => Some(Field::new(
3110 "lookahead_glyph_count",
3111 self.lookahead_glyph_count(),
3112 )),
3113 5usize => Some(Field::new("lookahead_sequence", self.lookahead_sequence())),
3114 6usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
3115 7usize => Some(Field::new(
3116 "seq_lookup_records",
3117 traversal::FieldType::array_of_records(
3118 stringify!(SequenceLookupRecord),
3119 self.seq_lookup_records(),
3120 self.offset_data(),
3121 ),
3122 )),
3123 _ => None,
3124 }
3125 }
3126}
3127
3128#[cfg(feature = "experimental_traverse")]
3129#[allow(clippy::needless_lifetimes)]
3130impl<'a> std::fmt::Debug for ChainedSequenceRule<'a> {
3131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3132 (self as &dyn SomeTable<'a>).fmt(f)
3133 }
3134}
3135
3136impl Format<u16> for ChainedSequenceContextFormat2Marker {
3137 const FORMAT: u16 = 2;
3138}
3139
3140#[derive(Debug, Clone, Copy)]
3142#[doc(hidden)]
3143pub struct ChainedSequenceContextFormat2Marker {
3144 chained_class_seq_rule_set_offsets_byte_len: usize,
3145}
3146
3147impl ChainedSequenceContextFormat2Marker {
3148 pub fn format_byte_range(&self) -> Range<usize> {
3149 let start = 0;
3150 start..start + u16::RAW_BYTE_LEN
3151 }
3152
3153 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
3154 let start = self.format_byte_range().end;
3155 start..start + Offset16::RAW_BYTE_LEN
3156 }
3157
3158 pub fn backtrack_class_def_offset_byte_range(&self) -> Range<usize> {
3159 let start = self.coverage_offset_byte_range().end;
3160 start..start + Offset16::RAW_BYTE_LEN
3161 }
3162
3163 pub fn input_class_def_offset_byte_range(&self) -> Range<usize> {
3164 let start = self.backtrack_class_def_offset_byte_range().end;
3165 start..start + Offset16::RAW_BYTE_LEN
3166 }
3167
3168 pub fn lookahead_class_def_offset_byte_range(&self) -> Range<usize> {
3169 let start = self.input_class_def_offset_byte_range().end;
3170 start..start + Offset16::RAW_BYTE_LEN
3171 }
3172
3173 pub fn chained_class_seq_rule_set_count_byte_range(&self) -> Range<usize> {
3174 let start = self.lookahead_class_def_offset_byte_range().end;
3175 start..start + u16::RAW_BYTE_LEN
3176 }
3177
3178 pub fn chained_class_seq_rule_set_offsets_byte_range(&self) -> Range<usize> {
3179 let start = self.chained_class_seq_rule_set_count_byte_range().end;
3180 start..start + self.chained_class_seq_rule_set_offsets_byte_len
3181 }
3182}
3183
3184impl MinByteRange for ChainedSequenceContextFormat2Marker {
3185 fn min_byte_range(&self) -> Range<usize> {
3186 0..self.chained_class_seq_rule_set_offsets_byte_range().end
3187 }
3188}
3189
3190impl<'a> FontRead<'a> for ChainedSequenceContextFormat2<'a> {
3191 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
3192 let mut cursor = data.cursor();
3193 cursor.advance::<u16>();
3194 cursor.advance::<Offset16>();
3195 cursor.advance::<Offset16>();
3196 cursor.advance::<Offset16>();
3197 cursor.advance::<Offset16>();
3198 let chained_class_seq_rule_set_count: u16 = cursor.read()?;
3199 let chained_class_seq_rule_set_offsets_byte_len = (chained_class_seq_rule_set_count
3200 as usize)
3201 .checked_mul(Offset16::RAW_BYTE_LEN)
3202 .ok_or(ReadError::OutOfBounds)?;
3203 cursor.advance_by(chained_class_seq_rule_set_offsets_byte_len);
3204 cursor.finish(ChainedSequenceContextFormat2Marker {
3205 chained_class_seq_rule_set_offsets_byte_len,
3206 })
3207 }
3208}
3209
3210pub type ChainedSequenceContextFormat2<'a> = TableRef<'a, ChainedSequenceContextFormat2Marker>;
3212
3213#[allow(clippy::needless_lifetimes)]
3214impl<'a> ChainedSequenceContextFormat2<'a> {
3215 pub fn format(&self) -> u16 {
3217 let range = self.shape.format_byte_range();
3218 self.data.read_at(range.start).unwrap()
3219 }
3220
3221 pub fn coverage_offset(&self) -> Offset16 {
3224 let range = self.shape.coverage_offset_byte_range();
3225 self.data.read_at(range.start).unwrap()
3226 }
3227
3228 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
3230 let data = self.data;
3231 self.coverage_offset().resolve(data)
3232 }
3233
3234 pub fn backtrack_class_def_offset(&self) -> Offset16 {
3237 let range = self.shape.backtrack_class_def_offset_byte_range();
3238 self.data.read_at(range.start).unwrap()
3239 }
3240
3241 pub fn backtrack_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3243 let data = self.data;
3244 self.backtrack_class_def_offset().resolve(data)
3245 }
3246
3247 pub fn input_class_def_offset(&self) -> Offset16 {
3250 let range = self.shape.input_class_def_offset_byte_range();
3251 self.data.read_at(range.start).unwrap()
3252 }
3253
3254 pub fn input_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3256 let data = self.data;
3257 self.input_class_def_offset().resolve(data)
3258 }
3259
3260 pub fn lookahead_class_def_offset(&self) -> Offset16 {
3263 let range = self.shape.lookahead_class_def_offset_byte_range();
3264 self.data.read_at(range.start).unwrap()
3265 }
3266
3267 pub fn lookahead_class_def(&self) -> Result<ClassDef<'a>, ReadError> {
3269 let data = self.data;
3270 self.lookahead_class_def_offset().resolve(data)
3271 }
3272
3273 pub fn chained_class_seq_rule_set_count(&self) -> u16 {
3275 let range = self.shape.chained_class_seq_rule_set_count_byte_range();
3276 self.data.read_at(range.start).unwrap()
3277 }
3278
3279 pub fn chained_class_seq_rule_set_offsets(&self) -> &'a [BigEndian<Nullable<Offset16>>] {
3282 let range = self.shape.chained_class_seq_rule_set_offsets_byte_range();
3283 self.data.read_array(range).unwrap()
3284 }
3285
3286 pub fn chained_class_seq_rule_sets(
3288 &self,
3289 ) -> ArrayOfNullableOffsets<'a, ChainedClassSequenceRuleSet<'a>, Offset16> {
3290 let data = self.data;
3291 let offsets = self.chained_class_seq_rule_set_offsets();
3292 ArrayOfNullableOffsets::new(offsets, data, ())
3293 }
3294}
3295
3296#[cfg(feature = "experimental_traverse")]
3297impl<'a> SomeTable<'a> for ChainedSequenceContextFormat2<'a> {
3298 fn type_name(&self) -> &str {
3299 "ChainedSequenceContextFormat2"
3300 }
3301 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3302 match idx {
3303 0usize => Some(Field::new("format", self.format())),
3304 1usize => Some(Field::new(
3305 "coverage_offset",
3306 FieldType::offset(self.coverage_offset(), self.coverage()),
3307 )),
3308 2usize => Some(Field::new(
3309 "backtrack_class_def_offset",
3310 FieldType::offset(
3311 self.backtrack_class_def_offset(),
3312 self.backtrack_class_def(),
3313 ),
3314 )),
3315 3usize => Some(Field::new(
3316 "input_class_def_offset",
3317 FieldType::offset(self.input_class_def_offset(), self.input_class_def()),
3318 )),
3319 4usize => Some(Field::new(
3320 "lookahead_class_def_offset",
3321 FieldType::offset(
3322 self.lookahead_class_def_offset(),
3323 self.lookahead_class_def(),
3324 ),
3325 )),
3326 5usize => Some(Field::new(
3327 "chained_class_seq_rule_set_count",
3328 self.chained_class_seq_rule_set_count(),
3329 )),
3330 6usize => Some({
3331 let data = self.data;
3332 Field::new(
3333 "chained_class_seq_rule_set_offsets",
3334 FieldType::array_of_offsets(
3335 better_type_name::<ChainedClassSequenceRuleSet>(),
3336 self.chained_class_seq_rule_set_offsets(),
3337 move |off| {
3338 let target = off.get().resolve::<ChainedClassSequenceRuleSet>(data);
3339 FieldType::offset(off.get(), target)
3340 },
3341 ),
3342 )
3343 }),
3344 _ => None,
3345 }
3346 }
3347}
3348
3349#[cfg(feature = "experimental_traverse")]
3350#[allow(clippy::needless_lifetimes)]
3351impl<'a> std::fmt::Debug for ChainedSequenceContextFormat2<'a> {
3352 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3353 (self as &dyn SomeTable<'a>).fmt(f)
3354 }
3355}
3356
3357#[derive(Debug, Clone, Copy)]
3359#[doc(hidden)]
3360pub struct ChainedClassSequenceRuleSetMarker {
3361 chained_class_seq_rule_offsets_byte_len: usize,
3362}
3363
3364impl ChainedClassSequenceRuleSetMarker {
3365 pub fn chained_class_seq_rule_count_byte_range(&self) -> Range<usize> {
3366 let start = 0;
3367 start..start + u16::RAW_BYTE_LEN
3368 }
3369
3370 pub fn chained_class_seq_rule_offsets_byte_range(&self) -> Range<usize> {
3371 let start = self.chained_class_seq_rule_count_byte_range().end;
3372 start..start + self.chained_class_seq_rule_offsets_byte_len
3373 }
3374}
3375
3376impl MinByteRange for ChainedClassSequenceRuleSetMarker {
3377 fn min_byte_range(&self) -> Range<usize> {
3378 0..self.chained_class_seq_rule_offsets_byte_range().end
3379 }
3380}
3381
3382impl<'a> FontRead<'a> for ChainedClassSequenceRuleSet<'a> {
3383 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
3384 let mut cursor = data.cursor();
3385 let chained_class_seq_rule_count: u16 = cursor.read()?;
3386 let chained_class_seq_rule_offsets_byte_len = (chained_class_seq_rule_count as usize)
3387 .checked_mul(Offset16::RAW_BYTE_LEN)
3388 .ok_or(ReadError::OutOfBounds)?;
3389 cursor.advance_by(chained_class_seq_rule_offsets_byte_len);
3390 cursor.finish(ChainedClassSequenceRuleSetMarker {
3391 chained_class_seq_rule_offsets_byte_len,
3392 })
3393 }
3394}
3395
3396pub type ChainedClassSequenceRuleSet<'a> = TableRef<'a, ChainedClassSequenceRuleSetMarker>;
3398
3399#[allow(clippy::needless_lifetimes)]
3400impl<'a> ChainedClassSequenceRuleSet<'a> {
3401 pub fn chained_class_seq_rule_count(&self) -> u16 {
3403 let range = self.shape.chained_class_seq_rule_count_byte_range();
3404 self.data.read_at(range.start).unwrap()
3405 }
3406
3407 pub fn chained_class_seq_rule_offsets(&self) -> &'a [BigEndian<Offset16>] {
3410 let range = self.shape.chained_class_seq_rule_offsets_byte_range();
3411 self.data.read_array(range).unwrap()
3412 }
3413
3414 pub fn chained_class_seq_rules(
3416 &self,
3417 ) -> ArrayOfOffsets<'a, ChainedClassSequenceRule<'a>, Offset16> {
3418 let data = self.data;
3419 let offsets = self.chained_class_seq_rule_offsets();
3420 ArrayOfOffsets::new(offsets, data, ())
3421 }
3422}
3423
3424#[cfg(feature = "experimental_traverse")]
3425impl<'a> SomeTable<'a> for ChainedClassSequenceRuleSet<'a> {
3426 fn type_name(&self) -> &str {
3427 "ChainedClassSequenceRuleSet"
3428 }
3429 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3430 match idx {
3431 0usize => Some(Field::new(
3432 "chained_class_seq_rule_count",
3433 self.chained_class_seq_rule_count(),
3434 )),
3435 1usize => Some({
3436 let data = self.data;
3437 Field::new(
3438 "chained_class_seq_rule_offsets",
3439 FieldType::array_of_offsets(
3440 better_type_name::<ChainedClassSequenceRule>(),
3441 self.chained_class_seq_rule_offsets(),
3442 move |off| {
3443 let target = off.get().resolve::<ChainedClassSequenceRule>(data);
3444 FieldType::offset(off.get(), target)
3445 },
3446 ),
3447 )
3448 }),
3449 _ => None,
3450 }
3451 }
3452}
3453
3454#[cfg(feature = "experimental_traverse")]
3455#[allow(clippy::needless_lifetimes)]
3456impl<'a> std::fmt::Debug for ChainedClassSequenceRuleSet<'a> {
3457 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3458 (self as &dyn SomeTable<'a>).fmt(f)
3459 }
3460}
3461
3462#[derive(Debug, Clone, Copy)]
3464#[doc(hidden)]
3465pub struct ChainedClassSequenceRuleMarker {
3466 backtrack_sequence_byte_len: usize,
3467 input_sequence_byte_len: usize,
3468 lookahead_sequence_byte_len: usize,
3469 seq_lookup_records_byte_len: usize,
3470}
3471
3472impl ChainedClassSequenceRuleMarker {
3473 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
3474 let start = 0;
3475 start..start + u16::RAW_BYTE_LEN
3476 }
3477
3478 pub fn backtrack_sequence_byte_range(&self) -> Range<usize> {
3479 let start = self.backtrack_glyph_count_byte_range().end;
3480 start..start + self.backtrack_sequence_byte_len
3481 }
3482
3483 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
3484 let start = self.backtrack_sequence_byte_range().end;
3485 start..start + u16::RAW_BYTE_LEN
3486 }
3487
3488 pub fn input_sequence_byte_range(&self) -> Range<usize> {
3489 let start = self.input_glyph_count_byte_range().end;
3490 start..start + self.input_sequence_byte_len
3491 }
3492
3493 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
3494 let start = self.input_sequence_byte_range().end;
3495 start..start + u16::RAW_BYTE_LEN
3496 }
3497
3498 pub fn lookahead_sequence_byte_range(&self) -> Range<usize> {
3499 let start = self.lookahead_glyph_count_byte_range().end;
3500 start..start + self.lookahead_sequence_byte_len
3501 }
3502
3503 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
3504 let start = self.lookahead_sequence_byte_range().end;
3505 start..start + u16::RAW_BYTE_LEN
3506 }
3507
3508 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
3509 let start = self.seq_lookup_count_byte_range().end;
3510 start..start + self.seq_lookup_records_byte_len
3511 }
3512}
3513
3514impl MinByteRange for ChainedClassSequenceRuleMarker {
3515 fn min_byte_range(&self) -> Range<usize> {
3516 0..self.seq_lookup_records_byte_range().end
3517 }
3518}
3519
3520impl<'a> FontRead<'a> for ChainedClassSequenceRule<'a> {
3521 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
3522 let mut cursor = data.cursor();
3523 let backtrack_glyph_count: u16 = cursor.read()?;
3524 let backtrack_sequence_byte_len = (backtrack_glyph_count as usize)
3525 .checked_mul(u16::RAW_BYTE_LEN)
3526 .ok_or(ReadError::OutOfBounds)?;
3527 cursor.advance_by(backtrack_sequence_byte_len);
3528 let input_glyph_count: u16 = cursor.read()?;
3529 let input_sequence_byte_len = (transforms::subtract(input_glyph_count, 1_usize))
3530 .checked_mul(u16::RAW_BYTE_LEN)
3531 .ok_or(ReadError::OutOfBounds)?;
3532 cursor.advance_by(input_sequence_byte_len);
3533 let lookahead_glyph_count: u16 = cursor.read()?;
3534 let lookahead_sequence_byte_len = (lookahead_glyph_count as usize)
3535 .checked_mul(u16::RAW_BYTE_LEN)
3536 .ok_or(ReadError::OutOfBounds)?;
3537 cursor.advance_by(lookahead_sequence_byte_len);
3538 let seq_lookup_count: u16 = cursor.read()?;
3539 let seq_lookup_records_byte_len = (seq_lookup_count as usize)
3540 .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN)
3541 .ok_or(ReadError::OutOfBounds)?;
3542 cursor.advance_by(seq_lookup_records_byte_len);
3543 cursor.finish(ChainedClassSequenceRuleMarker {
3544 backtrack_sequence_byte_len,
3545 input_sequence_byte_len,
3546 lookahead_sequence_byte_len,
3547 seq_lookup_records_byte_len,
3548 })
3549 }
3550}
3551
3552pub type ChainedClassSequenceRule<'a> = TableRef<'a, ChainedClassSequenceRuleMarker>;
3554
3555#[allow(clippy::needless_lifetimes)]
3556impl<'a> ChainedClassSequenceRule<'a> {
3557 pub fn backtrack_glyph_count(&self) -> u16 {
3559 let range = self.shape.backtrack_glyph_count_byte_range();
3560 self.data.read_at(range.start).unwrap()
3561 }
3562
3563 pub fn backtrack_sequence(&self) -> &'a [BigEndian<u16>] {
3565 let range = self.shape.backtrack_sequence_byte_range();
3566 self.data.read_array(range).unwrap()
3567 }
3568
3569 pub fn input_glyph_count(&self) -> u16 {
3571 let range = self.shape.input_glyph_count_byte_range();
3572 self.data.read_at(range.start).unwrap()
3573 }
3574
3575 pub fn input_sequence(&self) -> &'a [BigEndian<u16>] {
3578 let range = self.shape.input_sequence_byte_range();
3579 self.data.read_array(range).unwrap()
3580 }
3581
3582 pub fn lookahead_glyph_count(&self) -> u16 {
3584 let range = self.shape.lookahead_glyph_count_byte_range();
3585 self.data.read_at(range.start).unwrap()
3586 }
3587
3588 pub fn lookahead_sequence(&self) -> &'a [BigEndian<u16>] {
3590 let range = self.shape.lookahead_sequence_byte_range();
3591 self.data.read_array(range).unwrap()
3592 }
3593
3594 pub fn seq_lookup_count(&self) -> u16 {
3596 let range = self.shape.seq_lookup_count_byte_range();
3597 self.data.read_at(range.start).unwrap()
3598 }
3599
3600 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
3602 let range = self.shape.seq_lookup_records_byte_range();
3603 self.data.read_array(range).unwrap()
3604 }
3605}
3606
3607#[cfg(feature = "experimental_traverse")]
3608impl<'a> SomeTable<'a> for ChainedClassSequenceRule<'a> {
3609 fn type_name(&self) -> &str {
3610 "ChainedClassSequenceRule"
3611 }
3612 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3613 match idx {
3614 0usize => Some(Field::new(
3615 "backtrack_glyph_count",
3616 self.backtrack_glyph_count(),
3617 )),
3618 1usize => Some(Field::new("backtrack_sequence", self.backtrack_sequence())),
3619 2usize => Some(Field::new("input_glyph_count", self.input_glyph_count())),
3620 3usize => Some(Field::new("input_sequence", self.input_sequence())),
3621 4usize => Some(Field::new(
3622 "lookahead_glyph_count",
3623 self.lookahead_glyph_count(),
3624 )),
3625 5usize => Some(Field::new("lookahead_sequence", self.lookahead_sequence())),
3626 6usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
3627 7usize => Some(Field::new(
3628 "seq_lookup_records",
3629 traversal::FieldType::array_of_records(
3630 stringify!(SequenceLookupRecord),
3631 self.seq_lookup_records(),
3632 self.offset_data(),
3633 ),
3634 )),
3635 _ => None,
3636 }
3637 }
3638}
3639
3640#[cfg(feature = "experimental_traverse")]
3641#[allow(clippy::needless_lifetimes)]
3642impl<'a> std::fmt::Debug for ChainedClassSequenceRule<'a> {
3643 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3644 (self as &dyn SomeTable<'a>).fmt(f)
3645 }
3646}
3647
3648impl Format<u16> for ChainedSequenceContextFormat3Marker {
3649 const FORMAT: u16 = 3;
3650}
3651
3652#[derive(Debug, Clone, Copy)]
3654#[doc(hidden)]
3655pub struct ChainedSequenceContextFormat3Marker {
3656 backtrack_coverage_offsets_byte_len: usize,
3657 input_coverage_offsets_byte_len: usize,
3658 lookahead_coverage_offsets_byte_len: usize,
3659 seq_lookup_records_byte_len: usize,
3660}
3661
3662impl ChainedSequenceContextFormat3Marker {
3663 pub fn format_byte_range(&self) -> Range<usize> {
3664 let start = 0;
3665 start..start + u16::RAW_BYTE_LEN
3666 }
3667
3668 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
3669 let start = self.format_byte_range().end;
3670 start..start + u16::RAW_BYTE_LEN
3671 }
3672
3673 pub fn backtrack_coverage_offsets_byte_range(&self) -> Range<usize> {
3674 let start = self.backtrack_glyph_count_byte_range().end;
3675 start..start + self.backtrack_coverage_offsets_byte_len
3676 }
3677
3678 pub fn input_glyph_count_byte_range(&self) -> Range<usize> {
3679 let start = self.backtrack_coverage_offsets_byte_range().end;
3680 start..start + u16::RAW_BYTE_LEN
3681 }
3682
3683 pub fn input_coverage_offsets_byte_range(&self) -> Range<usize> {
3684 let start = self.input_glyph_count_byte_range().end;
3685 start..start + self.input_coverage_offsets_byte_len
3686 }
3687
3688 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
3689 let start = self.input_coverage_offsets_byte_range().end;
3690 start..start + u16::RAW_BYTE_LEN
3691 }
3692
3693 pub fn lookahead_coverage_offsets_byte_range(&self) -> Range<usize> {
3694 let start = self.lookahead_glyph_count_byte_range().end;
3695 start..start + self.lookahead_coverage_offsets_byte_len
3696 }
3697
3698 pub fn seq_lookup_count_byte_range(&self) -> Range<usize> {
3699 let start = self.lookahead_coverage_offsets_byte_range().end;
3700 start..start + u16::RAW_BYTE_LEN
3701 }
3702
3703 pub fn seq_lookup_records_byte_range(&self) -> Range<usize> {
3704 let start = self.seq_lookup_count_byte_range().end;
3705 start..start + self.seq_lookup_records_byte_len
3706 }
3707}
3708
3709impl MinByteRange for ChainedSequenceContextFormat3Marker {
3710 fn min_byte_range(&self) -> Range<usize> {
3711 0..self.seq_lookup_records_byte_range().end
3712 }
3713}
3714
3715impl<'a> FontRead<'a> for ChainedSequenceContextFormat3<'a> {
3716 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
3717 let mut cursor = data.cursor();
3718 cursor.advance::<u16>();
3719 let backtrack_glyph_count: u16 = cursor.read()?;
3720 let backtrack_coverage_offsets_byte_len = (backtrack_glyph_count as usize)
3721 .checked_mul(Offset16::RAW_BYTE_LEN)
3722 .ok_or(ReadError::OutOfBounds)?;
3723 cursor.advance_by(backtrack_coverage_offsets_byte_len);
3724 let input_glyph_count: u16 = cursor.read()?;
3725 let input_coverage_offsets_byte_len = (input_glyph_count as usize)
3726 .checked_mul(Offset16::RAW_BYTE_LEN)
3727 .ok_or(ReadError::OutOfBounds)?;
3728 cursor.advance_by(input_coverage_offsets_byte_len);
3729 let lookahead_glyph_count: u16 = cursor.read()?;
3730 let lookahead_coverage_offsets_byte_len = (lookahead_glyph_count as usize)
3731 .checked_mul(Offset16::RAW_BYTE_LEN)
3732 .ok_or(ReadError::OutOfBounds)?;
3733 cursor.advance_by(lookahead_coverage_offsets_byte_len);
3734 let seq_lookup_count: u16 = cursor.read()?;
3735 let seq_lookup_records_byte_len = (seq_lookup_count as usize)
3736 .checked_mul(SequenceLookupRecord::RAW_BYTE_LEN)
3737 .ok_or(ReadError::OutOfBounds)?;
3738 cursor.advance_by(seq_lookup_records_byte_len);
3739 cursor.finish(ChainedSequenceContextFormat3Marker {
3740 backtrack_coverage_offsets_byte_len,
3741 input_coverage_offsets_byte_len,
3742 lookahead_coverage_offsets_byte_len,
3743 seq_lookup_records_byte_len,
3744 })
3745 }
3746}
3747
3748pub type ChainedSequenceContextFormat3<'a> = TableRef<'a, ChainedSequenceContextFormat3Marker>;
3750
3751#[allow(clippy::needless_lifetimes)]
3752impl<'a> ChainedSequenceContextFormat3<'a> {
3753 pub fn format(&self) -> u16 {
3755 let range = self.shape.format_byte_range();
3756 self.data.read_at(range.start).unwrap()
3757 }
3758
3759 pub fn backtrack_glyph_count(&self) -> u16 {
3761 let range = self.shape.backtrack_glyph_count_byte_range();
3762 self.data.read_at(range.start).unwrap()
3763 }
3764
3765 pub fn backtrack_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3767 let range = self.shape.backtrack_coverage_offsets_byte_range();
3768 self.data.read_array(range).unwrap()
3769 }
3770
3771 pub fn backtrack_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3773 let data = self.data;
3774 let offsets = self.backtrack_coverage_offsets();
3775 ArrayOfOffsets::new(offsets, data, ())
3776 }
3777
3778 pub fn input_glyph_count(&self) -> u16 {
3780 let range = self.shape.input_glyph_count_byte_range();
3781 self.data.read_at(range.start).unwrap()
3782 }
3783
3784 pub fn input_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3786 let range = self.shape.input_coverage_offsets_byte_range();
3787 self.data.read_array(range).unwrap()
3788 }
3789
3790 pub fn input_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3792 let data = self.data;
3793 let offsets = self.input_coverage_offsets();
3794 ArrayOfOffsets::new(offsets, data, ())
3795 }
3796
3797 pub fn lookahead_glyph_count(&self) -> u16 {
3799 let range = self.shape.lookahead_glyph_count_byte_range();
3800 self.data.read_at(range.start).unwrap()
3801 }
3802
3803 pub fn lookahead_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
3805 let range = self.shape.lookahead_coverage_offsets_byte_range();
3806 self.data.read_array(range).unwrap()
3807 }
3808
3809 pub fn lookahead_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
3811 let data = self.data;
3812 let offsets = self.lookahead_coverage_offsets();
3813 ArrayOfOffsets::new(offsets, data, ())
3814 }
3815
3816 pub fn seq_lookup_count(&self) -> u16 {
3818 let range = self.shape.seq_lookup_count_byte_range();
3819 self.data.read_at(range.start).unwrap()
3820 }
3821
3822 pub fn seq_lookup_records(&self) -> &'a [SequenceLookupRecord] {
3824 let range = self.shape.seq_lookup_records_byte_range();
3825 self.data.read_array(range).unwrap()
3826 }
3827}
3828
3829#[cfg(feature = "experimental_traverse")]
3830impl<'a> SomeTable<'a> for ChainedSequenceContextFormat3<'a> {
3831 fn type_name(&self) -> &str {
3832 "ChainedSequenceContextFormat3"
3833 }
3834 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3835 match idx {
3836 0usize => Some(Field::new("format", self.format())),
3837 1usize => Some(Field::new(
3838 "backtrack_glyph_count",
3839 self.backtrack_glyph_count(),
3840 )),
3841 2usize => Some({
3842 let data = self.data;
3843 Field::new(
3844 "backtrack_coverage_offsets",
3845 FieldType::array_of_offsets(
3846 better_type_name::<CoverageTable>(),
3847 self.backtrack_coverage_offsets(),
3848 move |off| {
3849 let target = off.get().resolve::<CoverageTable>(data);
3850 FieldType::offset(off.get(), target)
3851 },
3852 ),
3853 )
3854 }),
3855 3usize => Some(Field::new("input_glyph_count", self.input_glyph_count())),
3856 4usize => Some({
3857 let data = self.data;
3858 Field::new(
3859 "input_coverage_offsets",
3860 FieldType::array_of_offsets(
3861 better_type_name::<CoverageTable>(),
3862 self.input_coverage_offsets(),
3863 move |off| {
3864 let target = off.get().resolve::<CoverageTable>(data);
3865 FieldType::offset(off.get(), target)
3866 },
3867 ),
3868 )
3869 }),
3870 5usize => Some(Field::new(
3871 "lookahead_glyph_count",
3872 self.lookahead_glyph_count(),
3873 )),
3874 6usize => Some({
3875 let data = self.data;
3876 Field::new(
3877 "lookahead_coverage_offsets",
3878 FieldType::array_of_offsets(
3879 better_type_name::<CoverageTable>(),
3880 self.lookahead_coverage_offsets(),
3881 move |off| {
3882 let target = off.get().resolve::<CoverageTable>(data);
3883 FieldType::offset(off.get(), target)
3884 },
3885 ),
3886 )
3887 }),
3888 7usize => Some(Field::new("seq_lookup_count", self.seq_lookup_count())),
3889 8usize => Some(Field::new(
3890 "seq_lookup_records",
3891 traversal::FieldType::array_of_records(
3892 stringify!(SequenceLookupRecord),
3893 self.seq_lookup_records(),
3894 self.offset_data(),
3895 ),
3896 )),
3897 _ => None,
3898 }
3899 }
3900}
3901
3902#[cfg(feature = "experimental_traverse")]
3903#[allow(clippy::needless_lifetimes)]
3904impl<'a> std::fmt::Debug for ChainedSequenceContextFormat3<'a> {
3905 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3906 (self as &dyn SomeTable<'a>).fmt(f)
3907 }
3908}
3909
3910#[derive(Clone)]
3911pub enum ChainedSequenceContext<'a> {
3912 Format1(ChainedSequenceContextFormat1<'a>),
3913 Format2(ChainedSequenceContextFormat2<'a>),
3914 Format3(ChainedSequenceContextFormat3<'a>),
3915}
3916
3917impl<'a> ChainedSequenceContext<'a> {
3918 pub fn offset_data(&self) -> FontData<'a> {
3920 match self {
3921 Self::Format1(item) => item.offset_data(),
3922 Self::Format2(item) => item.offset_data(),
3923 Self::Format3(item) => item.offset_data(),
3924 }
3925 }
3926
3927 pub fn format(&self) -> u16 {
3929 match self {
3930 Self::Format1(item) => item.format(),
3931 Self::Format2(item) => item.format(),
3932 Self::Format3(item) => item.format(),
3933 }
3934 }
3935}
3936
3937impl<'a> FontRead<'a> for ChainedSequenceContext<'a> {
3938 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
3939 let format: u16 = data.read_at(0usize)?;
3940 match format {
3941 ChainedSequenceContextFormat1Marker::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
3942 ChainedSequenceContextFormat2Marker::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
3943 ChainedSequenceContextFormat3Marker::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
3944 other => Err(ReadError::InvalidFormat(other.into())),
3945 }
3946 }
3947}
3948
3949impl MinByteRange for ChainedSequenceContext<'_> {
3950 fn min_byte_range(&self) -> Range<usize> {
3951 match self {
3952 Self::Format1(item) => item.min_byte_range(),
3953 Self::Format2(item) => item.min_byte_range(),
3954 Self::Format3(item) => item.min_byte_range(),
3955 }
3956 }
3957}
3958
3959#[cfg(feature = "experimental_traverse")]
3960impl<'a> ChainedSequenceContext<'a> {
3961 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
3962 match self {
3963 Self::Format1(table) => table,
3964 Self::Format2(table) => table,
3965 Self::Format3(table) => table,
3966 }
3967 }
3968}
3969
3970#[cfg(feature = "experimental_traverse")]
3971impl std::fmt::Debug for ChainedSequenceContext<'_> {
3972 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3973 self.dyn_inner().fmt(f)
3974 }
3975}
3976
3977#[cfg(feature = "experimental_traverse")]
3978impl<'a> SomeTable<'a> for ChainedSequenceContext<'a> {
3979 fn type_name(&self) -> &str {
3980 self.dyn_inner().type_name()
3981 }
3982 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3983 self.dyn_inner().get_field(idx)
3984 }
3985}
3986
3987#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
3990#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3991#[repr(u16)]
3992#[allow(clippy::manual_non_exhaustive)]
3993pub enum DeltaFormat {
3994 #[default]
3996 Local2BitDeltas = 0x0001,
3997 Local4BitDeltas = 0x0002,
3999 Local8BitDeltas = 0x0003,
4001 VariationIndex = 0x8000,
4003 #[doc(hidden)]
4004 Unknown,
4006}
4007
4008impl DeltaFormat {
4009 pub fn new(raw: u16) -> Self {
4013 match raw {
4014 0x0001 => Self::Local2BitDeltas,
4015 0x0002 => Self::Local4BitDeltas,
4016 0x0003 => Self::Local8BitDeltas,
4017 0x8000 => Self::VariationIndex,
4018 _ => Self::Unknown,
4019 }
4020 }
4021}
4022
4023impl font_types::Scalar for DeltaFormat {
4024 type Raw = <u16 as font_types::Scalar>::Raw;
4025 fn to_raw(self) -> Self::Raw {
4026 (self as u16).to_raw()
4027 }
4028 fn from_raw(raw: Self::Raw) -> Self {
4029 let t = <u16>::from_raw(raw);
4030 Self::new(t)
4031 }
4032}
4033
4034#[cfg(feature = "experimental_traverse")]
4035impl<'a> From<DeltaFormat> for FieldType<'a> {
4036 fn from(src: DeltaFormat) -> FieldType<'a> {
4037 (src as u16).into()
4038 }
4039}
4040
4041#[derive(Debug, Clone, Copy)]
4043#[doc(hidden)]
4044pub struct DeviceMarker {
4045 delta_value_byte_len: usize,
4046}
4047
4048impl DeviceMarker {
4049 pub fn start_size_byte_range(&self) -> Range<usize> {
4050 let start = 0;
4051 start..start + u16::RAW_BYTE_LEN
4052 }
4053
4054 pub fn end_size_byte_range(&self) -> Range<usize> {
4055 let start = self.start_size_byte_range().end;
4056 start..start + u16::RAW_BYTE_LEN
4057 }
4058
4059 pub fn delta_format_byte_range(&self) -> Range<usize> {
4060 let start = self.end_size_byte_range().end;
4061 start..start + DeltaFormat::RAW_BYTE_LEN
4062 }
4063
4064 pub fn delta_value_byte_range(&self) -> Range<usize> {
4065 let start = self.delta_format_byte_range().end;
4066 start..start + self.delta_value_byte_len
4067 }
4068}
4069
4070impl MinByteRange for DeviceMarker {
4071 fn min_byte_range(&self) -> Range<usize> {
4072 0..self.delta_value_byte_range().end
4073 }
4074}
4075
4076impl<'a> FontRead<'a> for Device<'a> {
4077 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
4078 let mut cursor = data.cursor();
4079 let start_size: u16 = cursor.read()?;
4080 let end_size: u16 = cursor.read()?;
4081 let delta_format: DeltaFormat = cursor.read()?;
4082 let delta_value_byte_len = (DeltaFormat::value_count(delta_format, start_size, end_size))
4083 .checked_mul(u16::RAW_BYTE_LEN)
4084 .ok_or(ReadError::OutOfBounds)?;
4085 cursor.advance_by(delta_value_byte_len);
4086 cursor.finish(DeviceMarker {
4087 delta_value_byte_len,
4088 })
4089 }
4090}
4091
4092pub type Device<'a> = TableRef<'a, DeviceMarker>;
4094
4095#[allow(clippy::needless_lifetimes)]
4096impl<'a> Device<'a> {
4097 pub fn start_size(&self) -> u16 {
4099 let range = self.shape.start_size_byte_range();
4100 self.data.read_at(range.start).unwrap()
4101 }
4102
4103 pub fn end_size(&self) -> u16 {
4105 let range = self.shape.end_size_byte_range();
4106 self.data.read_at(range.start).unwrap()
4107 }
4108
4109 pub fn delta_format(&self) -> DeltaFormat {
4111 let range = self.shape.delta_format_byte_range();
4112 self.data.read_at(range.start).unwrap()
4113 }
4114
4115 pub fn delta_value(&self) -> &'a [BigEndian<u16>] {
4117 let range = self.shape.delta_value_byte_range();
4118 self.data.read_array(range).unwrap()
4119 }
4120}
4121
4122#[cfg(feature = "experimental_traverse")]
4123impl<'a> SomeTable<'a> for Device<'a> {
4124 fn type_name(&self) -> &str {
4125 "Device"
4126 }
4127 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4128 match idx {
4129 0usize => Some(Field::new("start_size", self.start_size())),
4130 1usize => Some(Field::new("end_size", self.end_size())),
4131 2usize => Some(Field::new("delta_format", self.delta_format())),
4132 3usize => Some(Field::new("delta_value", self.delta_value())),
4133 _ => None,
4134 }
4135 }
4136}
4137
4138#[cfg(feature = "experimental_traverse")]
4139#[allow(clippy::needless_lifetimes)]
4140impl<'a> std::fmt::Debug for Device<'a> {
4141 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4142 (self as &dyn SomeTable<'a>).fmt(f)
4143 }
4144}
4145
4146#[derive(Debug, Clone, Copy)]
4148#[doc(hidden)]
4149pub struct VariationIndexMarker {}
4150
4151impl VariationIndexMarker {
4152 pub fn delta_set_outer_index_byte_range(&self) -> Range<usize> {
4153 let start = 0;
4154 start..start + u16::RAW_BYTE_LEN
4155 }
4156
4157 pub fn delta_set_inner_index_byte_range(&self) -> Range<usize> {
4158 let start = self.delta_set_outer_index_byte_range().end;
4159 start..start + u16::RAW_BYTE_LEN
4160 }
4161
4162 pub fn delta_format_byte_range(&self) -> Range<usize> {
4163 let start = self.delta_set_inner_index_byte_range().end;
4164 start..start + DeltaFormat::RAW_BYTE_LEN
4165 }
4166}
4167
4168impl MinByteRange for VariationIndexMarker {
4169 fn min_byte_range(&self) -> Range<usize> {
4170 0..self.delta_format_byte_range().end
4171 }
4172}
4173
4174impl<'a> FontRead<'a> for VariationIndex<'a> {
4175 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
4176 let mut cursor = data.cursor();
4177 cursor.advance::<u16>();
4178 cursor.advance::<u16>();
4179 cursor.advance::<DeltaFormat>();
4180 cursor.finish(VariationIndexMarker {})
4181 }
4182}
4183
4184pub type VariationIndex<'a> = TableRef<'a, VariationIndexMarker>;
4186
4187#[allow(clippy::needless_lifetimes)]
4188impl<'a> VariationIndex<'a> {
4189 pub fn delta_set_outer_index(&self) -> u16 {
4192 let range = self.shape.delta_set_outer_index_byte_range();
4193 self.data.read_at(range.start).unwrap()
4194 }
4195
4196 pub fn delta_set_inner_index(&self) -> u16 {
4199 let range = self.shape.delta_set_inner_index_byte_range();
4200 self.data.read_at(range.start).unwrap()
4201 }
4202
4203 pub fn delta_format(&self) -> DeltaFormat {
4205 let range = self.shape.delta_format_byte_range();
4206 self.data.read_at(range.start).unwrap()
4207 }
4208}
4209
4210#[cfg(feature = "experimental_traverse")]
4211impl<'a> SomeTable<'a> for VariationIndex<'a> {
4212 fn type_name(&self) -> &str {
4213 "VariationIndex"
4214 }
4215 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4216 match idx {
4217 0usize => Some(Field::new(
4218 "delta_set_outer_index",
4219 self.delta_set_outer_index(),
4220 )),
4221 1usize => Some(Field::new(
4222 "delta_set_inner_index",
4223 self.delta_set_inner_index(),
4224 )),
4225 2usize => Some(Field::new("delta_format", self.delta_format())),
4226 _ => None,
4227 }
4228 }
4229}
4230
4231#[cfg(feature = "experimental_traverse")]
4232#[allow(clippy::needless_lifetimes)]
4233impl<'a> std::fmt::Debug for VariationIndex<'a> {
4234 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4235 (self as &dyn SomeTable<'a>).fmt(f)
4236 }
4237}
4238
4239#[derive(Clone)]
4241pub enum DeviceOrVariationIndex<'a> {
4242 Device(Device<'a>),
4243 VariationIndex(VariationIndex<'a>),
4244}
4245
4246impl<'a> DeviceOrVariationIndex<'a> {
4247 pub fn offset_data(&self) -> FontData<'a> {
4249 match self {
4250 Self::Device(item) => item.offset_data(),
4251 Self::VariationIndex(item) => item.offset_data(),
4252 }
4253 }
4254}
4255
4256impl<'a> FontRead<'a> for DeviceOrVariationIndex<'a> {
4257 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
4258 let format: DeltaFormat = data.read_at(4usize)?;
4259
4260 #[allow(clippy::redundant_guards)]
4261 match format {
4262 format if format != DeltaFormat::VariationIndex => {
4263 Ok(Self::Device(FontRead::read(data)?))
4264 }
4265 format if format == DeltaFormat::VariationIndex => {
4266 Ok(Self::VariationIndex(FontRead::read(data)?))
4267 }
4268 other => Err(ReadError::InvalidFormat(other.into())),
4269 }
4270 }
4271}
4272
4273impl MinByteRange for DeviceOrVariationIndex<'_> {
4274 fn min_byte_range(&self) -> Range<usize> {
4275 match self {
4276 Self::Device(item) => item.min_byte_range(),
4277 Self::VariationIndex(item) => item.min_byte_range(),
4278 }
4279 }
4280}
4281
4282#[cfg(feature = "experimental_traverse")]
4283impl<'a> DeviceOrVariationIndex<'a> {
4284 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
4285 match self {
4286 Self::Device(table) => table,
4287 Self::VariationIndex(table) => table,
4288 }
4289 }
4290}
4291
4292#[cfg(feature = "experimental_traverse")]
4293impl std::fmt::Debug for DeviceOrVariationIndex<'_> {
4294 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4295 self.dyn_inner().fmt(f)
4296 }
4297}
4298
4299#[cfg(feature = "experimental_traverse")]
4300impl<'a> SomeTable<'a> for DeviceOrVariationIndex<'a> {
4301 fn type_name(&self) -> &str {
4302 self.dyn_inner().type_name()
4303 }
4304 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4305 self.dyn_inner().get_field(idx)
4306 }
4307}
4308
4309#[derive(Debug, Clone, Copy)]
4311#[doc(hidden)]
4312pub struct FeatureVariationsMarker {
4313 feature_variation_records_byte_len: usize,
4314}
4315
4316impl FeatureVariationsMarker {
4317 pub fn version_byte_range(&self) -> Range<usize> {
4318 let start = 0;
4319 start..start + MajorMinor::RAW_BYTE_LEN
4320 }
4321
4322 pub fn feature_variation_record_count_byte_range(&self) -> Range<usize> {
4323 let start = self.version_byte_range().end;
4324 start..start + u32::RAW_BYTE_LEN
4325 }
4326
4327 pub fn feature_variation_records_byte_range(&self) -> Range<usize> {
4328 let start = self.feature_variation_record_count_byte_range().end;
4329 start..start + self.feature_variation_records_byte_len
4330 }
4331}
4332
4333impl MinByteRange for FeatureVariationsMarker {
4334 fn min_byte_range(&self) -> Range<usize> {
4335 0..self.feature_variation_records_byte_range().end
4336 }
4337}
4338
4339impl<'a> FontRead<'a> for FeatureVariations<'a> {
4340 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
4341 let mut cursor = data.cursor();
4342 cursor.advance::<MajorMinor>();
4343 let feature_variation_record_count: u32 = cursor.read()?;
4344 let feature_variation_records_byte_len = (feature_variation_record_count as usize)
4345 .checked_mul(FeatureVariationRecord::RAW_BYTE_LEN)
4346 .ok_or(ReadError::OutOfBounds)?;
4347 cursor.advance_by(feature_variation_records_byte_len);
4348 cursor.finish(FeatureVariationsMarker {
4349 feature_variation_records_byte_len,
4350 })
4351 }
4352}
4353
4354pub type FeatureVariations<'a> = TableRef<'a, FeatureVariationsMarker>;
4356
4357#[allow(clippy::needless_lifetimes)]
4358impl<'a> FeatureVariations<'a> {
4359 pub fn version(&self) -> MajorMinor {
4360 let range = self.shape.version_byte_range();
4361 self.data.read_at(range.start).unwrap()
4362 }
4363
4364 pub fn feature_variation_record_count(&self) -> u32 {
4366 let range = self.shape.feature_variation_record_count_byte_range();
4367 self.data.read_at(range.start).unwrap()
4368 }
4369
4370 pub fn feature_variation_records(&self) -> &'a [FeatureVariationRecord] {
4372 let range = self.shape.feature_variation_records_byte_range();
4373 self.data.read_array(range).unwrap()
4374 }
4375}
4376
4377#[cfg(feature = "experimental_traverse")]
4378impl<'a> SomeTable<'a> for FeatureVariations<'a> {
4379 fn type_name(&self) -> &str {
4380 "FeatureVariations"
4381 }
4382 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4383 match idx {
4384 0usize => Some(Field::new("version", self.version())),
4385 1usize => Some(Field::new(
4386 "feature_variation_record_count",
4387 self.feature_variation_record_count(),
4388 )),
4389 2usize => Some(Field::new(
4390 "feature_variation_records",
4391 traversal::FieldType::array_of_records(
4392 stringify!(FeatureVariationRecord),
4393 self.feature_variation_records(),
4394 self.offset_data(),
4395 ),
4396 )),
4397 _ => None,
4398 }
4399 }
4400}
4401
4402#[cfg(feature = "experimental_traverse")]
4403#[allow(clippy::needless_lifetimes)]
4404impl<'a> std::fmt::Debug for FeatureVariations<'a> {
4405 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4406 (self as &dyn SomeTable<'a>).fmt(f)
4407 }
4408}
4409
4410#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
4412#[repr(C)]
4413#[repr(packed)]
4414pub struct FeatureVariationRecord {
4415 pub condition_set_offset: BigEndian<Nullable<Offset32>>,
4418 pub feature_table_substitution_offset: BigEndian<Nullable<Offset32>>,
4421}
4422
4423impl FeatureVariationRecord {
4424 pub fn condition_set_offset(&self) -> Nullable<Offset32> {
4427 self.condition_set_offset.get()
4428 }
4429
4430 pub fn condition_set<'a>(
4436 &self,
4437 data: FontData<'a>,
4438 ) -> Option<Result<ConditionSet<'a>, ReadError>> {
4439 self.condition_set_offset().resolve(data)
4440 }
4441
4442 pub fn feature_table_substitution_offset(&self) -> Nullable<Offset32> {
4445 self.feature_table_substitution_offset.get()
4446 }
4447
4448 pub fn feature_table_substitution<'a>(
4454 &self,
4455 data: FontData<'a>,
4456 ) -> Option<Result<FeatureTableSubstitution<'a>, ReadError>> {
4457 self.feature_table_substitution_offset().resolve(data)
4458 }
4459}
4460
4461impl FixedSize for FeatureVariationRecord {
4462 const RAW_BYTE_LEN: usize = Offset32::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
4463}
4464
4465#[cfg(feature = "experimental_traverse")]
4466impl<'a> SomeRecord<'a> for FeatureVariationRecord {
4467 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
4468 RecordResolver {
4469 name: "FeatureVariationRecord",
4470 get_field: Box::new(move |idx, _data| match idx {
4471 0usize => Some(Field::new(
4472 "condition_set_offset",
4473 FieldType::offset(self.condition_set_offset(), self.condition_set(_data)),
4474 )),
4475 1usize => Some(Field::new(
4476 "feature_table_substitution_offset",
4477 FieldType::offset(
4478 self.feature_table_substitution_offset(),
4479 self.feature_table_substitution(_data),
4480 ),
4481 )),
4482 _ => None,
4483 }),
4484 data,
4485 }
4486 }
4487}
4488
4489#[derive(Debug, Clone, Copy)]
4491#[doc(hidden)]
4492pub struct ConditionSetMarker {
4493 condition_offsets_byte_len: usize,
4494}
4495
4496impl ConditionSetMarker {
4497 pub fn condition_count_byte_range(&self) -> Range<usize> {
4498 let start = 0;
4499 start..start + u16::RAW_BYTE_LEN
4500 }
4501
4502 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
4503 let start = self.condition_count_byte_range().end;
4504 start..start + self.condition_offsets_byte_len
4505 }
4506}
4507
4508impl MinByteRange for ConditionSetMarker {
4509 fn min_byte_range(&self) -> Range<usize> {
4510 0..self.condition_offsets_byte_range().end
4511 }
4512}
4513
4514impl<'a> FontRead<'a> for ConditionSet<'a> {
4515 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
4516 let mut cursor = data.cursor();
4517 let condition_count: u16 = cursor.read()?;
4518 let condition_offsets_byte_len = (condition_count as usize)
4519 .checked_mul(Offset32::RAW_BYTE_LEN)
4520 .ok_or(ReadError::OutOfBounds)?;
4521 cursor.advance_by(condition_offsets_byte_len);
4522 cursor.finish(ConditionSetMarker {
4523 condition_offsets_byte_len,
4524 })
4525 }
4526}
4527
4528pub type ConditionSet<'a> = TableRef<'a, ConditionSetMarker>;
4530
4531#[allow(clippy::needless_lifetimes)]
4532impl<'a> ConditionSet<'a> {
4533 pub fn condition_count(&self) -> u16 {
4535 let range = self.shape.condition_count_byte_range();
4536 self.data.read_at(range.start).unwrap()
4537 }
4538
4539 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset32>] {
4542 let range = self.shape.condition_offsets_byte_range();
4543 self.data.read_array(range).unwrap()
4544 }
4545
4546 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset32> {
4548 let data = self.data;
4549 let offsets = self.condition_offsets();
4550 ArrayOfOffsets::new(offsets, data, ())
4551 }
4552}
4553
4554#[cfg(feature = "experimental_traverse")]
4555impl<'a> SomeTable<'a> for ConditionSet<'a> {
4556 fn type_name(&self) -> &str {
4557 "ConditionSet"
4558 }
4559 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4560 match idx {
4561 0usize => Some(Field::new("condition_count", self.condition_count())),
4562 1usize => Some({
4563 let data = self.data;
4564 Field::new(
4565 "condition_offsets",
4566 FieldType::array_of_offsets(
4567 better_type_name::<Condition>(),
4568 self.condition_offsets(),
4569 move |off| {
4570 let target = off.get().resolve::<Condition>(data);
4571 FieldType::offset(off.get(), target)
4572 },
4573 ),
4574 )
4575 }),
4576 _ => None,
4577 }
4578 }
4579}
4580
4581#[cfg(feature = "experimental_traverse")]
4582#[allow(clippy::needless_lifetimes)]
4583impl<'a> std::fmt::Debug for ConditionSet<'a> {
4584 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4585 (self as &dyn SomeTable<'a>).fmt(f)
4586 }
4587}
4588
4589#[derive(Clone)]
4594pub enum Condition<'a> {
4595 Format1AxisRange(ConditionFormat1<'a>),
4596 Format2VariableValue(ConditionFormat2<'a>),
4597 Format3And(ConditionFormat3<'a>),
4598 Format4Or(ConditionFormat4<'a>),
4599 Format5Negate(ConditionFormat5<'a>),
4600}
4601
4602impl<'a> Condition<'a> {
4603 pub fn offset_data(&self) -> FontData<'a> {
4605 match self {
4606 Self::Format1AxisRange(item) => item.offset_data(),
4607 Self::Format2VariableValue(item) => item.offset_data(),
4608 Self::Format3And(item) => item.offset_data(),
4609 Self::Format4Or(item) => item.offset_data(),
4610 Self::Format5Negate(item) => item.offset_data(),
4611 }
4612 }
4613
4614 pub fn format(&self) -> u16 {
4616 match self {
4617 Self::Format1AxisRange(item) => item.format(),
4618 Self::Format2VariableValue(item) => item.format(),
4619 Self::Format3And(item) => item.format(),
4620 Self::Format4Or(item) => item.format(),
4621 Self::Format5Negate(item) => item.format(),
4622 }
4623 }
4624}
4625
4626impl<'a> FontRead<'a> for Condition<'a> {
4627 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
4628 let format: u16 = data.read_at(0usize)?;
4629 match format {
4630 ConditionFormat1Marker::FORMAT => Ok(Self::Format1AxisRange(FontRead::read(data)?)),
4631 ConditionFormat2Marker::FORMAT => Ok(Self::Format2VariableValue(FontRead::read(data)?)),
4632 ConditionFormat3Marker::FORMAT => Ok(Self::Format3And(FontRead::read(data)?)),
4633 ConditionFormat4Marker::FORMAT => Ok(Self::Format4Or(FontRead::read(data)?)),
4634 ConditionFormat5Marker::FORMAT => Ok(Self::Format5Negate(FontRead::read(data)?)),
4635 other => Err(ReadError::InvalidFormat(other.into())),
4636 }
4637 }
4638}
4639
4640impl MinByteRange for Condition<'_> {
4641 fn min_byte_range(&self) -> Range<usize> {
4642 match self {
4643 Self::Format1AxisRange(item) => item.min_byte_range(),
4644 Self::Format2VariableValue(item) => item.min_byte_range(),
4645 Self::Format3And(item) => item.min_byte_range(),
4646 Self::Format4Or(item) => item.min_byte_range(),
4647 Self::Format5Negate(item) => item.min_byte_range(),
4648 }
4649 }
4650}
4651
4652#[cfg(feature = "experimental_traverse")]
4653impl<'a> Condition<'a> {
4654 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
4655 match self {
4656 Self::Format1AxisRange(table) => table,
4657 Self::Format2VariableValue(table) => table,
4658 Self::Format3And(table) => table,
4659 Self::Format4Or(table) => table,
4660 Self::Format5Negate(table) => table,
4661 }
4662 }
4663}
4664
4665#[cfg(feature = "experimental_traverse")]
4666impl std::fmt::Debug for Condition<'_> {
4667 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4668 self.dyn_inner().fmt(f)
4669 }
4670}
4671
4672#[cfg(feature = "experimental_traverse")]
4673impl<'a> SomeTable<'a> for Condition<'a> {
4674 fn type_name(&self) -> &str {
4675 self.dyn_inner().type_name()
4676 }
4677 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4678 self.dyn_inner().get_field(idx)
4679 }
4680}
4681
4682impl Format<u16> for ConditionFormat1Marker {
4683 const FORMAT: u16 = 1;
4684}
4685
4686#[derive(Debug, Clone, Copy)]
4688#[doc(hidden)]
4689pub struct ConditionFormat1Marker {}
4690
4691impl ConditionFormat1Marker {
4692 pub fn format_byte_range(&self) -> Range<usize> {
4693 let start = 0;
4694 start..start + u16::RAW_BYTE_LEN
4695 }
4696
4697 pub fn axis_index_byte_range(&self) -> Range<usize> {
4698 let start = self.format_byte_range().end;
4699 start..start + u16::RAW_BYTE_LEN
4700 }
4701
4702 pub fn filter_range_min_value_byte_range(&self) -> Range<usize> {
4703 let start = self.axis_index_byte_range().end;
4704 start..start + F2Dot14::RAW_BYTE_LEN
4705 }
4706
4707 pub fn filter_range_max_value_byte_range(&self) -> Range<usize> {
4708 let start = self.filter_range_min_value_byte_range().end;
4709 start..start + F2Dot14::RAW_BYTE_LEN
4710 }
4711}
4712
4713impl MinByteRange for ConditionFormat1Marker {
4714 fn min_byte_range(&self) -> Range<usize> {
4715 0..self.filter_range_max_value_byte_range().end
4716 }
4717}
4718
4719impl<'a> FontRead<'a> for ConditionFormat1<'a> {
4720 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
4721 let mut cursor = data.cursor();
4722 cursor.advance::<u16>();
4723 cursor.advance::<u16>();
4724 cursor.advance::<F2Dot14>();
4725 cursor.advance::<F2Dot14>();
4726 cursor.finish(ConditionFormat1Marker {})
4727 }
4728}
4729
4730pub type ConditionFormat1<'a> = TableRef<'a, ConditionFormat1Marker>;
4732
4733#[allow(clippy::needless_lifetimes)]
4734impl<'a> ConditionFormat1<'a> {
4735 pub fn format(&self) -> u16 {
4737 let range = self.shape.format_byte_range();
4738 self.data.read_at(range.start).unwrap()
4739 }
4740
4741 pub fn axis_index(&self) -> u16 {
4744 let range = self.shape.axis_index_byte_range();
4745 self.data.read_at(range.start).unwrap()
4746 }
4747
4748 pub fn filter_range_min_value(&self) -> F2Dot14 {
4751 let range = self.shape.filter_range_min_value_byte_range();
4752 self.data.read_at(range.start).unwrap()
4753 }
4754
4755 pub fn filter_range_max_value(&self) -> F2Dot14 {
4758 let range = self.shape.filter_range_max_value_byte_range();
4759 self.data.read_at(range.start).unwrap()
4760 }
4761}
4762
4763#[cfg(feature = "experimental_traverse")]
4764impl<'a> SomeTable<'a> for ConditionFormat1<'a> {
4765 fn type_name(&self) -> &str {
4766 "ConditionFormat1"
4767 }
4768 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4769 match idx {
4770 0usize => Some(Field::new("format", self.format())),
4771 1usize => Some(Field::new("axis_index", self.axis_index())),
4772 2usize => Some(Field::new(
4773 "filter_range_min_value",
4774 self.filter_range_min_value(),
4775 )),
4776 3usize => Some(Field::new(
4777 "filter_range_max_value",
4778 self.filter_range_max_value(),
4779 )),
4780 _ => None,
4781 }
4782 }
4783}
4784
4785#[cfg(feature = "experimental_traverse")]
4786#[allow(clippy::needless_lifetimes)]
4787impl<'a> std::fmt::Debug for ConditionFormat1<'a> {
4788 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4789 (self as &dyn SomeTable<'a>).fmt(f)
4790 }
4791}
4792
4793impl Format<u16> for ConditionFormat2Marker {
4794 const FORMAT: u16 = 2;
4795}
4796
4797#[derive(Debug, Clone, Copy)]
4799#[doc(hidden)]
4800pub struct ConditionFormat2Marker {}
4801
4802impl ConditionFormat2Marker {
4803 pub fn format_byte_range(&self) -> Range<usize> {
4804 let start = 0;
4805 start..start + u16::RAW_BYTE_LEN
4806 }
4807
4808 pub fn default_value_byte_range(&self) -> Range<usize> {
4809 let start = self.format_byte_range().end;
4810 start..start + i16::RAW_BYTE_LEN
4811 }
4812
4813 pub fn var_index_byte_range(&self) -> Range<usize> {
4814 let start = self.default_value_byte_range().end;
4815 start..start + u32::RAW_BYTE_LEN
4816 }
4817}
4818
4819impl MinByteRange for ConditionFormat2Marker {
4820 fn min_byte_range(&self) -> Range<usize> {
4821 0..self.var_index_byte_range().end
4822 }
4823}
4824
4825impl<'a> FontRead<'a> for ConditionFormat2<'a> {
4826 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
4827 let mut cursor = data.cursor();
4828 cursor.advance::<u16>();
4829 cursor.advance::<i16>();
4830 cursor.advance::<u32>();
4831 cursor.finish(ConditionFormat2Marker {})
4832 }
4833}
4834
4835pub type ConditionFormat2<'a> = TableRef<'a, ConditionFormat2Marker>;
4837
4838#[allow(clippy::needless_lifetimes)]
4839impl<'a> ConditionFormat2<'a> {
4840 pub fn format(&self) -> u16 {
4842 let range = self.shape.format_byte_range();
4843 self.data.read_at(range.start).unwrap()
4844 }
4845
4846 pub fn default_value(&self) -> i16 {
4848 let range = self.shape.default_value_byte_range();
4849 self.data.read_at(range.start).unwrap()
4850 }
4851
4852 pub fn var_index(&self) -> u32 {
4854 let range = self.shape.var_index_byte_range();
4855 self.data.read_at(range.start).unwrap()
4856 }
4857}
4858
4859#[cfg(feature = "experimental_traverse")]
4860impl<'a> SomeTable<'a> for ConditionFormat2<'a> {
4861 fn type_name(&self) -> &str {
4862 "ConditionFormat2"
4863 }
4864 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4865 match idx {
4866 0usize => Some(Field::new("format", self.format())),
4867 1usize => Some(Field::new("default_value", self.default_value())),
4868 2usize => Some(Field::new("var_index", self.var_index())),
4869 _ => None,
4870 }
4871 }
4872}
4873
4874#[cfg(feature = "experimental_traverse")]
4875#[allow(clippy::needless_lifetimes)]
4876impl<'a> std::fmt::Debug for ConditionFormat2<'a> {
4877 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4878 (self as &dyn SomeTable<'a>).fmt(f)
4879 }
4880}
4881
4882impl Format<u16> for ConditionFormat3Marker {
4883 const FORMAT: u16 = 3;
4884}
4885
4886#[derive(Debug, Clone, Copy)]
4888#[doc(hidden)]
4889pub struct ConditionFormat3Marker {
4890 condition_offsets_byte_len: usize,
4891}
4892
4893impl ConditionFormat3Marker {
4894 pub fn format_byte_range(&self) -> Range<usize> {
4895 let start = 0;
4896 start..start + u16::RAW_BYTE_LEN
4897 }
4898
4899 pub fn condition_count_byte_range(&self) -> Range<usize> {
4900 let start = self.format_byte_range().end;
4901 start..start + u8::RAW_BYTE_LEN
4902 }
4903
4904 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
4905 let start = self.condition_count_byte_range().end;
4906 start..start + self.condition_offsets_byte_len
4907 }
4908}
4909
4910impl MinByteRange for ConditionFormat3Marker {
4911 fn min_byte_range(&self) -> Range<usize> {
4912 0..self.condition_offsets_byte_range().end
4913 }
4914}
4915
4916impl<'a> FontRead<'a> for ConditionFormat3<'a> {
4917 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
4918 let mut cursor = data.cursor();
4919 cursor.advance::<u16>();
4920 let condition_count: u8 = cursor.read()?;
4921 let condition_offsets_byte_len = (condition_count as usize)
4922 .checked_mul(Offset24::RAW_BYTE_LEN)
4923 .ok_or(ReadError::OutOfBounds)?;
4924 cursor.advance_by(condition_offsets_byte_len);
4925 cursor.finish(ConditionFormat3Marker {
4926 condition_offsets_byte_len,
4927 })
4928 }
4929}
4930
4931pub type ConditionFormat3<'a> = TableRef<'a, ConditionFormat3Marker>;
4933
4934#[allow(clippy::needless_lifetimes)]
4935impl<'a> ConditionFormat3<'a> {
4936 pub fn format(&self) -> u16 {
4938 let range = self.shape.format_byte_range();
4939 self.data.read_at(range.start).unwrap()
4940 }
4941
4942 pub fn condition_count(&self) -> u8 {
4944 let range = self.shape.condition_count_byte_range();
4945 self.data.read_at(range.start).unwrap()
4946 }
4947
4948 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
4950 let range = self.shape.condition_offsets_byte_range();
4951 self.data.read_array(range).unwrap()
4952 }
4953
4954 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
4956 let data = self.data;
4957 let offsets = self.condition_offsets();
4958 ArrayOfOffsets::new(offsets, data, ())
4959 }
4960}
4961
4962#[cfg(feature = "experimental_traverse")]
4963impl<'a> SomeTable<'a> for ConditionFormat3<'a> {
4964 fn type_name(&self) -> &str {
4965 "ConditionFormat3"
4966 }
4967 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
4968 match idx {
4969 0usize => Some(Field::new("format", self.format())),
4970 1usize => Some(Field::new("condition_count", self.condition_count())),
4971 2usize => Some({
4972 let data = self.data;
4973 Field::new(
4974 "condition_offsets",
4975 FieldType::array_of_offsets(
4976 better_type_name::<Condition>(),
4977 self.condition_offsets(),
4978 move |off| {
4979 let target = off.get().resolve::<Condition>(data);
4980 FieldType::offset(off.get(), target)
4981 },
4982 ),
4983 )
4984 }),
4985 _ => None,
4986 }
4987 }
4988}
4989
4990#[cfg(feature = "experimental_traverse")]
4991#[allow(clippy::needless_lifetimes)]
4992impl<'a> std::fmt::Debug for ConditionFormat3<'a> {
4993 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4994 (self as &dyn SomeTable<'a>).fmt(f)
4995 }
4996}
4997
4998impl Format<u16> for ConditionFormat4Marker {
4999 const FORMAT: u16 = 4;
5000}
5001
5002#[derive(Debug, Clone, Copy)]
5004#[doc(hidden)]
5005pub struct ConditionFormat4Marker {
5006 condition_offsets_byte_len: usize,
5007}
5008
5009impl ConditionFormat4Marker {
5010 pub fn format_byte_range(&self) -> Range<usize> {
5011 let start = 0;
5012 start..start + u16::RAW_BYTE_LEN
5013 }
5014
5015 pub fn condition_count_byte_range(&self) -> Range<usize> {
5016 let start = self.format_byte_range().end;
5017 start..start + u8::RAW_BYTE_LEN
5018 }
5019
5020 pub fn condition_offsets_byte_range(&self) -> Range<usize> {
5021 let start = self.condition_count_byte_range().end;
5022 start..start + self.condition_offsets_byte_len
5023 }
5024}
5025
5026impl MinByteRange for ConditionFormat4Marker {
5027 fn min_byte_range(&self) -> Range<usize> {
5028 0..self.condition_offsets_byte_range().end
5029 }
5030}
5031
5032impl<'a> FontRead<'a> for ConditionFormat4<'a> {
5033 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
5034 let mut cursor = data.cursor();
5035 cursor.advance::<u16>();
5036 let condition_count: u8 = cursor.read()?;
5037 let condition_offsets_byte_len = (condition_count as usize)
5038 .checked_mul(Offset24::RAW_BYTE_LEN)
5039 .ok_or(ReadError::OutOfBounds)?;
5040 cursor.advance_by(condition_offsets_byte_len);
5041 cursor.finish(ConditionFormat4Marker {
5042 condition_offsets_byte_len,
5043 })
5044 }
5045}
5046
5047pub type ConditionFormat4<'a> = TableRef<'a, ConditionFormat4Marker>;
5049
5050#[allow(clippy::needless_lifetimes)]
5051impl<'a> ConditionFormat4<'a> {
5052 pub fn format(&self) -> u16 {
5054 let range = self.shape.format_byte_range();
5055 self.data.read_at(range.start).unwrap()
5056 }
5057
5058 pub fn condition_count(&self) -> u8 {
5060 let range = self.shape.condition_count_byte_range();
5061 self.data.read_at(range.start).unwrap()
5062 }
5063
5064 pub fn condition_offsets(&self) -> &'a [BigEndian<Offset24>] {
5066 let range = self.shape.condition_offsets_byte_range();
5067 self.data.read_array(range).unwrap()
5068 }
5069
5070 pub fn conditions(&self) -> ArrayOfOffsets<'a, Condition<'a>, Offset24> {
5072 let data = self.data;
5073 let offsets = self.condition_offsets();
5074 ArrayOfOffsets::new(offsets, data, ())
5075 }
5076}
5077
5078#[cfg(feature = "experimental_traverse")]
5079impl<'a> SomeTable<'a> for ConditionFormat4<'a> {
5080 fn type_name(&self) -> &str {
5081 "ConditionFormat4"
5082 }
5083 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5084 match idx {
5085 0usize => Some(Field::new("format", self.format())),
5086 1usize => Some(Field::new("condition_count", self.condition_count())),
5087 2usize => Some({
5088 let data = self.data;
5089 Field::new(
5090 "condition_offsets",
5091 FieldType::array_of_offsets(
5092 better_type_name::<Condition>(),
5093 self.condition_offsets(),
5094 move |off| {
5095 let target = off.get().resolve::<Condition>(data);
5096 FieldType::offset(off.get(), target)
5097 },
5098 ),
5099 )
5100 }),
5101 _ => None,
5102 }
5103 }
5104}
5105
5106#[cfg(feature = "experimental_traverse")]
5107#[allow(clippy::needless_lifetimes)]
5108impl<'a> std::fmt::Debug for ConditionFormat4<'a> {
5109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5110 (self as &dyn SomeTable<'a>).fmt(f)
5111 }
5112}
5113
5114impl Format<u16> for ConditionFormat5Marker {
5115 const FORMAT: u16 = 5;
5116}
5117
5118#[derive(Debug, Clone, Copy)]
5120#[doc(hidden)]
5121pub struct ConditionFormat5Marker {}
5122
5123impl ConditionFormat5Marker {
5124 pub fn format_byte_range(&self) -> Range<usize> {
5125 let start = 0;
5126 start..start + u16::RAW_BYTE_LEN
5127 }
5128
5129 pub fn condition_offset_byte_range(&self) -> Range<usize> {
5130 let start = self.format_byte_range().end;
5131 start..start + Offset24::RAW_BYTE_LEN
5132 }
5133}
5134
5135impl MinByteRange for ConditionFormat5Marker {
5136 fn min_byte_range(&self) -> Range<usize> {
5137 0..self.condition_offset_byte_range().end
5138 }
5139}
5140
5141impl<'a> FontRead<'a> for ConditionFormat5<'a> {
5142 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
5143 let mut cursor = data.cursor();
5144 cursor.advance::<u16>();
5145 cursor.advance::<Offset24>();
5146 cursor.finish(ConditionFormat5Marker {})
5147 }
5148}
5149
5150pub type ConditionFormat5<'a> = TableRef<'a, ConditionFormat5Marker>;
5152
5153#[allow(clippy::needless_lifetimes)]
5154impl<'a> ConditionFormat5<'a> {
5155 pub fn format(&self) -> u16 {
5157 let range = self.shape.format_byte_range();
5158 self.data.read_at(range.start).unwrap()
5159 }
5160
5161 pub fn condition_offset(&self) -> Offset24 {
5163 let range = self.shape.condition_offset_byte_range();
5164 self.data.read_at(range.start).unwrap()
5165 }
5166
5167 pub fn condition(&self) -> Result<Condition<'a>, ReadError> {
5169 let data = self.data;
5170 self.condition_offset().resolve(data)
5171 }
5172}
5173
5174#[cfg(feature = "experimental_traverse")]
5175impl<'a> SomeTable<'a> for ConditionFormat5<'a> {
5176 fn type_name(&self) -> &str {
5177 "ConditionFormat5"
5178 }
5179 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5180 match idx {
5181 0usize => Some(Field::new("format", self.format())),
5182 1usize => Some(Field::new(
5183 "condition_offset",
5184 FieldType::offset(self.condition_offset(), self.condition()),
5185 )),
5186 _ => None,
5187 }
5188 }
5189}
5190
5191#[cfg(feature = "experimental_traverse")]
5192#[allow(clippy::needless_lifetimes)]
5193impl<'a> std::fmt::Debug for ConditionFormat5<'a> {
5194 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5195 (self as &dyn SomeTable<'a>).fmt(f)
5196 }
5197}
5198
5199#[derive(Debug, Clone, Copy)]
5201#[doc(hidden)]
5202pub struct FeatureTableSubstitutionMarker {
5203 substitutions_byte_len: usize,
5204}
5205
5206impl FeatureTableSubstitutionMarker {
5207 pub fn version_byte_range(&self) -> Range<usize> {
5208 let start = 0;
5209 start..start + MajorMinor::RAW_BYTE_LEN
5210 }
5211
5212 pub fn substitution_count_byte_range(&self) -> Range<usize> {
5213 let start = self.version_byte_range().end;
5214 start..start + u16::RAW_BYTE_LEN
5215 }
5216
5217 pub fn substitutions_byte_range(&self) -> Range<usize> {
5218 let start = self.substitution_count_byte_range().end;
5219 start..start + self.substitutions_byte_len
5220 }
5221}
5222
5223impl MinByteRange for FeatureTableSubstitutionMarker {
5224 fn min_byte_range(&self) -> Range<usize> {
5225 0..self.substitutions_byte_range().end
5226 }
5227}
5228
5229impl<'a> FontRead<'a> for FeatureTableSubstitution<'a> {
5230 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
5231 let mut cursor = data.cursor();
5232 cursor.advance::<MajorMinor>();
5233 let substitution_count: u16 = cursor.read()?;
5234 let substitutions_byte_len = (substitution_count as usize)
5235 .checked_mul(FeatureTableSubstitutionRecord::RAW_BYTE_LEN)
5236 .ok_or(ReadError::OutOfBounds)?;
5237 cursor.advance_by(substitutions_byte_len);
5238 cursor.finish(FeatureTableSubstitutionMarker {
5239 substitutions_byte_len,
5240 })
5241 }
5242}
5243
5244pub type FeatureTableSubstitution<'a> = TableRef<'a, FeatureTableSubstitutionMarker>;
5246
5247#[allow(clippy::needless_lifetimes)]
5248impl<'a> FeatureTableSubstitution<'a> {
5249 pub fn version(&self) -> MajorMinor {
5251 let range = self.shape.version_byte_range();
5252 self.data.read_at(range.start).unwrap()
5253 }
5254
5255 pub fn substitution_count(&self) -> u16 {
5257 let range = self.shape.substitution_count_byte_range();
5258 self.data.read_at(range.start).unwrap()
5259 }
5260
5261 pub fn substitutions(&self) -> &'a [FeatureTableSubstitutionRecord] {
5263 let range = self.shape.substitutions_byte_range();
5264 self.data.read_array(range).unwrap()
5265 }
5266}
5267
5268#[cfg(feature = "experimental_traverse")]
5269impl<'a> SomeTable<'a> for FeatureTableSubstitution<'a> {
5270 fn type_name(&self) -> &str {
5271 "FeatureTableSubstitution"
5272 }
5273 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5274 match idx {
5275 0usize => Some(Field::new("version", self.version())),
5276 1usize => Some(Field::new("substitution_count", self.substitution_count())),
5277 2usize => Some(Field::new(
5278 "substitutions",
5279 traversal::FieldType::array_of_records(
5280 stringify!(FeatureTableSubstitutionRecord),
5281 self.substitutions(),
5282 self.offset_data(),
5283 ),
5284 )),
5285 _ => None,
5286 }
5287 }
5288}
5289
5290#[cfg(feature = "experimental_traverse")]
5291#[allow(clippy::needless_lifetimes)]
5292impl<'a> std::fmt::Debug for FeatureTableSubstitution<'a> {
5293 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5294 (self as &dyn SomeTable<'a>).fmt(f)
5295 }
5296}
5297
5298#[derive(Clone, Debug, Copy, bytemuck :: AnyBitPattern)]
5300#[repr(C)]
5301#[repr(packed)]
5302pub struct FeatureTableSubstitutionRecord {
5303 pub feature_index: BigEndian<u16>,
5305 pub alternate_feature_offset: BigEndian<Offset32>,
5308}
5309
5310impl FeatureTableSubstitutionRecord {
5311 pub fn feature_index(&self) -> u16 {
5313 self.feature_index.get()
5314 }
5315
5316 pub fn alternate_feature_offset(&self) -> Offset32 {
5319 self.alternate_feature_offset.get()
5320 }
5321}
5322
5323impl FixedSize for FeatureTableSubstitutionRecord {
5324 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN;
5325}
5326
5327#[cfg(feature = "experimental_traverse")]
5328impl<'a> SomeRecord<'a> for FeatureTableSubstitutionRecord {
5329 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
5330 RecordResolver {
5331 name: "FeatureTableSubstitutionRecord",
5332 get_field: Box::new(move |idx, _data| match idx {
5333 0usize => Some(Field::new("feature_index", self.feature_index())),
5334 1usize => Some(Field::new(
5335 "alternate_feature_offset",
5336 FieldType::offset(
5337 self.alternate_feature_offset(),
5338 self.alternate_feature(_data),
5339 ),
5340 )),
5341 _ => None,
5342 }),
5343 data,
5344 }
5345 }
5346}
5347
5348#[derive(Debug, Clone, Copy)]
5349#[doc(hidden)]
5350pub struct SizeParamsMarker {}
5351
5352impl SizeParamsMarker {
5353 pub fn design_size_byte_range(&self) -> Range<usize> {
5354 let start = 0;
5355 start..start + u16::RAW_BYTE_LEN
5356 }
5357
5358 pub fn identifier_byte_range(&self) -> Range<usize> {
5359 let start = self.design_size_byte_range().end;
5360 start..start + u16::RAW_BYTE_LEN
5361 }
5362
5363 pub fn name_entry_byte_range(&self) -> Range<usize> {
5364 let start = self.identifier_byte_range().end;
5365 start..start + u16::RAW_BYTE_LEN
5366 }
5367
5368 pub fn range_start_byte_range(&self) -> Range<usize> {
5369 let start = self.name_entry_byte_range().end;
5370 start..start + u16::RAW_BYTE_LEN
5371 }
5372
5373 pub fn range_end_byte_range(&self) -> Range<usize> {
5374 let start = self.range_start_byte_range().end;
5375 start..start + u16::RAW_BYTE_LEN
5376 }
5377}
5378
5379impl MinByteRange for SizeParamsMarker {
5380 fn min_byte_range(&self) -> Range<usize> {
5381 0..self.range_end_byte_range().end
5382 }
5383}
5384
5385impl<'a> FontRead<'a> for SizeParams<'a> {
5386 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
5387 let mut cursor = data.cursor();
5388 cursor.advance::<u16>();
5389 cursor.advance::<u16>();
5390 cursor.advance::<u16>();
5391 cursor.advance::<u16>();
5392 cursor.advance::<u16>();
5393 cursor.finish(SizeParamsMarker {})
5394 }
5395}
5396
5397pub type SizeParams<'a> = TableRef<'a, SizeParamsMarker>;
5398
5399#[allow(clippy::needless_lifetimes)]
5400impl<'a> SizeParams<'a> {
5401 pub fn design_size(&self) -> u16 {
5406 let range = self.shape.design_size_byte_range();
5407 self.data.read_at(range.start).unwrap()
5408 }
5409
5410 pub fn identifier(&self) -> u16 {
5417 let range = self.shape.identifier_byte_range();
5418 self.data.read_at(range.start).unwrap()
5419 }
5420
5421 pub fn name_entry(&self) -> u16 {
5432 let range = self.shape.name_entry_byte_range();
5433 self.data.read_at(range.start).unwrap()
5434 }
5435
5436 pub fn range_start(&self) -> u16 {
5442 let range = self.shape.range_start_byte_range();
5443 self.data.read_at(range.start).unwrap()
5444 }
5445
5446 pub fn range_end(&self) -> u16 {
5447 let range = self.shape.range_end_byte_range();
5448 self.data.read_at(range.start).unwrap()
5449 }
5450}
5451
5452#[cfg(feature = "experimental_traverse")]
5453impl<'a> SomeTable<'a> for SizeParams<'a> {
5454 fn type_name(&self) -> &str {
5455 "SizeParams"
5456 }
5457 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5458 match idx {
5459 0usize => Some(Field::new("design_size", self.design_size())),
5460 1usize => Some(Field::new("identifier", self.identifier())),
5461 2usize => Some(Field::new("name_entry", self.name_entry())),
5462 3usize => Some(Field::new("range_start", self.range_start())),
5463 4usize => Some(Field::new("range_end", self.range_end())),
5464 _ => None,
5465 }
5466 }
5467}
5468
5469#[cfg(feature = "experimental_traverse")]
5470#[allow(clippy::needless_lifetimes)]
5471impl<'a> std::fmt::Debug for SizeParams<'a> {
5472 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5473 (self as &dyn SomeTable<'a>).fmt(f)
5474 }
5475}
5476
5477#[derive(Debug, Clone, Copy)]
5478#[doc(hidden)]
5479pub struct StylisticSetParamsMarker {}
5480
5481impl StylisticSetParamsMarker {
5482 pub fn version_byte_range(&self) -> Range<usize> {
5483 let start = 0;
5484 start..start + u16::RAW_BYTE_LEN
5485 }
5486
5487 pub fn ui_name_id_byte_range(&self) -> Range<usize> {
5488 let start = self.version_byte_range().end;
5489 start..start + NameId::RAW_BYTE_LEN
5490 }
5491}
5492
5493impl MinByteRange for StylisticSetParamsMarker {
5494 fn min_byte_range(&self) -> Range<usize> {
5495 0..self.ui_name_id_byte_range().end
5496 }
5497}
5498
5499impl<'a> FontRead<'a> for StylisticSetParams<'a> {
5500 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
5501 let mut cursor = data.cursor();
5502 cursor.advance::<u16>();
5503 cursor.advance::<NameId>();
5504 cursor.finish(StylisticSetParamsMarker {})
5505 }
5506}
5507
5508pub type StylisticSetParams<'a> = TableRef<'a, StylisticSetParamsMarker>;
5509
5510#[allow(clippy::needless_lifetimes)]
5511impl<'a> StylisticSetParams<'a> {
5512 pub fn version(&self) -> u16 {
5513 let range = self.shape.version_byte_range();
5514 self.data.read_at(range.start).unwrap()
5515 }
5516
5517 pub fn ui_name_id(&self) -> NameId {
5527 let range = self.shape.ui_name_id_byte_range();
5528 self.data.read_at(range.start).unwrap()
5529 }
5530}
5531
5532#[cfg(feature = "experimental_traverse")]
5533impl<'a> SomeTable<'a> for StylisticSetParams<'a> {
5534 fn type_name(&self) -> &str {
5535 "StylisticSetParams"
5536 }
5537 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5538 match idx {
5539 0usize => Some(Field::new("version", self.version())),
5540 1usize => Some(Field::new("ui_name_id", self.ui_name_id())),
5541 _ => None,
5542 }
5543 }
5544}
5545
5546#[cfg(feature = "experimental_traverse")]
5547#[allow(clippy::needless_lifetimes)]
5548impl<'a> std::fmt::Debug for StylisticSetParams<'a> {
5549 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5550 (self as &dyn SomeTable<'a>).fmt(f)
5551 }
5552}
5553
5554impl Format<u16> for CharacterVariantParamsMarker {
5555 const FORMAT: u16 = 0;
5556}
5557
5558#[derive(Debug, Clone, Copy)]
5560#[doc(hidden)]
5561pub struct CharacterVariantParamsMarker {
5562 character_byte_len: usize,
5563}
5564
5565impl CharacterVariantParamsMarker {
5566 pub fn format_byte_range(&self) -> Range<usize> {
5567 let start = 0;
5568 start..start + u16::RAW_BYTE_LEN
5569 }
5570
5571 pub fn feat_ui_label_name_id_byte_range(&self) -> Range<usize> {
5572 let start = self.format_byte_range().end;
5573 start..start + NameId::RAW_BYTE_LEN
5574 }
5575
5576 pub fn feat_ui_tooltip_text_name_id_byte_range(&self) -> Range<usize> {
5577 let start = self.feat_ui_label_name_id_byte_range().end;
5578 start..start + NameId::RAW_BYTE_LEN
5579 }
5580
5581 pub fn sample_text_name_id_byte_range(&self) -> Range<usize> {
5582 let start = self.feat_ui_tooltip_text_name_id_byte_range().end;
5583 start..start + NameId::RAW_BYTE_LEN
5584 }
5585
5586 pub fn num_named_parameters_byte_range(&self) -> Range<usize> {
5587 let start = self.sample_text_name_id_byte_range().end;
5588 start..start + u16::RAW_BYTE_LEN
5589 }
5590
5591 pub fn first_param_ui_label_name_id_byte_range(&self) -> Range<usize> {
5592 let start = self.num_named_parameters_byte_range().end;
5593 start..start + NameId::RAW_BYTE_LEN
5594 }
5595
5596 pub fn char_count_byte_range(&self) -> Range<usize> {
5597 let start = self.first_param_ui_label_name_id_byte_range().end;
5598 start..start + u16::RAW_BYTE_LEN
5599 }
5600
5601 pub fn character_byte_range(&self) -> Range<usize> {
5602 let start = self.char_count_byte_range().end;
5603 start..start + self.character_byte_len
5604 }
5605}
5606
5607impl MinByteRange for CharacterVariantParamsMarker {
5608 fn min_byte_range(&self) -> Range<usize> {
5609 0..self.character_byte_range().end
5610 }
5611}
5612
5613impl<'a> FontRead<'a> for CharacterVariantParams<'a> {
5614 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
5615 let mut cursor = data.cursor();
5616 cursor.advance::<u16>();
5617 cursor.advance::<NameId>();
5618 cursor.advance::<NameId>();
5619 cursor.advance::<NameId>();
5620 cursor.advance::<u16>();
5621 cursor.advance::<NameId>();
5622 let char_count: u16 = cursor.read()?;
5623 let character_byte_len = (char_count as usize)
5624 .checked_mul(Uint24::RAW_BYTE_LEN)
5625 .ok_or(ReadError::OutOfBounds)?;
5626 cursor.advance_by(character_byte_len);
5627 cursor.finish(CharacterVariantParamsMarker { character_byte_len })
5628 }
5629}
5630
5631pub type CharacterVariantParams<'a> = TableRef<'a, CharacterVariantParamsMarker>;
5633
5634#[allow(clippy::needless_lifetimes)]
5635impl<'a> CharacterVariantParams<'a> {
5636 pub fn format(&self) -> u16 {
5638 let range = self.shape.format_byte_range();
5639 self.data.read_at(range.start).unwrap()
5640 }
5641
5642 pub fn feat_ui_label_name_id(&self) -> NameId {
5646 let range = self.shape.feat_ui_label_name_id_byte_range();
5647 self.data.read_at(range.start).unwrap()
5648 }
5649
5650 pub fn feat_ui_tooltip_text_name_id(&self) -> NameId {
5654 let range = self.shape.feat_ui_tooltip_text_name_id_byte_range();
5655 self.data.read_at(range.start).unwrap()
5656 }
5657
5658 pub fn sample_text_name_id(&self) -> NameId {
5661 let range = self.shape.sample_text_name_id_byte_range();
5662 self.data.read_at(range.start).unwrap()
5663 }
5664
5665 pub fn num_named_parameters(&self) -> u16 {
5667 let range = self.shape.num_named_parameters_byte_range();
5668 self.data.read_at(range.start).unwrap()
5669 }
5670
5671 pub fn first_param_ui_label_name_id(&self) -> NameId {
5675 let range = self.shape.first_param_ui_label_name_id_byte_range();
5676 self.data.read_at(range.start).unwrap()
5677 }
5678
5679 pub fn char_count(&self) -> u16 {
5682 let range = self.shape.char_count_byte_range();
5683 self.data.read_at(range.start).unwrap()
5684 }
5685
5686 pub fn character(&self) -> &'a [BigEndian<Uint24>] {
5689 let range = self.shape.character_byte_range();
5690 self.data.read_array(range).unwrap()
5691 }
5692}
5693
5694#[cfg(feature = "experimental_traverse")]
5695impl<'a> SomeTable<'a> for CharacterVariantParams<'a> {
5696 fn type_name(&self) -> &str {
5697 "CharacterVariantParams"
5698 }
5699 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
5700 match idx {
5701 0usize => Some(Field::new("format", self.format())),
5702 1usize => Some(Field::new(
5703 "feat_ui_label_name_id",
5704 self.feat_ui_label_name_id(),
5705 )),
5706 2usize => Some(Field::new(
5707 "feat_ui_tooltip_text_name_id",
5708 self.feat_ui_tooltip_text_name_id(),
5709 )),
5710 3usize => Some(Field::new(
5711 "sample_text_name_id",
5712 self.sample_text_name_id(),
5713 )),
5714 4usize => Some(Field::new(
5715 "num_named_parameters",
5716 self.num_named_parameters(),
5717 )),
5718 5usize => Some(Field::new(
5719 "first_param_ui_label_name_id",
5720 self.first_param_ui_label_name_id(),
5721 )),
5722 6usize => Some(Field::new("char_count", self.char_count())),
5723 7usize => Some(Field::new("character", self.character())),
5724 _ => None,
5725 }
5726 }
5727}
5728
5729#[cfg(feature = "experimental_traverse")]
5730#[allow(clippy::needless_lifetimes)]
5731impl<'a> std::fmt::Debug for CharacterVariantParams<'a> {
5732 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5733 (self as &dyn SomeTable<'a>).fmt(f)
5734 }
5735}