1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for Gsub<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.lookup_list_offset_byte_range().end
11 }
12 fn min_table_bytes(&self) -> &'a [u8] {
13 let range = self.min_byte_range();
14 self.data.as_bytes().get(range).unwrap_or_default()
15 }
16}
17
18impl TopLevelTable for Gsub<'_> {
19 const TAG: Tag = Tag::new(b"GSUB");
21}
22
23impl ReadArgs for Gsub<'_> {
24 type Args = ();
25}
26
27impl<'a> FontRead<'a> for Gsub<'a> {
28 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
29 #[allow(clippy::absurd_extreme_comparisons)]
30 if data.len() < Self::MIN_SIZE {
31 return Err(ReadError::OutOfBounds);
32 }
33 Ok(Self { data })
34 }
35}
36
37#[derive(Clone)]
39pub struct Gsub<'a> {
40 data: FontData<'a>,
41}
42
43#[allow(clippy::needless_lifetimes)]
44impl<'a> Gsub<'a> {
45 pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
46 + Offset16::RAW_BYTE_LEN
47 + Offset16::RAW_BYTE_LEN
48 + Offset16::RAW_BYTE_LEN);
49 basic_table_impls!(impl_the_methods);
50
51 pub fn version(&self) -> MajorMinor {
53 let range = self.version_byte_range();
54 self.data.read_at(range.start).ok().unwrap()
55 }
56
57 pub fn script_list_offset(&self) -> Offset16 {
59 let range = self.script_list_offset_byte_range();
60 self.data.read_at(range.start).ok().unwrap()
61 }
62
63 pub fn script_list(&self) -> Result<ScriptList<'a>, ReadError> {
65 let data = self.data;
66 self.script_list_offset().resolve(data)
67 }
68
69 pub fn feature_list_offset(&self) -> Offset16 {
71 let range = self.feature_list_offset_byte_range();
72 self.data.read_at(range.start).ok().unwrap()
73 }
74
75 pub fn feature_list(&self) -> Result<FeatureList<'a>, ReadError> {
77 let data = self.data;
78 self.feature_list_offset().resolve(data)
79 }
80
81 pub fn lookup_list_offset(&self) -> Offset16 {
83 let range = self.lookup_list_offset_byte_range();
84 self.data.read_at(range.start).ok().unwrap()
85 }
86
87 pub fn lookup_list(&self) -> Result<SubstitutionLookupList<'a>, ReadError> {
89 let data = self.data;
90 self.lookup_list_offset().resolve(data)
91 }
92
93 pub fn feature_variations_offset(&self) -> Option<Nullable<Offset32>> {
96 let range = self.feature_variations_offset_byte_range();
97 (!range.is_empty())
98 .then(|| self.data.read_at(range.start).ok())
99 .flatten()
100 }
101
102 pub fn feature_variations(&self) -> Option<Result<FeatureVariations<'a>, ReadError>> {
104 let data = self.data;
105 self.feature_variations_offset().map(|x| x.resolve(data))?
106 }
107
108 pub fn version_byte_range(&self) -> Range<usize> {
109 let start = 0;
110 let end = start + MajorMinor::RAW_BYTE_LEN;
111 start..end
112 }
113
114 pub fn script_list_offset_byte_range(&self) -> Range<usize> {
115 let start = self.version_byte_range().end;
116 let end = start + Offset16::RAW_BYTE_LEN;
117 start..end
118 }
119
120 pub fn feature_list_offset_byte_range(&self) -> Range<usize> {
121 let start = self.script_list_offset_byte_range().end;
122 let end = start + Offset16::RAW_BYTE_LEN;
123 start..end
124 }
125
126 pub fn lookup_list_offset_byte_range(&self) -> Range<usize> {
127 let start = self.feature_list_offset_byte_range().end;
128 let end = start + Offset16::RAW_BYTE_LEN;
129 start..end
130 }
131
132 pub fn feature_variations_offset_byte_range(&self) -> Range<usize> {
133 let start = self.lookup_list_offset_byte_range().end;
134 let end = if self.version().compatible((1u16, 1u16)) {
135 start + Offset32::RAW_BYTE_LEN
136 } else {
137 start
138 };
139 start..end
140 }
141}
142
143const _: () = assert!(FontData::default_data_long_enough(Gsub::MIN_SIZE));
144
145impl Default for Gsub<'_> {
146 fn default() -> Self {
147 Self {
148 data: FontData::default_table_data(),
149 }
150 }
151}
152
153pub enum SubstitutionLookup<'a> {
155 Single(Lookup<'a, SingleSubst<'a>>),
156 Multiple(Lookup<'a, MultipleSubstFormat1<'a>>),
157 Alternate(Lookup<'a, AlternateSubstFormat1<'a>>),
158 Ligature(Lookup<'a, LigatureSubstFormat1<'a>>),
159 Contextual(Lookup<'a, SubstitutionSequenceContext<'a>>),
160 ChainContextual(Lookup<'a, SubstitutionChainContext<'a>>),
161 Extension(Lookup<'a, ExtensionSubtable<'a>>),
162 Reverse(Lookup<'a, ReverseChainSingleSubstFormat1<'a>>),
163}
164
165impl Default for SubstitutionLookup<'_> {
166 fn default() -> Self {
167 Self::Single(Default::default())
168 }
169}
170
171impl ReadArgs for SubstitutionLookup<'_> {
172 type Args = ();
173}
174
175impl<'a> FontRead<'a> for SubstitutionLookup<'a> {
176 fn read_with_args(bytes: FontData<'a>, _: ()) -> Result<Self, ReadError> {
177 let discriminant = Lookup::read_discriminant(bytes)?;
178 match discriminant {
179 1 => Ok(SubstitutionLookup::Single(FontRead::read(bytes)?)),
180 2 => Ok(SubstitutionLookup::Multiple(FontRead::read(bytes)?)),
181 3 => Ok(SubstitutionLookup::Alternate(FontRead::read(bytes)?)),
182 4 => Ok(SubstitutionLookup::Ligature(FontRead::read(bytes)?)),
183 5 => Ok(SubstitutionLookup::Contextual(FontRead::read(bytes)?)),
184 6 => Ok(SubstitutionLookup::ChainContextual(FontRead::read(bytes)?)),
185 7 => Ok(SubstitutionLookup::Extension(FontRead::read(bytes)?)),
186 8 => Ok(SubstitutionLookup::Reverse(FontRead::read(bytes)?)),
187 other => Err(ReadError::InvalidFormat(other.into())),
188 }
189 }
190}
191
192impl<'a> SubstitutionLookup<'a> {
193 #[allow(dead_code)]
194 pub(crate) fn of_unit_type(&self) -> Lookup<'a, ()> {
198 match self {
199 SubstitutionLookup::Single(inner) => inner.of_unit_type(),
200 SubstitutionLookup::Multiple(inner) => inner.of_unit_type(),
201 SubstitutionLookup::Alternate(inner) => inner.of_unit_type(),
202 SubstitutionLookup::Ligature(inner) => inner.of_unit_type(),
203 SubstitutionLookup::Contextual(inner) => inner.of_unit_type(),
204 SubstitutionLookup::ChainContextual(inner) => inner.of_unit_type(),
205 SubstitutionLookup::Extension(inner) => inner.of_unit_type(),
206 SubstitutionLookup::Reverse(inner) => inner.of_unit_type(),
207 }
208 }
209}
210
211#[derive(Clone)]
213pub enum SingleSubst<'a> {
214 Format1(SingleSubstFormat1<'a>),
215 Format2(SingleSubstFormat2<'a>),
216}
217
218impl Default for SingleSubst<'_> {
219 fn default() -> Self {
220 Self::Format1(Default::default())
221 }
222}
223
224impl<'a> SingleSubst<'a> {
225 pub fn offset_data(&self) -> FontData<'a> {
227 match self {
228 Self::Format1(item) => item.offset_data(),
229 Self::Format2(item) => item.offset_data(),
230 }
231 }
232
233 pub fn subst_format(&self) -> u16 {
235 match self {
236 Self::Format1(item) => item.subst_format(),
237 Self::Format2(item) => item.subst_format(),
238 }
239 }
240
241 pub fn coverage_offset(&self) -> Offset16 {
244 match self {
245 Self::Format1(item) => item.coverage_offset(),
246 Self::Format2(item) => item.coverage_offset(),
247 }
248 }
249}
250
251impl ReadArgs for SingleSubst<'_> {
252 type Args = ();
253}
254
255impl<'a> FontRead<'a> for SingleSubst<'a> {
256 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
257 let format: u16 = data.read_at(0usize)?;
258 match format {
259 SingleSubstFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
260 SingleSubstFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
261 other => Err(ReadError::InvalidFormat(other.into())),
262 }
263 }
264}
265
266impl<'a> MinByteRange<'a> for SingleSubst<'a> {
267 fn min_byte_range(&self) -> Range<usize> {
268 match self {
269 Self::Format1(item) => item.min_byte_range(),
270 Self::Format2(item) => item.min_byte_range(),
271 }
272 }
273 fn min_table_bytes(&self) -> &'a [u8] {
274 match self {
275 Self::Format1(item) => item.min_table_bytes(),
276 Self::Format2(item) => item.min_table_bytes(),
277 }
278 }
279}
280
281impl Format<u16> for SingleSubstFormat1<'_> {
282 const FORMAT: u16 = 1;
283}
284
285impl<'a> MinByteRange<'a> for SingleSubstFormat1<'a> {
286 fn min_byte_range(&self) -> Range<usize> {
287 0..self.delta_glyph_id_byte_range().end
288 }
289 fn min_table_bytes(&self) -> &'a [u8] {
290 let range = self.min_byte_range();
291 self.data.as_bytes().get(range).unwrap_or_default()
292 }
293}
294
295impl ReadArgs for SingleSubstFormat1<'_> {
296 type Args = ();
297}
298
299impl<'a> FontRead<'a> for SingleSubstFormat1<'a> {
300 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
301 #[allow(clippy::absurd_extreme_comparisons)]
302 if data.len() < Self::MIN_SIZE {
303 return Err(ReadError::OutOfBounds);
304 }
305 Ok(Self { data })
306 }
307}
308
309#[derive(Clone)]
311pub struct SingleSubstFormat1<'a> {
312 data: FontData<'a>,
313}
314
315#[allow(clippy::needless_lifetimes)]
316impl<'a> SingleSubstFormat1<'a> {
317 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN);
318 basic_table_impls!(impl_the_methods);
319
320 pub fn subst_format(&self) -> u16 {
322 let range = self.subst_format_byte_range();
323 self.data.read_at(range.start).ok().unwrap()
324 }
325
326 pub fn coverage_offset(&self) -> Offset16 {
329 let range = self.coverage_offset_byte_range();
330 self.data.read_at(range.start).ok().unwrap()
331 }
332
333 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
335 let data = self.data;
336 self.coverage_offset().resolve(data)
337 }
338
339 pub fn delta_glyph_id(&self) -> i16 {
341 let range = self.delta_glyph_id_byte_range();
342 self.data.read_at(range.start).ok().unwrap()
343 }
344
345 pub fn subst_format_byte_range(&self) -> Range<usize> {
346 let start = 0;
347 let end = start + u16::RAW_BYTE_LEN;
348 start..end
349 }
350
351 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
352 let start = self.subst_format_byte_range().end;
353 let end = start + Offset16::RAW_BYTE_LEN;
354 start..end
355 }
356
357 pub fn delta_glyph_id_byte_range(&self) -> Range<usize> {
358 let start = self.coverage_offset_byte_range().end;
359 let end = start + i16::RAW_BYTE_LEN;
360 start..end
361 }
362}
363
364const _: () = assert!(FontData::default_data_long_enough(
365 SingleSubstFormat1::MIN_SIZE
366));
367
368impl Default for SingleSubstFormat1<'_> {
369 fn default() -> Self {
370 Self {
371 data: FontData::default_format_1_u16_table_data(),
372 }
373 }
374}
375
376impl Format<u16> for SingleSubstFormat2<'_> {
377 const FORMAT: u16 = 2;
378}
379
380impl<'a> MinByteRange<'a> for SingleSubstFormat2<'a> {
381 fn min_byte_range(&self) -> Range<usize> {
382 0..self.substitute_glyph_ids_byte_range().end
383 }
384 fn min_table_bytes(&self) -> &'a [u8] {
385 let range = self.min_byte_range();
386 self.data.as_bytes().get(range).unwrap_or_default()
387 }
388}
389
390impl ReadArgs for SingleSubstFormat2<'_> {
391 type Args = ();
392}
393
394impl<'a> FontRead<'a> for SingleSubstFormat2<'a> {
395 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
396 #[allow(clippy::absurd_extreme_comparisons)]
397 if data.len() < Self::MIN_SIZE {
398 return Err(ReadError::OutOfBounds);
399 }
400 Ok(Self { data })
401 }
402}
403
404#[derive(Clone)]
406pub struct SingleSubstFormat2<'a> {
407 data: FontData<'a>,
408}
409
410#[allow(clippy::needless_lifetimes)]
411impl<'a> SingleSubstFormat2<'a> {
412 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
413 basic_table_impls!(impl_the_methods);
414
415 pub fn subst_format(&self) -> u16 {
417 let range = self.subst_format_byte_range();
418 self.data.read_at(range.start).ok().unwrap()
419 }
420
421 pub fn coverage_offset(&self) -> Offset16 {
424 let range = self.coverage_offset_byte_range();
425 self.data.read_at(range.start).ok().unwrap()
426 }
427
428 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
430 let data = self.data;
431 self.coverage_offset().resolve(data)
432 }
433
434 pub fn glyph_count(&self) -> u16 {
436 let range = self.glyph_count_byte_range();
437 self.data.read_at(range.start).ok().unwrap()
438 }
439
440 pub fn substitute_glyph_ids(&self) -> &'a [BigEndian<GlyphId16>] {
442 let range = self.substitute_glyph_ids_byte_range();
443 self.data.read_array(range).ok().unwrap_or_default()
444 }
445
446 pub fn subst_format_byte_range(&self) -> Range<usize> {
447 let start = 0;
448 let end = start + u16::RAW_BYTE_LEN;
449 start..end
450 }
451
452 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
453 let start = self.subst_format_byte_range().end;
454 let end = start + Offset16::RAW_BYTE_LEN;
455 start..end
456 }
457
458 pub fn glyph_count_byte_range(&self) -> Range<usize> {
459 let start = self.coverage_offset_byte_range().end;
460 let end = start + u16::RAW_BYTE_LEN;
461 start..end
462 }
463
464 pub fn substitute_glyph_ids_byte_range(&self) -> Range<usize> {
465 let glyph_count = self.glyph_count();
466 let start = self.glyph_count_byte_range().end;
467 let end =
468 start + (transforms::to_usize(glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
469 start..end
470 }
471}
472
473impl Format<u16> for MultipleSubstFormat1<'_> {
474 const FORMAT: u16 = 1;
475}
476
477impl<'a> MinByteRange<'a> for MultipleSubstFormat1<'a> {
478 fn min_byte_range(&self) -> Range<usize> {
479 0..self.sequence_offsets_byte_range().end
480 }
481 fn min_table_bytes(&self) -> &'a [u8] {
482 let range = self.min_byte_range();
483 self.data.as_bytes().get(range).unwrap_or_default()
484 }
485}
486
487impl ReadArgs for MultipleSubstFormat1<'_> {
488 type Args = ();
489}
490
491impl<'a> FontRead<'a> for MultipleSubstFormat1<'a> {
492 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
493 #[allow(clippy::absurd_extreme_comparisons)]
494 if data.len() < Self::MIN_SIZE {
495 return Err(ReadError::OutOfBounds);
496 }
497 Ok(Self { data })
498 }
499}
500
501#[derive(Clone)]
503pub struct MultipleSubstFormat1<'a> {
504 data: FontData<'a>,
505}
506
507#[allow(clippy::needless_lifetimes)]
508impl<'a> MultipleSubstFormat1<'a> {
509 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
510 basic_table_impls!(impl_the_methods);
511
512 pub fn subst_format(&self) -> u16 {
514 let range = self.subst_format_byte_range();
515 self.data.read_at(range.start).ok().unwrap()
516 }
517
518 pub fn coverage_offset(&self) -> Offset16 {
521 let range = self.coverage_offset_byte_range();
522 self.data.read_at(range.start).ok().unwrap()
523 }
524
525 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
527 let data = self.data;
528 self.coverage_offset().resolve(data)
529 }
530
531 pub fn sequence_count(&self) -> u16 {
533 let range = self.sequence_count_byte_range();
534 self.data.read_at(range.start).ok().unwrap()
535 }
536
537 pub fn sequence_offsets(&self) -> &'a [BigEndian<Offset16>] {
540 let range = self.sequence_offsets_byte_range();
541 self.data.read_array(range).ok().unwrap_or_default()
542 }
543
544 pub fn sequences(&self) -> ArrayOfOffsets<'a, Sequence<'a>, Offset16> {
546 let data = self.data;
547 let offsets = self.sequence_offsets();
548 ArrayOfOffsets::new(offsets, data, ())
549 }
550
551 pub fn subst_format_byte_range(&self) -> Range<usize> {
552 let start = 0;
553 let end = start + u16::RAW_BYTE_LEN;
554 start..end
555 }
556
557 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
558 let start = self.subst_format_byte_range().end;
559 let end = start + Offset16::RAW_BYTE_LEN;
560 start..end
561 }
562
563 pub fn sequence_count_byte_range(&self) -> Range<usize> {
564 let start = self.coverage_offset_byte_range().end;
565 let end = start + u16::RAW_BYTE_LEN;
566 start..end
567 }
568
569 pub fn sequence_offsets_byte_range(&self) -> Range<usize> {
570 let sequence_count = self.sequence_count();
571 let start = self.sequence_count_byte_range().end;
572 let end =
573 start + (transforms::to_usize(sequence_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
574 start..end
575 }
576}
577
578const _: () = assert!(FontData::default_data_long_enough(
579 MultipleSubstFormat1::MIN_SIZE
580));
581
582impl Default for MultipleSubstFormat1<'_> {
583 fn default() -> Self {
584 Self {
585 data: FontData::default_format_1_u16_table_data(),
586 }
587 }
588}
589
590impl<'a> MinByteRange<'a> for Sequence<'a> {
591 fn min_byte_range(&self) -> Range<usize> {
592 0..self.substitute_glyph_ids_byte_range().end
593 }
594 fn min_table_bytes(&self) -> &'a [u8] {
595 let range = self.min_byte_range();
596 self.data.as_bytes().get(range).unwrap_or_default()
597 }
598}
599
600impl ReadArgs for Sequence<'_> {
601 type Args = ();
602}
603
604impl<'a> FontRead<'a> for Sequence<'a> {
605 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
606 #[allow(clippy::absurd_extreme_comparisons)]
607 if data.len() < Self::MIN_SIZE {
608 return Err(ReadError::OutOfBounds);
609 }
610 Ok(Self { data })
611 }
612}
613
614#[derive(Clone)]
616pub struct Sequence<'a> {
617 data: FontData<'a>,
618}
619
620#[allow(clippy::needless_lifetimes)]
621impl<'a> Sequence<'a> {
622 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
623 basic_table_impls!(impl_the_methods);
624
625 pub fn glyph_count(&self) -> u16 {
628 let range = self.glyph_count_byte_range();
629 self.data.read_at(range.start).ok().unwrap()
630 }
631
632 pub fn substitute_glyph_ids(&self) -> &'a [BigEndian<GlyphId16>] {
634 let range = self.substitute_glyph_ids_byte_range();
635 self.data.read_array(range).ok().unwrap_or_default()
636 }
637
638 pub fn glyph_count_byte_range(&self) -> Range<usize> {
639 let start = 0;
640 let end = start + u16::RAW_BYTE_LEN;
641 start..end
642 }
643
644 pub fn substitute_glyph_ids_byte_range(&self) -> Range<usize> {
645 let glyph_count = self.glyph_count();
646 let start = self.glyph_count_byte_range().end;
647 let end =
648 start + (transforms::to_usize(glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
649 start..end
650 }
651}
652
653const _: () = assert!(FontData::default_data_long_enough(Sequence::MIN_SIZE));
654
655impl Default for Sequence<'_> {
656 fn default() -> Self {
657 Self {
658 data: FontData::default_table_data(),
659 }
660 }
661}
662
663impl Format<u16> for AlternateSubstFormat1<'_> {
664 const FORMAT: u16 = 1;
665}
666
667impl<'a> MinByteRange<'a> for AlternateSubstFormat1<'a> {
668 fn min_byte_range(&self) -> Range<usize> {
669 0..self.alternate_set_offsets_byte_range().end
670 }
671 fn min_table_bytes(&self) -> &'a [u8] {
672 let range = self.min_byte_range();
673 self.data.as_bytes().get(range).unwrap_or_default()
674 }
675}
676
677impl ReadArgs for AlternateSubstFormat1<'_> {
678 type Args = ();
679}
680
681impl<'a> FontRead<'a> for AlternateSubstFormat1<'a> {
682 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
683 #[allow(clippy::absurd_extreme_comparisons)]
684 if data.len() < Self::MIN_SIZE {
685 return Err(ReadError::OutOfBounds);
686 }
687 Ok(Self { data })
688 }
689}
690
691#[derive(Clone)]
693pub struct AlternateSubstFormat1<'a> {
694 data: FontData<'a>,
695}
696
697#[allow(clippy::needless_lifetimes)]
698impl<'a> AlternateSubstFormat1<'a> {
699 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
700 basic_table_impls!(impl_the_methods);
701
702 pub fn subst_format(&self) -> u16 {
704 let range = self.subst_format_byte_range();
705 self.data.read_at(range.start).ok().unwrap()
706 }
707
708 pub fn coverage_offset(&self) -> Offset16 {
711 let range = self.coverage_offset_byte_range();
712 self.data.read_at(range.start).ok().unwrap()
713 }
714
715 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
717 let data = self.data;
718 self.coverage_offset().resolve(data)
719 }
720
721 pub fn alternate_set_count(&self) -> u16 {
723 let range = self.alternate_set_count_byte_range();
724 self.data.read_at(range.start).ok().unwrap()
725 }
726
727 pub fn alternate_set_offsets(&self) -> &'a [BigEndian<Offset16>] {
730 let range = self.alternate_set_offsets_byte_range();
731 self.data.read_array(range).ok().unwrap_or_default()
732 }
733
734 pub fn alternate_sets(&self) -> ArrayOfOffsets<'a, AlternateSet<'a>, Offset16> {
736 let data = self.data;
737 let offsets = self.alternate_set_offsets();
738 ArrayOfOffsets::new(offsets, data, ())
739 }
740
741 pub fn subst_format_byte_range(&self) -> Range<usize> {
742 let start = 0;
743 let end = start + u16::RAW_BYTE_LEN;
744 start..end
745 }
746
747 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
748 let start = self.subst_format_byte_range().end;
749 let end = start + Offset16::RAW_BYTE_LEN;
750 start..end
751 }
752
753 pub fn alternate_set_count_byte_range(&self) -> Range<usize> {
754 let start = self.coverage_offset_byte_range().end;
755 let end = start + u16::RAW_BYTE_LEN;
756 start..end
757 }
758
759 pub fn alternate_set_offsets_byte_range(&self) -> Range<usize> {
760 let alternate_set_count = self.alternate_set_count();
761 let start = self.alternate_set_count_byte_range().end;
762 let end = start
763 + (transforms::to_usize(alternate_set_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
764 start..end
765 }
766}
767
768const _: () = assert!(FontData::default_data_long_enough(
769 AlternateSubstFormat1::MIN_SIZE
770));
771
772impl Default for AlternateSubstFormat1<'_> {
773 fn default() -> Self {
774 Self {
775 data: FontData::default_format_1_u16_table_data(),
776 }
777 }
778}
779
780impl<'a> MinByteRange<'a> for AlternateSet<'a> {
781 fn min_byte_range(&self) -> Range<usize> {
782 0..self.alternate_glyph_ids_byte_range().end
783 }
784 fn min_table_bytes(&self) -> &'a [u8] {
785 let range = self.min_byte_range();
786 self.data.as_bytes().get(range).unwrap_or_default()
787 }
788}
789
790impl ReadArgs for AlternateSet<'_> {
791 type Args = ();
792}
793
794impl<'a> FontRead<'a> for AlternateSet<'a> {
795 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
796 #[allow(clippy::absurd_extreme_comparisons)]
797 if data.len() < Self::MIN_SIZE {
798 return Err(ReadError::OutOfBounds);
799 }
800 Ok(Self { data })
801 }
802}
803
804#[derive(Clone)]
806pub struct AlternateSet<'a> {
807 data: FontData<'a>,
808}
809
810#[allow(clippy::needless_lifetimes)]
811impl<'a> AlternateSet<'a> {
812 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
813 basic_table_impls!(impl_the_methods);
814
815 pub fn glyph_count(&self) -> u16 {
817 let range = self.glyph_count_byte_range();
818 self.data.read_at(range.start).ok().unwrap()
819 }
820
821 pub fn alternate_glyph_ids(&self) -> &'a [BigEndian<GlyphId16>] {
823 let range = self.alternate_glyph_ids_byte_range();
824 self.data.read_array(range).ok().unwrap_or_default()
825 }
826
827 pub fn glyph_count_byte_range(&self) -> Range<usize> {
828 let start = 0;
829 let end = start + u16::RAW_BYTE_LEN;
830 start..end
831 }
832
833 pub fn alternate_glyph_ids_byte_range(&self) -> Range<usize> {
834 let glyph_count = self.glyph_count();
835 let start = self.glyph_count_byte_range().end;
836 let end =
837 start + (transforms::to_usize(glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
838 start..end
839 }
840}
841
842const _: () = assert!(FontData::default_data_long_enough(AlternateSet::MIN_SIZE));
843
844impl Default for AlternateSet<'_> {
845 fn default() -> Self {
846 Self {
847 data: FontData::default_table_data(),
848 }
849 }
850}
851
852impl Format<u16> for LigatureSubstFormat1<'_> {
853 const FORMAT: u16 = 1;
854}
855
856impl<'a> MinByteRange<'a> for LigatureSubstFormat1<'a> {
857 fn min_byte_range(&self) -> Range<usize> {
858 0..self.ligature_set_offsets_byte_range().end
859 }
860 fn min_table_bytes(&self) -> &'a [u8] {
861 let range = self.min_byte_range();
862 self.data.as_bytes().get(range).unwrap_or_default()
863 }
864}
865
866impl ReadArgs for LigatureSubstFormat1<'_> {
867 type Args = ();
868}
869
870impl<'a> FontRead<'a> for LigatureSubstFormat1<'a> {
871 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
872 #[allow(clippy::absurd_extreme_comparisons)]
873 if data.len() < Self::MIN_SIZE {
874 return Err(ReadError::OutOfBounds);
875 }
876 Ok(Self { data })
877 }
878}
879
880#[derive(Clone)]
882pub struct LigatureSubstFormat1<'a> {
883 data: FontData<'a>,
884}
885
886#[allow(clippy::needless_lifetimes)]
887impl<'a> LigatureSubstFormat1<'a> {
888 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
889 basic_table_impls!(impl_the_methods);
890
891 pub fn subst_format(&self) -> u16 {
893 let range = self.subst_format_byte_range();
894 self.data.read_at(range.start).ok().unwrap()
895 }
896
897 pub fn coverage_offset(&self) -> Offset16 {
900 let range = self.coverage_offset_byte_range();
901 self.data.read_at(range.start).ok().unwrap()
902 }
903
904 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
906 let data = self.data;
907 self.coverage_offset().resolve(data)
908 }
909
910 pub fn ligature_set_count(&self) -> u16 {
912 let range = self.ligature_set_count_byte_range();
913 self.data.read_at(range.start).ok().unwrap()
914 }
915
916 pub fn ligature_set_offsets(&self) -> &'a [BigEndian<Offset16>] {
919 let range = self.ligature_set_offsets_byte_range();
920 self.data.read_array(range).ok().unwrap_or_default()
921 }
922
923 pub fn ligature_sets(&self) -> ArrayOfOffsets<'a, LigatureSet<'a>, Offset16> {
925 let data = self.data;
926 let offsets = self.ligature_set_offsets();
927 ArrayOfOffsets::new(offsets, data, ())
928 }
929
930 pub fn subst_format_byte_range(&self) -> Range<usize> {
931 let start = 0;
932 let end = start + u16::RAW_BYTE_LEN;
933 start..end
934 }
935
936 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
937 let start = self.subst_format_byte_range().end;
938 let end = start + Offset16::RAW_BYTE_LEN;
939 start..end
940 }
941
942 pub fn ligature_set_count_byte_range(&self) -> Range<usize> {
943 let start = self.coverage_offset_byte_range().end;
944 let end = start + u16::RAW_BYTE_LEN;
945 start..end
946 }
947
948 pub fn ligature_set_offsets_byte_range(&self) -> Range<usize> {
949 let ligature_set_count = self.ligature_set_count();
950 let start = self.ligature_set_count_byte_range().end;
951 let end = start
952 + (transforms::to_usize(ligature_set_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
953 start..end
954 }
955}
956
957const _: () = assert!(FontData::default_data_long_enough(
958 LigatureSubstFormat1::MIN_SIZE
959));
960
961impl Default for LigatureSubstFormat1<'_> {
962 fn default() -> Self {
963 Self {
964 data: FontData::default_format_1_u16_table_data(),
965 }
966 }
967}
968
969impl<'a> MinByteRange<'a> for LigatureSet<'a> {
970 fn min_byte_range(&self) -> Range<usize> {
971 0..self.ligature_offsets_byte_range().end
972 }
973 fn min_table_bytes(&self) -> &'a [u8] {
974 let range = self.min_byte_range();
975 self.data.as_bytes().get(range).unwrap_or_default()
976 }
977}
978
979impl ReadArgs for LigatureSet<'_> {
980 type Args = ();
981}
982
983impl<'a> FontRead<'a> for LigatureSet<'a> {
984 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
985 #[allow(clippy::absurd_extreme_comparisons)]
986 if data.len() < Self::MIN_SIZE {
987 return Err(ReadError::OutOfBounds);
988 }
989 Ok(Self { data })
990 }
991}
992
993#[derive(Clone)]
995pub struct LigatureSet<'a> {
996 data: FontData<'a>,
997}
998
999#[allow(clippy::needless_lifetimes)]
1000impl<'a> LigatureSet<'a> {
1001 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
1002 basic_table_impls!(impl_the_methods);
1003
1004 pub fn ligature_count(&self) -> u16 {
1006 let range = self.ligature_count_byte_range();
1007 self.data.read_at(range.start).ok().unwrap()
1008 }
1009
1010 pub fn ligature_offsets(&self) -> &'a [BigEndian<Offset16>] {
1013 let range = self.ligature_offsets_byte_range();
1014 self.data.read_array(range).ok().unwrap_or_default()
1015 }
1016
1017 pub fn ligatures(&self) -> ArrayOfOffsets<'a, Ligature<'a>, Offset16> {
1019 let data = self.data;
1020 let offsets = self.ligature_offsets();
1021 ArrayOfOffsets::new(offsets, data, ())
1022 }
1023
1024 pub fn ligature_count_byte_range(&self) -> Range<usize> {
1025 let start = 0;
1026 let end = start + u16::RAW_BYTE_LEN;
1027 start..end
1028 }
1029
1030 pub fn ligature_offsets_byte_range(&self) -> Range<usize> {
1031 let ligature_count = self.ligature_count();
1032 let start = self.ligature_count_byte_range().end;
1033 let end =
1034 start + (transforms::to_usize(ligature_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1035 start..end
1036 }
1037}
1038
1039const _: () = assert!(FontData::default_data_long_enough(LigatureSet::MIN_SIZE));
1040
1041impl Default for LigatureSet<'_> {
1042 fn default() -> Self {
1043 Self {
1044 data: FontData::default_table_data(),
1045 }
1046 }
1047}
1048
1049impl<'a> MinByteRange<'a> for Ligature<'a> {
1050 fn min_byte_range(&self) -> Range<usize> {
1051 0..self.component_glyph_ids_byte_range().end
1052 }
1053 fn min_table_bytes(&self) -> &'a [u8] {
1054 let range = self.min_byte_range();
1055 self.data.as_bytes().get(range).unwrap_or_default()
1056 }
1057}
1058
1059impl ReadArgs for Ligature<'_> {
1060 type Args = ();
1061}
1062
1063impl<'a> FontRead<'a> for Ligature<'a> {
1064 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1065 #[allow(clippy::absurd_extreme_comparisons)]
1066 if data.len() < Self::MIN_SIZE {
1067 return Err(ReadError::OutOfBounds);
1068 }
1069 Ok(Self { data })
1070 }
1071}
1072
1073#[derive(Clone)]
1075pub struct Ligature<'a> {
1076 data: FontData<'a>,
1077}
1078
1079#[allow(clippy::needless_lifetimes)]
1080impl<'a> Ligature<'a> {
1081 pub const MIN_SIZE: usize = (GlyphId16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1082 basic_table_impls!(impl_the_methods);
1083
1084 pub fn ligature_glyph(&self) -> GlyphId16 {
1086 let range = self.ligature_glyph_byte_range();
1087 self.data.read_at(range.start).ok().unwrap()
1088 }
1089
1090 pub fn component_count(&self) -> u16 {
1092 let range = self.component_count_byte_range();
1093 self.data.read_at(range.start).ok().unwrap()
1094 }
1095
1096 pub fn component_glyph_ids(&self) -> &'a [BigEndian<GlyphId16>] {
1099 let range = self.component_glyph_ids_byte_range();
1100 self.data.read_array(range).ok().unwrap_or_default()
1101 }
1102
1103 pub fn ligature_glyph_byte_range(&self) -> Range<usize> {
1104 let start = 0;
1105 let end = start + GlyphId16::RAW_BYTE_LEN;
1106 start..end
1107 }
1108
1109 pub fn component_count_byte_range(&self) -> Range<usize> {
1110 let start = self.ligature_glyph_byte_range().end;
1111 let end = start + u16::RAW_BYTE_LEN;
1112 start..end
1113 }
1114
1115 pub fn component_glyph_ids_byte_range(&self) -> Range<usize> {
1116 let component_count = self.component_count();
1117 let start = self.component_count_byte_range().end;
1118 let end = start
1119 + (transforms::subtract(component_count, 1_usize))
1120 .saturating_mul(GlyphId16::RAW_BYTE_LEN);
1121 start..end
1122 }
1123}
1124
1125const _: () = assert!(FontData::default_data_long_enough(Ligature::MIN_SIZE));
1126
1127impl Default for Ligature<'_> {
1128 fn default() -> Self {
1129 Self {
1130 data: FontData::default_table_data(),
1131 }
1132 }
1133}
1134
1135impl Format<u16> for ExtensionSubstFormat1<'_> {
1136 const FORMAT: u16 = 1;
1137}
1138
1139impl Discriminant for ExtensionSubstFormat1<'_, ()> {
1140 fn read_discriminant(data: FontData<'_>) -> Result<u16, ReadError> {
1141 data.read_at(u16::RAW_BYTE_LEN)
1142 }
1143}
1144
1145impl<'a, T> MinByteRange<'a> for ExtensionSubstFormat1<'a, T> {
1146 fn min_byte_range(&self) -> Range<usize> {
1147 0..self.extension_offset_byte_range().end
1148 }
1149 fn min_table_bytes(&self) -> &'a [u8] {
1150 let range = self.min_byte_range();
1151 self.data.as_bytes().get(range).unwrap_or_default()
1152 }
1153}
1154
1155impl<T> ReadArgs for ExtensionSubstFormat1<'_, T> {
1156 type Args = ();
1157}
1158
1159impl<'a, T> FontRead<'a> for ExtensionSubstFormat1<'a, T> {
1160 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1161 #[allow(clippy::absurd_extreme_comparisons)]
1162 if data.len() < Self::MIN_SIZE {
1163 return Err(ReadError::OutOfBounds);
1164 }
1165 Ok(Self {
1166 data,
1167 offset_type: std::marker::PhantomData,
1168 })
1169 }
1170}
1171
1172impl<'a, T> ExtensionSubstFormat1<'a, T> {
1173 #[allow(dead_code)]
1174 pub(crate) fn of_unit_type(&self) -> ExtensionSubstFormat1<'a, ()> {
1176 ExtensionSubstFormat1 {
1177 data: self.data,
1178 offset_type: std::marker::PhantomData,
1179 }
1180 }
1181}
1182
1183#[derive(Clone)]
1185pub struct ExtensionSubstFormat1<'a, T = ()> {
1186 data: FontData<'a>,
1187 offset_type: std::marker::PhantomData<*const T>,
1188}
1189
1190#[allow(clippy::needless_lifetimes)]
1191impl<'a, T> ExtensionSubstFormat1<'a, T> {
1192 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + Offset32::RAW_BYTE_LEN);
1193 basic_table_impls!(impl_the_methods);
1194
1195 pub fn subst_format(&self) -> u16 {
1197 let range = self.subst_format_byte_range();
1198 self.data.read_at(range.start).ok().unwrap()
1199 }
1200
1201 pub fn extension_lookup_type(&self) -> u16 {
1204 let range = self.extension_lookup_type_byte_range();
1205 self.data.read_at(range.start).ok().unwrap()
1206 }
1207
1208 pub fn extension_offset(&self) -> Offset32 {
1212 let range = self.extension_offset_byte_range();
1213 self.data.read_at(range.start).ok().unwrap()
1214 }
1215
1216 pub fn extension(&self) -> Result<T, ReadError>
1218 where
1219 T: FontRead<'a, Args = ()>,
1220 {
1221 let data = self.data;
1222 self.extension_offset().resolve(data)
1223 }
1224
1225 pub fn subst_format_byte_range(&self) -> Range<usize> {
1226 let start = 0;
1227 let end = start + u16::RAW_BYTE_LEN;
1228 start..end
1229 }
1230
1231 pub fn extension_lookup_type_byte_range(&self) -> Range<usize> {
1232 let start = self.subst_format_byte_range().end;
1233 let end = start + u16::RAW_BYTE_LEN;
1234 start..end
1235 }
1236
1237 pub fn extension_offset_byte_range(&self) -> Range<usize> {
1238 let start = self.extension_lookup_type_byte_range().end;
1239 let end = start + Offset32::RAW_BYTE_LEN;
1240 start..end
1241 }
1242}
1243
1244const _: () = assert!(FontData::default_data_long_enough(
1245 ExtensionSubstFormat1::<()>::MIN_SIZE
1246));
1247
1248impl<T> Default for ExtensionSubstFormat1<'_, T> {
1249 fn default() -> Self {
1250 Self {
1251 data: FontData::default_format_1_u16_table_data(),
1252 offset_type: std::marker::PhantomData,
1253 }
1254 }
1255}
1256
1257pub enum ExtensionSubtable<'a> {
1259 Single(ExtensionSubstFormat1<'a, SingleSubst<'a>>),
1260 Multiple(ExtensionSubstFormat1<'a, MultipleSubstFormat1<'a>>),
1261 Alternate(ExtensionSubstFormat1<'a, AlternateSubstFormat1<'a>>),
1262 Ligature(ExtensionSubstFormat1<'a, LigatureSubstFormat1<'a>>),
1263 Contextual(ExtensionSubstFormat1<'a, SubstitutionSequenceContext<'a>>),
1264 ChainContextual(ExtensionSubstFormat1<'a, SubstitutionChainContext<'a>>),
1265 Reverse(ExtensionSubstFormat1<'a, ReverseChainSingleSubstFormat1<'a>>),
1266}
1267
1268impl Default for ExtensionSubtable<'_> {
1269 fn default() -> Self {
1270 Self::Single(Default::default())
1271 }
1272}
1273
1274impl ReadArgs for ExtensionSubtable<'_> {
1275 type Args = ();
1276}
1277
1278impl<'a> FontRead<'a> for ExtensionSubtable<'a> {
1279 fn read_with_args(bytes: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1280 let discriminant = ExtensionSubstFormat1::read_discriminant(bytes)?;
1281 match discriminant {
1282 1 => Ok(ExtensionSubtable::Single(FontRead::read(bytes)?)),
1283 2 => Ok(ExtensionSubtable::Multiple(FontRead::read(bytes)?)),
1284 3 => Ok(ExtensionSubtable::Alternate(FontRead::read(bytes)?)),
1285 4 => Ok(ExtensionSubtable::Ligature(FontRead::read(bytes)?)),
1286 5 => Ok(ExtensionSubtable::Contextual(FontRead::read(bytes)?)),
1287 6 => Ok(ExtensionSubtable::ChainContextual(FontRead::read(bytes)?)),
1288 8 => Ok(ExtensionSubtable::Reverse(FontRead::read(bytes)?)),
1289 other => Err(ReadError::InvalidFormat(other.into())),
1290 }
1291 }
1292}
1293
1294impl<'a> ExtensionSubtable<'a> {
1295 #[allow(dead_code)]
1296 pub(crate) fn of_unit_type(&self) -> ExtensionSubstFormat1<'a, ()> {
1300 match self {
1301 ExtensionSubtable::Single(inner) => inner.of_unit_type(),
1302 ExtensionSubtable::Multiple(inner) => inner.of_unit_type(),
1303 ExtensionSubtable::Alternate(inner) => inner.of_unit_type(),
1304 ExtensionSubtable::Ligature(inner) => inner.of_unit_type(),
1305 ExtensionSubtable::Contextual(inner) => inner.of_unit_type(),
1306 ExtensionSubtable::ChainContextual(inner) => inner.of_unit_type(),
1307 ExtensionSubtable::Reverse(inner) => inner.of_unit_type(),
1308 }
1309 }
1310}
1311
1312impl Format<u16> for ReverseChainSingleSubstFormat1<'_> {
1313 const FORMAT: u16 = 1;
1314}
1315
1316impl<'a> MinByteRange<'a> for ReverseChainSingleSubstFormat1<'a> {
1317 fn min_byte_range(&self) -> Range<usize> {
1318 0..self.substitute_glyph_ids_byte_range().end
1319 }
1320 fn min_table_bytes(&self) -> &'a [u8] {
1321 let range = self.min_byte_range();
1322 self.data.as_bytes().get(range).unwrap_or_default()
1323 }
1324}
1325
1326impl ReadArgs for ReverseChainSingleSubstFormat1<'_> {
1327 type Args = ();
1328}
1329
1330impl<'a> FontRead<'a> for ReverseChainSingleSubstFormat1<'a> {
1331 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1332 #[allow(clippy::absurd_extreme_comparisons)]
1333 if data.len() < Self::MIN_SIZE {
1334 return Err(ReadError::OutOfBounds);
1335 }
1336 Ok(Self { data })
1337 }
1338}
1339
1340#[derive(Clone)]
1342pub struct ReverseChainSingleSubstFormat1<'a> {
1343 data: FontData<'a>,
1344}
1345
1346#[allow(clippy::needless_lifetimes)]
1347impl<'a> ReverseChainSingleSubstFormat1<'a> {
1348 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
1349 + Offset16::RAW_BYTE_LEN
1350 + u16::RAW_BYTE_LEN
1351 + u16::RAW_BYTE_LEN
1352 + u16::RAW_BYTE_LEN);
1353 basic_table_impls!(impl_the_methods);
1354
1355 pub fn subst_format(&self) -> u16 {
1357 let range = self.subst_format_byte_range();
1358 self.data.read_at(range.start).ok().unwrap()
1359 }
1360
1361 pub fn coverage_offset(&self) -> Offset16 {
1364 let range = self.coverage_offset_byte_range();
1365 self.data.read_at(range.start).ok().unwrap()
1366 }
1367
1368 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
1370 let data = self.data;
1371 self.coverage_offset().resolve(data)
1372 }
1373
1374 pub fn backtrack_glyph_count(&self) -> u16 {
1376 let range = self.backtrack_glyph_count_byte_range();
1377 self.data.read_at(range.start).ok().unwrap()
1378 }
1379
1380 pub fn backtrack_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
1383 let range = self.backtrack_coverage_offsets_byte_range();
1384 self.data.read_array(range).ok().unwrap_or_default()
1385 }
1386
1387 pub fn backtrack_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
1389 let data = self.data;
1390 let offsets = self.backtrack_coverage_offsets();
1391 ArrayOfOffsets::new(offsets, data, ())
1392 }
1393
1394 pub fn lookahead_glyph_count(&self) -> u16 {
1396 let range = self.lookahead_glyph_count_byte_range();
1397 self.data.read_at(range.start).ok().unwrap_or_default()
1398 }
1399
1400 pub fn lookahead_coverage_offsets(&self) -> &'a [BigEndian<Offset16>] {
1403 let range = self.lookahead_coverage_offsets_byte_range();
1404 self.data.read_array(range).ok().unwrap_or_default()
1405 }
1406
1407 pub fn lookahead_coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset16> {
1409 let data = self.data;
1410 let offsets = self.lookahead_coverage_offsets();
1411 ArrayOfOffsets::new(offsets, data, ())
1412 }
1413
1414 pub fn glyph_count(&self) -> u16 {
1416 let range = self.glyph_count_byte_range();
1417 self.data.read_at(range.start).ok().unwrap_or_default()
1418 }
1419
1420 pub fn substitute_glyph_ids(&self) -> &'a [BigEndian<GlyphId16>] {
1422 let range = self.substitute_glyph_ids_byte_range();
1423 self.data.read_array(range).ok().unwrap_or_default()
1424 }
1425
1426 pub fn subst_format_byte_range(&self) -> Range<usize> {
1427 let start = 0;
1428 let end = start + u16::RAW_BYTE_LEN;
1429 start..end
1430 }
1431
1432 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
1433 let start = self.subst_format_byte_range().end;
1434 let end = start + Offset16::RAW_BYTE_LEN;
1435 start..end
1436 }
1437
1438 pub fn backtrack_glyph_count_byte_range(&self) -> Range<usize> {
1439 let start = self.coverage_offset_byte_range().end;
1440 let end = start + u16::RAW_BYTE_LEN;
1441 start..end
1442 }
1443
1444 pub fn backtrack_coverage_offsets_byte_range(&self) -> Range<usize> {
1445 let backtrack_glyph_count = self.backtrack_glyph_count();
1446 let start = self.backtrack_glyph_count_byte_range().end;
1447 let end = start
1448 + (transforms::to_usize(backtrack_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1449 start..end
1450 }
1451
1452 pub fn lookahead_glyph_count_byte_range(&self) -> Range<usize> {
1453 let start = self.backtrack_coverage_offsets_byte_range().end;
1454 let end = start + u16::RAW_BYTE_LEN;
1455 start..end
1456 }
1457
1458 pub fn lookahead_coverage_offsets_byte_range(&self) -> Range<usize> {
1459 let lookahead_glyph_count = self.lookahead_glyph_count();
1460 let start = self.lookahead_glyph_count_byte_range().end;
1461 let end = start
1462 + (transforms::to_usize(lookahead_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
1463 start..end
1464 }
1465
1466 pub fn glyph_count_byte_range(&self) -> Range<usize> {
1467 let start = self.lookahead_coverage_offsets_byte_range().end;
1468 let end = start + u16::RAW_BYTE_LEN;
1469 start..end
1470 }
1471
1472 pub fn substitute_glyph_ids_byte_range(&self) -> Range<usize> {
1473 let glyph_count = self.glyph_count();
1474 let start = self.glyph_count_byte_range().end;
1475 let end =
1476 start + (transforms::to_usize(glyph_count)).saturating_mul(GlyphId16::RAW_BYTE_LEN);
1477 start..end
1478 }
1479}
1480
1481const _: () = assert!(FontData::default_data_long_enough(
1482 ReverseChainSingleSubstFormat1::MIN_SIZE
1483));
1484
1485impl Default for ReverseChainSingleSubstFormat1<'_> {
1486 fn default() -> Self {
1487 Self {
1488 data: FontData::default_format_1_u16_table_data(),
1489 }
1490 }
1491}