Coverage Report

Created: 2026-08-11 07:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fontations/write-fonts/generated/generated_gsub.rs
Line
Count
Source
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)]
6
use 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))]
11
pub 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
23
impl Gsub {
24
    /// Construct a new `Gsub`
25
0
    pub fn new(
26
0
        script_list: ScriptList,
27
0
        feature_list: FeatureList,
28
0
        lookup_list: SubstitutionLookupList,
29
0
    ) -> Self {
30
0
        Self {
31
0
            script_list: script_list.into(),
32
0
            feature_list: feature_list.into(),
33
0
            lookup_list: lookup_list.into(),
34
0
            ..Default::default()
35
0
        }
36
0
    }
37
}
38
39
impl FontWrite for Gsub {
40
    #[allow(clippy::unnecessary_cast)]
41
0
    fn write_into(&self, writer: &mut TableWriter) {
42
0
        let version = self.compute_version() as MajorMinor;
43
0
        version.write_into(writer);
44
0
        self.script_list.write_into(writer);
45
0
        self.feature_list.write_into(writer);
46
0
        self.lookup_list.write_into(writer);
47
0
        version
48
0
            .compatible((1u16, 1u16))
49
0
            .then(|| self.feature_variations.write_into(writer));
50
0
    }
51
0
    fn table_type(&self) -> TableType {
52
0
        TableType::TopLevel(Gsub::TAG)
53
0
    }
54
}
55
56
impl Validate for Gsub {
57
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
58
0
        ctx.in_table("Gsub", |ctx| {
59
0
            ctx.in_field("script_list", |ctx| {
60
0
                self.script_list.validate_impl(ctx);
61
0
            });
62
0
            ctx.in_field("feature_list", |ctx| {
63
0
                self.feature_list.validate_impl(ctx);
64
0
            });
65
0
            ctx.in_field("lookup_list", |ctx| {
66
0
                self.lookup_list.validate_impl(ctx);
67
0
            });
68
0
            ctx.in_field("feature_variations", |ctx| {
69
0
                self.feature_variations.validate_impl(ctx);
70
0
            });
71
0
        })
72
0
    }
73
}
74
75
impl TopLevelTable for Gsub {
76
    const TAG: Tag = Tag::new(b"GSUB");
77
}
78
79
impl<'a> FromObjRef<read_fonts::tables::gsub::Gsub<'a>> for Gsub {
80
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::Gsub<'a>, _: FontData) -> Self {
81
0
        Gsub {
82
0
            script_list: obj.script_list().to_owned_table(),
83
0
            feature_list: obj.feature_list().to_owned_table(),
84
0
            lookup_list: obj.lookup_list().to_owned_table(),
85
0
            feature_variations: obj.feature_variations().to_owned_table(),
86
0
        }
87
0
    }
88
}
89
90
#[allow(clippy::needless_lifetimes)]
91
impl<'a> FromTableRef<read_fonts::tables::gsub::Gsub<'a>> for Gsub {}
92
93
impl ReadArgs for Gsub {
94
    type Args = ();
95
}
96
97
impl<'a> FontRead<'a> for Gsub {
98
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
99
0
        <read_fonts::tables::gsub::Gsub as FontRead>::read(data).map(|x| x.to_owned_table())
100
0
    }
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))]
106
pub 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
117
impl Default for SubstitutionLookup {
118
0
    fn default() -> Self {
119
0
        Self::Single(Default::default())
120
0
    }
121
}
122
123
impl FontWrite for SubstitutionLookup {
124
0
    fn write_into(&self, writer: &mut TableWriter) {
125
0
        match self {
126
0
            Self::Single(table) => table.write_into(writer),
127
0
            Self::Multiple(table) => table.write_into(writer),
128
0
            Self::Alternate(table) => table.write_into(writer),
129
0
            Self::Ligature(table) => table.write_into(writer),
130
0
            Self::Contextual(table) => table.write_into(writer),
131
0
            Self::ChainContextual(table) => table.write_into(writer),
132
0
            Self::Extension(table) => table.write_into(writer),
133
0
            Self::Reverse(table) => table.write_into(writer),
134
        }
135
0
    }
136
0
    fn table_type(&self) -> TableType {
137
0
        match self {
138
0
            Self::Single(table) => table.table_type(),
139
0
            Self::Multiple(table) => table.table_type(),
140
0
            Self::Alternate(table) => table.table_type(),
141
0
            Self::Ligature(table) => table.table_type(),
142
0
            Self::Contextual(table) => table.table_type(),
143
0
            Self::ChainContextual(table) => table.table_type(),
144
0
            Self::Extension(table) => table.table_type(),
145
0
            Self::Reverse(table) => table.table_type(),
146
        }
147
0
    }
148
}
149
150
impl Validate for SubstitutionLookup {
151
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
152
0
        match self {
153
0
            Self::Single(table) => table.validate_impl(ctx),
154
0
            Self::Multiple(table) => table.validate_impl(ctx),
155
0
            Self::Alternate(table) => table.validate_impl(ctx),
156
0
            Self::Ligature(table) => table.validate_impl(ctx),
157
0
            Self::Contextual(table) => table.validate_impl(ctx),
158
0
            Self::ChainContextual(table) => table.validate_impl(ctx),
159
0
            Self::Extension(table) => table.validate_impl(ctx),
160
0
            Self::Reverse(table) => table.validate_impl(ctx),
161
        }
162
0
    }
163
}
164
165
impl FromObjRef<read_fonts::tables::gsub::SubstitutionLookup<'_>> for SubstitutionLookup {
166
0
    fn from_obj_ref(
167
0
        from: &read_fonts::tables::gsub::SubstitutionLookup<'_>,
168
0
        data: FontData,
169
0
    ) -> Self {
170
0
        match from {
171
0
            read_fonts::tables::gsub::SubstitutionLookup::Single(table) => {
172
0
                Self::Single(table.to_owned_obj(data))
173
            }
174
0
            read_fonts::tables::gsub::SubstitutionLookup::Multiple(table) => {
175
0
                Self::Multiple(table.to_owned_obj(data))
176
            }
177
0
            read_fonts::tables::gsub::SubstitutionLookup::Alternate(table) => {
178
0
                Self::Alternate(table.to_owned_obj(data))
179
            }
180
0
            read_fonts::tables::gsub::SubstitutionLookup::Ligature(table) => {
181
0
                Self::Ligature(table.to_owned_obj(data))
182
            }
183
0
            read_fonts::tables::gsub::SubstitutionLookup::Contextual(table) => {
184
0
                Self::Contextual(table.to_owned_obj(data))
185
            }
186
0
            read_fonts::tables::gsub::SubstitutionLookup::ChainContextual(table) => {
187
0
                Self::ChainContextual(table.to_owned_obj(data))
188
            }
189
0
            read_fonts::tables::gsub::SubstitutionLookup::Extension(table) => {
190
0
                Self::Extension(table.to_owned_obj(data))
191
            }
192
0
            read_fonts::tables::gsub::SubstitutionLookup::Reverse(table) => {
193
0
                Self::Reverse(table.to_owned_obj(data))
194
            }
195
        }
196
0
    }
