write_fonts/generated/
generated_gsub.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/// [GSUB](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#gsub-header)
9#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct Gsub {
12    /// Offset to ScriptList table, from beginning of GSUB table
13    pub script_list: OffsetMarker<ScriptList>,
14    /// Offset to FeatureList table, from beginning of GSUB table
15    pub feature_list: OffsetMarker<FeatureList>,
16    /// Offset to LookupList table, from beginning of GSUB table
17    pub lookup_list: OffsetMarker<SubstitutionLookupList>,
18    /// Offset to FeatureVariations table, from beginning of the GSUB
19    /// table (may be NULL)
20    pub feature_variations: NullableOffsetMarker<FeatureVariations, WIDTH_32>,
21}
22
23impl Gsub {
24    /// Construct a new `Gsub`
25    pub fn new(
26        script_list: ScriptList,
27        feature_list: FeatureList,
28        lookup_list: SubstitutionLookupList,
29    ) -> Self {
30        Self {
31            script_list: script_list.into(),
32            feature_list: feature_list.into(),
33            lookup_list: lookup_list.into(),
34            ..Default::default()
35        }
36    }
37}
38
39impl FontWrite for Gsub {
40    #[allow(clippy::unnecessary_cast)]
41    fn write_into(&self, writer: &mut TableWriter) {
42        let version = self.compute_version() as MajorMinor;
43        version.write_into(writer);
44        self.script_list.write_into(writer);
45        self.feature_list.write_into(writer);
46        self.lookup_list.write_into(writer);
47        version
48            .compatible((1u16, 1u16))
49            .then(|| self.feature_variations.write_into(writer));
50    }
51    fn table_type(&self) -> TableType {
52        TableType::TopLevel(Gsub::TAG)
53    }
54}
55
56impl Validate for Gsub {
57    fn validate_impl(&self, ctx: &mut ValidationCtx) {
58        ctx.in_table("Gsub", |ctx| {
59            ctx.in_field("script_list", |ctx| {
60                self.script_list.validate_impl(ctx);
61            });
62            ctx.in_field("feature_list", |ctx| {
63                self.feature_list.validate_impl(ctx);
64            });
65            ctx.in_field("lookup_list", |ctx| {
66                self.lookup_list.validate_impl(ctx);
67            });
68            ctx.in_field("feature_variations", |ctx| {
69                self.feature_variations.validate_impl(ctx);
70            });
71        })
72    }
73}
74
75impl TopLevelTable for Gsub {
76    const TAG: Tag = Tag::new(b"GSUB");
77}
78
79impl<'a> FromObjRef<read_fonts::tables::gsub::Gsub<'a>> for Gsub {
80    fn from_obj_ref(obj: &read_fonts::tables::gsub::Gsub<'a>, _: FontData) -> Self {
81        Gsub {
82            script_list: obj.script_list().to_owned_table(),
83            feature_list: obj.feature_list().to_owned_table(),
84            lookup_list: obj.lookup_list().to_owned_table(),
85            feature_variations: obj.feature_variations().to_owned_table(),
86        }
87    }
88}
89
90#[allow(clippy::needless_lifetimes)]
91impl<'a> FromTableRef<read_fonts::tables::gsub::Gsub<'a>> for Gsub {}
92
93impl<'a> FontRead<'a> for Gsub {
94    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
95        <read_fonts::tables::gsub::Gsub as FontRead>::read(data).map(|x| x.to_owned_table())
96    }
97}
98
99/// A [GSUB Lookup](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#gsubLookupTypeEnum) subtable.
100#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
101#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
102pub enum SubstitutionLookup {
103    Single(Lookup<SingleSubst>),
104    Multiple(Lookup<MultipleSubstFormat1>),
105    Alternate(Lookup<AlternateSubstFormat1>),
106    Ligature(Lookup<LigatureSubstFormat1>),
107    Contextual(Lookup<SubstitutionSequenceContext>),
108    ChainContextual(Lookup<SubstitutionChainContext>),
109    Extension(Lookup<ExtensionSubtable>),
110    Reverse(Lookup<ReverseChainSingleSubstFormat1>),
111}
112
113impl Default for SubstitutionLookup {
114    fn default() -> Self {
115        Self::Single(Default::default())
116    }
117}
118
119impl FontWrite for SubstitutionLookup {
120    fn write_into(&self, writer: &mut TableWriter) {
121        match self {
122            Self::Single(table) => table.write_into(writer),
123            Self::Multiple(table) => table.write_into(writer),
124            Self::Alternate(table) => table.write_into(writer),
125            Self::Ligature(table) => table.write_into(writer),
126            Self::Contextual(table) => table.write_into(writer),
127            Self::ChainContextual(table) => table.write_into(writer),
128            Self::Extension(table) => table.write_into(writer),
129            Self::Reverse(table) => table.write_into(writer),
130        }
131    }
132    fn table_type(&self) -> TableType {
133        match self {
134            Self::Single(table) => table.table_type(),
135            Self::Multiple(table) => table.table_type(),
136            Self::Alternate(table) => table.table_type(),
137            Self::Ligature(table) => table.table_type(),
138            Self::Contextual(table) => table.table_type(),
139            Self::ChainContextual(table) => table.table_type(),
140            Self::Extension(table) => table.table_type(),
141            Self::Reverse(table) => table.table_type(),
142        }
143    }
144}
145
146impl Validate for SubstitutionLookup {
147    fn validate_impl(&self, ctx: &mut ValidationCtx) {
148        match self {
149            Self::Single(table) => table.validate_impl(ctx),
150            Self::Multiple(table) => table.validate_impl(ctx),
151            Self::Alternate(table) => table.validate_impl(ctx),
152            Self::Ligature(table) => table.validate_impl(ctx),
153            Self::Contextual(table) => table.validate_impl(ctx),
154            Self::ChainContextual(table) => table.validate_impl(ctx),
155            Self::Extension(table) => table.validate_impl(ctx),
156            Self::Reverse(table) => table.validate_impl(ctx),
157        }
158    }
159}
160
161impl FromObjRef<read_fonts::tables::gsub::SubstitutionLookup<'_>> for SubstitutionLookup {
162    fn from_obj_ref(
163        from: &read_fonts::tables::gsub::SubstitutionLookup<'_>,
164        data: FontData,
165    ) -> Self {
166        match from {
167            read_fonts::tables::gsub::SubstitutionLookup::Single(table) => {
168                Self::Single(table.to_owned_obj(data))
169            }
170            read_fonts::tables::gsub::SubstitutionLookup::Multiple(table) => {
171                Self::Multiple(table.to_owned_obj(data))
172            }
173            read_fonts::tables::gsub::SubstitutionLookup::Alternate(table) => {
174                Self::Alternate(table.to_owned_obj(data))
175            }
176            read_fonts::tables::gsub::SubstitutionLookup::Ligature(table) => {
177                Self::Ligature(table.to_owned_obj(data))
178            }
179            read_fonts::tables::gsub::SubstitutionLookup::Contextual(table) => {
180                Self::Contextual(table.to_owned_obj(data))
181            }
182            read_fonts::tables::gsub::SubstitutionLookup::ChainContextual(table) => {
183                Self::ChainContextual(table.to_owned_obj(data))
184            }
185            read_fonts::tables::gsub::SubstitutionLookup::Extension(table) => {
186                Self::Extension(table.to_owned_obj(data))
187            }
188            read_fonts::tables::gsub::SubstitutionLookup::Reverse(table) => {
189                Self::Reverse(table.to_owned_obj(data))
190            }
191        }
192    }
193}
194
195impl FromTableRef<read_fonts::tables::gsub::SubstitutionLookup<'_>> for SubstitutionLookup {}
196
197impl From<Lookup<SingleSubst>> for SubstitutionLookup {
198    fn from(src: Lookup<SingleSubst>) -> SubstitutionLookup {
199        SubstitutionLookup::Single(src)
200    }
201}
202
203impl From<Lookup<MultipleSubstFormat1>> for SubstitutionLookup {
204    fn from(src: Lookup<MultipleSubstFormat1>) -> SubstitutionLookup {
205        SubstitutionLookup::Multiple(src)
206    }
207}
208
209impl From<Lookup<AlternateSubstFormat1>> for SubstitutionLookup {
210    fn from(src: Lookup<AlternateSubstFormat1>) -> SubstitutionLookup {
211        SubstitutionLookup::Alternate(src)
212    }
213}
214
215impl From<Lookup<LigatureSubstFormat1>> for SubstitutionLookup {
216    fn from(src: Lookup<LigatureSubstFormat1>) -> SubstitutionLookup {
217        SubstitutionLookup::Ligature(src)
218    }
219}
220
221impl From<Lookup<SubstitutionSequenceContext>> for SubstitutionLookup {
222    fn from(src: Lookup<SubstitutionSequenceContext>) -> SubstitutionLookup {
223        SubstitutionLookup::Contextual(src)
224    }
225}
226
227impl From<Lookup<SubstitutionChainContext>> for SubstitutionLookup {
228    fn from(src: Lookup<SubstitutionChainContext>) -> SubstitutionLookup {
229        SubstitutionLookup::ChainContextual(src)
230    }
231}
232
233impl From<Lookup<ExtensionSubtable>> for SubstitutionLookup {
234    fn from(src: Lookup<ExtensionSubtable>) -> SubstitutionLookup {
235        SubstitutionLookup::Extension(src)
236    }
237}
238
239impl From<Lookup<ReverseChainSingleSubstFormat1>> for SubstitutionLookup {
240    fn from(src: Lookup<ReverseChainSingleSubstFormat1>) -> SubstitutionLookup {
241        SubstitutionLookup::Reverse(src)
242    }
243}
244
245/// LookupType 1: [Single Substitution](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#lookuptype-1-single-substitution-subtable) Subtable
246#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
247#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
248pub enum SingleSubst {
249    Format1(SingleSubstFormat1),
250    Format2(SingleSubstFormat2),
251}
252
253impl SingleSubst {
254    /// Construct a new `SingleSubstFormat1` subtable
255    pub fn format_1(coverage: CoverageTable, delta_glyph_id: i16) -> Self {
256        Self::Format1(SingleSubstFormat1::new(coverage, delta_glyph_id))
257    }
258
259    /// Construct a new `SingleSubstFormat2` subtable
260    pub fn format_2(coverage: CoverageTable, substitute_glyph_ids: Vec<GlyphId16>) -> Self {
261        Self::Format2(SingleSubstFormat2::new(coverage, substitute_glyph_ids))
262    }
263}
264
265impl Default for SingleSubst {
266    fn default() -> Self {
267        Self::Format1(Default::default())
268    }
269}
270
271impl FontWrite for SingleSubst {
272    fn write_into(&self, writer: &mut TableWriter) {
273        match self {
274            Self::Format1(item) => item.write_into(writer),
275            Self::Format2(item) => item.write_into(writer),
276        }
277    }
278    fn table_type(&self) -> TableType {
279        match self {
280            Self::Format1(item) => item.table_type(),
281            Self::Format2(item) => item.table_type(),
282        }
283    }
284}
285
286impl Validate for SingleSubst {
287    fn validate_impl(&self, ctx: &mut ValidationCtx) {
288        match self {
289            Self::Format1(item) => item.validate_impl(ctx),
290            Self::Format2(item) => item.validate_impl(ctx),
291        }
292    }
293}
294
295impl FromObjRef<read_fonts::tables::gsub::SingleSubst<'_>> for SingleSubst {
296    fn from_obj_ref(obj: &read_fonts::tables::gsub::SingleSubst, _: FontData) -> Self {
297        use read_fonts::tables::gsub::SingleSubst as ObjRefType;
298        match obj {
299            ObjRefType::Format1(item) => SingleSubst::Format1(item.to_owned_table()),
300            ObjRefType::Format2(item) => SingleSubst::Format2(item.to_owned_table()),
301        }
302    }
303}
304
305impl FromTableRef<read_fonts::tables::gsub::SingleSubst<'_>> for SingleSubst {}
306
307impl<'a> FontRead<'a> for SingleSubst {
308    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
309        <read_fonts::tables::gsub::SingleSubst as FontRead>::read(data).map(|x| x.to_owned_table())
310    }
311}
312
313impl From<SingleSubstFormat1> for SingleSubst {
314    fn from(src: SingleSubstFormat1) -> SingleSubst {
315        SingleSubst::Format1(src)
316    }
317}
318
319impl From<SingleSubstFormat2> for SingleSubst {
320    fn from(src: SingleSubstFormat2) -> SingleSubst {
321        SingleSubst::Format2(src)
322    }
323}
324
325/// [Single Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#11-single-substitution-format-1)
326#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
327#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
328pub struct SingleSubstFormat1 {
329    /// Offset to Coverage table, from beginning of substitution
330    /// subtable
331    pub coverage: OffsetMarker<CoverageTable>,
332    /// Add to original glyph ID to get substitute glyph ID
333    pub delta_glyph_id: i16,
334}
335
336impl SingleSubstFormat1 {
337    /// Construct a new `SingleSubstFormat1`
338    pub fn new(coverage: CoverageTable, delta_glyph_id: i16) -> Self {
339        Self {
340            coverage: coverage.into(),
341            delta_glyph_id,
342        }
343    }
344}
345
346impl FontWrite for SingleSubstFormat1 {
347    #[allow(clippy::unnecessary_cast)]
348    fn write_into(&self, writer: &mut TableWriter) {
349        (1 as u16).write_into(writer);
350        self.coverage.write_into(writer);
351        self.delta_glyph_id.write_into(writer);
352    }
353    fn table_type(&self) -> TableType {
354        TableType::Named("SingleSubstFormat1")
355    }
356}
357
358impl Validate for SingleSubstFormat1 {
359    fn validate_impl(&self, ctx: &mut ValidationCtx) {
360        ctx.in_table("SingleSubstFormat1", |ctx| {
361            ctx.in_field("coverage", |ctx| {
362                self.coverage.validate_impl(ctx);
363            });
364        })
365    }
366}
367
368impl<'a> FromObjRef<read_fonts::tables::gsub::SingleSubstFormat1<'a>> for SingleSubstFormat1 {
369    fn from_obj_ref(obj: &read_fonts::tables::gsub::SingleSubstFormat1<'a>, _: FontData) -> Self {
370        SingleSubstFormat1 {
371            coverage: obj.coverage().to_owned_table(),
372            delta_glyph_id: obj.delta_glyph_id(),
373        }
374    }
375}
376
377#[allow(clippy::needless_lifetimes)]
378impl<'a> FromTableRef<read_fonts::tables::gsub::SingleSubstFormat1<'a>> for SingleSubstFormat1 {}
379
380impl<'a> FontRead<'a> for SingleSubstFormat1 {
381    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
382        <read_fonts::tables::gsub::SingleSubstFormat1 as FontRead>::read(data)
383            .map(|x| x.to_owned_table())
384    }
385}
386
387/// [Single Substitution Format 2](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#12-single-substitution-format-2)
388#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
389#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
390pub struct SingleSubstFormat2 {
391    /// Offset to Coverage table, from beginning of substitution
392    /// subtable
393    pub coverage: OffsetMarker<CoverageTable>,
394    /// Array of substitute glyph IDs — ordered by Coverage index
395    pub substitute_glyph_ids: Vec<GlyphId16>,
396}
397
398impl SingleSubstFormat2 {
399    /// Construct a new `SingleSubstFormat2`
400    pub fn new(coverage: CoverageTable, substitute_glyph_ids: Vec<GlyphId16>) -> Self {
401        Self {
402            coverage: coverage.into(),
403            substitute_glyph_ids,
404        }
405    }
406}
407
408impl FontWrite for SingleSubstFormat2 {
409    #[allow(clippy::unnecessary_cast)]
410    fn write_into(&self, writer: &mut TableWriter) {
411        (2 as u16).write_into(writer);
412        self.coverage.write_into(writer);
413        (u16::try_from(array_len(&self.substitute_glyph_ids)).unwrap()).write_into(writer);
414        self.substitute_glyph_ids.write_into(writer);
415    }
416    fn table_type(&self) -> TableType {
417        TableType::Named("SingleSubstFormat2")
418    }
419}
420
421impl Validate for SingleSubstFormat2 {
422    fn validate_impl(&self, ctx: &mut ValidationCtx) {
423        ctx.in_table("SingleSubstFormat2", |ctx| {
424            ctx.in_field("coverage", |ctx| {
425                self.coverage.validate_impl(ctx);
426            });
427            ctx.in_field("substitute_glyph_ids", |ctx| {
428                if self.substitute_glyph_ids.len() > (u16::MAX as usize) {
429                    ctx.report("array exceeds max length");
430                }
431            });
432        })
433    }
434}
435
436impl<'a> FromObjRef<read_fonts::tables::gsub::SingleSubstFormat2<'a>> for SingleSubstFormat2 {
437    fn from_obj_ref(obj: &read_fonts::tables::gsub::SingleSubstFormat2<'a>, _: FontData) -> Self {
438        let offset_data = obj.offset_data();
439        SingleSubstFormat2 {
440            coverage: obj.coverage().to_owned_table(),
441            substitute_glyph_ids: obj.substitute_glyph_ids().to_owned_obj(offset_data),
442        }
443    }
444}
445
446#[allow(clippy::needless_lifetimes)]
447impl<'a> FromTableRef<read_fonts::tables::gsub::SingleSubstFormat2<'a>> for SingleSubstFormat2 {}
448
449impl<'a> FontRead<'a> for SingleSubstFormat2 {
450    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
451        <read_fonts::tables::gsub::SingleSubstFormat2 as FontRead>::read(data)
452            .map(|x| x.to_owned_table())
453    }
454}
455
456/// [Multiple Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#21-multiple-substitution-format-1)
457#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
458#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
459pub struct MultipleSubstFormat1 {
460    /// Offset to Coverage table, from beginning of substitution
461    /// subtable
462    pub coverage: OffsetMarker<CoverageTable>,
463    /// Array of offsets to Sequence tables. Offsets are from beginning
464    /// of substitution subtable, ordered by Coverage index
465    pub sequences: Vec<OffsetMarker<Sequence>>,
466}
467
468impl MultipleSubstFormat1 {
469    /// Construct a new `MultipleSubstFormat1`
470    pub fn new(coverage: CoverageTable, sequences: Vec<Sequence>) -> Self {
471        Self {
472            coverage: coverage.into(),
473            sequences: sequences.into_iter().map(Into::into).collect(),
474        }
475    }
476}
477
478impl FontWrite for MultipleSubstFormat1 {
479    #[allow(clippy::unnecessary_cast)]
480    fn write_into(&self, writer: &mut TableWriter) {
481        (1 as u16).write_into(writer);
482        self.coverage.write_into(writer);
483        (u16::try_from(array_len(&self.sequences)).unwrap()).write_into(writer);
484        self.sequences.write_into(writer);
485    }
486    fn table_type(&self) -> TableType {
487        TableType::Named("MultipleSubstFormat1")
488    }
489}
490
491impl Validate for MultipleSubstFormat1 {
492    fn validate_impl(&self, ctx: &mut ValidationCtx) {
493        ctx.in_table("MultipleSubstFormat1", |ctx| {
494            ctx.in_field("coverage", |ctx| {
495                self.coverage.validate_impl(ctx);
496            });
497            ctx.in_field("sequences", |ctx| {
498                if self.sequences.len() > (u16::MAX as usize) {
499                    ctx.report("array exceeds max length");
500                }
501                self.sequences.validate_impl(ctx);
502            });
503        })
504    }
505}
506
507impl<'a> FromObjRef<read_fonts::tables::gsub::MultipleSubstFormat1<'a>> for MultipleSubstFormat1 {
508    fn from_obj_ref(obj: &read_fonts::tables::gsub::MultipleSubstFormat1<'a>, _: FontData) -> Self {
509        MultipleSubstFormat1 {
510            coverage: obj.coverage().to_owned_table(),
511            sequences: obj.sequences().to_owned_table(),
512        }
513    }
514}
515
516#[allow(clippy::needless_lifetimes)]
517impl<'a> FromTableRef<read_fonts::tables::gsub::MultipleSubstFormat1<'a>> for MultipleSubstFormat1 {}
518
519impl<'a> FontRead<'a> for MultipleSubstFormat1 {
520    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
521        <read_fonts::tables::gsub::MultipleSubstFormat1 as FontRead>::read(data)
522            .map(|x| x.to_owned_table())
523    }
524}
525
526/// Part of [MultipleSubstFormat1]
527#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
528#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
529pub struct Sequence {
530    /// String of glyph IDs to substitute
531    pub substitute_glyph_ids: Vec<GlyphId16>,
532}
533
534impl Sequence {
535    /// Construct a new `Sequence`
536    pub fn new(substitute_glyph_ids: Vec<GlyphId16>) -> Self {
537        Self {
538            substitute_glyph_ids,
539        }
540    }
541}
542
543impl FontWrite for Sequence {
544    #[allow(clippy::unnecessary_cast)]
545    fn write_into(&self, writer: &mut TableWriter) {
546        (u16::try_from(array_len(&self.substitute_glyph_ids)).unwrap()).write_into(writer);
547        self.substitute_glyph_ids.write_into(writer);
548    }
549    fn table_type(&self) -> TableType {
550        TableType::Named("Sequence")
551    }
552}
553
554impl Validate for Sequence {
555    fn validate_impl(&self, ctx: &mut ValidationCtx) {
556        ctx.in_table("Sequence", |ctx| {
557            ctx.in_field("substitute_glyph_ids", |ctx| {
558                if self.substitute_glyph_ids.len() > (u16::MAX as usize) {
559                    ctx.report("array exceeds max length");
560                }
561            });
562        })
563    }
564}
565
566impl<'a> FromObjRef<read_fonts::tables::gsub::Sequence<'a>> for Sequence {
567    fn from_obj_ref(obj: &read_fonts::tables::gsub::Sequence<'a>, _: FontData) -> Self {
568        let offset_data = obj.offset_data();
569        Sequence {
570            substitute_glyph_ids: obj.substitute_glyph_ids().to_owned_obj(offset_data),
571        }
572    }
573}
574
575#[allow(clippy::needless_lifetimes)]
576impl<'a> FromTableRef<read_fonts::tables::gsub::Sequence<'a>> for Sequence {}
577
578impl<'a> FontRead<'a> for Sequence {
579    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
580        <read_fonts::tables::gsub::Sequence as FontRead>::read(data).map(|x| x.to_owned_table())
581    }
582}
583
584/// [Alternate Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#31-alternate-substitution-format-1)
585#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
586#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
587pub struct AlternateSubstFormat1 {
588    /// Offset to Coverage table, from beginning of substitution
589    /// subtable
590    pub coverage: OffsetMarker<CoverageTable>,
591    /// Array of offsets to AlternateSet tables. Offsets are from
592    /// beginning of substitution subtable, ordered by Coverage index
593    pub alternate_sets: Vec<OffsetMarker<AlternateSet>>,
594}
595
596impl AlternateSubstFormat1 {
597    /// Construct a new `AlternateSubstFormat1`
598    pub fn new(coverage: CoverageTable, alternate_sets: Vec<AlternateSet>) -> Self {
599        Self {
600            coverage: coverage.into(),
601            alternate_sets: alternate_sets.into_iter().map(Into::into).collect(),
602        }
603    }
604}
605
606impl FontWrite for AlternateSubstFormat1 {
607    #[allow(clippy::unnecessary_cast)]
608    fn write_into(&self, writer: &mut TableWriter) {
609        (1 as u16).write_into(writer);
610        self.coverage.write_into(writer);
611        (u16::try_from(array_len(&self.alternate_sets)).unwrap()).write_into(writer);
612        self.alternate_sets.write_into(writer);
613    }
614    fn table_type(&self) -> TableType {
615        TableType::Named("AlternateSubstFormat1")
616    }
617}
618
619impl Validate for AlternateSubstFormat1 {
620    fn validate_impl(&self, ctx: &mut ValidationCtx) {
621        ctx.in_table("AlternateSubstFormat1", |ctx| {
622            ctx.in_field("coverage", |ctx| {
623                self.coverage.validate_impl(ctx);
624            });
625            ctx.in_field("alternate_sets", |ctx| {
626                if self.alternate_sets.len() > (u16::MAX as usize) {
627                    ctx.report("array exceeds max length");
628                }
629                self.alternate_sets.validate_impl(ctx);
630            });
631        })
632    }
633}
634
635impl<'a> FromObjRef<read_fonts::tables::gsub::AlternateSubstFormat1<'a>> for AlternateSubstFormat1 {
636    fn from_obj_ref(
637        obj: &read_fonts::tables::gsub::AlternateSubstFormat1<'a>,
638        _: FontData,
639    ) -> Self {
640        AlternateSubstFormat1 {
641            coverage: obj.coverage().to_owned_table(),
642            alternate_sets: obj.alternate_sets().to_owned_table(),
643        }
644    }
645}
646
647#[allow(clippy::needless_lifetimes)]
648impl<'a> FromTableRef<read_fonts::tables::gsub::AlternateSubstFormat1<'a>>
649    for AlternateSubstFormat1
650{
651}
652
653impl<'a> FontRead<'a> for AlternateSubstFormat1 {
654    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
655        <read_fonts::tables::gsub::AlternateSubstFormat1 as FontRead>::read(data)
656            .map(|x| x.to_owned_table())
657    }
658}
659
660/// Part of [AlternateSubstFormat1]
661#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
662#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
663pub struct AlternateSet {
664    /// Array of alternate glyph IDs, in arbitrary order
665    pub alternate_glyph_ids: Vec<GlyphId16>,
666}
667
668impl AlternateSet {
669    /// Construct a new `AlternateSet`
670    pub fn new(alternate_glyph_ids: Vec<GlyphId16>) -> Self {
671        Self {
672            alternate_glyph_ids,
673        }
674    }
675}
676
677impl FontWrite for AlternateSet {
678    #[allow(clippy::unnecessary_cast)]
679    fn write_into(&self, writer: &mut TableWriter) {
680        (u16::try_from(array_len(&self.alternate_glyph_ids)).unwrap()).write_into(writer);
681        self.alternate_glyph_ids.write_into(writer);
682    }
683    fn table_type(&self) -> TableType {
684        TableType::Named("AlternateSet")
685    }
686}
687
688impl Validate for AlternateSet {
689    fn validate_impl(&self, ctx: &mut ValidationCtx) {
690        ctx.in_table("AlternateSet", |ctx| {
691            ctx.in_field("alternate_glyph_ids", |ctx| {
692                if self.alternate_glyph_ids.len() > (u16::MAX as usize) {
693                    ctx.report("array exceeds max length");
694                }
695            });
696        })
697    }
698}
699
700impl<'a> FromObjRef<read_fonts::tables::gsub::AlternateSet<'a>> for AlternateSet {
701    fn from_obj_ref(obj: &read_fonts::tables::gsub::AlternateSet<'a>, _: FontData) -> Self {
702        let offset_data = obj.offset_data();
703        AlternateSet {
704            alternate_glyph_ids: obj.alternate_glyph_ids().to_owned_obj(offset_data),
705        }
706    }
707}
708
709#[allow(clippy::needless_lifetimes)]
710impl<'a> FromTableRef<read_fonts::tables::gsub::AlternateSet<'a>> for AlternateSet {}
711
712impl<'a> FontRead<'a> for AlternateSet {
713    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
714        <read_fonts::tables::gsub::AlternateSet as FontRead>::read(data).map(|x| x.to_owned_table())
715    }
716}
717
718/// [Ligature Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#41-ligature-substitution-format-1)
719#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
720#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
721pub struct LigatureSubstFormat1 {
722    /// Offset to Coverage table, from beginning of substitution
723    /// subtable
724    pub coverage: OffsetMarker<CoverageTable>,
725    /// Array of offsets to LigatureSet tables. Offsets are from
726    /// beginning of substitution subtable, ordered by Coverage index
727    pub ligature_sets: Vec<OffsetMarker<LigatureSet>>,
728}
729
730impl LigatureSubstFormat1 {
731    /// Construct a new `LigatureSubstFormat1`
732    pub fn new(coverage: CoverageTable, ligature_sets: Vec<LigatureSet>) -> Self {
733        Self {
734            coverage: coverage.into(),
735            ligature_sets: ligature_sets.into_iter().map(Into::into).collect(),
736        }
737    }
738}
739
740impl FontWrite for LigatureSubstFormat1 {
741    #[allow(clippy::unnecessary_cast)]
742    fn write_into(&self, writer: &mut TableWriter) {
743        (1 as u16).write_into(writer);
744        self.coverage.write_into(writer);
745        (u16::try_from(array_len(&self.ligature_sets)).unwrap()).write_into(writer);
746        self.ligature_sets.write_into(writer);
747    }
748    fn table_type(&self) -> TableType {
749        TableType::Named("LigatureSubstFormat1")
750    }
751}
752
753impl Validate for LigatureSubstFormat1 {
754    fn validate_impl(&self, ctx: &mut ValidationCtx) {
755        ctx.in_table("LigatureSubstFormat1", |ctx| {
756            ctx.in_field("coverage", |ctx| {
757                self.coverage.validate_impl(ctx);
758            });
759            ctx.in_field("ligature_sets", |ctx| {
760                if self.ligature_sets.len() > (u16::MAX as usize) {
761                    ctx.report("array exceeds max length");
762                }
763                self.ligature_sets.validate_impl(ctx);
764            });
765        })
766    }
767}
768
769impl<'a> FromObjRef<read_fonts::tables::gsub::LigatureSubstFormat1<'a>> for LigatureSubstFormat1 {
770    fn from_obj_ref(obj: &read_fonts::tables::gsub::LigatureSubstFormat1<'a>, _: FontData) -> Self {
771        LigatureSubstFormat1 {
772            coverage: obj.coverage().to_owned_table(),
773            ligature_sets: obj.ligature_sets().to_owned_table(),
774        }
775    }
776}
777
778#[allow(clippy::needless_lifetimes)]
779impl<'a> FromTableRef<read_fonts::tables::gsub::LigatureSubstFormat1<'a>> for LigatureSubstFormat1 {}
780
781impl<'a> FontRead<'a> for LigatureSubstFormat1 {
782    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
783        <read_fonts::tables::gsub::LigatureSubstFormat1 as FontRead>::read(data)
784            .map(|x| x.to_owned_table())
785    }
786}
787
788/// Part of [LigatureSubstFormat1]
789#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
790#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
791pub struct LigatureSet {
792    /// Array of offsets to Ligature tables. Offsets are from beginning
793    /// of LigatureSet table, ordered by preference.
794    pub ligatures: Vec<OffsetMarker<Ligature>>,
795}
796
797impl LigatureSet {
798    /// Construct a new `LigatureSet`
799    pub fn new(ligatures: Vec<Ligature>) -> Self {
800        Self {
801            ligatures: ligatures.into_iter().map(Into::into).collect(),
802        }
803    }
804}
805
806impl FontWrite for LigatureSet {
807    #[allow(clippy::unnecessary_cast)]
808    fn write_into(&self, writer: &mut TableWriter) {
809        (u16::try_from(array_len(&self.ligatures)).unwrap()).write_into(writer);
810        self.ligatures.write_into(writer);
811    }
812    fn table_type(&self) -> TableType {
813        TableType::Named("LigatureSet")
814    }
815}
816
817impl Validate for LigatureSet {
818    fn validate_impl(&self, ctx: &mut ValidationCtx) {
819        ctx.in_table("LigatureSet", |ctx| {
820            ctx.in_field("ligatures", |ctx| {
821                if self.ligatures.len() > (u16::MAX as usize) {
822                    ctx.report("array exceeds max length");
823                }
824                self.ligatures.validate_impl(ctx);
825            });
826        })
827    }
828}
829
830impl<'a> FromObjRef<read_fonts::tables::gsub::LigatureSet<'a>> for LigatureSet {
831    fn from_obj_ref(obj: &read_fonts::tables::gsub::LigatureSet<'a>, _: FontData) -> Self {
832        LigatureSet {
833            ligatures: obj.ligatures().to_owned_table(),
834        }
835    }
836}
837
838#[allow(clippy::needless_lifetimes)]
839impl<'a> FromTableRef<read_fonts::tables::gsub::LigatureSet<'a>> for LigatureSet {}
840
841impl<'a> FontRead<'a> for LigatureSet {
842    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
843        <read_fonts::tables::gsub::LigatureSet as FontRead>::read(data).map(|x| x.to_owned_table())
844    }
845}
846
847/// Part of [LigatureSubstFormat1]
848#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
849#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
850pub struct Ligature {
851    /// glyph ID of ligature to substitute
852    pub ligature_glyph: GlyphId16,
853    /// Array of component glyph IDs — start with the second
854    /// component, ordered in writing direction
855    pub component_glyph_ids: Vec<GlyphId16>,
856}
857
858impl Ligature {
859    /// Construct a new `Ligature`
860    pub fn new(ligature_glyph: GlyphId16, component_glyph_ids: Vec<GlyphId16>) -> Self {
861        Self {
862            ligature_glyph,
863            component_glyph_ids,
864        }
865    }
866}
867
868impl FontWrite for Ligature {
869    #[allow(clippy::unnecessary_cast)]
870    fn write_into(&self, writer: &mut TableWriter) {
871        self.ligature_glyph.write_into(writer);
872        (u16::try_from(plus_one(&self.component_glyph_ids.len())).unwrap()).write_into(writer);
873        self.component_glyph_ids.write_into(writer);
874    }
875    fn table_type(&self) -> TableType {
876        TableType::Named("Ligature")
877    }
878}
879
880impl Validate for Ligature {
881    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
882}
883
884impl<'a> FromObjRef<read_fonts::tables::gsub::Ligature<'a>> for Ligature {
885    fn from_obj_ref(obj: &read_fonts::tables::gsub::Ligature<'a>, _: FontData) -> Self {
886        let offset_data = obj.offset_data();
887        Ligature {
888            ligature_glyph: obj.ligature_glyph(),
889            component_glyph_ids: obj.component_glyph_ids().to_owned_obj(offset_data),
890        }
891    }
892}
893
894#[allow(clippy::needless_lifetimes)]
895impl<'a> FromTableRef<read_fonts::tables::gsub::Ligature<'a>> for Ligature {}
896
897impl<'a> FontRead<'a> for Ligature {
898    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
899        <read_fonts::tables::gsub::Ligature as FontRead>::read(data).map(|x| x.to_owned_table())
900    }
901}
902
903/// [Extension Substitution Subtable Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#71-extension-substitution-subtable-format-1)
904#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
905#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
906pub struct ExtensionSubstFormat1<T> {
907    /// Lookup type of subtable referenced by extensionOffset (that is,
908    /// the extension subtable).
909    pub extension_lookup_type: u16,
910    /// Offset to the extension subtable, of lookup type
911    /// extensionLookupType, relative to the start of the
912    /// ExtensionSubstFormat1 subtable.
913    pub extension: OffsetMarker<T, WIDTH_32>,
914}
915
916impl<T: Default> ExtensionSubstFormat1<T> {
917    /// Construct a new `ExtensionSubstFormat1`
918    pub fn new(extension_lookup_type: u16, extension: T) -> Self {
919        Self {
920            extension_lookup_type,
921            extension: extension.into(),
922        }
923    }
924}
925
926impl<T: Validate> Validate for ExtensionSubstFormat1<T> {
927    fn validate_impl(&self, ctx: &mut ValidationCtx) {
928        ctx.in_table("ExtensionSubstFormat1", |ctx| {
929            ctx.in_field("extension", |ctx| {
930                self.extension.validate_impl(ctx);
931            });
932        })
933    }
934}
935
936impl<'a, T, U> FromObjRef<read_fonts::tables::gsub::ExtensionSubstFormat1<'a, U>>
937    for ExtensionSubstFormat1<T>
938where
939    U: FontRead<'a>,
940    T: FromTableRef<U> + Default + 'static,
941{
942    fn from_obj_ref(
943        obj: &read_fonts::tables::gsub::ExtensionSubstFormat1<'a, U>,
944        _: FontData,
945    ) -> Self {
946        ExtensionSubstFormat1 {
947            extension_lookup_type: obj.extension_lookup_type(),
948            extension: obj.extension().to_owned_table(),
949        }
950    }
951}
952
953#[allow(clippy::needless_lifetimes)]
954impl<'a, T, U> FromTableRef<read_fonts::tables::gsub::ExtensionSubstFormat1<'a, U>>
955    for ExtensionSubstFormat1<T>
956where
957    U: FontRead<'a>,
958    T: FromTableRef<U> + Default + 'static,
959{
960}
961
962/// A [GSUB Extension Substitution](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#ES) subtable
963#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
964#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
965pub enum ExtensionSubtable {
966    Single(ExtensionSubstFormat1<SingleSubst>),
967    Multiple(ExtensionSubstFormat1<MultipleSubstFormat1>),
968    Alternate(ExtensionSubstFormat1<AlternateSubstFormat1>),
969    Ligature(ExtensionSubstFormat1<LigatureSubstFormat1>),
970    Contextual(ExtensionSubstFormat1<SubstitutionSequenceContext>),
971    ChainContextual(ExtensionSubstFormat1<SubstitutionChainContext>),
972    Reverse(ExtensionSubstFormat1<ReverseChainSingleSubstFormat1>),
973}
974
975impl Default for ExtensionSubtable {
976    fn default() -> Self {
977        Self::Single(Default::default())
978    }
979}
980
981impl FontWrite for ExtensionSubtable {
982    fn write_into(&self, writer: &mut TableWriter) {
983        match self {
984            Self::Single(table) => table.write_into(writer),
985            Self::Multiple(table) => table.write_into(writer),
986            Self::Alternate(table) => table.write_into(writer),
987            Self::Ligature(table) => table.write_into(writer),
988            Self::Contextual(table) => table.write_into(writer),
989            Self::ChainContextual(table) => table.write_into(writer),
990            Self::Reverse(table) => table.write_into(writer),
991        }
992    }
993    fn table_type(&self) -> TableType {
994        match self {
995            Self::Single(table) => table.table_type(),
996            Self::Multiple(table) => table.table_type(),
997            Self::Alternate(table) => table.table_type(),
998            Self::Ligature(table) => table.table_type(),
999            Self::Contextual(table) => table.table_type(),
1000            Self::ChainContextual(table) => table.table_type(),
1001            Self::Reverse(table) => table.table_type(),
1002        }
1003    }
1004}
1005
1006impl Validate for ExtensionSubtable {
1007    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1008        match self {
1009            Self::Single(table) => table.validate_impl(ctx),
1010            Self::Multiple(table) => table.validate_impl(ctx),
1011            Self::Alternate(table) => table.validate_impl(ctx),
1012            Self::Ligature(table) => table.validate_impl(ctx),
1013            Self::Contextual(table) => table.validate_impl(ctx),
1014            Self::ChainContextual(table) => table.validate_impl(ctx),
1015            Self::Reverse(table) => table.validate_impl(ctx),
1016        }
1017    }
1018}
1019
1020impl FromObjRef<read_fonts::tables::gsub::ExtensionSubtable<'_>> for ExtensionSubtable {
1021    fn from_obj_ref(
1022        from: &read_fonts::tables::gsub::ExtensionSubtable<'_>,
1023        data: FontData,
1024    ) -> Self {
1025        match from {
1026            read_fonts::tables::gsub::ExtensionSubtable::Single(table) => {
1027                Self::Single(table.to_owned_obj(data))
1028            }
1029            read_fonts::tables::gsub::ExtensionSubtable::Multiple(table) => {
1030                Self::Multiple(table.to_owned_obj(data))
1031            }
1032            read_fonts::tables::gsub::ExtensionSubtable::Alternate(table) => {
1033                Self::Alternate(table.to_owned_obj(data))
1034            }
1035            read_fonts::tables::gsub::ExtensionSubtable::Ligature(table) => {
1036                Self::Ligature(table.to_owned_obj(data))
1037            }
1038            read_fonts::tables::gsub::ExtensionSubtable::Contextual(table) => {
1039                Self::Contextual(table.to_owned_obj(data))
1040            }
1041            read_fonts::tables::gsub::ExtensionSubtable::ChainContextual(table) => {
1042                Self::ChainContextual(table.to_owned_obj(data))
1043            }
1044            read_fonts::tables::gsub::ExtensionSubtable::Reverse(table) => {
1045                Self::Reverse(table.to_owned_obj(data))
1046            }
1047        }
1048    }
1049}
1050
1051impl FromTableRef<read_fonts::tables::gsub::ExtensionSubtable<'_>> for ExtensionSubtable {}
1052
1053impl From<ExtensionSubstFormat1<SingleSubst>> for ExtensionSubtable {
1054    fn from(src: ExtensionSubstFormat1<SingleSubst>) -> ExtensionSubtable {
1055        ExtensionSubtable::Single(src)
1056    }
1057}
1058
1059impl From<ExtensionSubstFormat1<MultipleSubstFormat1>> for ExtensionSubtable {
1060    fn from(src: ExtensionSubstFormat1<MultipleSubstFormat1>) -> ExtensionSubtable {
1061        ExtensionSubtable::Multiple(src)
1062    }
1063}
1064
1065impl From<ExtensionSubstFormat1<AlternateSubstFormat1>> for ExtensionSubtable {
1066    fn from(src: ExtensionSubstFormat1<AlternateSubstFormat1>) -> ExtensionSubtable {
1067        ExtensionSubtable::Alternate(src)
1068    }
1069}
1070
1071impl From<ExtensionSubstFormat1<LigatureSubstFormat1>> for ExtensionSubtable {
1072    fn from(src: ExtensionSubstFormat1<LigatureSubstFormat1>) -> ExtensionSubtable {
1073        ExtensionSubtable::Ligature(src)
1074    }
1075}
1076
1077impl From<ExtensionSubstFormat1<SubstitutionSequenceContext>> for ExtensionSubtable {
1078    fn from(src: ExtensionSubstFormat1<SubstitutionSequenceContext>) -> ExtensionSubtable {
1079        ExtensionSubtable::Contextual(src)
1080    }
1081}
1082
1083impl From<ExtensionSubstFormat1<SubstitutionChainContext>> for ExtensionSubtable {
1084    fn from(src: ExtensionSubstFormat1<SubstitutionChainContext>) -> ExtensionSubtable {
1085        ExtensionSubtable::ChainContextual(src)
1086    }
1087}
1088
1089impl From<ExtensionSubstFormat1<ReverseChainSingleSubstFormat1>> for ExtensionSubtable {
1090    fn from(src: ExtensionSubstFormat1<ReverseChainSingleSubstFormat1>) -> ExtensionSubtable {
1091        ExtensionSubtable::Reverse(src)
1092    }
1093}
1094
1095/// [Reverse Chaining Contextual Single Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#81-reverse-chaining-contextual-single-substitution-format-1-coverage-based-glyph-contexts)
1096#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1097#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1098pub struct ReverseChainSingleSubstFormat1 {
1099    /// Offset to Coverage table, from beginning of substitution
1100    /// subtable.
1101    pub coverage: OffsetMarker<CoverageTable>,
1102    /// Array of offsets to coverage tables in backtrack sequence, in
1103    /// glyph sequence order.
1104    pub backtrack_coverages: Vec<OffsetMarker<CoverageTable>>,
1105    /// Array of offsets to coverage tables in lookahead sequence, in
1106    /// glyph sequence order.
1107    pub lookahead_coverages: Vec<OffsetMarker<CoverageTable>>,
1108    /// Array of substitute glyph IDs — ordered by Coverage index.
1109    pub substitute_glyph_ids: Vec<GlyphId16>,
1110}
1111
1112impl ReverseChainSingleSubstFormat1 {
1113    /// Construct a new `ReverseChainSingleSubstFormat1`
1114    pub fn new(
1115        coverage: CoverageTable,
1116        backtrack_coverages: Vec<CoverageTable>,
1117        lookahead_coverages: Vec<CoverageTable>,
1118        substitute_glyph_ids: Vec<GlyphId16>,
1119    ) -> Self {
1120        Self {
1121            coverage: coverage.into(),
1122            backtrack_coverages: backtrack_coverages.into_iter().map(Into::into).collect(),
1123            lookahead_coverages: lookahead_coverages.into_iter().map(Into::into).collect(),
1124            substitute_glyph_ids,
1125        }
1126    }
1127}
1128
1129impl FontWrite for ReverseChainSingleSubstFormat1 {
1130    #[allow(clippy::unnecessary_cast)]
1131    fn write_into(&self, writer: &mut TableWriter) {
1132        (1 as u16).write_into(writer);
1133        self.coverage.write_into(writer);
1134        (u16::try_from(array_len(&self.backtrack_coverages)).unwrap()).write_into(writer);
1135        self.backtrack_coverages.write_into(writer);
1136        (u16::try_from(array_len(&self.lookahead_coverages)).unwrap()).write_into(writer);
1137        self.lookahead_coverages.write_into(writer);
1138        (u16::try_from(array_len(&self.substitute_glyph_ids)).unwrap()).write_into(writer);
1139        self.substitute_glyph_ids.write_into(writer);
1140    }
1141    fn table_type(&self) -> TableType {
1142        TableType::Named("ReverseChainSingleSubstFormat1")
1143    }
1144}
1145
1146impl Validate for ReverseChainSingleSubstFormat1 {
1147    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1148        ctx.in_table("ReverseChainSingleSubstFormat1", |ctx| {
1149            ctx.in_field("coverage", |ctx| {
1150                self.coverage.validate_impl(ctx);
1151            });
1152            ctx.in_field("backtrack_coverages", |ctx| {
1153                if self.backtrack_coverages.len() > (u16::MAX as usize) {
1154                    ctx.report("array exceeds max length");
1155                }
1156                self.backtrack_coverages.validate_impl(ctx);
1157            });
1158            ctx.in_field("lookahead_coverages", |ctx| {
1159                if self.lookahead_coverages.len() > (u16::MAX as usize) {
1160                    ctx.report("array exceeds max length");
1161                }
1162                self.lookahead_coverages.validate_impl(ctx);
1163            });
1164            ctx.in_field("substitute_glyph_ids", |ctx| {
1165                if self.substitute_glyph_ids.len() > (u16::MAX as usize) {
1166                    ctx.report("array exceeds max length");
1167                }
1168            });
1169        })
1170    }
1171}
1172
1173impl<'a> FromObjRef<read_fonts::tables::gsub::ReverseChainSingleSubstFormat1<'a>>
1174    for ReverseChainSingleSubstFormat1
1175{
1176    fn from_obj_ref(
1177        obj: &read_fonts::tables::gsub::ReverseChainSingleSubstFormat1<'a>,
1178        _: FontData,
1179    ) -> Self {
1180        let offset_data = obj.offset_data();
1181        ReverseChainSingleSubstFormat1 {
1182            coverage: obj.coverage().to_owned_table(),
1183            backtrack_coverages: obj.backtrack_coverages().to_owned_table(),
1184            lookahead_coverages: obj.lookahead_coverages().to_owned_table(),
1185            substitute_glyph_ids: obj.substitute_glyph_ids().to_owned_obj(offset_data),
1186        }
1187    }
1188}
1189
1190#[allow(clippy::needless_lifetimes)]
1191impl<'a> FromTableRef<read_fonts::tables::gsub::ReverseChainSingleSubstFormat1<'a>>
1192    for ReverseChainSingleSubstFormat1
1193{
1194}
1195
1196impl<'a> FontRead<'a> for ReverseChainSingleSubstFormat1 {
1197    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1198        <read_fonts::tables::gsub::ReverseChainSingleSubstFormat1 as FontRead>::read(data)
1199            .map(|x| x.to_owned_table())
1200    }
1201}