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