197
}
198
199
impl FromTableRef<read_fonts::tables::gsub::SubstitutionLookup<'_>> for SubstitutionLookup {}
200
201
impl From<Lookup<SingleSubst>> for SubstitutionLookup {
202
0
    fn from(src: Lookup<SingleSubst>) -> SubstitutionLookup {
203
0
        SubstitutionLookup::Single(src)
204
0
    }
205
}
206
207
impl From<Lookup<MultipleSubstFormat1>> for SubstitutionLookup {
208
0
    fn from(src: Lookup<MultipleSubstFormat1>) -> SubstitutionLookup {
209
0
        SubstitutionLookup::Multiple(src)
210
0
    }
211
}
212
213
impl From<Lookup<AlternateSubstFormat1>> for SubstitutionLookup {
214
0
    fn from(src: Lookup<AlternateSubstFormat1>) -> SubstitutionLookup {
215
0
        SubstitutionLookup::Alternate(src)
216
0
    }
217
}
218
219
impl From<Lookup<LigatureSubstFormat1>> for SubstitutionLookup {
220
0
    fn from(src: Lookup<LigatureSubstFormat1>) -> SubstitutionLookup {
221
0
        SubstitutionLookup::Ligature(src)
222
0
    }
223
}
224
225
impl From<Lookup<SubstitutionSequenceContext>> for SubstitutionLookup {
226
0
    fn from(src: Lookup<SubstitutionSequenceContext>) -> SubstitutionLookup {
227
0
        SubstitutionLookup::Contextual(src)
228
0
    }
229
}
230
231
impl From<Lookup<SubstitutionChainContext>> for SubstitutionLookup {
232
0
    fn from(src: Lookup<SubstitutionChainContext>) -> SubstitutionLookup {
233
0
        SubstitutionLookup::ChainContextual(src)
234
0
    }
235
}
236
237
impl From<Lookup<ExtensionSubtable>> for SubstitutionLookup {
238
0
    fn from(src: Lookup<ExtensionSubtable>) -> SubstitutionLookup {
239
0
        SubstitutionLookup::Extension(src)
240
0
    }
241
}
242
243
impl From<Lookup<ReverseChainSingleSubstFormat1>> for SubstitutionLookup {
244
0
    fn from(src: Lookup<ReverseChainSingleSubstFormat1>) -> SubstitutionLookup {
245
0
        SubstitutionLookup::Reverse(src)
246
0
    }
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))]
252
pub enum SingleSubst {
253
    Format1(SingleSubstFormat1),
254
    Format2(SingleSubstFormat2),
255
}
256
257
impl SingleSubst {
258
    /// Construct a new `SingleSubstFormat1` subtable
259
0
    pub fn format_1(coverage: CoverageTable, delta_glyph_id: i16) -> Self {
260
0
        Self::Format1(SingleSubstFormat1::new(coverage, delta_glyph_id))
261
0
    }
262
263
    /// Construct a new `SingleSubstFormat2` subtable
264
0
    pub fn format_2(coverage: CoverageTable, substitute_glyph_ids: Vec<GlyphId16>) -> Self {
265
0
        Self::Format2(SingleSubstFormat2::new(coverage, substitute_glyph_ids))
266
0
    }
267
}
268
269
impl Default for SingleSubst {
270
0
    fn default() -> Self {
271
0
        Self::Format1(Default::default())
272
0
    }
273
}
274
275
impl FontWrite for SingleSubst {
276
0
    fn write_into(&self, writer: &mut TableWriter) {
277
0
        match self {
278
0
            Self::Format1(item) => item.write_into(writer),
279
0
            Self::Format2(item) => item.write_into(writer),
280
        }
281
0
    }
282
0
    fn table_type(&self) -> TableType {
283
0
        match self {
284
0
            Self::Format1(item) => item.table_type(),
285
0
            Self::Format2(item) => item.table_type(),
286
        }
287
0
    }
288
}
289
290
impl Validate for SingleSubst {
291
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
292
0
        match self {
293
0
            Self::Format1(item) => item.validate_impl(ctx),
294
0
            Self::Format2(item) => item.validate_impl(ctx),
295
        }
296
0
    }
297
}
298
299
impl FromObjRef<read_fonts::tables::gsub::SingleSubst<'_>> for SingleSubst {
300
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::SingleSubst, _: FontData) -> Self {
301
        use read_fonts::tables::gsub::SingleSubst as ObjRefType;
302
0
        match obj {
303
0
            ObjRefType::Format1(item) => SingleSubst::Format1(item.to_owned_table()),
304
0
            ObjRefType::Format2(item) => SingleSubst::Format2(item.to_owned_table()),
305
        }
306
0
    }
307
}
308
309
impl FromTableRef<read_fonts::tables::gsub::SingleSubst<'_>> for SingleSubst {}
310
311
impl ReadArgs for SingleSubst {
312
    type Args = ();
313
}
314
315
impl<'a> FontRead<'a> for SingleSubst {
316
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
317
0
        <read_fonts::tables::gsub::SingleSubst as FontRead>::read(data).map(|x| x.to_owned_table())
318
0
    }
