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