Skip to main content

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