319
}
320
321
impl From<SingleSubstFormat1> for SingleSubst {
322
0
    fn from(src: SingleSubstFormat1) -> SingleSubst {
323
0
        SingleSubst::Format1(src)
324
0
    }
325
}
326
327
impl From<SingleSubstFormat2> for SingleSubst {
328
0
    fn from(src: SingleSubstFormat2) -> SingleSubst {
329
0
        SingleSubst::Format2(src)
330
0
    }
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))]
336
pub 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
344
impl SingleSubstFormat1 {
345
    /// Construct a new `SingleSubstFormat1`
346
0
    pub fn new(coverage: CoverageTable, delta_glyph_id: i16) -> Self {
347
0
        Self {
348
0
            coverage: coverage.into(),
349
0
            delta_glyph_id,
350
0
        }
351
0
    }
352
}
353
354
impl FontWrite for SingleSubstFormat1 {
355
    #[allow(clippy::unnecessary_cast)]
356
0
    fn write_into(&self, writer: &mut TableWriter) {
357
0
        (1 as u16).write_into(writer);
358
0
        self.coverage.write_into(writer);
359
0
        self.delta_glyph_id.write_into(writer);
360
0
    }
361
0
    fn table_type(&self) -> TableType {
362
0
        TableType::Named("SingleSubstFormat1")
363
0
    }
364
}
365
366
impl Validate for SingleSubstFormat1 {
367
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
368
0
        ctx.in_table("SingleSubstFormat1", |ctx| {
369
0
            ctx.in_field("coverage", |ctx| {
370
0
                self.coverage.validate_impl(ctx);
371
0
            });
372
0
        })
373
0
    }
374
}
375
376
impl<'a> FromObjRef<read_fonts::tables::gsub::SingleSubstFormat1<'a>> for SingleSubstFormat1 {
377
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::SingleSubstFormat1<'a>, _: FontData) -> Self {
378
0
        SingleSubstFormat1 {
379
0
            coverage: obj.coverage().to_owned_table(),
380
0
            delta_glyph_id: obj.delta_glyph_id(),
381
0
        }
382
0
    }
383
}
384
385
#[allow(clippy::needless_lifetimes)]
386
impl<'a> FromTableRef<read_fonts::tables::gsub::SingleSubstFormat1<'a>> for SingleSubstFormat1 {}
387
388
impl ReadArgs for SingleSubstFormat1 {
389
    type Args = ();
390
}
391
392
impl<'a> FontRead<'a> for SingleSubstFormat1 {
393
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
394
0
        <read_fonts::tables::gsub::SingleSubstFormat1 as FontRead>::read(data)
395
0
            .map(|x| x.to_owned_table())
396
0
    }
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))]
402
pub 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
410
impl SingleSubstFormat2 {
411
    /// Construct a new `SingleSubstFormat2`
412
0
    pub fn new(coverage: CoverageTable, substitute_glyph_ids: Vec<GlyphId16>) -> Self {
413
0
        Self {
414
0
            coverage: coverage.into(),
415
0
            substitute_glyph_ids,
416
0
        }
417
0
    }
418
}
419
420
impl FontWrite for SingleSubstFormat2 {
421
    #[allow(clippy::unnecessary_cast)]
422
0
    fn write_into(&self, writer: &mut TableWriter) {
423
0
        (2 as u16).write_into(writer);
424
0
        self.coverage.write_into(writer);
425
0
        (u16::try_from(array_len(&self.substitute_glyph_ids)).unwrap()).write_into(writer);
426
0
        self.substitute_glyph_ids.write_into(writer);
427
0
    }
428
0
    fn table_type(&self) -> TableType {
429
0
        TableType::Named("SingleSubstFormat2")
430
0
    }
431
}
432
433
impl Validate for SingleSubstFormat2 {
434
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
435
0
        ctx.in_table("SingleSubstFormat2", |ctx| {
436
0
            ctx.in_field("coverage", |ctx| {
437
0
                self.coverage.validate_impl(ctx);
438
0
            });
439
0
            ctx.in_field("substitute_glyph_ids", |ctx| {
440
0
                if self.substitute_glyph_ids.len() > to_usize(u16::MAX) {
441
0
                    ctx.report("array exceeds max length");
442
0
                }
443
0
            });
444
0
        })
445
0
    }
446
}
447
448
impl<'a> FromObjRef<read_fonts::tables::gsub::SingleSubstFormat2<'a>> for SingleSubstFormat2 {
449
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::SingleSubstFormat2<'a>, _: FontData) -> Self {
450
0
        let offset_data = obj.offset_data();
451
0
        SingleSubstFormat2 {
452
0
            coverage: obj.coverage().to_owned_table(),
453
0
            substitute_glyph_ids: obj.substitute_glyph_ids().to_owned_obj(offset_data),
454
0
        }
455
0
    }
456
}
457
458
#[allow(clippy::needless_lifetimes)]
459
impl<'a> FromTableRef<read_fonts::tables::gsub::SingleSubstFormat2<'a>> for SingleSubstFormat2 {}
460
461
impl ReadArgs for SingleSubstFormat2 {
462
    type Args = ();
463
}
464
465
impl<'a> FontRead<'a> for SingleSubstFormat2 {
466
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
467
0
        <read_fonts::tables::gsub::SingleSubstFormat2 as FontRead>::read(data)
468
0
            .map(|x| x.to_owned_table())
469
0
    }
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))]
475
pub 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
484
impl MultipleSubstFormat1 {
485
    /// Construct a new `MultipleSubstFormat1`
486
0
    pub fn new(coverage: CoverageTable, sequences: Vec<Sequence>) -> Self {
487
0
        Self {
488
0
            coverage: coverage.into(),
489
0
            sequences: sequences.into_iter().map(Into::into).collect(),
490
0
        }
491
0
    }
492
}
493
494
impl FontWrite for MultipleSubstFormat1 {
495
    #[allow(clippy::unnecessary_cast)]
496
0
    fn write_into(&self, writer: &mut TableWriter) {
497
0
        (1 as u16).write_into(writer);
498
0
        self.coverage.write_into(writer);
499
0
        (u16::try_from(array_len(&self.sequences)).unwrap()).write_into(writer);
500
0
        self.sequences.write_into(writer);
501
0
    }
502
0
    fn table_type(&self) -> TableType {
503
0
        TableType::Named("MultipleSubstFormat1")
504
0
    }
505
}
506
507
impl Validate for MultipleSubstFormat1 {
508
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
509
0
        ctx.in_table("MultipleSubstFormat1", |ctx| {
510
0
            ctx.in_field("coverage", |ctx| {
511
0
                self.coverage.validate_impl(ctx);
512
0
            });
513
0
            ctx.in_field("sequences", |ctx| {
514
0
                if self.sequences.len() > to_usize(u16::MAX) {
515
0
                    ctx.report("array exceeds max length");
516
0
                }
517
0
                self.sequences.validate_impl(ctx);
518
0
            });
519
0
        })
520
0
    }
