Skip to main content

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
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    /// `GDEF`
20    const TAG: Tag = Tag::new(b"GDEF");
21}
22
23impl ReadArgs for Gdef<'_> {
24    type Args = ();
25}
26
27impl<'a> FontRead<'a> for Gdef<'a> {
28    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
29        #[allow(clippy::absurd_extreme_comparisons)]
30        if data.len() < Self::MIN_SIZE {
31            return Err(ReadError::OutOfBounds);
32        }
33        Ok(Self { data })
34    }
35}
36
37/// [GDEF](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#gdef-header) 1.0
38#[derive(Clone)]
39pub struct Gdef<'a> {
40    data: FontData<'a>,
41}
42
43#[allow(clippy::needless_lifetimes)]
44impl<'a> Gdef<'a> {
45    pub const MIN_SIZE: usize = (MajorMinor::RAW_BYTE_LEN
46        + Offset16::RAW_BYTE_LEN
47        + Offset16::RAW_BYTE_LEN
48        + Offset16::RAW_BYTE_LEN
49        + Offset16::RAW_BYTE_LEN);
50    basic_table_impls!(impl_the_methods);
51
52    /// The major/minor version of the GDEF table
53    pub fn version(&self) -> MajorMinor {
54        let range = self.version_byte_range();
55        self.data.read_at(range.start).ok().unwrap()
56    }
57
58    /// Offset to class definition table for glyph type, from beginning
59    /// of GDEF header (may be NULL)
60    pub fn glyph_class_def_offset(&self) -> Nullable<Offset16> {
61        let range = self.glyph_class_def_offset_byte_range();
62        self.data.read_at(range.start).ok().unwrap()
63    }
64
65    /// Attempt to resolve [`glyph_class_def_offset`][Self::glyph_class_def_offset].
66    pub fn glyph_class_def(&self) -> Option<Result<ClassDef<'a>, ReadError>> {
67        let data = self.data;
68        self.glyph_class_def_offset().resolve(data)
69    }
70
71    /// Offset to attachment point list table, from beginning of GDEF
72    /// header (may be NULL)
73    pub fn attach_list_offset(&self) -> Nullable<Offset16> {
74        let range = self.attach_list_offset_byte_range();
75        self.data.read_at(range.start).ok().unwrap()
76    }
77
78    /// Attempt to resolve [`attach_list_offset`][Self::attach_list_offset].
79    pub fn attach_list(&self) -> Option<Result<AttachList<'a>, ReadError>> {
80        let data = self.data;
81        self.attach_list_offset().resolve(data)
82    }
83
84    /// Offset to ligature caret list table, from beginning of GDEF
85    /// header (may be NULL)
86    pub fn lig_caret_list_offset(&self) -> Nullable<Offset16> {
87        let range = self.lig_caret_list_offset_byte_range();
88        self.data.read_at(range.start).ok().unwrap()
89    }
90
91    /// Attempt to resolve [`lig_caret_list_offset`][Self::lig_caret_list_offset].
92    pub fn lig_caret_list(&self) -> Option<Result<LigCaretList<'a>, ReadError>> {
93        let data = self.data;
94        self.lig_caret_list_offset().resolve(data)
95    }
96
97    /// Offset to class definition table for mark attachment type, from
98    /// beginning of GDEF header (may be NULL)
99    pub fn mark_attach_class_def_offset(&self) -> Nullable<Offset16> {
100        let range = self.mark_attach_class_def_offset_byte_range();
101        self.data.read_at(range.start).ok().unwrap()
102    }
103
104    /// Attempt to resolve [`mark_attach_class_def_offset`][Self::mark_attach_class_def_offset].
105    pub fn mark_attach_class_def(&self) -> Option<Result<ClassDef<'a>, ReadError>> {
106        let data = self.data;
107        self.mark_attach_class_def_offset().resolve(data)
108    }
109
110    /// Offset to the table of mark glyph set definitions, from
111    /// beginning of GDEF header (may be NULL)
112    pub fn mark_glyph_sets_def_offset(&self) -> Option<Nullable<Offset16>> {
113        let range = self.mark_glyph_sets_def_offset_byte_range();
114        (!range.is_empty())
115            .then(|| self.data.read_at(range.start).ok())
116            .flatten()
117    }
118
119    /// Attempt to resolve [`mark_glyph_sets_def_offset`][Self::mark_glyph_sets_def_offset].
120    pub fn mark_glyph_sets_def(&self) -> Option<Result<MarkGlyphSets<'a>, ReadError>> {
121        let data = self.data;
122        self.mark_glyph_sets_def_offset().map(|x| x.resolve(data))?
123    }
124
125    /// Offset to the Item Variation Store table, from beginning of
126    /// GDEF header (may be NULL)
127    pub fn item_var_store_offset(&self) -> Option<Nullable<Offset32>> {
128        let range = self.item_var_store_offset_byte_range();
129        (!range.is_empty())
130            .then(|| self.data.read_at(range.start).ok())
131            .flatten()
132    }
133
134    /// Attempt to resolve [`item_var_store_offset`][Self::item_var_store_offset].
135    pub fn item_var_store(&self) -> Option<Result<ItemVariationStore<'a>, ReadError>> {
136        let data = self.data;
137        self.item_var_store_offset().map(|x| x.resolve(data))?
138    }
139
140    pub fn version_byte_range(&self) -> Range<usize> {
141        let start = 0;
142        let end = start + MajorMinor::RAW_BYTE_LEN;
143        start..end
144    }
145
146    pub fn glyph_class_def_offset_byte_range(&self) -> Range<usize> {
147        let start = self.version_byte_range().end;
148        let end = start + Offset16::RAW_BYTE_LEN;
149        start..end
150    }
151
152    pub fn attach_list_offset_byte_range(&self) -> Range<usize> {
153        let start = self.glyph_class_def_offset_byte_range().end;
154        let end = start + Offset16::RAW_BYTE_LEN;
155        start..end
156    }
157
158    pub fn lig_caret_list_offset_byte_range(&self) -> Range<usize> {
159        let start = self.attach_list_offset_byte_range().end;
160        let end = start + Offset16::RAW_BYTE_LEN;
161        start..end
162    }
163
164    pub fn mark_attach_class_def_offset_byte_range(&self) -> Range<usize> {
165        let start = self.lig_caret_list_offset_byte_range().end;
166        let end = start + Offset16::RAW_BYTE_LEN;
167        start..end
168    }
169
170    pub fn mark_glyph_sets_def_offset_byte_range(&self) -> Range<usize> {
171        let start = self.mark_attach_class_def_offset_byte_range().end;
172        let end = if self.version().compatible((1u16, 2u16)) {
173            start + Offset16::RAW_BYTE_LEN
174        } else {
175            start
176        };
177        start..end
178    }
179
180    pub fn item_var_store_offset_byte_range(&self) -> Range<usize> {
181        let start = self.mark_glyph_sets_def_offset_byte_range().end;
182        let end = if self.version().compatible((1u16, 3u16)) {
183            start + Offset32::RAW_BYTE_LEN
184        } else {
185            start
186        };
187        start..end
188    }
189}
190
191const _: () = assert!(FontData::default_data_long_enough(Gdef::MIN_SIZE));
192
193impl Default for Gdef<'_> {
194    fn default() -> Self {
195        Self {
196            data: FontData::default_table_data(),
197        }
198    }
199}
200
201/// Used in the [Glyph Class Definition Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#glyph-class-definition-table)
202#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
203#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
204#[repr(u16)]
205#[allow(clippy::manual_non_exhaustive)]
206pub enum GlyphClassDef {
207    #[default]
208    Base = 1,
209    Ligature = 2,
210    Mark = 3,
211    Component = 4,
212    #[doc(hidden)]
213    /// If font data is malformed we will map unknown values to this variant
214    Unknown,
215}
216
217impl GlyphClassDef {
218    /// Create from a raw scalar.
219    ///
220    /// This will never fail; unknown values will be mapped to the `Unknown` variant
221    pub fn new(raw: u16) -> Self {
222        match raw {
223            1 => Self::Base,
224            2 => Self::Ligature,
225            3 => Self::Mark,
226            4 => Self::Component,
227            _ => Self::Unknown,
228        }
229    }
230}
231
232impl font_types::Scalar for GlyphClassDef {
233    type Raw = <u16 as font_types::Scalar>::Raw;
234    fn to_raw(self) -> Self::Raw {
235        (self as u16).to_raw()
236    }
237    fn from_raw(raw: Self::Raw) -> Self {
238        let t = <u16>::from_raw(raw);
239        Self::new(t)
240    }
241}
242
243impl<'a> MinByteRange<'a> for AttachList<'a> {
244    fn min_byte_range(&self) -> Range<usize> {
245        0..self.attach_point_offsets_byte_range().end
246    }
247    fn min_table_bytes(&self) -> &'a [u8] {
248        let range = self.min_byte_range();
249        self.data.as_bytes().get(range).unwrap_or_default()
250    }
251}
252
253impl ReadArgs for AttachList<'_> {
254    type Args = ();
255}
256
257impl<'a> FontRead<'a> for AttachList<'a> {
258    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
259        #[allow(clippy::absurd_extreme_comparisons)]
260        if data.len() < Self::MIN_SIZE {
261            return Err(ReadError::OutOfBounds);
262        }
263        Ok(Self { data })
264    }
265}
266
267/// [Attachment Point List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#attachment-point-list-table)
268#[derive(Clone)]
269pub struct AttachList<'a> {
270    data: FontData<'a>,
271}
272
273#[allow(clippy::needless_lifetimes)]
274impl<'a> AttachList<'a> {
275    pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
276    basic_table_impls!(impl_the_methods);
277
278    /// Offset to Coverage table - from beginning of AttachList table
279    pub fn coverage_offset(&self) -> Offset16 {
280        let range = self.coverage_offset_byte_range();
281        self.data.read_at(range.start).ok().unwrap()
282    }
283
284    /// Attempt to resolve [`coverage_offset`][Self::coverage_offset].
285    pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
286        let data = self.data;
287        self.coverage_offset().resolve(data)
288    }
289
290    /// Number of glyphs with attachment points
291    pub fn glyph_count(&self) -> u16 {
292        let range = self.glyph_count_byte_range();
293        self.data.read_at(range.start).ok().unwrap()
294    }
295
296    /// Array of offsets to AttachPoint tables-from beginning of
297    /// AttachList table-in Coverage Index order
298    pub fn attach_point_offsets(&self) -> &'a [BigEndian<Offset16>] {
299        let range = self.attach_point_offsets_byte_range();
300        self.data.read_array(range).ok().unwrap_or_default()
301    }
302
303    /// A dynamically resolving wrapper for [`attach_point_offsets`][Self::attach_point_offsets].
304    pub fn attach_points(&self) -> ArrayOfOffsets<'a, AttachPoint<'a>, Offset16> {
305        let data = self.data;
306        let offsets = self.attach_point_offsets();
307        ArrayOfOffsets::new(offsets, data, ())
308    }
309
310    pub fn coverage_offset_byte_range(&self) -> Range<usize> {
311        let start = 0;
312        let end = start + Offset16::RAW_BYTE_LEN;
313        start..end
314    }
315
316    pub fn glyph_count_byte_range(&self) -> Range<usize> {
317        let start = self.coverage_offset_byte_range().end;
318        let end = start + u16::RAW_BYTE_LEN;
319        start..end
320    }
321
322    pub fn attach_point_offsets_byte_range(&self) -> Range<usize> {
323        let glyph_count = self.glyph_count();
324        let start = self.glyph_count_byte_range().end;
325        let end =
326            start + (transforms::to_usize(glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
327        start..end
328    }
329}
330
331const _: () = assert!(FontData::default_data_long_enough(AttachList::MIN_SIZE));
332
333impl Default for AttachList<'_> {
334    fn default() -> Self {
335        Self {
336            data: FontData::default_table_data(),
337        }
338    }
339}
340
341impl<'a> MinByteRange<'a> for AttachPoint<'a> {
342    fn min_byte_range(&self) -> Range<usize> {
343        0..self.point_indices_byte_range().end
344    }
345    fn min_table_bytes(&self) -> &'a [u8] {
346        let range = self.min_byte_range();
347        self.data.as_bytes().get(range).unwrap_or_default()
348    }
349}
350
351impl ReadArgs for AttachPoint<'_> {
352    type Args = ();
353}
354
355impl<'a> FontRead<'a> for AttachPoint<'a> {
356    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
357        #[allow(clippy::absurd_extreme_comparisons)]
358        if data.len() < Self::MIN_SIZE {
359            return Err(ReadError::OutOfBounds);
360        }
361        Ok(Self { data })
362    }
363}
364
365/// Part of [AttachList]
366#[derive(Clone)]
367pub struct AttachPoint<'a> {
368    data: FontData<'a>,
369}
370
371#[allow(clippy::needless_lifetimes)]
372impl<'a> AttachPoint<'a> {
373    pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
374    basic_table_impls!(impl_the_methods);
375
376    /// Number of attachment points on this glyph
377    pub fn point_count(&self) -> u16 {
378        let range = self.point_count_byte_range();
379        self.data.read_at(range.start).ok().unwrap()
380    }
381
382    /// Array of contour point indices -in increasing numerical order
383    pub fn point_indices(&self) -> &'a [BigEndian<u16>] {
384        let range = self.point_indices_byte_range();
385        self.data.read_array(range).ok().unwrap_or_default()
386    }
387
388    pub fn point_count_byte_range(&self) -> Range<usize> {
389        let start = 0;
390        let end = start + u16::RAW_BYTE_LEN;
391        start..end
392    }
393
394    pub fn point_indices_byte_range(&self) -> Range<usize> {
395        let point_count = self.point_count();
396        let start = self.point_count_byte_range().end;
397        let end = start + (transforms::to_usize(point_count)).saturating_mul(u16::RAW_BYTE_LEN);
398        start..end
399    }
400}
401
402const _: () = assert!(FontData::default_data_long_enough(AttachPoint::MIN_SIZE));
403
404impl Default for AttachPoint<'_> {
405    fn default() -> Self {
406        Self {
407            data: FontData::default_table_data(),
408        }
409    }
410}
411
412impl<'a> MinByteRange<'a> for LigCaretList<'a> {
413    fn min_byte_range(&self) -> Range<usize> {
414        0..self.lig_glyph_offsets_byte_range().end
415    }
416    fn min_table_bytes(&self) -> &'a [u8] {
417        let range = self.min_byte_range();
418        self.data.as_bytes().get(range).unwrap_or_default()
419    }
420}
421
422impl ReadArgs for LigCaretList<'_> {
423    type Args = ();
424}
425
426impl<'a> FontRead<'a> for LigCaretList<'a> {
427    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
428        #[allow(clippy::absurd_extreme_comparisons)]
429        if data.len() < Self::MIN_SIZE {
430            return Err(ReadError::OutOfBounds);
431        }
432        Ok(Self { data })
433    }
434}
435
436/// [Ligature Caret List Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#ligature-caret-list-table)
437#[derive(Clone)]
438pub struct LigCaretList<'a> {
439    data: FontData<'a>,
440}
441
442#[allow(clippy::needless_lifetimes)]
443impl<'a> LigCaretList<'a> {
444    pub const MIN_SIZE: usize = (Offset16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
445    basic_table_impls!(impl_the_methods);
446
447    /// Offset to Coverage table - from beginning of LigCaretList table
448    pub fn coverage_offset(&self) -> Offset16 {
449        let range = self.coverage_offset_byte_range();
450        self.data.read_at(range.start).ok().unwrap()
451    }
452
453    /// Attempt to resolve [`coverage_offset`][Self::coverage_offset].
454    pub fn coverage(&self) -> Result<CoverageTable<'a>, ReadError> {
455        let data = self.data;
456        self.coverage_offset().resolve(data)
457    }
458
459    /// Number of ligature glyphs
460    pub fn lig_glyph_count(&self) -> u16 {
461        let range = self.lig_glyph_count_byte_range();
462        self.data.read_at(range.start).ok().unwrap()
463    }
464
465    /// Array of offsets to LigGlyph tables, from beginning of
466    /// LigCaretList table —in Coverage Index order
467    pub fn lig_glyph_offsets(&self) -> &'a [BigEndian<Offset16>] {
468        let range = self.lig_glyph_offsets_byte_range();
469        self.data.read_array(range).ok().unwrap_or_default()
470    }
471
472    /// A dynamically resolving wrapper for [`lig_glyph_offsets`][Self::lig_glyph_offsets].
473    pub fn lig_glyphs(&self) -> ArrayOfOffsets<'a, LigGlyph<'a>, Offset16> {
474        let data = self.data;
475        let offsets = self.lig_glyph_offsets();
476        ArrayOfOffsets::new(offsets, data, ())
477    }
478
479    pub fn coverage_offset_byte_range(&self) -> Range<usize> {
480        let start = 0;
481        let end = start + Offset16::RAW_BYTE_LEN;
482        start..end
483    }
484
485    pub fn lig_glyph_count_byte_range(&self) -> Range<usize> {
486        let start = self.coverage_offset_byte_range().end;
487        let end = start + u16::RAW_BYTE_LEN;
488        start..end
489    }
490
491    pub fn lig_glyph_offsets_byte_range(&self) -> Range<usize> {
492        let lig_glyph_count = self.lig_glyph_count();
493        let start = self.lig_glyph_count_byte_range().end;
494        let end =
495            start + (transforms::to_usize(lig_glyph_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
496        start..end
497    }
498}
499
500const _: () = assert!(FontData::default_data_long_enough(LigCaretList::MIN_SIZE));
501
502impl Default for LigCaretList<'_> {
503    fn default() -> Self {
504        Self {
505            data: FontData::default_table_data(),
506        }
507    }
508}
509
510impl<'a> MinByteRange<'a> for LigGlyph<'a> {
511    fn min_byte_range(&self) -> Range<usize> {
512        0..self.caret_value_offsets_byte_range().end
513    }
514    fn min_table_bytes(&self) -> &'a [u8] {
515        let range = self.min_byte_range();
516        self.data.as_bytes().get(range).unwrap_or_default()
517    }
518}
519
520impl ReadArgs for LigGlyph<'_> {
521    type Args = ();
522}
523
524impl<'a> FontRead<'a> for LigGlyph<'a> {
525    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
526        #[allow(clippy::absurd_extreme_comparisons)]
527        if data.len() < Self::MIN_SIZE {
528            return Err(ReadError::OutOfBounds);
529        }
530        Ok(Self { data })
531    }
532}
533
534/// [Ligature Glyph Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#ligature-glyph-table)
535#[derive(Clone)]
536pub struct LigGlyph<'a> {
537    data: FontData<'a>,
538}
539
540#[allow(clippy::needless_lifetimes)]
541impl<'a> LigGlyph<'a> {
542    pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
543    basic_table_impls!(impl_the_methods);
544
545    /// Number of CaretValue tables for this ligature (components - 1)
546    pub fn caret_count(&self) -> u16 {
547        let range = self.caret_count_byte_range();
548        self.data.read_at(range.start).ok().unwrap()
549    }
550
551    /// Array of offsets to CaretValue tables, from beginning of
552    /// LigGlyph table — in increasing coordinate order
553    pub fn caret_value_offsets(&self) -> &'a [BigEndian<Offset16>] {
554        let range = self.caret_value_offsets_byte_range();
555        self.data.read_array(range).ok().unwrap_or_default()
556    }
557
558    /// A dynamically resolving wrapper for [`caret_value_offsets`][Self::caret_value_offsets].
559    pub fn caret_values(&self) -> ArrayOfOffsets<'a, CaretValue<'a>, Offset16> {
560        let data = self.data;
561        let offsets = self.caret_value_offsets();
562        ArrayOfOffsets::new(offsets, data, ())
563    }
564
565    pub fn caret_count_byte_range(&self) -> Range<usize> {
566        let start = 0;
567        let end = start + u16::RAW_BYTE_LEN;
568        start..end
569    }
570
571    pub fn caret_value_offsets_byte_range(&self) -> Range<usize> {
572        let caret_count = self.caret_count();
573        let start = self.caret_count_byte_range().end;
574        let end =
575            start + (transforms::to_usize(caret_count)).saturating_mul(Offset16::RAW_BYTE_LEN);
576        start..end
577    }
578}
579
580const _: () = assert!(FontData::default_data_long_enough(LigGlyph::MIN_SIZE));
581
582impl Default for LigGlyph<'_> {
583    fn default() -> Self {
584        Self {
585            data: FontData::default_table_data(),
586        }
587    }
588}
589
590/// [Caret Value Tables](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caret-value-tables)
591#[derive(Clone)]
592pub enum CaretValue<'a> {
593    Format1(CaretValueFormat1<'a>),
594    Format2(CaretValueFormat2<'a>),
595    Format3(CaretValueFormat3<'a>),
596}
597
598impl Default for CaretValue<'_> {
599    fn default() -> Self {
600        Self::Format1(Default::default())
601    }
602}
603
604impl<'a> CaretValue<'a> {
605    ///Return the `FontData` used to resolve offsets for this table.
606    pub fn offset_data(&self) -> FontData<'a> {
607        match self {
608            Self::Format1(item) => item.offset_data(),
609            Self::Format2(item) => item.offset_data(),
610            Self::Format3(item) => item.offset_data(),
611        }
612    }
613
614    /// Format identifier: format = 1
615    pub fn caret_value_format(&self) -> u16 {
616        match self {
617            Self::Format1(item) => item.caret_value_format(),
618            Self::Format2(item) => item.caret_value_format(),
619            Self::Format3(item) => item.caret_value_format(),
620        }
621    }
622}
623
624impl ReadArgs for CaretValue<'_> {
625    type Args = ();
626}
627
628impl<'a> FontRead<'a> for CaretValue<'a> {
629    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
630        let format: u16 = data.read_at(0usize)?;
631        match format {
632            CaretValueFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
633            CaretValueFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
634            CaretValueFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
635            other => Err(ReadError::InvalidFormat(other.into())),
636        }
637    }
638}
639
640impl<'a> MinByteRange<'a> for CaretValue<'a> {
641    fn min_byte_range(&self) -> Range<usize> {
642        match self {
643            Self::Format1(item) => item.min_byte_range(),
644            Self::Format2(item) => item.min_byte_range(),
645            Self::Format3(item) => item.min_byte_range(),
646        }
647    }
648    fn min_table_bytes(&self) -> &'a [u8] {
649        match self {
650            Self::Format1(item) => item.min_table_bytes(),
651            Self::Format2(item) => item.min_table_bytes(),
652            Self::Format3(item) => item.min_table_bytes(),
653        }
654    }
655}
656
657impl Format<u16> for CaretValueFormat1<'_> {
658    const FORMAT: u16 = 1;
659}
660
661impl<'a> MinByteRange<'a> for CaretValueFormat1<'a> {
662    fn min_byte_range(&self) -> Range<usize> {
663        0..self.coordinate_byte_range().end
664    }
665    fn min_table_bytes(&self) -> &'a [u8] {
666        let range = self.min_byte_range();
667        self.data.as_bytes().get(range).unwrap_or_default()
668    }
669}
670
671impl ReadArgs for CaretValueFormat1<'_> {
672    type Args = ();
673}
674
675impl<'a> FontRead<'a> for CaretValueFormat1<'a> {
676    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
677        #[allow(clippy::absurd_extreme_comparisons)]
678        if data.len() < Self::MIN_SIZE {
679            return Err(ReadError::OutOfBounds);
680        }
681        Ok(Self { data })
682    }
683}
684
685/// [CaretValue Format 1](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-1)
686#[derive(Clone)]
687pub struct CaretValueFormat1<'a> {
688    data: FontData<'a>,
689}
690
691#[allow(clippy::needless_lifetimes)]
692impl<'a> CaretValueFormat1<'a> {
693    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN);
694    basic_table_impls!(impl_the_methods);
695
696    /// Format identifier: format = 1
697    pub fn caret_value_format(&self) -> u16 {
698        let range = self.caret_value_format_byte_range();
699        self.data.read_at(range.start).ok().unwrap()
700    }
701
702    /// X or Y value, in design units
703    pub fn coordinate(&self) -> i16 {
704        let range = self.coordinate_byte_range();
705        self.data.read_at(range.start).ok().unwrap()
706    }
707
708    pub fn caret_value_format_byte_range(&self) -> Range<usize> {
709        let start = 0;
710        let end = start + u16::RAW_BYTE_LEN;
711        start..end
712    }
713
714    pub fn coordinate_byte_range(&self) -> Range<usize> {
715        let start = self.caret_value_format_byte_range().end;
716        let end = start + i16::RAW_BYTE_LEN;
717        start..end
718    }
719}
720
721const _: () = assert!(FontData::default_data_long_enough(
722    CaretValueFormat1::MIN_SIZE
723));
724
725impl Default for CaretValueFormat1<'_> {
726    fn default() -> Self {
727        Self {
728            data: FontData::default_format_1_u16_table_data(),
729        }
730    }
731}
732
733impl Format<u16> for CaretValueFormat2<'_> {
734    const FORMAT: u16 = 2;
735}
736
737impl<'a> MinByteRange<'a> for CaretValueFormat2<'a> {
738    fn min_byte_range(&self) -> Range<usize> {
739        0..self.caret_value_point_index_byte_range().end
740    }
741    fn min_table_bytes(&self) -> &'a [u8] {
742        let range = self.min_byte_range();
743        self.data.as_bytes().get(range).unwrap_or_default()
744    }
745}
746
747impl ReadArgs for CaretValueFormat2<'_> {
748    type Args = ();
749}
750
751impl<'a> FontRead<'a> for CaretValueFormat2<'a> {
752    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
753        #[allow(clippy::absurd_extreme_comparisons)]
754        if data.len() < Self::MIN_SIZE {
755            return Err(ReadError::OutOfBounds);
756        }
757        Ok(Self { data })
758    }
759}
760
761/// [CaretValue Format 2](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-2)
762#[derive(Clone)]
763pub struct CaretValueFormat2<'a> {
764    data: FontData<'a>,
765}
766
767#[allow(clippy::needless_lifetimes)]
768impl<'a> CaretValueFormat2<'a> {
769    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
770    basic_table_impls!(impl_the_methods);
771
772    /// Format identifier: format = 2
773    pub fn caret_value_format(&self) -> u16 {
774        let range = self.caret_value_format_byte_range();
775        self.data.read_at(range.start).ok().unwrap()
776    }
777
778    /// Contour point index on glyph
779    pub fn caret_value_point_index(&self) -> u16 {
780        let range = self.caret_value_point_index_byte_range();
781        self.data.read_at(range.start).ok().unwrap()
782    }
783
784    pub fn caret_value_format_byte_range(&self) -> Range<usize> {
785        let start = 0;
786        let end = start + u16::RAW_BYTE_LEN;
787        start..end
788    }
789
790    pub fn caret_value_point_index_byte_range(&self) -> Range<usize> {
791        let start = self.caret_value_format_byte_range().end;
792        let end = start + u16::RAW_BYTE_LEN;
793        start..end
794    }
795}
796
797impl Format<u16> for CaretValueFormat3<'_> {
798    const FORMAT: u16 = 3;
799}
800
801impl<'a> MinByteRange<'a> for CaretValueFormat3<'a> {
802    fn min_byte_range(&self) -> Range<usize> {
803        0..self.device_offset_byte_range().end
804    }
805    fn min_table_bytes(&self) -> &'a [u8] {
806        let range = self.min_byte_range();
807        self.data.as_bytes().get(range).unwrap_or_default()
808    }
809}
810
811impl ReadArgs for CaretValueFormat3<'_> {
812    type Args = ();
813}
814
815impl<'a> FontRead<'a> for CaretValueFormat3<'a> {
816    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
817        #[allow(clippy::absurd_extreme_comparisons)]
818        if data.len() < Self::MIN_SIZE {
819            return Err(ReadError::OutOfBounds);
820        }
821        Ok(Self { data })
822    }
823}
824
825/// [CaretValue Format 3](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#caretvalue-format-3)
826#[derive(Clone)]
827pub struct CaretValueFormat3<'a> {
828    data: FontData<'a>,
829}
830
831#[allow(clippy::needless_lifetimes)]
832impl<'a> CaretValueFormat3<'a> {
833    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + i16::RAW_BYTE_LEN + Offset16::RAW_BYTE_LEN);
834    basic_table_impls!(impl_the_methods);
835
836    /// Format identifier-format = 3
837    pub fn caret_value_format(&self) -> u16 {
838        let range = self.caret_value_format_byte_range();
839        self.data.read_at(range.start).ok().unwrap()
840    }
841
842    /// X or Y value, in design units
843    pub fn coordinate(&self) -> i16 {
844        let range = self.coordinate_byte_range();
845        self.data.read_at(range.start).ok().unwrap()
846    }
847
848    /// Offset to Device table (non-variable font) / Variation Index
849    /// table (variable font) for X or Y value-from beginning of
850    /// CaretValue table
851    pub fn device_offset(&self) -> Offset16 {
852        let range = self.device_offset_byte_range();
853        self.data.read_at(range.start).ok().unwrap()
854    }
855
856    /// Attempt to resolve [`device_offset`][Self::device_offset].
857    pub fn device(&self) -> Result<DeviceOrVariationIndex<'a>, ReadError> {
858        let data = self.data;
859        self.device_offset().resolve(data)
860    }
861
862    pub fn caret_value_format_byte_range(&self) -> Range<usize> {
863        let start = 0;
864        let end = start + u16::RAW_BYTE_LEN;
865        start..end
866    }
867
868    pub fn coordinate_byte_range(&self) -> Range<usize> {
869        let start = self.caret_value_format_byte_range().end;
870        let end = start + i16::RAW_BYTE_LEN;
871        start..end
872    }
873
874    pub fn device_offset_byte_range(&self) -> Range<usize> {
875        let start = self.coordinate_byte_range().end;
876        let end = start + Offset16::RAW_BYTE_LEN;
877        start..end
878    }
879}
880
881impl Format<u16> for MarkGlyphSets<'_> {
882    const FORMAT: u16 = 1;
883}
884
885impl<'a> MinByteRange<'a> for MarkGlyphSets<'a> {
886    fn min_byte_range(&self) -> Range<usize> {
887        0..self.coverage_offsets_byte_range().end
888    }
889    fn min_table_bytes(&self) -> &'a [u8] {
890        let range = self.min_byte_range();
891        self.data.as_bytes().get(range).unwrap_or_default()
892    }
893}
894
895impl ReadArgs for MarkGlyphSets<'_> {
896    type Args = ();
897}
898
899impl<'a> FontRead<'a> for MarkGlyphSets<'a> {
900    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
901        #[allow(clippy::absurd_extreme_comparisons)]
902        if data.len() < Self::MIN_SIZE {
903            return Err(ReadError::OutOfBounds);
904        }
905        Ok(Self { data })
906    }
907}
908
909/// [Mark Glyph Sets Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef#mark-glyph-sets-table)
910#[derive(Clone)]
911pub struct MarkGlyphSets<'a> {
912    data: FontData<'a>,
913}
914
915#[allow(clippy::needless_lifetimes)]
916impl<'a> MarkGlyphSets<'a> {
917    pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
918    basic_table_impls!(impl_the_methods);
919
920    /// Format identifier == 1
921    pub fn format(&self) -> u16 {
922        let range = self.format_byte_range();
923        self.data.read_at(range.start).ok().unwrap()
924    }
925
926    /// Number of mark glyph sets defined
927    pub fn mark_glyph_set_count(&self) -> u16 {
928        let range = self.mark_glyph_set_count_byte_range();
929        self.data.read_at(range.start).ok().unwrap()
930    }
931
932    /// Array of offsets to mark glyph set coverage tables, from the
933    /// start of the MarkGlyphSets table.
934    pub fn coverage_offsets(&self) -> &'a [BigEndian<Offset32>] {
935        let range = self.coverage_offsets_byte_range();
936        self.data.read_array(range).ok().unwrap_or_default()
937    }
938
939    /// A dynamically resolving wrapper for [`coverage_offsets`][Self::coverage_offsets].
940    pub fn coverages(&self) -> ArrayOfOffsets<'a, CoverageTable<'a>, Offset32> {
941        let data = self.data;
942        let offsets = self.coverage_offsets();
943        ArrayOfOffsets::new(offsets, data, ())
944    }
945
946    pub fn format_byte_range(&self) -> Range<usize> {
947        let start = 0;
948        let end = start + u16::RAW_BYTE_LEN;
949        start..end
950    }
951
952    pub fn mark_glyph_set_count_byte_range(&self) -> Range<usize> {
953        let start = self.format_byte_range().end;
954        let end = start + u16::RAW_BYTE_LEN;
955        start..end
956    }
957
958    pub fn coverage_offsets_byte_range(&self) -> Range<usize> {
959        let mark_glyph_set_count = self.mark_glyph_set_count();
960        let start = self.mark_glyph_set_count_byte_range().end;
961        let end = start
962            + (transforms::to_usize(mark_glyph_set_count)).saturating_mul(Offset32::RAW_BYTE_LEN);
963        start..end
964    }
965}
966
967const _: () = assert!(FontData::default_data_long_enough(MarkGlyphSets::MIN_SIZE));
968
969impl Default for MarkGlyphSets<'_> {
970    fn default() -> Self {
971        Self {
972            data: FontData::default_format_1_u16_table_data(),
973        }
974    }
975}