read_fonts/generated/
generated_gdef.rs

1// THIS FILE IS AUTOGENERATED.
2// Any changes to this file will be overwritten.
3// For more information about how codegen works, see font-codegen/README.md
4
5#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8/// [GDEF](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#gdef-header) 1.0
9#[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    /// `GDEF`
61    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
93/// [GDEF](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#gdef-header) 1.0
94pub type Gdef<'a> = TableRef<'a, GdefMarker>;
95
96#[allow(clippy::needless_lifetimes)]
97impl<'a> Gdef<'a> {
98    /// The major/minor version of the GDEF table
99    pub fn version(&self) -> MajorMinor {
100        let range = self.shape.version_byte_range();
101        self.data.read_at(range.start).unwrap()
102    }
103
104    /// Offset to class definition table for glyph type, from beginning
105    /// of GDEF header (may be NULL)
106    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    /// Attempt to resolve [`glyph_class_def_offset`][Self::glyph_class_def_offset].
112    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    /// Offset to attachment point list table, from beginning of GDEF
118    /// header (may be NULL)
119    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    /// Attempt to resolve [`attach_list_offset`][Self::attach_list_offset].
125    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    /// Offset to ligature caret list table, from beginning of GDEF
131    /// header (may be NULL)
132    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    /// Attempt to resolve [`lig_caret_list_offset`][Self::lig_caret_list_offset].
138    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    /// Offset to class definition table for mark attachment type, from
144    /// beginning of GDEF header (may be NULL)
145    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    /// Attempt to resolve [`mark_attach_class_def_offset`][Self::mark_attach_class_def_offset].
151    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    /// Offset to the table of mark glyph set definitions, from
157    /// beginning of GDEF header (may be NULL)
158    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    /// Attempt to resolve [`mark_glyph_sets_def_offset`][Self::mark_glyph_sets_def_offset].
164    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    /// Offset to the Item Variation Store table, from beginning of
170    /// GDEF header (may be NULL)
171    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    /// Attempt to resolve [`item_var_store_offset`][Self::item_var_store_offset].
177    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/// Used in the [Glyph Class Definition Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#glyph-class-definition-table)
236#[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    /// If font data is malformed we will map unknown values to this variant
248    Unknown,
249}
250
251impl GlyphClassDef {
252    /// Create from a raw scalar.
253    ///
254    /// This will never fail; unknown values will be mapped to the `Unknown` variant
255    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/// [Attachment Point List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#attachment-point-list-table)
285#[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
329/// [Attachment Point List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#attachment-point-list-table)
330pub type AttachList<'a> = TableRef<'a, AttachListMarker>;
331
332#[allow(clippy::needless_lifetimes)]
333impl<'a> AttachList<'a> {
334    /// Offset to Coverage table - from beginning of AttachList table
335    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    /// Attempt to resolve [`coverage_offset`][Self::coverage_offset].
341    pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
342        let data = self.data;
343        self.coverage_offset().resolve(data)
344    }
345
346    /// Number of glyphs with attachment points
347    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    /// Array of offsets to AttachPoint tables-from beginning of
353    /// AttachList table-in Coverage Index order
354    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    /// A dynamically resolving wrapper for [`attach_point_offsets`][Self::attach_point_offsets].
360    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/// Part of [AttachList]
407#[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
445/// Part of [AttachList]
446pub type AttachPoint<'a> = TableRef<'a, AttachPointMarker>;
447
448#[allow(clippy::needless_lifetimes)]
449impl<'a> AttachPoint<'a> {
450    /// Number of attachment points on this glyph
451    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    /// Array of contour point indices -in increasing numerical order
457    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/// [Ligature Caret List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#ligature-caret-list-table)
486#[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
530/// [Ligature Caret List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#ligature-caret-list-table)
531pub type LigCaretList<'a> = TableRef<'a, LigCaretListMarker>;
532
533#[allow(clippy::needless_lifetimes)]
534impl<'a> LigCaretList<'a> {
535    /// Offset to Coverage table - from beginning of LigCaretList table
536    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    /// Attempt to resolve [`coverage_offset`][Self::coverage_offset].
542    pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
543        let data = self.data;
544        self.coverage_offset().resolve(data)
545    }
546
547    /// Number of ligature glyphs
548    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    /// Array of offsets to LigGlyph tables, from beginning of
554    /// LigCaretList table —in Coverage Index order
555    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    /// A dynamically resolving wrapper for [`lig_glyph_offsets`][Self::lig_glyph_offsets].
561    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/// [Ligature Glyph Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#ligature-glyph-table)
608#[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
646/// [Ligature Glyph Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#ligature-glyph-table)
647pub type LigGlyph<'a> = TableRef<'a, LigGlyphMarker>;
648
649#[allow(clippy::needless_lifetimes)]
650impl<'a> LigGlyph<'a> {
651    /// Number of CaretValue tables for this ligature (components - 1)
652    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    /// Array of offsets to CaretValue tables, from beginning of
658    /// LigGlyph table — in increasing coordinate order
659    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    /// A dynamically resolving wrapper for [`caret_value_offsets`][Self::caret_value_offsets].
665    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/// [Caret Value Tables](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caret-value-tables)
708#[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    ///Return the `FontData` used to resolve offsets for this table.
717    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    /// Format identifier: format = 1
726    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/// [CaretValue Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-1)
790#[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
821/// [CaretValue Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-1)
822pub type CaretValueFormat1<'a> = TableRef<'a, CaretValueFormat1Marker>;
823
824#[allow(clippy::needless_lifetimes)]
825impl<'a> CaretValueFormat1<'a> {
826    /// Format identifier: format = 1
827    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    /// X or Y value, in design units
833    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/// [CaretValue Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-2)
866#[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
897/// [CaretValue Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-2)
898pub type CaretValueFormat2<'a> = TableRef<'a, CaretValueFormat2Marker>;
899
900#[allow(clippy::needless_lifetimes)]
901impl<'a> CaretValueFormat2<'a> {
902    /// Format identifier: format = 2
903    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    /// Contour point index on glyph
909    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/// [CaretValue Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-3)
945#[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
982/// [CaretValue Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-3)
983pub type CaretValueFormat3<'a> = TableRef<'a, CaretValueFormat3Marker>;
984
985#[allow(clippy::needless_lifetimes)]
986impl<'a> CaretValueFormat3<'a> {
987    /// Format identifier-format = 3
988    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    /// X or Y value, in design units
994    pub fn coordinate(&self) -> i16 {
995        let range = self.shape.coordinate_byte_range();
996        self.data.read_at(range.start).unwrap()
997    }
998
999    /// Offset to Device table (non-variable font) / Variation Index
1000    /// table (variable font) for X or Y value-from beginning of
1001    /// CaretValue table
1002    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    /// Attempt to resolve [`device_offset`][Self::device_offset].
1008    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/// [Mark Glyph Sets Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#mark-glyph-sets-table)
1045#[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
1089/// [Mark Glyph Sets Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#mark-glyph-sets-table)
1090pub type MarkGlyphSets<'a> = TableRef<'a, MarkGlyphSetsMarker>;
1091
1092#[allow(clippy::needless_lifetimes)]
1093impl<'a> MarkGlyphSets<'a> {
1094    /// Format identifier == 1
1095    pub fn format(&self) -> u16 {
1096        let range = self.shape.format_byte_range();
1097        self.data.read_at(range.start).unwrap()
1098    }
1099
1100    /// Number of mark glyph sets defined
1101    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    /// Array of offsets to mark glyph set coverage tables, from the
1107    /// start of the MarkGlyphSets table.
1108    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    /// A dynamically resolving wrapper for [`coverage_offsets`][Self::coverage_offsets].
1114    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}