521
}
522
523
impl<'a> FromObjRef<read_fonts::tables::gsub::MultipleSubstFormat1<'a>> for MultipleSubstFormat1 {
524
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::MultipleSubstFormat1<'a>, _: FontData) -> Self {
525
0
        MultipleSubstFormat1 {
526
0
            coverage: obj.coverage().to_owned_table(),
527
0
            sequences: obj.sequences().to_owned_table(),
528
0
        }
529
0
    }
530
}
531
532
#[allow(clippy::needless_lifetimes)]
533
impl<'a> FromTableRef<read_fonts::tables::gsub::MultipleSubstFormat1<'a>> for MultipleSubstFormat1 {}
534
535
impl ReadArgs for MultipleSubstFormat1 {
536
    type Args = ();
537
}
538
539
impl<'a> FontRead<'a> for MultipleSubstFormat1 {
540
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
541
0
        <read_fonts::tables::gsub::MultipleSubstFormat1 as FontRead>::read(data)
542
0
            .map(|x| x.to_owned_table())
543
0
    }
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))]
549
pub struct Sequence {
550
    /// String of glyph IDs to substitute
551
    pub substitute_glyph_ids: Vec<GlyphId16>,
552
}
553
554
impl Sequence {
555
    /// Construct a new `Sequence`
556
0
    pub fn new(substitute_glyph_ids: Vec<GlyphId16>) -> Self {
557
0
        Self {
558
0
            substitute_glyph_ids,
559
0
        }
560
0
    }
561
}
562
563
impl FontWrite for Sequence {
564
    #[allow(clippy::unnecessary_cast)]
565
0
    fn write_into(&self, writer: &mut TableWriter) {
566
0
        (u16::try_from(array_len(&self.substitute_glyph_ids)).unwrap()).write_into(writer);
567
0
        self.substitute_glyph_ids.write_into(writer);
568
0
    }
569
0
    fn table_type(&self) -> TableType {
570
0
        TableType::Named("Sequence")
571
0
    }
572
}
573
574
impl Validate for Sequence {
575
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
576
0
        ctx.in_table("Sequence", |ctx| {
577
0
            ctx.in_field("substitute_glyph_ids", |ctx| {
578
0
                if self.substitute_glyph_ids.len() > to_usize(u16::MAX) {
579
0
                    ctx.report("array exceeds max length");
580
0
                }
581
0
            });
582
0
        })
583
0
    }
584
}
585
586
impl<'a> FromObjRef<read_fonts::tables::gsub::Sequence<'a>> for Sequence {
587
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::Sequence<'a>, _: FontData) -> Self {
588
0
        let offset_data = obj.offset_data();
589
0
        Sequence {
590
0
            substitute_glyph_ids: obj.substitute_glyph_ids().to_owned_obj(offset_data),
591
0
        }
592
0
    }
593
}
594
595
#[allow(clippy::needless_lifetimes)]
596
impl<'a> FromTableRef<read_fonts::tables::gsub::Sequence<'a>> for Sequence {}
597
598
impl ReadArgs for Sequence {
599
    type Args = ();
600
}
601
602
impl<'a> FontRead<'a> for Sequence {
603
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
604
0
        <read_fonts::tables::gsub::Sequence as FontRead>::read(data).map(|x| x.to_owned_table())
605
0
    }
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))]
611
pub 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
620
impl AlternateSubstFormat1 {
621
    /// Construct a new `AlternateSubstFormat1`
622
0
    pub fn new(coverage: CoverageTable, alternate_sets: Vec<AlternateSet>) -> Self {
623
0
        Self {
624
0
            coverage: coverage.into(),
625
0
            alternate_sets: alternate_sets.into_iter().map(Into::into).collect(),
626
0
        }
627
0
    }
628
}
629
630
impl FontWrite for AlternateSubstFormat1 {
631
    #[allow(clippy::unnecessary_cast)]
632
0
    fn write_into(&self, writer: &mut TableWriter) {
633
0
        (1 as u16).write_into(writer);
634
0
        self.coverage.write_into(writer);
635
0
        (u16::try_from(array_len(&self.alternate_sets)).unwrap()).write_into(writer);
636
0
        self.alternate_sets.write_into(writer);
637
0
    }
638
0
    fn table_type(&self) -> TableType {
639
0
        TableType::Named("AlternateSubstFormat1")
640
0
    }
641
}
642
643
impl Validate for AlternateSubstFormat1 {
644
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
645
0
        ctx.in_table("AlternateSubstFormat1", |ctx| {
646
0
            ctx.in_field("coverage", |ctx| {
647
0
                self.coverage.validate_impl(ctx);
648
0
            });
649
0
            ctx.in_field("alternate_sets", |ctx| {
650
0
                if self.alternate_sets.len() > to_usize(u16::MAX) {
651
0
                    ctx.report("array exceeds max length");
652
0
                }
653
0
                self.alternate_sets.validate_impl(ctx);
654
0
            });
655
0
        })
656
0
    }
657
}
658
659
impl<'a> FromObjRef<read_fonts::tables::gsub::AlternateSubstFormat1<'a>> for AlternateSubstFormat1 {
660
0
    fn from_obj_ref(
661
0
        obj: &read_fonts::tables::gsub::AlternateSubstFormat1<'a>,
662
0
        _: FontData,
663
0
    ) -> Self {
664
0
        AlternateSubstFormat1 {
665
0
            coverage: obj.coverage().to_owned_table(),
666
0
            alternate_sets: obj.alternate_sets().to_owned_table(),
667
0
        }
668
0
    }
669
}
670
671
#[allow(clippy::needless_lifetimes)]
672
impl<'a> FromTableRef<read_fonts::tables::gsub::AlternateSubstFormat1<'a>>
673
    for AlternateSubstFormat1
