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