1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for Gdef<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.mark_attach_class_def_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 Gdef<'_> {
19 const TAG: Tag = Tag::new(b"GDEF");
21}
22
23impl ReadArgs for Gdef<'_> {
24 type Args = ();
25}
26
27impl<'a> FontRead<'a> for Gdef<'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 Gdef<'a> {
40 data: FontData<'a>,
41}
42
43#[allow(clippy::needless_lifetimes)]
44impl<'a> Gdef<'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 + Offset16::RAW_BYTE_LEN);
50 basic_table_impls!(impl_the_methods);
51
52 pub fn version(&self) -> MajorMinor {
54 let range = self.version_byte_range();
55 self.data.read_at(range.start).ok().unwrap()
56 }
57
58 pub fn glyph_class_def_offset(&self) -> Nullable<Offset16> {
61 let range = self.glyph_class_def_offset_byte_range();
62 self.data.read_at(range.start).ok().unwrap()
63 }
64
65 pub fn glyph_class_def(&self) -> Option<Result<ClassDef<'a>, ReadError>> {
67 let data = self.data;
68 self.glyph_class_def_offset().resolve(data)
69 }
70
71 pub fn attach_list_offset(&self) -> Nullable<Offset16> {
74 let range = self.attach_list_offset_byte_range();
75 self.data.read_at(range.start).ok().unwrap()
76 }
77
78 pub fn attach_list(&self) -> Option<Result<AttachList<'a>, ReadError>> {
80 let data = self.data;
81 self.attach_list_offset().resolve(data)
82 }
83
84 pub fn lig_caret_list_offset(&self) -> Nullable<Offset16> {
87 let range = self.lig_caret_list_offset_byte_range();
88 self.data.read_at(range.start).ok().unwrap()
89 }
90
91 pub fn lig_caret_list(&self) -> Option<Result<LigCaretList<'a>, ReadError>> {
93 let data = self.data;
94 self.lig_caret_list_offset().resolve(data)
95 }
96
97 pub fn mark_attach_class_def_offset(&self) -> Nullable<Offset16> {
100 let range = self.mark_attach_class_def_offset_byte_range();
101 self.data.read_at(range.start).ok().unwrap()
102 }
103
104 pub fn mark_attach_class_def(&self) -> Option<Result<ClassDef<'a>, ReadError>> {
106 let data = self.data;
107 self.mark_attach_class_def_offset().resolve(data)
108 }
109
110 pub fn mark_glyph_sets_def_offset(&self) -> Option<Nullable<Offset16>> {
113 let range = self.mark_glyph_sets_def_offset_byte_range();
114 (!range.is_empty())
115 .then(|| self.data.read_at(range.start).ok())
116 .flatten()
117 }
118
119 pub fn mark_glyph_sets_def(&self) -> Option<Result<MarkGlyphSets<'a>, ReadError>> {
121 let data = self.data;
122 self.mark_glyph_sets_def_offset().map(|x| x.resolve(data))?
123 }
124
125 pub fn item_var_store_offset(&self) -> Option<Nullable<Offset32>> {
128 let range = self.item_var_store_offset_byte_range();
129 (!range.is_empty())
130 .then(|| self.data.read_at(range.start).ok())
131 .flatten()
132 }
133
134 pub fn item_var_store(&self) -> Option<Result<ItemVariationStore<'a>, ReadError>> {
136 let data = self.data;
137 self.item_var_store_offset().map(|x| x.resolve(data))?
138 }
139
140 pub fn version_byte_range(&self) -> Range<usize> {
141 let start = 0;
142 let end = start + MajorMinor::RAW_BYTE_LEN;
143 start..end
144 }
145
146 pub fn glyph_class_def_offset_byte_range(&self) -> Range<usize> {
147 let start = self.version_byte_range().end;
148 let end = start + Offset16::RAW_BYTE_LEN;
149 start..end
150 }
151
152 pub fn attach_list_offset_byte_range(&self) -> Range<usize> {
153 let start = self.glyph_class_def_offset_byte_range().end;
154 let end = start + Offset16::RAW_BYTE_LEN;
155 start..end
156 }
157
158 pub fn lig_caret_list_offset_byte_range(&self) -> Range<usize> {
159 let start = self.attach_list_offset_byte_range().end;
160 let end = start + Offset16::RAW_BYTE_LEN;
161 start..end
162 }
163
164 pub fn mark_attach_class_def_offset_byte_range(&self) -> Range<usize> {
165 let start = self.lig_caret_list_offset_byte_range().end;
166 let end = start + Offset16::RAW_BYTE_LEN;
167 start..end
168 }
169
170 pub fn mark_glyph_sets_def_offset_byte_range(&self) -> Range<usize> {
171 let start = self.mark_attach_class_def_offset_byte_range().end;
172 let end = if self.version().compatible((1u16, 2u16)) {
173 start + Offset16::RAW_BYTE_LEN
174 } else {
175 start
176 };
177 start..end
178 }
179
180 pub fn item_var_store_offset_byte_range(&self) -> Range<usize> {
181 let start = self.mark_glyph_sets_def_offset_byte_range().end;
182 let end = if self.version().compatible((1u16, 3u16)) {
183 start + Offset32::RAW_BYTE_LEN
184 } else {
185 start
186 };
187 start..end
188 }
189}
190
191const _: () = assert!(FontData::default_data_long_enough(Gdef::MIN_SIZE));
192
193impl Default for Gdef<'_> {
194 fn default() -> Self {
195 Self {
196 data: FontData::default_table_data(),
197 }
198 }
199}
200
201#[cfg(feature = "experimental_traverse")]
202impl<'a> SomeTable<'a> for Gdef<'a> {
203 fn type_name(&self) -> &str {
204 "Gdef"
205 }
206 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
207 match idx {
208 0usize => Some(Field::new("version", self.version())),
209 1usize => Some(Field::new(
210 "glyph_class_def_offset",
211 FieldType::offset(self.glyph_class_def_offset(), self.glyph_class_def()),
212 )),
213 2usize => Some(Field::new(
214 "attach_list_offset",
215 FieldType::offset(self.attach_list_offset(), self.attach_list()),
216 )),
217 3usize => Some(Field::new(
218 "lig_caret_list_offset",
219 FieldType::offset(self.lig_caret_list_offset(), self.lig_caret_list()),
220 )),
221 4usize => Some(Field::new(
222 "mark_attach_class_def_offset",
223 FieldType::offset(
224 self.mark_attach_class_def_offset(),
225 self.mark_attach_class_def(),
226 ),
227 )),
228 5usize if self.version().compatible((1u16, 2u16)) => Some(Field::new(
229 "mark_glyph_sets_def_offset",
230 FieldType::offset(
231 self.mark_glyph_sets_def_offset().unwrap(),
232 self.mark_glyph_sets_def(),
233 ),
234 )),
235 6usize if self.version().compatible((1u16, 3u16)) => Some(Field::new(
236 "item_var_store_offset",
237 FieldType::offset(self.item_var_store_offset().unwrap(), self.item_var_store()),
238 )),
239 _ => None,
240 }
241 }
242}
243
244#[cfg(feature = "experimental_traverse")]
245#[allow(clippy::needless_lifetimes)]
246impl<'a> std::fmt::Debug for Gdef<'a> {
247 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
248 (self as &dyn SomeTable<'a>).fmt(f)
249 }
250}
251
252#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
254#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
255#[repr(u16)]
256#[allow(clippy::manual_non_exhaustive)]
257pub enum GlyphClassDef {
258 #[default]
259 Base = 1,
260 Ligature = 2,
261 Mark = 3,
262 Component = 4,
263 #[doc(hidden)]
264 Unknown,
266}
267
268impl GlyphClassDef {
269 pub fn new(raw: u16) -> Self {
273 match raw {
274 1 => Self::Base,
275 2 => Self::Ligature,
276 3 => Self::Mark,
277 4 => Self::Component,
278 _ => Self::Unknown,
279 }
280 }
281}
282
283impl font_types::Scalar for GlyphClassDef {
284 type Raw = <u16 as font_types::Scalar>::Raw;
285 fn to_raw(self) -> Self::Raw {
286 (self as u16).to_raw()
287 }
288 fn from_raw(raw: Self::Raw) -> Self {
289 let t = <u16>::from_raw(raw);
290 Self::new(t)
291 }
292}
293
294#[cfg(feature = "experimental_traverse")]
295impl<'a> From<GlyphClassDef> for FieldType<'a> {
296 fn from(src: GlyphClassDef) -> FieldType<'a> {
297 (src as u16).into()
298 }
299}
300
301impl<'a> MinByteRange<'a> for AttachList<'a> {
302 fn min_byte_range(&self) -> Range<usize> {
303 0..self.attach_point_offsets_byte_range().end
304 }
305 fn min_table_bytes(&self) -> &'a [u8] {
306 let range = self.min_byte_range();
307 self.data.as_bytes().get(range).unwrap_or_default()
308 }
309}
310
311impl ReadArgs for AttachList<'_> {
312 type Args = ();
313}
314
315impl<'a> FontRead<'a> for AttachList<'a> {
316 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
317 #[allow(clippy::absurd_extreme_comparisons)]
318 if data.len() < Self::MIN_SIZE {
319 return Err(ReadError::OutOfBounds);
320 }
321 Ok(Self { data })
322 }
323}
324
325#[derive(Clone)]
327pub struct AttachList<'a> {
328 data: FontData<'a>,
329}
330
331#[allow(clippy::needless_lifetimes)]
332impl<'a> AttachList<'a> {
333 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
334 basic_table_impls!(impl_the_methods);
335
336 pub fn coverage_offset(&self) -> Offset16 {
338 let range = self.coverage_offset_byte_range();
339 self.data.read_at(range.start).ok().unwrap()
340 }
341
342 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
344 let data = self.data;
345 self.coverage_offset().resolve(data)
346 }
347
348 pub fn glyph_count(&self) -> u16 {
350 let range = self.glyph_count_byte_range();
351 self.data.read_at(range.start).ok().unwrap()
352 }
353
354 pub fn attach_point_offsets(&self) -> &'a [BigEndian<Offset16>] {
357 let range = self.attach_point_offsets_byte_range();
358 self.data.read_array(range).ok().unwrap_or_default()
359 }
360
361 pub fn attach_points(&self) -> ArrayOfOffsets<'a, AttachPoint<'a>, Offset16> {
363 let data = self.data;
364 let offsets = self.attach_point_offsets();
365 ArrayOfOffsets::new(offsets, data, ())
366 }
367
368 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
369 let start = 0;
370 let end = start + Offset16::RAW_BYTE_LEN;
371 start..end
372 }
373
374 pub fn glyph_count_byte_range(&self) -> Range<usize> {
375 let start = self.coverage_offset_byte_range().end;
376 let end = start + u16::RAW_BYTE_LEN;
377 start..end
378 }
379
380 pub fn attach_point_offsets_byte_range(&self) -> Range<usize> {
381 let glyph_count = self.glyph_count();
382 let start = self.glyph_count_byte_range().end;
383 let end =
384 start + (transforms::to_usize(glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
385 start..end
386 }
387}
388
389const _: () = assert!(FontData::default_data_long_enough(AttachList::MIN_SIZE));
390
391impl Default for AttachList<'_> {
392 fn default() -> Self {
393 Self {
394 data: FontData::default_table_data(),
395 }
396 }
397}
398
399#[cfg(feature = "experimental_traverse")]
400impl<'a> SomeTable<'a> for AttachList<'a> {
401 fn type_name(&self) -> &str {
402 "AttachList"
403 }
404 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
405 match idx {
406 0usize => Some(Field::new(
407 "coverage_offset",
408 FieldType::offset(self.coverage_offset(), self.coverage()),
409 )),
410 1usize => Some(Field::new("glyph_count", self.glyph_count())),
411 2usize => Some(Field::new(
412 "attach_point_offsets",
413 FieldType::from(self.attach_points()),
414 )),
415 _ => None,
416 }
417 }
418}
419
420#[cfg(feature = "experimental_traverse")]
421#[allow(clippy::needless_lifetimes)]
422impl<'a> std::fmt::Debug for AttachList<'a> {
423 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
424 (self as &dyn SomeTable<'a>).fmt(f)
425 }
426}
427
428impl<'a> MinByteRange<'a> for AttachPoint<'a> {
429 fn min_byte_range(&self) -> Range<usize> {
430 0..self.point_indices_byte_range().end
431 }
432 fn min_table_bytes(&self) -> &'a [u8] {
433 let range = self.min_byte_range();
434 self.data.as_bytes().get(range).unwrap_or_default()
435 }
436}
437
438impl ReadArgs for AttachPoint<'_> {
439 type Args = ();
440}
441
442impl<'a> FontRead<'a> for AttachPoint<'a> {
443 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
444 #[allow(clippy::absurd_extreme_comparisons)]
445 if data.len() < Self::MIN_SIZE {
446 return Err(ReadError::OutOfBounds);
447 }
448 Ok(Self { data })
449 }
450}
451
452#[derive(Clone)]
454pub struct AttachPoint<'a> {
455 data: FontData<'a>,
456}
457
458#[allow(clippy::needless_lifetimes)]
459impl<'a> AttachPoint<'a> {
460 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
461 basic_table_impls!(impl_the_methods);
462
463 pub fn point_count(&self) -> u16 {
465 let range = self.point_count_byte_range();
466 self.data.read_at(range.start).ok().unwrap()
467 }
468
469 pub fn point_indices(&self) -> &'a [BigEndian<u16>] {
471 let range = self.point_indices_byte_range();
472 self.data.read_array(range).ok().unwrap_or_default()
473 }
474
475 pub fn point_count_byte_range(&self) -> Range<usize> {
476 let start = 0;
477 let end = start + u16::RAW_BYTE_LEN;
478 start..end
479 }
480
481 pub fn point_indices_byte_range(&self) -> Range<usize> {
482 let point_count = self.point_count();
483 let start = self.point_count_byte_range().end;
484 let end = start + (transforms::to_usize(point_count)).saturating_mul(u16::RAW_BYTE_LEN);
485 start..end
486 }
487}
488
489const _: () = assert!(FontData::default_data_long_enough(AttachPoint::MIN_SIZE));
490
491impl Default for AttachPoint<'_> {
492 fn default() -> Self {
493 Self {
494 data: FontData::default_table_data(),
495 }
496 }
497}
498
499#[cfg(feature = "experimental_traverse")]
500impl<'a> SomeTable<'a> for AttachPoint<'a> {
501 fn type_name(&self) -> &str {
502 "AttachPoint"
503 }
504 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
505 match idx {
506 0usize => Some(Field::new("point_count", self.point_count())),
507 1usize => Some(Field::new("point_indices", self.point_indices())),
508 _ => None,
509 }
510 }
511}
512
513#[cfg(feature = "experimental_traverse")]
514#[allow(clippy::needless_lifetimes)]
515impl<'a> std::fmt::Debug for AttachPoint<'a> {
516 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
517 (self as &dyn SomeTable<'a>).fmt(f)
518 }
519}
520
521impl<'a> MinByteRange<'a> for LigCaretList<'a> {
522 fn min_byte_range(&self) -> Range<usize> {
523 0..self.lig_glyph_offsets_byte_range().end
524 }
525 fn min_table_bytes(&self) -> &'a [u8] {
526 let range = self.min_byte_range();
527 self.data.as_bytes().get(range).unwrap_or_default()
528 }
529}
530
531impl ReadArgs for LigCaretList<'_> {
532 type Args = ();
533}
534
535impl<'a> FontRead<'a> for LigCaretList<'a> {
536 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
537 #[allow(clippy::absurd_extreme_comparisons)]
538 if data.len() < Self::MIN_SIZE {
539 return Err(ReadError::OutOfBounds);
540 }
541 Ok(Self { data })
542 }
543}
544
545#[derive(Clone)]
547pub struct LigCaretList<'a> {
548 data: FontData<'a>,
549}
550
551#[allow(clippy::needless_lifetimes)]
552impl<'a> LigCaretList<'a> {
553 pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
554 basic_table_impls!(impl_the_methods);
555
556 pub fn coverage_offset(&self) -> Offset16 {
558 let range = self.coverage_offset_byte_range();
559 self.data.read_at(range.start).ok().unwrap()
560 }
561
562 pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
564 let data = self.data;
565 self.coverage_offset().resolve(data)
566 }
567
568 pub fn lig_glyph_count(&self) -> u16 {
570 let range = self.lig_glyph_count_byte_range();
571 self.data.read_at(range.start).ok().unwrap()
572 }
573
574 pub fn lig_glyph_offsets(&self) -> &'a [BigEndian<Offset16>] {
577 let range = self.lig_glyph_offsets_byte_range();
578 self.data.read_array(range).ok().unwrap_or_default()
579 }
580
581 pub fn lig_glyphs(&self) -> ArrayOfOffsets<'a, LigGlyph<'a>, Offset16> {
583 let data = self.data;
584 let offsets = self.lig_glyph_offsets();
585 ArrayOfOffsets::new(offsets, data, ())
586 }
587
588 pub fn coverage_offset_byte_range(&self) -> Range<usize> {
589 let start = 0;
590 let end = start + Offset16::RAW_BYTE_LEN;
591 start..end
592 }
593
594 pub fn lig_glyph_count_byte_range(&self) -> Range<usize> {
595 let start = self.coverage_offset_byte_range().end;
596 let end = start + u16::RAW_BYTE_LEN;
597 start..end
598 }
599
600 pub fn lig_glyph_offsets_byte_range(&self) -> Range<usize> {
601 let lig_glyph_count = self.lig_glyph_count();
602 let start = self.lig_glyph_count_byte_range().end;
603 let end =
604 start + (transforms::to_usize(lig_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
605 start..end
606 }
607}
608
609const _: () = assert!(FontData::default_data_long_enough(LigCaretList::MIN_SIZE));
610
611impl Default for LigCaretList<'_> {
612 fn default() -> Self {
613 Self {
614 data: FontData::default_table_data(),
615 }
616 }
617}
618
619#[cfg(feature = "experimental_traverse")]
620impl<'a> SomeTable<'a> for LigCaretList<'a> {
621 fn type_name(&self) -> &str {
622 "LigCaretList"
623 }
624 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
625 match idx {
626 0usize => Some(Field::new(
627 "coverage_offset",
628 FieldType::offset(self.coverage_offset(), self.coverage()),
629 )),
630 1usize => Some(Field::new("lig_glyph_count", self.lig_glyph_count())),
631 2usize => Some(Field::new(
632 "lig_glyph_offsets",
633 FieldType::from(self.lig_glyphs()),
634 )),
635 _ => None,
636 }
637 }
638}
639
640#[cfg(feature = "experimental_traverse")]
641#[allow(clippy::needless_lifetimes)]
642impl<'a> std::fmt::Debug for LigCaretList<'a> {
643 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
644 (self as &dyn SomeTable<'a>).fmt(f)
645 }
646}
647
648impl<'a> MinByteRange<'a> for LigGlyph<'a> {
649 fn min_byte_range(&self) -> Range<usize> {
650 0..self.caret_value_offsets_byte_range().end
651 }
652 fn min_table_bytes(&self) -> &'a [u8] {
653 let range = self.min_byte_range();
654 self.data.as_bytes().get(range).unwrap_or_default()
655 }
656}
657
658impl ReadArgs for LigGlyph<'_> {
659 type Args = ();
660}
661
662impl<'a> FontRead<'a> for LigGlyph<'a> {
663 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
664 #[allow(clippy::absurd_extreme_comparisons)]
665 if data.len() < Self::MIN_SIZE {
666 return Err(ReadError::OutOfBounds);
667 }
668 Ok(Self { data })
669 }
670}
671
672#[derive(Clone)]
674pub struct LigGlyph<'a> {
675 data: FontData<'a>,
676}
677
678#[allow(clippy::needless_lifetimes)]
679impl<'a> LigGlyph<'a> {
680 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
681 basic_table_impls!(impl_the_methods);
682
683 pub fn caret_count(&self) -> u16 {
685 let range = self.caret_count_byte_range();
686 self.data.read_at(range.start).ok().unwrap()
687 }
688
689 pub fn caret_value_offsets(&self) -> &'a [BigEndian<Offset16>] {
692 let range = self.caret_value_offsets_byte_range();
693 self.data.read_array(range).ok().unwrap_or_default()
694 }
695
696 pub fn caret_values(&self) -> ArrayOfOffsets<'a, CaretValue<'a>, Offset16> {
698 let data = self.data;
699 let offsets = self.caret_value_offsets();
700 ArrayOfOffsets::new(offsets, data, ())
701 }
702
703 pub fn caret_count_byte_range(&self) -> Range<usize> {
704 let start = 0;
705 let end = start + u16::RAW_BYTE_LEN;
706 start..end
707 }
708
709 pub fn caret_value_offsets_byte_range(&self) -> Range<usize> {
710 let caret_count = self.caret_count();
711 let start = self.caret_count_byte_range().end;
712 let end =
713 start + (transforms::to_usize(caret_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
714 start..end
715 }
716}
717
718const _: () = assert!(FontData::default_data_long_enough(LigGlyph::MIN_SIZE));
719
720impl Default for LigGlyph<'_> {
721 fn default() -> Self {
722 Self {
723 data: FontData::default_table_data(),
724 }
725 }
726}
727
728#[cfg(feature = "experimental_traverse")]
729impl<'a> SomeTable<'a> for LigGlyph<'a> {
730 fn type_name(&self) -> &str {
731 "LigGlyph"
732 }
733 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
734 match idx {
735 0usize => Some(Field::new("caret_count", self.caret_count())),
736 1usize => Some(Field::new(
737 "caret_value_offsets",
738 FieldType::from(self.caret_values()),
739 )),
740 _ => None,
741 }
742 }
743}
744
745#[cfg(feature = "experimental_traverse")]
746#[allow(clippy::needless_lifetimes)]
747impl<'a> std::fmt::Debug for LigGlyph<'a> {
748 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
749 (self as &dyn SomeTable<'a>).fmt(f)
750 }
751}
752
753#[derive(Clone)]
755pub enum CaretValue<'a> {
756 Format1(CaretValueFormat1<'a>),
757 Format2(CaretValueFormat2<'a>),
758 Format3(CaretValueFormat3<'a>),
759}
760
761impl Default for CaretValue<'_> {
762 fn default() -> Self {
763 Self::Format1(Default::default())
764 }
765}
766
767impl<'a> CaretValue<'a> {
768 pub fn offset_data(&self) -> FontData<'a> {
770 match self {
771 Self::Format1(item) => item.offset_data(),
772 Self::Format2(item) => item.offset_data(),
773 Self::Format3(item) => item.offset_data(),
774 }
775 }
776
777 pub fn caret_value_format(&self) -> u16 {
779 match self {
780 Self::Format1(item) => item.caret_value_format(),
781 Self::Format2(item) => item.caret_value_format(),
782 Self::Format3(item) => item.caret_value_format(),
783 }
784 }
785}
786
787impl ReadArgs for CaretValue<'_> {
788 type Args = ();
789}
790
791impl<'a> FontRead<'a> for CaretValue<'a> {
792 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
793 let format: u16 = data.read_at(0usize)?;
794 match format {
795 CaretValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
796 CaretValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
797 CaretValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
798 other => Err(ReadError::InvalidFormat(other.into())),
799 }
800 }
801}
802
803impl<'a> MinByteRange<'a> for CaretValue<'a> {
804 fn min_byte_range(&self) -> Range<usize> {
805 match self {
806 Self::Format1(item) => item.min_byte_range(),
807 Self::Format2(item) => item.min_byte_range(),
808 Self::Format3(item) => item.min_byte_range(),
809 }
810 }
811 fn min_table_bytes(&self) -> &'a [u8] {
812 match self {
813 Self::Format1(item) => item.min_table_bytes(),
814 Self::Format2(item) => item.min_table_bytes(),
815 Self::Format3(item) => item.min_table_bytes(),
816 }
817 }
818}
819
820#[cfg(feature = "experimental_traverse")]
821impl<'a> CaretValue<'a> {
822 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
823 match self {
824 Self::Format1(table) => table,
825 Self::Format2(table) => table,
826 Self::Format3(table) => table,
827 }
828 }
829}
830
831#[cfg(feature = "experimental_traverse")]
832impl std::fmt::Debug for CaretValue<'_> {
833 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
834 self.dyn_inner().fmt(f)
835 }
836}
837
838#[cfg(feature = "experimental_traverse")]
839impl<'a> SomeTable<'a> for CaretValue<'a> {
840 fn type_name(&self) -> &str {
841 self.dyn_inner().type_name()
842 }
843 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
844 self.dyn_inner().get_field(idx)
845 }
846}
847
848impl Format<u16> for CaretValueFormat1<'_> {
849 const FORMAT: u16 = 1;
850}
851
852impl<'a> MinByteRange<'a> for CaretValueFormat1<'a> {
853 fn min_byte_range(&self) -> Range<usize> {
854 0..self.coordinate_byte_range().end
855 }
856 fn min_table_bytes(&self) -> &'a [u8] {
857 let range = self.min_byte_range();
858 self.data.as_bytes().get(range).unwrap_or_default()
859 }
860}
861
862impl ReadArgs for CaretValueFormat1<'_> {
863 type Args = ();
864}
865
866impl<'a> FontRead<'a> for CaretValueFormat1<'a> {
867 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
868 #[allow(clippy::absurd_extreme_comparisons)]
869 if data.len() < Self::MIN_SIZE {
870 return Err(ReadError::OutOfBounds);
871 }
872 Ok(Self { data })
873 }
874}
875
876#[derive(Clone)]
878pub struct CaretValueFormat1<'a> {
879 data: FontData<'a>,
880}
881
882#[allow(clippy::needless_lifetimes)]
883impl<'a> CaretValueFormat1<'a> {
884 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN);
885 basic_table_impls!(impl_the_methods);
886
887 pub fn caret_value_format(&self) -> u16 {
889 let range = self.caret_value_format_byte_range();
890 self.data.read_at(range.start).ok().unwrap()
891 }
892
893 pub fn coordinate(&self) -> i16 {
895 let range = self.coordinate_byte_range();
896 self.data.read_at(range.start).ok().unwrap()
897 }
898
899 pub fn caret_value_format_byte_range(&self) -> Range<usize> {
900 let start = 0;
901 let end = start + u16::RAW_BYTE_LEN;
902 start..end
903 }
904
905 pub fn coordinate_byte_range(&self) -> Range<usize> {
906 let start = self.caret_value_format_byte_range().end;
907 let end = start + i16::RAW_BYTE_LEN;
908 start..end
909 }
910}
911
912const _: () = assert!(FontData::default_data_long_enough(
913 CaretValueFormat1::MIN_SIZE
914));
915
916impl Default for CaretValueFormat1<'_> {
917 fn default() -> Self {
918 Self {
919 data: FontData::default_format_1_u16_table_data(),
920 }
921 }
922}
923
924#[cfg(feature = "experimental_traverse")]
925impl<'a> SomeTable<'a> for CaretValueFormat1<'a> {
926 fn type_name(&self) -> &str {
927 "CaretValueFormat1"
928 }
929 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
930 match idx {
931 0usize => Some(Field::new("caret_value_format", self.caret_value_format())),
932 1usize => Some(Field::new("coordinate", self.coordinate())),
933 _ => None,
934 }
935 }
936}
937
938#[cfg(feature = "experimental_traverse")]
939#[allow(clippy::needless_lifetimes)]
940impl<'a> std::fmt::Debug for CaretValueFormat1<'a> {
941 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
942 (self as &dyn SomeTable<'a>).fmt(f)
943 }
944}
945
946impl Format<u16> for CaretValueFormat2<'_> {
947 const FORMAT: u16 = 2;
948}
949
950impl<'a> MinByteRange<'a> for CaretValueFormat2<'a> {
951 fn min_byte_range(&self) -> Range<usize> {
952 0..self.caret_value_point_index_byte_range().end
953 }
954 fn min_table_bytes(&self) -> &'a [u8] {
955 let range = self.min_byte_range();
956 self.data.as_bytes().get(range).unwrap_or_default()
957 }
958}
959
960impl ReadArgs for CaretValueFormat2<'_> {
961 type Args = ();
962}
963
964impl<'a> FontRead<'a> for CaretValueFormat2<'a> {
965 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
966 #[allow(clippy::absurd_extreme_comparisons)]
967 if data.len() < Self::MIN_SIZE {
968 return Err(ReadError::OutOfBounds);
969 }
970 Ok(Self { data })
971 }
972}
973
974#[derive(Clone)]
976pub struct CaretValueFormat2<'a> {
977 data: FontData<'a>,
978}
979
980#[allow(clippy::needless_lifetimes)]
981impl<'a> CaretValueFormat2<'a> {
982 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
983 basic_table_impls!(impl_the_methods);
984
985 pub fn caret_value_format(&self) -> u16 {
987 let range = self.caret_value_format_byte_range();
988 self.data.read_at(range.start).ok().unwrap()
989 }
990
991 pub fn caret_value_point_index(&self) -> u16 {
993 let range = self.caret_value_point_index_byte_range();
994 self.data.read_at(range.start).ok().unwrap()
995 }
996
997 pub fn caret_value_format_byte_range(&self) -> Range<usize> {
998 let start = 0;
999 let end = start + u16::RAW_BYTE_LEN;
1000 start..end
1001 }
1002
1003 pub fn caret_value_point_index_byte_range(&self) -> Range<usize> {
1004 let start = self.caret_value_format_byte_range().end;
1005 let end = start + u16::RAW_BYTE_LEN;
1006 start..end
1007 }
1008}
1009
1010#[cfg(feature = "experimental_traverse")]
1011impl<'a> SomeTable<'a> for CaretValueFormat2<'a> {
1012 fn type_name(&self) -> &str {
1013 "CaretValueFormat2"
1014 }
1015 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1016 match idx {
1017 0usize => Some(Field::new("caret_value_format", self.caret_value_format())),
1018 1usize => Some(Field::new(
1019 "caret_value_point_index",
1020 self.caret_value_point_index(),
1021 )),
1022 _ => None,
1023 }
1024 }
1025}
1026
1027#[cfg(feature = "experimental_traverse")]
1028#[allow(clippy::needless_lifetimes)]
1029impl<'a> std::fmt::Debug for CaretValueFormat2<'a> {
1030 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1031 (self as &dyn SomeTable<'a>).fmt(f)
1032 }
1033}
1034
1035impl Format<u16> for CaretValueFormat3<'_> {
1036 const FORMAT: u16 = 3;
1037}
1038
1039impl<'a> MinByteRange<'a> for CaretValueFormat3<'a> {
1040 fn min_byte_range(&self) -> Range<usize> {
1041 0..self.device_offset_byte_range().end
1042 }
1043 fn min_table_bytes(&self) -> &'a [u8] {
1044 let range = self.min_byte_range();
1045 self.data.as_bytes().get(range).unwrap_or_default()
1046 }
1047}
1048
1049impl ReadArgs for CaretValueFormat3<'_> {
1050 type Args = ();
1051}
1052
1053impl<'a> FontRead<'a> for CaretValueFormat3<'a> {
1054 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1055 #[allow(clippy::absurd_extreme_comparisons)]
1056 if data.len() < Self::MIN_SIZE {
1057 return Err(ReadError::OutOfBounds);
1058 }
1059 Ok(Self { data })
1060 }
1061}
1062
1063#[derive(Clone)]
1065pub struct CaretValueFormat3<'a> {
1066 data: FontData<'a>,
1067}
1068
1069#[allow(clippy::needless_lifetimes)]
1070impl<'a> CaretValueFormat3<'a> {
1071 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
1072 basic_table_impls!(impl_the_methods);
1073
1074 pub fn caret_value_format(&self) -> u16 {
1076 let range = self.caret_value_format_byte_range();
1077 self.data.read_at(range.start).ok().unwrap()
1078 }
1079
1080 pub fn coordinate(&self) -> i16 {
1082 let range = self.coordinate_byte_range();
1083 self.data.read_at(range.start).ok().unwrap()
1084 }
1085
1086 pub fn device_offset(&self) -> Offset16 {
1090 let range = self.device_offset_byte_range();
1091 self.data.read_at(range.start).ok().unwrap()
1092 }
1093
1094 pub fn device(&self) -> Result<DeviceOrVariationIndex<'a>, ReadError> {
1096 let data = self.data;
1097 self.device_offset().resolve(data)
1098 }
1099
1100 pub fn caret_value_format_byte_range(&self) -> Range<usize> {
1101 let start = 0;
1102 let end = start + u16::RAW_BYTE_LEN;
1103 start..end
1104 }
1105
1106 pub fn coordinate_byte_range(&self) -> Range<usize> {
1107 let start = self.caret_value_format_byte_range().end;
1108 let end = start + i16::RAW_BYTE_LEN;
1109 start..end
1110 }
1111
1112 pub fn device_offset_byte_range(&self) -> Range<usize> {
1113 let start = self.coordinate_byte_range().end;
1114 let end = start + Offset16::RAW_BYTE_LEN;
1115 start..end
1116 }
1117}
1118
1119#[cfg(feature = "experimental_traverse")]
1120impl<'a> SomeTable<'a> for CaretValueFormat3<'a> {
1121 fn type_name(&self) -> &str {
1122 "CaretValueFormat3"
1123 }
1124 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1125 match idx {
1126 0usize => Some(Field::new("caret_value_format", self.caret_value_format())),
1127 1usize => Some(Field::new("coordinate", self.coordinate())),
1128 2usize => Some(Field::new(
1129 "device_offset",
1130 FieldType::offset(self.device_offset(), self.device()),
1131 )),
1132 _ => None,
1133 }
1134 }
1135}
1136
1137#[cfg(feature = "experimental_traverse")]
1138#[allow(clippy::needless_lifetimes)]
1139impl<'a> std::fmt::Debug for CaretValueFormat3<'a> {
1140 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1141 (self as &dyn SomeTable<'a>).fmt(f)
1142 }
1143}
1144
1145impl Format<u16> for MarkGlyphSets<'_> {
1146 const FORMAT: u16 = 1;
1147}
1148
1149impl<'a> MinByteRange<'a> for MarkGlyphSets<'a> {
1150 fn min_byte_range(&self) -> Range<usize> {
1151 0..self.coverage_offsets_byte_range().end
1152 }
1153 fn min_table_bytes(&self) -> &'a [u8] {
1154 let range = self.min_byte_range();
1155 self.data.as_bytes().get(range).unwrap_or_default()
1156 }
1157}
1158
1159impl ReadArgs for MarkGlyphSets<'_> {
1160 type Args = ();
1161}
1162
1163impl<'a> FontRead<'a> for MarkGlyphSets<'a> {
1164 fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1165 #[allow(clippy::absurd_extreme_comparisons)]
1166 if data.len() < Self::MIN_SIZE {
1167 return Err(ReadError::OutOfBounds);
1168 }
1169 Ok(Self { data })
1170 }
1171}
1172
1173#[derive(Clone)]
1175pub struct MarkGlyphSets<'a> {
1176 data: FontData<'a>,
1177}
1178
1179#[allow(clippy::needless_lifetimes)]
1180impl<'a> MarkGlyphSets<'a> {
1181 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1182 basic_table_impls!(impl_the_methods);
1183
1184 pub fn format(&self) -> u16 {
1186 let range = self.format_byte_range();
1187 self.data.read_at(range.start).ok().unwrap()
1188 }
1189
1190 pub fn mark_glyph_set_count(&self) -> u16 {
1192 let range = self.mark_glyph_set_count_byte_range();
1193 self.data.read_at(range.start).ok().unwrap()
1194 }
1195
1196 pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset32>] {
1199 let range = self.coverage_offsets_byte_range();
1200 self.data.read_array(range).ok().unwrap_or_default()
1201 }
1202
1203 pub fn coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset32> {
1205 let data = self.data;
1206 let offsets = self.coverage_offsets();
1207 ArrayOfOffsets::new(offsets, data, ())
1208 }
1209
1210 pub fn format_byte_range(&self) -> Range<usize> {
1211 let start = 0;
1212 let end = start + u16::RAW_BYTE_LEN;
1213 start..end
1214 }
1215
1216 pub fn mark_glyph_set_count_byte_range(&self) -> Range<usize> {
1217 let start = self.format_byte_range().end;
1218 let end = start + u16::RAW_BYTE_LEN;
1219 start..end
1220 }
1221
1222 pub fn coverage_offsets_byte_range(&self) -> Range<usize> {
1223 let mark_glyph_set_count = self.mark_glyph_set_count();
1224 let start = self.mark_glyph_set_count_byte_range().end;
1225 let end = start
1226 + (transforms::to_usize(mark_glyph_set_count)).saturating_mul(Offset32::RAW_BYTE_LEN);
1227 start..end
1228 }
1229}
1230
1231const _: () = assert!(FontData::default_data_long_enough(MarkGlyphSets::MIN_SIZE));
1232
1233impl Default for MarkGlyphSets<'_> {
1234 fn default() -> Self {
1235 Self {
1236 data: FontData::default_format_1_u16_table_data(),
1237 }
1238 }
1239}
1240
1241#[cfg(feature = "experimental_traverse")]
1242impl<'a> SomeTable<'a> for MarkGlyphSets<'a> {
1243 fn type_name(&self) -> &str {
1244 "MarkGlyphSets"
1245 }
1246 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1247 match idx {
1248 0usize => Some(Field::new("format", self.format())),
1249 1usize => Some(Field::new(
1250 "mark_glyph_set_count",
1251 self.mark_glyph_set_count(),
1252 )),
1253 2usize => Some(Field::new(
1254 "coverage_offsets",
1255 FieldType::from(self.coverages()),
1256 )),
1257 _ => None,
1258 }
1259 }
1260}
1261
1262#[cfg(feature = "experimental_traverse")]
1263#[allow(clippy::needless_lifetimes)]
1264impl<'a> std::fmt::Debug for MarkGlyphSets<'a> {
1265 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1266 (self as &dyn SomeTable<'a>).fmt(f)
1267 }
1268}