674
{
675
}
676
677
impl ReadArgs for AlternateSubstFormat1 {
678
    type Args = ();
679
}
680
681
impl<'a> FontRead<'a> for AlternateSubstFormat1 {
682
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
683
0
        <read_fonts::tables::gsub::AlternateSubstFormat1 as FontRead>::read(data)
684
0
            .map(|x| x.to_owned_table())
685
0
    }
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))]
691
pub struct AlternateSet {
692
    /// Array of alternate glyph IDs, in arbitrary order
693
    pub alternate_glyph_ids: Vec<GlyphId16>,
694
}
695
696
impl AlternateSet {
697
    /// Construct a new `AlternateSet`
698
0
    pub fn new(alternate_glyph_ids: Vec<GlyphId16>) -> Self {
699
0
        Self {
700
0
            alternate_glyph_ids,
701
0
        }
702
0
    }
703
}
704
705
impl FontWrite for AlternateSet {
706
    #[allow(clippy::unnecessary_cast)]
707
0
    fn write_into(&self, writer: &mut TableWriter) {
708
0
        (u16::try_from(array_len(&self.alternate_glyph_ids)).unwrap()).write_into(writer);
709
0
        self.alternate_glyph_ids.write_into(writer);
710
0
    }
711
0
    fn table_type(&self) -> TableType {
712
0
        TableType::Named("AlternateSet")
713
0
    }
714
}
715
716
impl Validate for AlternateSet {
717
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
718
0
        ctx.in_table("AlternateSet", |ctx| {
719
0
            ctx.in_field("alternate_glyph_ids", |ctx| {
720
0
                if self.alternate_glyph_ids.len() > to_usize(u16::MAX) {
721
0
                    ctx.report("array exceeds max length");
722
0
                }
723
0
            });
724
0
        })
725
0
    }
726
}
727
728
impl<'a> FromObjRef<read_fonts::tables::gsub::AlternateSet<'a>> for AlternateSet {
729
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::AlternateSet<'a>, _: FontData) -> Self {
730
0
        let offset_data = obj.offset_data();
731
0
        AlternateSet {
732
0
            alternate_glyph_ids: obj.alternate_glyph_ids().to_owned_obj(offset_data),
733
0
        }
734
0
    }
735
}
736
737
#[allow(clippy::needless_lifetimes)]
738
impl<'a> FromTableRef<read_fonts::tables::gsub::AlternateSet<'a>> for AlternateSet {}
739
740
impl ReadArgs for AlternateSet {
741
    type Args = ();
742
}
743
744
impl<'a> FontRead<'a> for AlternateSet {
745
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
746
0
        <read_fonts::tables::gsub::AlternateSet as FontRead>::read(data).map(|x| x.to_owned_table())
747
0
    }
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))]
753
pub 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
762
impl LigatureSubstFormat1 {
763
    /// Construct a new `LigatureSubstFormat1`
764
0
    pub fn new(coverage: CoverageTable, ligature_sets: Vec<LigatureSet>) -> Self {
765
0
        Self {
766
0
            coverage: coverage.into(),
767
0
            ligature_sets: ligature_sets.into_iter().map(Into::into).collect(),
768
0
        }
769
0
    }
770
}
771
772
impl FontWrite for LigatureSubstFormat1 {
773
    #[allow(clippy::unnecessary_cast)]
774
0
    fn write_into(&self, writer: &mut TableWriter) {
775
0
        (1 as u16).write_into(writer);
776
0
        self.coverage.write_into(writer);
777
0
        (u16::try_from(array_len(&self.ligature_sets)).unwrap()).write_into(writer);
778
0
        self.ligature_sets.write_into(writer);
779
0
    }
780
0
    fn table_type(&self) -> TableType {
781
0
        TableType::Named("LigatureSubstFormat1")
782
0
    }
783
}
784
785
impl Validate for LigatureSubstFormat1 {
786
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
787
0
        ctx.in_table("LigatureSubstFormat1", |ctx| {
788
0
            ctx.in_field("coverage", |ctx| {
789
0
                self.coverage.validate_impl(ctx);
790
0
            });
791
0
            ctx.in_field("ligature_sets", |ctx| {
792
0
                if self.ligature_sets.len() > to_usize(u16::MAX) {
793
0
                    ctx.report("array exceeds max length");
794
0
                }
795
0
                self.ligature_sets.validate_impl(ctx);
796
0
            });
797
0
        })
798
0
    }
799
}
800
801
impl<'a> FromObjRef<read_fonts::tables::gsub::LigatureSubstFormat1<'a>> for LigatureSubstFormat1 {
802
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::LigatureSubstFormat1<'a>, _: FontData) -> Self {
803
0
        LigatureSubstFormat1 {
804
0
            coverage: obj.coverage().to_owned_table(),
805
0
            ligature_sets: obj.ligature_sets().to_owned_table(),
806
0
        }
807
0
    }
808
}
809
810
#[allow(clippy::needless_lifetimes)]
811
impl<'a> FromTableRef<read_fonts::tables::gsub::LigatureSubstFormat1<'a>> for LigatureSubstFormat1 {}
812
813
impl ReadArgs for LigatureSubstFormat1 {
814
    type Args = ();
815
}
816
817
impl<'a> FontRead<'a> for LigatureSubstFormat1 {
818
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
819
0
        <read_fonts::tables::gsub::LigatureSubstFormat1 as FontRead>::read(data)
820
0
            .map(|x| x.to_owned_table())
821
0
    }
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))]
827
pub 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
833
impl LigatureSet {
834
    /// Construct a new `LigatureSet`
835
0
    pub fn new(ligatures: Vec<Ligature>) -> Self {
836
0
        Self {
837
0
            ligatures: ligatures.into_iter().map(Into::into).collect(),
838
0
        }
839
0
    }
840
}
841
842
impl FontWrite for LigatureSet {
843
    #[allow(clippy::unnecessary_cast)]
844
0
    fn write_into(&self, writer: &mut TableWriter) {
845
0
        (u16::try_from(array_len(&self.ligatures)).unwrap()).write_into(writer);
846
0
        self.ligatures.write_into(writer);
847
0
    }
848
0
    fn table_type(&self) -> TableType {
849
0
        TableType::Named("LigatureSet")
850
0
    }
851
}
852
853
impl Validate for LigatureSet {
854
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
855
0
        ctx.in_table("LigatureSet", |ctx| {
856
0
            ctx.in_field("ligatures", |ctx| {
857
0
                if self.ligatures.len() > to_usize(u16::MAX) {
858
0
                    ctx.report("array exceeds max length");
859
0
                }
860
0
                self.ligatures.validate_impl(ctx);
861
0
            });
862
0
        })
863
0
    }
