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