864
}
865
866
impl<'a> FromObjRef<read_fonts::tables::gsub::LigatureSet<'a>> for LigatureSet {
867
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::LigatureSet<'a>, _: FontData) -> Self {
868
0
        LigatureSet {
869
0
            ligatures: obj.ligatures().to_owned_table(),
870
0
        }
871
0
    }
872
}
873
874
#[allow(clippy::needless_lifetimes)]
875
impl<'a> FromTableRef<read_fonts::tables::gsub::LigatureSet<'a>> for LigatureSet {}
876
877
impl ReadArgs for LigatureSet {
878
    type Args = ();
879
}
880
881
impl<'a> FontRead<'a> for LigatureSet {
882
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
883
0
        <read_fonts::tables::gsub::LigatureSet as FontRead>::read(data).map(|x| x.to_owned_table())
884
0
    }
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))]
890
pub 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
898
impl Ligature {
899
    /// Construct a new `Ligature`
900
0
    pub fn new(ligature_glyph: GlyphId16, component_glyph_ids: Vec<GlyphId16>) -> Self {
901
0
        Self {
902
0
            ligature_glyph,
903
0
            component_glyph_ids,
904
0
        }
905
0
    }
906
}
907
908
impl FontWrite for Ligature {
909
    #[allow(clippy::unnecessary_cast)]
910
0
    fn write_into(&self, writer: &mut TableWriter) {
911
0
        self.ligature_glyph.write_into(writer);
912
0
        (u16::try_from(plus_one(&self.component_glyph_ids.len())).unwrap()).write_into(writer);
913
0
        self.component_glyph_ids.write_into(writer);
914
0
    }
915
0
    fn table_type(&self) -> TableType {
916
0
        TableType::Named("Ligature")
917
0
    }
918
}
919
920
impl Validate for Ligature {
921
0
    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
922
}
923
924
impl<'a> FromObjRef<read_fonts::tables::gsub::Ligature<'a>> for Ligature {
925
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::Ligature<'a>, _: FontData) -> Self {
926
0
        let offset_data = obj.offset_data();
927
0
        Ligature {
928
0
            ligature_glyph: obj.ligature_glyph(),
929
0
            component_glyph_ids: obj.component_glyph_ids().to_owned_obj(offset_data),
930
0
        }
931
0
    }
932
}
933
934
#[allow(clippy::needless_lifetimes)]
935
impl<'a> FromTableRef<read_fonts::tables::gsub::Ligature<'a>> for Ligature {}
936
937
impl ReadArgs for Ligature {
938
    type Args = ();
939
}
940
941
impl<'a> FontRead<'a> for Ligature {
942
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
943
0
        <read_fonts::tables::gsub::Ligature as FontRead>::read(data).map(|x| x.to_owned_table())
944
0
    }
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))]
950
pub 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
960
impl<T: Default> ExtensionSubstFormat1<T> {
961
    /// Construct a new `ExtensionSubstFormat1`
962
0
    pub fn new(extension_lookup_type: u16, extension: T) -> Self {
963
0
        Self {
964
0
            extension_lookup_type,
965
0
            extension: extension.into(),
966
0
        }
967
0
    }
968
}
969
970
impl<T: Validate> Validate for ExtensionSubstFormat1<T> {
971
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
972
0
        ctx.in_table("ExtensionSubstFormat1", |ctx| {
973
0
            ctx.in_field("extension", |ctx| {
974
0
                self.extension.validate_impl(ctx);
975
0
            });
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::SingleSubst> as write_fonts::validate::Validate>::validate_impl::{closure#0}::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::LigatureSubstFormat1> as write_fonts::validate::Validate>::validate_impl::{closure#0}::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::MultipleSubstFormat1> as write_fonts::validate::Validate>::validate_impl::{closure#0}::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::AlternateSubstFormat1> as write_fonts::validate::Validate>::validate_impl::{closure#0}::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::SubstitutionChainContext> as write_fonts::validate::Validate>::validate_impl::{closure#0}::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::SubstitutionSequenceContext> as write_fonts::validate::Validate>::validate_impl::{closure#0}::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::ReverseChainSingleSubstFormat1> as write_fonts::validate::Validate>::validate_impl::{closure#0}::{closure#0}
976
0
        })
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::SingleSubst> as write_fonts::validate::Validate>::validate_impl::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::LigatureSubstFormat1> as write_fonts::validate::Validate>::validate_impl::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::MultipleSubstFormat1> as write_fonts::validate::Validate>::validate_impl::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::AlternateSubstFormat1> as write_fonts::validate::Validate>::validate_impl::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::SubstitutionChainContext> as write_fonts::validate::Validate>::validate_impl::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::SubstitutionSequenceContext> as write_fonts::validate::Validate>::validate_impl::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::ReverseChainSingleSubstFormat1> as write_fonts::validate::Validate>::validate_impl::{closure#0}
977
0
    }
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::SingleSubst> as write_fonts::validate::Validate>::validate_impl
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::LigatureSubstFormat1> as write_fonts::validate::Validate>::validate_impl
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::MultipleSubstFormat1> as write_fonts::validate::Validate>::validate_impl
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::AlternateSubstFormat1> as write_fonts::validate::Validate>::validate_impl
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::SubstitutionChainContext> as write_fonts::validate::Validate>::validate_impl
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::SubstitutionSequenceContext> as write_fonts::validate::Validate>::validate_impl
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::ReverseChainSingleSubstFormat1> as write_fonts::validate::Validate>::validate_impl
978
}
979
980
impl<'a, T, U> FromObjRef<read_fonts::tables::gsub::ExtensionSubstFormat1<'a, U>>
981
    for ExtensionSubstFormat1<T>
982
where
983
    U: FontRead<'a, Args = ()>,
984
    T: FromTableRef<U> + Default + 'static,
985
{
986
0
    fn from_obj_ref(
987
0
        obj: &read_fonts::tables::gsub::ExtensionSubstFormat1<'a, U>,
988
0
        _: FontData,
989
0
    ) -> Self {
990
0
        ExtensionSubstFormat1 {
991
0
            extension_lookup_type: obj.extension_lookup_type(),
992
0
            extension: obj.extension().to_owned_table(),
993
0
        }
994
0
    }
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::SingleSubst> as write_fonts::from_obj::FromObjRef<read_fonts::tables::gsub::ExtensionSubstFormat1<read_fonts::tables::gsub::SingleSubst>>>::from_obj_ref
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::LigatureSubstFormat1> as write_fonts::from_obj::FromObjRef<read_fonts::tables::gsub::ExtensionSubstFormat1<read_fonts::tables::gsub::LigatureSubstFormat1>>>::from_obj_ref
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::MultipleSubstFormat1> as write_fonts::from_obj::FromObjRef<read_fonts::tables::gsub::ExtensionSubstFormat1<read_fonts::tables::gsub::MultipleSubstFormat1>>>::from_obj_ref
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::AlternateSubstFormat1> as write_fonts::from_obj::FromObjRef<read_fonts::tables::gsub::ExtensionSubstFormat1<read_fonts::tables::gsub::AlternateSubstFormat1>>>::from_obj_ref
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::SubstitutionChainContext> as write_fonts::from_obj::FromObjRef<read_fonts::tables::gsub::ExtensionSubstFormat1<read_fonts::tables::layout::ChainedSequenceContext>>>::from_obj_ref
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::SubstitutionSequenceContext> as write_fonts::from_obj::FromObjRef<read_fonts::tables::gsub::ExtensionSubstFormat1<read_fonts::tables::layout::SequenceContext>>>::from_obj_ref
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::ReverseChainSingleSubstFormat1> as write_fonts::from_obj::FromObjRef<read_fonts::tables::gsub::ExtensionSubstFormat1<read_fonts::tables::gsub::ReverseChainSingleSubstFormat1>>>::from_obj_ref
995
}
996
997
#[allow(clippy::needless_lifetimes)]
998
impl<'a, T, U> FromTableRef<read_fonts::tables::gsub::ExtensionSubstFormat1<'a, U>>
999
    for ExtensionSubstFormat1<T>
1000
where
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))]
1009
pub 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
1019
impl Default for ExtensionSubtable {
1020
0
    fn default() -> Self {
1021
0
        Self::Single(Default::default())
1022
0
    }
1023
}
1024
1025
impl FontWrite for ExtensionSubtable {
1026
0
    fn write_into(&self, writer: &mut TableWriter) {
1027
0
        match self {
1028
0
            Self::Single(table) => table.write_into(writer),
1029
0
            Self::Multiple(table) => table.write_into(writer),
1030
0
            Self::Alternate(table) => table.write_into(writer),
1031
0
            Self::Ligature(table) => table.write_into(writer),
1032
0
            Self::Contextual(table) => table.write_into(writer),
1033
0
            Self::ChainContextual(table) => table.write_into(writer),
1034
0
            Self::Reverse(table) => table.write_into(writer),
1035
        }
1036
0
    }
1037
0
    fn table_type(&self) -> TableType {
1038
0
        match self {
1039
0
            Self::Single(table) => table.table_type(),
1040
0
            Self::Multiple(table) => table.table_type(),
1041
0
            Self::Alternate(table) => table.table_type(),
1042
0
            Self::Ligature(table) => table.table_type(),
1043
0
            Self::Contextual(table) => table.table_type(),
1044
0
            Self::ChainContextual(table) => table.table_type(),
1045
0
            Self::Reverse(table) => table.table_type(),
1046
        }
1047
0
    }
1048
}
1049
1050
impl Validate for ExtensionSubtable {
1051
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1052
0
        match self {
1053
0
            Self::Single(table) => table.validate_impl(ctx),
1054
0
            Self::Multiple(table) => table.validate_impl(ctx),
1055
0
            Self::Alternate(table) => table.validate_impl(ctx),
1056
0
            Self::Ligature(table) => table.validate_impl(ctx),
1057
0
            Self::Contextual(table) => table.validate_impl(ctx),
1058
0
            Self::ChainContextual(table) => table.validate_impl(ctx),
1059
0
            Self::Reverse(table) => table.validate_impl(ctx),
1060
        }
1061
0
    }
1062
}
1063
1064
impl FromObjRef<read_fonts::tables::gsub::ExtensionSubtable<'_>> for ExtensionSubtable {
1065
0
    fn from_obj_ref(
1066
0
        from: &read_fonts::tables::gsub::ExtensionSubtable<'_>,
1067
0
        data: FontData,
1068
0
    ) -> Self {
1069
0
        match from {
1070
0
            read_fonts::tables::gsub::ExtensionSubtable::Single(table) => {
1071
0
                Self::Single(table.to_owned_obj(data))
1072
            }
1073
0
            read_fonts::tables::gsub::ExtensionSubtable::Multiple(table) => {
1074
0
                Self::Multiple(table.to_owned_obj(data))
1075
            }
1076
0
            read_fonts::tables::gsub::ExtensionSubtable::Alternate(table) => {
1077
0
                Self::Alternate(table.to_owned_obj(data))
1078
            }
1079
0
            read_fonts::tables::gsub::ExtensionSubtable::Ligature(table) => {
1080
0
                Self::Ligature(table.to_owned_obj(data))
1081
            }
1082
0
            read_fonts::tables::gsub::ExtensionSubtable::Contextual(table) => {
1083
0
                Self::Contextual(table.to_owned_obj(data))
1084
            }
1085
0
            read_fonts::tables::gsub::ExtensionSubtable::ChainContextual(table) => {
1086
0
                Self::ChainContextual(table.to_owned_obj(data))
1087
            }
1088
0
            read_fonts::tables::gsub::ExtensionSubtable::Reverse(table) => {
1089
0
                Self::Reverse(table.to_owned_obj(data))
1090
            }
1091
        }
1092
0
    }
1093
}
1094
1095
impl FromTableRef<read_fonts::tables::gsub::ExtensionSubtable<'_>> for ExtensionSubtable {}
1096
1097
impl From<ExtensionSubstFormat1<SingleSubst>> for ExtensionSubtable {
1098
0
    fn from(src: ExtensionSubstFormat1<SingleSubst>) -> ExtensionSubtable {
1099
0
        ExtensionSubtable::Single(src)
1100
0
    }
1101
}
1102
1103
impl From<ExtensionSubstFormat1<MultipleSubstFormat1>> for ExtensionSubtable {
1104
0
    fn from(src: ExtensionSubstFormat1<MultipleSubstFormat1>) -> ExtensionSubtable {
1105
0
        ExtensionSubtable::Multiple(src)
1106
0
    }
1107
}
1108
1109
impl From<ExtensionSubstFormat1<AlternateSubstFormat1>> for ExtensionSubtable {
1110
0
    fn from(src: ExtensionSubstFormat1<AlternateSubstFormat1>) -> ExtensionSubtable {
1111
0
        ExtensionSubtable::Alternate(src)
1112
0
    }
1113
}
1114
1115
impl From<ExtensionSubstFormat1<LigatureSubstFormat1>> for ExtensionSubtable {
1116
0
    fn from(src: ExtensionSubstFormat1<LigatureSubstFormat1>) -> ExtensionSubtable {
1117
0
        ExtensionSubtable::Ligature(src)
1118
0
    }
1119
}
1120
1121
impl From<ExtensionSubstFormat1<SubstitutionSequenceContext>> for ExtensionSubtable {
1122
0
    fn from(src: ExtensionSubstFormat1<SubstitutionSequenceContext>) -> ExtensionSubtable {
1123
0
        ExtensionSubtable::Contextual(src)
1124
0
    }
1125
}
1126
1127
impl From<ExtensionSubstFormat1<SubstitutionChainContext>> for ExtensionSubtable {
1128
0
    fn from(src: ExtensionSubstFormat1<SubstitutionChainContext>) -> ExtensionSubtable {
1129
0
        ExtensionSubtable::ChainContextual(src)
1130
0
    }
1131
}
1132
1133
impl From<ExtensionSubstFormat1<ReverseChainSingleSubstFormat1>> for ExtensionSubtable {
1134
0
    fn from(src: ExtensionSubstFormat1<ReverseChainSingleSubstFormat1>) -> ExtensionSubtable {
1135
0
        ExtensionSubtable::Reverse(src)
1136
0
    }
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))]
1142
pub 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
1156
impl ReverseChainSingleSubstFormat1 {
1157
    /// Construct a new `ReverseChainSingleSubstFormat1`
1158
0
    pub fn new(
1159
0
        coverage: CoverageTable,
1160
0
        backtrack_coverages: Vec<CoverageTable>,
1161
0
        lookahead_coverages: Vec<CoverageTable>,
1162
0
        substitute_glyph_ids: Vec<GlyphId16>,
1163
0
    ) -> Self {
1164
0
        Self {
1165
0
            coverage: coverage.into(),
1166
0
            backtrack_coverages: backtrack_coverages.into_iter().map(Into::into).collect(),
1167
0
            lookahead_coverages: lookahead_coverages.into_iter().map(Into::into).collect(),
1168
0
            substitute_glyph_ids,
1169
0
        }
1170
0
    }
1171
}
1172
1173
impl FontWrite for ReverseChainSingleSubstFormat1 {
1174
    #[allow(clippy::unnecessary_cast)]
1175
0
    fn write_into(&self, writer: &mut TableWriter) {
1176
0
        (1 as u16).write_into(writer);
1177
0
        self.coverage.write_into(writer);
1178
0
        (u16::try_from(array_len(&self.backtrack_coverages)).unwrap()).write_into(writer);
1179
0
        self.backtrack_coverages.write_into(writer);
1180
0
        (u16::try_from(array_len(&self.lookahead_coverages)).unwrap()).write_into(writer);
1181
0
        self.lookahead_coverages.write_into(writer);
1182
0
        (u16::try_from(array_len(&self.substitute_glyph_ids)).unwrap()).write_into(writer);
1183
0
        self.substitute_glyph_ids.write_into(writer);
1184
0
    }
1185
0
    fn table_type(&self) -> TableType {
1186
0
        TableType::Named("ReverseChainSingleSubstFormat1")
1187
0
    }
1188
}
1189
1190
impl Validate for ReverseChainSingleSubstFormat1 {
1191
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1192
0
        ctx.in_table("ReverseChainSingleSubstFormat1", |ctx| {
1193
0
            ctx.in_field("coverage", |ctx| {
1194
0
                self.coverage.validate_impl(ctx);
1195
0
            });
1196
0
            ctx.in_field("backtrack_coverages", |ctx| {
1197
0
                if self.backtrack_coverages.len() > to_usize(u16::MAX) {
1198
0
                    ctx.report("array exceeds max length");
1199
0
                }
1200
0
                self.backtrack_coverages.validate_impl(ctx);
1201
0
            });
1202
0
            ctx.in_field("lookahead_coverages", |ctx| {
1203
0
                if self.lookahead_coverages.len() > to_usize(u16::MAX) {
1204
0
                    ctx.report("array exceeds max length");
1205
0
                }
1206
0
                self.lookahead_coverages.validate_impl(ctx);
1207
0
            });
1208
0
            ctx.in_field("substitute_glyph_ids", |ctx| {
1209
0
                if self.substitute_glyph_ids.len() > to_usize(u16::MAX) {
1210
0
                    ctx.report("array exceeds max length");
1211
0
                }
1212
0
            });
1213
0
        })
1214
0
    }
1215
}
1216
1217
impl<'a> FromObjRef<read_fonts::tables::gsub::ReverseChainSingleSubstFormat1<'a>>
1218
    for ReverseChainSingleSubstFormat1
1219
{
1220
0
    fn from_obj_ref(
1221
0
        obj: &read_fonts::tables::gsub::ReverseChainSingleSubstFormat1<'a>,
1222
0
        _: FontData,
1223
0
    ) -> Self {
1224
0
        let offset_data = obj.offset_data();
1225
0
        ReverseChainSingleSubstFormat1 {
1226
0
            coverage: obj.coverage().to_owned_table(),
1227
0
            backtrack_coverages: obj.backtrack_coverages().to_owned_table(),
1228
0
            lookahead_coverages: obj.lookahead_coverages().to_owned_table(),
1229
0
            substitute_glyph_ids: obj.substitute_glyph_ids().to_owned_obj(offset_data),
1230
0
        }
1231
0
    }
1232
}
1233
1234
#[allow(clippy::needless_lifetimes)]
1235
impl<'a> FromTableRef<read_fonts::tables::gsub::ReverseChainSingleSubstFormat1<'a>>
1236
    for ReverseChainSingleSubstFormat1
1237
{
1238
}
1239
1240
impl ReadArgs for ReverseChainSingleSubstFormat1 {
1241
    type Args = ();
1242
}
1243
1244
impl<'a> FontRead<'a> for ReverseChainSingleSubstFormat1 {
1245
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1246
0
        <read_fonts::tables::gsub::ReverseChainSingleSubstFormat1 as FontRead>::read(data)
1247
0
            .map(|x| x.to_owned_table())
1248
0
    }
1249
}