Coverage Report

Created: 2026-10-28 07:26

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, 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: NullableOffsetMarker<ScriptList>,
14
    /// Offset to FeatureList table, from beginning of GSUB table
15
    pub feature_list: NullableOffsetMarker<FeatureList>,
16
    /// Offset to LookupList table, from beginning of GSUB table
17
    pub lookup_list: NullableOffsetMarker<OriginalSubstitutionLookupList>,
18
    /// Offset to FeatureVariations table, from beginning of the GSUB
19
    /// table (may be NULL)
20
    pub feature_variations: NullableOffsetMarker<FeatureVariations, WIDTH_32>,
21
    /// 32-bit offset to ScriptList, taking precedence when nonzero.
22
    pub script_list2: NullableOffsetMarker<ScriptList, WIDTH_32>,
23
    /// 32-bit offset to FeatureList, taking precedence when nonzero.
24
    pub feature_list2: NullableOffsetMarker<FeatureList, WIDTH_32>,
25
    /// 32-bit offset to LookupList2, taking precedence when nonzero.
26
    pub lookup_list2: NullableOffsetMarker<SubstitutionLookupList2, WIDTH_32>,
27
}
28
29
impl Default for Gsub {
30
0
    fn default() -> Self {
31
0
        Self {
32
0
            script_list: Some(Default::default()).into(),
33
0
            feature_list: Some(Default::default()).into(),
34
0
            lookup_list: Some(Default::default()).into(),
35
0
            feature_variations: Default::default(),
36
0
            script_list2: Default::default(),
37
0
            feature_list2: Default::default(),
38
0
            lookup_list2: Default::default(),
39
0
        }
40
0
    }
41
}
42
43
impl FontWrite for Gsub {
44
    #[allow(clippy::unnecessary_cast)]
45
0
    fn write_into(&self, writer: &mut TableWriter) {
46
0
        let version = self.compute_version() as MajorMinor;
47
0
        version.write_into(writer);
48
0
        self.script_list.write_into(writer);
49
0
        self.feature_list.write_into(writer);
50
0
        self.lookup_list.write_into(writer);
51
0
        version
52
0
            .compatible((1u16, 1u16))
53
0
            .then(|| self.feature_variations.write_into(writer));
54
0
        version
55
0
            .compatible((1u16, 2u16))
56
0
            .then(|| self.script_list2.write_into(writer));
57
0
        version
58
0
            .compatible((1u16, 2u16))
59
0
            .then(|| self.feature_list2.write_into(writer));
60
0
        version
61
0
            .compatible((1u16, 2u16))
62
0
            .then(|| self.lookup_list2.write_into(writer));
63
0
    }
64
0
    fn table_type(&self) -> TableType {
65
0
        TableType::TopLevel(Gsub::TAG)
66
0
    }
67
}
68
69
impl Validate for Gsub {
70
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
71
0
        ctx.in_table("Gsub", |ctx| {
72
0
            ctx.in_field("script_list", |ctx| {
73
0
                self.script_list.validate_impl(ctx);
74
0
            });
75
0
            ctx.in_field("feature_list", |ctx| {
76
0
                self.feature_list.validate_impl(ctx);
77
0
            });
78
0
            ctx.in_field("lookup_list", |ctx| {
79
0
                self.lookup_list.validate_impl(ctx);
80
0
            });
81
0
            ctx.in_field("feature_variations", |ctx| {
82
0
                self.feature_variations.validate_impl(ctx);
83
0
            });
84
0
            ctx.in_field("script_list2", |ctx| {
85
0
                self.script_list2.validate_impl(ctx);
86
0
            });
87
0
            ctx.in_field("feature_list2", |ctx| {
88
0
                self.feature_list2.validate_impl(ctx);
89
0
            });
90
0
            ctx.in_field("lookup_list2", |ctx| {
91
0
                self.lookup_list2.validate_impl(ctx);
92
0
            });
93
0
        })
94
0
    }
95
}
96
97
impl TopLevelTable for Gsub {
98
    const TAG: Tag = Tag::new(b"GSUB");
99
}
100
101
impl<'a> FromObjRef<read_fonts::tables::gsub::Gsub<'a>> for Gsub {
102
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::Gsub<'a>, _: FontData) -> Self {
103
0
        Gsub {
104
0
            script_list: obj.original_script_list().to_owned_table(),
105
0
            feature_list: obj.original_feature_list().to_owned_table(),
106
0
            lookup_list: obj.original_lookup_list().to_owned_table(),
107
0
            feature_variations: obj.feature_variations().to_owned_table(),
108
0
            script_list2: obj.script_list2().to_owned_table(),
109
0
            feature_list2: obj.feature_list2().to_owned_table(),
110
0
            lookup_list2: obj.lookup_list2().to_owned_table(),
111
0
        }
112
0
    }
113
}
114
115
#[allow(clippy::needless_lifetimes)]
116
impl<'a> FromTableRef<read_fonts::tables::gsub::Gsub<'a>> for Gsub {}
117
118
impl ReadArgs for Gsub {
119
    type Args = ();
120
}
121
122
impl<'a> FontRead<'a> for Gsub {
123
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
124
0
        <read_fonts::tables::gsub::Gsub as FontRead>::read(data).map(|x| x.to_owned_table())
125
0
    }
126
}
127
128
/// A [GSUB Lookup](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#gsubLookupTypeEnum) subtable.
129
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
130
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
131
pub enum SubstitutionLookup {
132
    Single(Lookup<SingleSubst>),
133
    Multiple(Lookup<MultipleSubst>),
134
    Alternate(Lookup<AlternateSubst>),
135
    Ligature(Lookup<LigatureSubst>),
136
    Contextual(Lookup<SubstitutionSequenceContext>),
137
    ChainContextual(Lookup<SubstitutionChainContext>),
138
    Extension(Lookup<ExtensionSubtable>),
139
    Reverse(Lookup<ReverseChainSingleSubst>),
140
}
141
142
impl Default for SubstitutionLookup {
143
0
    fn default() -> Self {
144
0
        Self::Single(Default::default())
145
0
    }
146
}
147
148
impl FontWrite for SubstitutionLookup {
149
0
    fn write_into(&self, writer: &mut TableWriter) {
150
0
        match self {
151
0
            Self::Single(table) => table.write_into(writer),
152
0
            Self::Multiple(table) => table.write_into(writer),
153
0
            Self::Alternate(table) => table.write_into(writer),
154
0
            Self::Ligature(table) => table.write_into(writer),
155
0
            Self::Contextual(table) => table.write_into(writer),
156
0
            Self::ChainContextual(table) => table.write_into(writer),
157
0
            Self::Extension(table) => table.write_into(writer),
158
0
            Self::Reverse(table) => table.write_into(writer),
159
        }
160
0
    }
161
0
    fn table_type(&self) -> TableType {
162
0
        match self {
163
0
            Self::Single(table) => table.table_type(),
164
0
            Self::Multiple(table) => table.table_type(),
165
0
            Self::Alternate(table) => table.table_type(),
166
0
            Self::Ligature(table) => table.table_type(),
167
0
            Self::Contextual(table) => table.table_type(),
168
0
            Self::ChainContextual(table) => table.table_type(),
169
0
            Self::Extension(table) => table.table_type(),
170
0
            Self::Reverse(table) => table.table_type(),
171
        }
172
0
    }
173
}
174
175
impl Validate for SubstitutionLookup {
176
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
177
0
        match self {
178
0
            Self::Single(table) => table.validate_impl(ctx),
179
0
            Self::Multiple(table) => table.validate_impl(ctx),
180
0
            Self::Alternate(table) => table.validate_impl(ctx),
181
0
            Self::Ligature(table) => table.validate_impl(ctx),
182
0
            Self::Contextual(table) => table.validate_impl(ctx),
183
0
            Self::ChainContextual(table) => table.validate_impl(ctx),
184
0
            Self::Extension(table) => table.validate_impl(ctx),
185
0
            Self::Reverse(table) => table.validate_impl(ctx),
186
        }
187
0
    }
188
}
189
190
impl FromObjRef<read_fonts::tables::gsub::SubstitutionLookup<'_>> for SubstitutionLookup {
191
0
    fn from_obj_ref(
192
0
        from: &read_fonts::tables::gsub::SubstitutionLookup<'_>,
193
0
        data: FontData,
194
0
    ) -> Self {
195
0
        match from {
196
0
            read_fonts::tables::gsub::SubstitutionLookup::Single(table) => {
197
0
                Self::Single(table.to_owned_obj(data))
198
            }
199
0
            read_fonts::tables::gsub::SubstitutionLookup::Multiple(table) => {
200
0
                Self::Multiple(table.to_owned_obj(data))
201
            }
202
0
            read_fonts::tables::gsub::SubstitutionLookup::Alternate(table) => {
203
0
                Self::Alternate(table.to_owned_obj(data))
204
            }
205
0
            read_fonts::tables::gsub::SubstitutionLookup::Ligature(table) => {
206
0
                Self::Ligature(table.to_owned_obj(data))
207
            }
208
0
            read_fonts::tables::gsub::SubstitutionLookup::Contextual(table) => {
209
0
                Self::Contextual(table.to_owned_obj(data))
210
            }
211
0
            read_fonts::tables::gsub::SubstitutionLookup::ChainContextual(table) => {
212
0
                Self::ChainContextual(table.to_owned_obj(data))
213
            }
214
0
            read_fonts::tables::gsub::SubstitutionLookup::Extension(table) => {
215
0
                Self::Extension(table.to_owned_obj(data))
216
            }
217
0
            read_fonts::tables::gsub::SubstitutionLookup::Reverse(table) => {
218
0
                Self::Reverse(table.to_owned_obj(data))
219
            }
220
        }
221
0
    }
222
}
223
224
impl FromTableRef<read_fonts::tables::gsub::SubstitutionLookup<'_>> for SubstitutionLookup {}
225
226
impl From<Lookup<SingleSubst>> for SubstitutionLookup {
227
0
    fn from(src: Lookup<SingleSubst>) -> SubstitutionLookup {
228
0
        SubstitutionLookup::Single(src)
229
0
    }
230
}
231
232
impl From<Lookup<MultipleSubst>> for SubstitutionLookup {
233
0
    fn from(src: Lookup<MultipleSubst>) -> SubstitutionLookup {
234
0
        SubstitutionLookup::Multiple(src)
235
0
    }
236
}
237
238
impl From<Lookup<AlternateSubst>> for SubstitutionLookup {
239
0
    fn from(src: Lookup<AlternateSubst>) -> SubstitutionLookup {
240
0
        SubstitutionLookup::Alternate(src)
241
0
    }
242
}
243
244
impl From<Lookup<LigatureSubst>> for SubstitutionLookup {
245
0
    fn from(src: Lookup<LigatureSubst>) -> SubstitutionLookup {
246
0
        SubstitutionLookup::Ligature(src)
247
0
    }
248
}
249
250
impl From<Lookup<SubstitutionSequenceContext>> for SubstitutionLookup {
251
0
    fn from(src: Lookup<SubstitutionSequenceContext>) -> SubstitutionLookup {
252
0
        SubstitutionLookup::Contextual(src)
253
0
    }
254
}
255
256
impl From<Lookup<SubstitutionChainContext>> for SubstitutionLookup {
257
0
    fn from(src: Lookup<SubstitutionChainContext>) -> SubstitutionLookup {
258
0
        SubstitutionLookup::ChainContextual(src)
259
0
    }
260
}
261
262
impl From<Lookup<ExtensionSubtable>> for SubstitutionLookup {
263
0
    fn from(src: Lookup<ExtensionSubtable>) -> SubstitutionLookup {
264
0
        SubstitutionLookup::Extension(src)
265
0
    }
266
}
267
268
impl From<Lookup<ReverseChainSingleSubst>> for SubstitutionLookup {
269
0
    fn from(src: Lookup<ReverseChainSingleSubst>) -> SubstitutionLookup {
270
0
        SubstitutionLookup::Reverse(src)
271
0
    }
272
}
273
274
/// LookupType 1: [Single Substitution](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#lookuptype-1-single-substitution-subtable) Subtable
275
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
276
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
277
pub enum SingleSubst {
278
    Format1(SingleSubstFormat1),
279
    Format2(SingleSubstFormat2),
280
    Format3(SingleSubstFormat3),
281
    Format4(SingleSubstFormat4),
282
}
283
284
impl SingleSubst {
285
    /// Construct a new `SingleSubstFormat1` subtable
286
0
    pub fn format_1(coverage: CoverageTable, delta_glyph_id: i16) -> Self {
287
0
        Self::Format1(SingleSubstFormat1::new(coverage, delta_glyph_id))
288
0
    }
289
290
    /// Construct a new `SingleSubstFormat2` subtable
291
0
    pub fn format_2(coverage: CoverageTable, substitute_glyph_ids: Vec<GlyphId16>) -> Self {
292
0
        Self::Format2(SingleSubstFormat2::new(coverage, substitute_glyph_ids))
293
0
    }
294
295
    /// Construct a new `SingleSubstFormat3` subtable
296
0
    pub fn format_3(coverage: CoverageTable, delta_glyph_id: Int24) -> Self {
297
0
        Self::Format3(SingleSubstFormat3::new(coverage, delta_glyph_id))
298
0
    }
299
300
    /// Construct a new `SingleSubstFormat4` subtable
301
0
    pub fn format_4(coverage: CoverageTable, substitute_glyph_ids: Vec<GlyphId24>) -> Self {
302
0
        Self::Format4(SingleSubstFormat4::new(coverage, substitute_glyph_ids))
303
0
    }
304
}
305
306
impl Default for SingleSubst {
307
0
    fn default() -> Self {
308
0
        Self::Format1(Default::default())
309
0
    }
310
}
311
312
impl FontWrite for SingleSubst {
313
0
    fn write_into(&self, writer: &mut TableWriter) {
314
0
        match self {
315
0
            Self::Format1(item) => item.write_into(writer),
316
0
            Self::Format2(item) => item.write_into(writer),
317
0
            Self::Format3(item) => item.write_into(writer),
318
0
            Self::Format4(item) => item.write_into(writer),
319
        }
320
0
    }
321
0
    fn table_type(&self) -> TableType {
322
0
        match self {
323
0
            Self::Format1(item) => item.table_type(),
324
0
            Self::Format2(item) => item.table_type(),
325
0
            Self::Format3(item) => item.table_type(),
326
0
            Self::Format4(item) => item.table_type(),
327
        }
328
0
    }
329
}
330
331
impl Validate for SingleSubst {
332
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
333
0
        match self {
334
0
            Self::Format1(item) => item.validate_impl(ctx),
335
0
            Self::Format2(item) => item.validate_impl(ctx),
336
0
            Self::Format3(item) => item.validate_impl(ctx),
337
0
            Self::Format4(item) => item.validate_impl(ctx),
338
        }
339
0
    }
340
}
341
342
impl FromObjRef<read_fonts::tables::gsub::SingleSubst<'_>> for SingleSubst {
343
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::SingleSubst, _: FontData) -> Self {
344
        use read_fonts::tables::gsub::SingleSubst as ObjRefType;
345
0
        match obj {
346
0
            ObjRefType::Format1(item) => SingleSubst::Format1(item.to_owned_table()),
347
0
            ObjRefType::Format2(item) => SingleSubst::Format2(item.to_owned_table()),
348
0
            ObjRefType::Format3(item) => SingleSubst::Format3(item.to_owned_table()),
349
0
            ObjRefType::Format4(item) => SingleSubst::Format4(item.to_owned_table()),
350
        }
351
0
    }
352
}
353
354
impl FromTableRef<read_fonts::tables::gsub::SingleSubst<'_>> for SingleSubst {}
355
356
impl ReadArgs for SingleSubst {
357
    type Args = ();
358
}
359
360
impl<'a> FontRead<'a> for SingleSubst {
361
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
362
0
        <read_fonts::tables::gsub::SingleSubst as FontRead>::read(data).map(|x| x.to_owned_table())
363
0
    }
364
}
365
366
impl From<SingleSubstFormat1> for SingleSubst {
367
0
    fn from(src: SingleSubstFormat1) -> SingleSubst {
368
0
        SingleSubst::Format1(src)
369
0
    }
370
}
371
372
impl From<SingleSubstFormat2> for SingleSubst {
373
0
    fn from(src: SingleSubstFormat2) -> SingleSubst {
374
0
        SingleSubst::Format2(src)
375
0
    }
376
}
377
378
impl From<SingleSubstFormat3> for SingleSubst {
379
0
    fn from(src: SingleSubstFormat3) -> SingleSubst {
380
0
        SingleSubst::Format3(src)
381
0
    }
382
}
383
384
impl From<SingleSubstFormat4> for SingleSubst {
385
0
    fn from(src: SingleSubstFormat4) -> SingleSubst {
386
0
        SingleSubst::Format4(src)
387
0
    }
388
}
389
390
/// [Single Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#11-single-substitution-format-1)
391
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
392
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
393
pub struct SingleSubstFormat1 {
394
    /// Offset to Coverage table, from beginning of substitution
395
    /// subtable
396
    pub coverage: OffsetMarker<CoverageTable>,
397
    /// Add to original glyph ID to get substitute glyph ID
398
    pub delta_glyph_id: i16,
399
}
400
401
impl SingleSubstFormat1 {
402
    /// Construct a new `SingleSubstFormat1`
403
0
    pub fn new(coverage: CoverageTable, delta_glyph_id: i16) -> Self {
404
0
        Self {
405
0
            coverage: coverage.into(),
406
0
            delta_glyph_id,
407
0
        }
408
0
    }
409
}
410
411
impl FontWrite for SingleSubstFormat1 {
412
    #[allow(clippy::unnecessary_cast)]
413
0
    fn write_into(&self, writer: &mut TableWriter) {
414
0
        (1 as u16).write_into(writer);
415
0
        self.coverage.write_into(writer);
416
0
        self.delta_glyph_id.write_into(writer);
417
0
    }
418
0
    fn table_type(&self) -> TableType {
419
0
        TableType::Named("SingleSubstFormat1")
420
0
    }
421
}
422
423
impl Validate for SingleSubstFormat1 {
424
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
425
0
        ctx.in_table("SingleSubstFormat1", |ctx| {
426
0
            ctx.in_field("coverage", |ctx| {
427
0
                self.coverage.validate_impl(ctx);
428
0
            });
429
0
        })
430
0
    }
431
}
432
433
impl<'a> FromObjRef<read_fonts::tables::gsub::SingleSubstFormat1<'a>> for SingleSubstFormat1 {
434
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::SingleSubstFormat1<'a>, _: FontData) -> Self {
435
0
        SingleSubstFormat1 {
436
0
            coverage: obj.coverage().to_owned_table(),
437
0
            delta_glyph_id: obj.delta_glyph_id(),
438
0
        }
439
0
    }
440
}
441
442
#[allow(clippy::needless_lifetimes)]
443
impl<'a> FromTableRef<read_fonts::tables::gsub::SingleSubstFormat1<'a>> for SingleSubstFormat1 {}
444
445
impl ReadArgs for SingleSubstFormat1 {
446
    type Args = ();
447
}
448
449
impl<'a> FontRead<'a> for SingleSubstFormat1 {
450
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
451
0
        <read_fonts::tables::gsub::SingleSubstFormat1 as FontRead>::read(data)
452
0
            .map(|x| x.to_owned_table())
453
0
    }
454
}
455
456
/// [Single Substitution Format 2](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#12-single-substitution-format-2)
457
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
458
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
459
pub struct SingleSubstFormat2 {
460
    /// Offset to Coverage table, from beginning of substitution
461
    /// subtable
462
    pub coverage: OffsetMarker<CoverageTable>,
463
    /// Array of substitute glyph IDs — ordered by Coverage index
464
    pub substitute_glyph_ids: Vec<GlyphId16>,
465
}
466
467
impl SingleSubstFormat2 {
468
    /// Construct a new `SingleSubstFormat2`
469
0
    pub fn new(coverage: CoverageTable, substitute_glyph_ids: Vec<GlyphId16>) -> Self {
470
0
        Self {
471
0
            coverage: coverage.into(),
472
0
            substitute_glyph_ids,
473
0
        }
474
0
    }
475
}
476
477
impl FontWrite for SingleSubstFormat2 {
478
    #[allow(clippy::unnecessary_cast)]
479
0
    fn write_into(&self, writer: &mut TableWriter) {
480
0
        (2 as u16).write_into(writer);
481
0
        self.coverage.write_into(writer);
482
0
        (u16::try_from(array_len(&self.substitute_glyph_ids)).unwrap()).write_into(writer);
483
0
        self.substitute_glyph_ids.write_into(writer);
484
0
    }
485
0
    fn table_type(&self) -> TableType {
486
0
        TableType::Named("SingleSubstFormat2")
487
0
    }
488
}
489
490
impl Validate for SingleSubstFormat2 {
491
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
492
0
        ctx.in_table("SingleSubstFormat2", |ctx| {
493
0
            ctx.in_field("coverage", |ctx| {
494
0
                self.coverage.validate_impl(ctx);
495
0
            });
496
0
            ctx.in_field("substitute_glyph_ids", |ctx| {
497
0
                if self.substitute_glyph_ids.len() > to_usize(u16::MAX) {
498
0
                    ctx.report("array exceeds max length");
499
0
                }
500
0
            });
501
0
        })
502
0
    }
503
}
504
505
impl<'a> FromObjRef<read_fonts::tables::gsub::SingleSubstFormat2<'a>> for SingleSubstFormat2 {
506
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::SingleSubstFormat2<'a>, _: FontData) -> Self {
507
0
        let offset_data = obj.offset_data();
508
0
        SingleSubstFormat2 {
509
0
            coverage: obj.coverage().to_owned_table(),
510
0
            substitute_glyph_ids: obj.substitute_glyph_ids().to_owned_obj(offset_data),
511
0
        }
512
0
    }
513
}
514
515
#[allow(clippy::needless_lifetimes)]
516
impl<'a> FromTableRef<read_fonts::tables::gsub::SingleSubstFormat2<'a>> for SingleSubstFormat2 {}
517
518
impl ReadArgs for SingleSubstFormat2 {
519
    type Args = ();
520
}
521
522
impl<'a> FontRead<'a> for SingleSubstFormat2 {
523
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
524
0
        <read_fonts::tables::gsub::SingleSubstFormat2 as FontRead>::read(data)
525
0
            .map(|x| x.to_owned_table())
526
0
    }
527
}
528
529
/// [Multiple Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#21-multiple-substitution-format-1)
530
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
531
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
532
pub struct MultipleSubstFormat1 {
533
    /// Offset to Coverage table, from beginning of substitution
534
    /// subtable
535
    pub coverage: OffsetMarker<CoverageTable>,
536
    /// Array of offsets to Sequence tables. Offsets are from beginning
537
    /// of substitution subtable, ordered by Coverage index
538
    pub sequences: Vec<OffsetMarker<Sequence>>,
539
}
540
541
impl MultipleSubstFormat1 {
542
    /// Construct a new `MultipleSubstFormat1`
543
0
    pub fn new(coverage: CoverageTable, sequences: Vec<Sequence>) -> Self {
544
0
        Self {
545
0
            coverage: coverage.into(),
546
0
            sequences: sequences.into_iter().map(Into::into).collect(),
547
0
        }
548
0
    }
549
}
550
551
impl FontWrite for MultipleSubstFormat1 {
552
    #[allow(clippy::unnecessary_cast)]
553
0
    fn write_into(&self, writer: &mut TableWriter) {
554
0
        (1 as u16).write_into(writer);
555
0
        self.coverage.write_into(writer);
556
0
        (u16::try_from(array_len(&self.sequences)).unwrap()).write_into(writer);
557
0
        self.sequences.write_into(writer);
558
0
    }
559
0
    fn table_type(&self) -> TableType {
560
0
        TableType::Named("MultipleSubstFormat1")
561
0
    }
562
}
563
564
impl Validate for MultipleSubstFormat1 {
565
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
566
0
        ctx.in_table("MultipleSubstFormat1", |ctx| {
567
0
            ctx.in_field("coverage", |ctx| {
568
0
                self.coverage.validate_impl(ctx);
569
0
            });
570
0
            ctx.in_field("sequences", |ctx| {
571
0
                if self.sequences.len() > to_usize(u16::MAX) {
572
0
                    ctx.report("array exceeds max length");
573
0
                }
574
0
                self.sequences.validate_impl(ctx);
575
0
            });
576
0
        })
577
0
    }
578
}
579
580
impl<'a> FromObjRef<read_fonts::tables::gsub::MultipleSubstFormat1<'a>> for MultipleSubstFormat1 {
581
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::MultipleSubstFormat1<'a>, _: FontData) -> Self {
582
0
        MultipleSubstFormat1 {
583
0
            coverage: obj.coverage().to_owned_table(),
584
0
            sequences: obj.sequences().to_owned_table(),
585
0
        }
586
0
    }
587
}
588
589
#[allow(clippy::needless_lifetimes)]
590
impl<'a> FromTableRef<read_fonts::tables::gsub::MultipleSubstFormat1<'a>> for MultipleSubstFormat1 {}
591
592
impl ReadArgs for MultipleSubstFormat1 {
593
    type Args = ();
594
}
595
596
impl<'a> FontRead<'a> for MultipleSubstFormat1 {
597
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
598
0
        <read_fonts::tables::gsub::MultipleSubstFormat1 as FontRead>::read(data)
599
0
            .map(|x| x.to_owned_table())
600
0
    }
601
}
602
603
/// Part of [MultipleSubstFormat1]
604
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
605
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
606
pub struct Sequence {
607
    /// String of glyph IDs to substitute
608
    pub substitute_glyph_ids: Vec<GlyphId16>,
609
}
610
611
impl Sequence {
612
    /// Construct a new `Sequence`
613
0
    pub fn new(substitute_glyph_ids: Vec<GlyphId16>) -> Self {
614
0
        Self {
615
0
            substitute_glyph_ids,
616
0
        }
617
0
    }
618
}
619
620
impl FontWrite for Sequence {
621
    #[allow(clippy::unnecessary_cast)]
622
0
    fn write_into(&self, writer: &mut TableWriter) {
623
0
        (u16::try_from(array_len(&self.substitute_glyph_ids)).unwrap()).write_into(writer);
624
0
        self.substitute_glyph_ids.write_into(writer);
625
0
    }
626
0
    fn table_type(&self) -> TableType {
627
0
        TableType::Named("Sequence")
628
0
    }
629
}
630
631
impl Validate for Sequence {
632
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
633
0
        ctx.in_table("Sequence", |ctx| {
634
0
            ctx.in_field("substitute_glyph_ids", |ctx| {
635
0
                if self.substitute_glyph_ids.len() > to_usize(u16::MAX) {
636
0
                    ctx.report("array exceeds max length");
637
0
                }
638
0
            });
639
0
        })
640
0
    }
641
}
642
643
impl<'a> FromObjRef<read_fonts::tables::gsub::Sequence<'a>> for Sequence {
644
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::Sequence<'a>, _: FontData) -> Self {
645
0
        let offset_data = obj.offset_data();
646
0
        Sequence {
647
0
            substitute_glyph_ids: obj.substitute_glyph_ids().to_owned_obj(offset_data),
648
0
        }
649
0
    }
650
}
651
652
#[allow(clippy::needless_lifetimes)]
653
impl<'a> FromTableRef<read_fonts::tables::gsub::Sequence<'a>> for Sequence {}
654
655
impl ReadArgs for Sequence {
656
    type Args = ();
657
}
658
659
impl<'a> FontRead<'a> for Sequence {
660
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
661
0
        <read_fonts::tables::gsub::Sequence as FontRead>::read(data).map(|x| x.to_owned_table())
662
0
    }
663
}
664
665
/// [Alternate Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#31-alternate-substitution-format-1)
666
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
667
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
668
pub struct AlternateSubstFormat1 {
669
    /// Offset to Coverage table, from beginning of substitution
670
    /// subtable
671
    pub coverage: OffsetMarker<CoverageTable>,
672
    /// Array of offsets to AlternateSet tables. Offsets are from
673
    /// beginning of substitution subtable, ordered by Coverage index
674
    pub alternate_sets: Vec<OffsetMarker<AlternateSet>>,
675
}
676
677
impl AlternateSubstFormat1 {
678
    /// Construct a new `AlternateSubstFormat1`
679
0
    pub fn new(coverage: CoverageTable, alternate_sets: Vec<AlternateSet>) -> Self {
680
0
        Self {
681
0
            coverage: coverage.into(),
682
0
            alternate_sets: alternate_sets.into_iter().map(Into::into).collect(),
683
0
        }
684
0
    }
685
}
686
687
impl FontWrite for AlternateSubstFormat1 {
688
    #[allow(clippy::unnecessary_cast)]
689
0
    fn write_into(&self, writer: &mut TableWriter) {
690
0
        (1 as u16).write_into(writer);
691
0
        self.coverage.write_into(writer);
692
0
        (u16::try_from(array_len(&self.alternate_sets)).unwrap()).write_into(writer);
693
0
        self.alternate_sets.write_into(writer);
694
0
    }
695
0
    fn table_type(&self) -> TableType {
696
0
        TableType::Named("AlternateSubstFormat1")
697
0
    }
698
}
699
700
impl Validate for AlternateSubstFormat1 {
701
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
702
0
        ctx.in_table("AlternateSubstFormat1", |ctx| {
703
0
            ctx.in_field("coverage", |ctx| {
704
0
                self.coverage.validate_impl(ctx);
705
0
            });
706
0
            ctx.in_field("alternate_sets", |ctx| {
707
0
                if self.alternate_sets.len() > to_usize(u16::MAX) {
708
0
                    ctx.report("array exceeds max length");
709
0
                }
710
0
                self.alternate_sets.validate_impl(ctx);
711
0
            });
712
0
        })
713
0
    }
714
}
715
716
impl<'a> FromObjRef<read_fonts::tables::gsub::AlternateSubstFormat1<'a>> for AlternateSubstFormat1 {
717
0
    fn from_obj_ref(
718
0
        obj: &read_fonts::tables::gsub::AlternateSubstFormat1<'a>,
719
0
        _: FontData,
720
0
    ) -> Self {
721
0
        AlternateSubstFormat1 {
722
0
            coverage: obj.coverage().to_owned_table(),
723
0
            alternate_sets: obj.alternate_sets().to_owned_table(),
724
0
        }
725
0
    }
726
}
727
728
#[allow(clippy::needless_lifetimes)]
729
impl<'a> FromTableRef<read_fonts::tables::gsub::AlternateSubstFormat1<'a>>
730
    for AlternateSubstFormat1
731
{
732
}
733
734
impl ReadArgs for AlternateSubstFormat1 {
735
    type Args = ();
736
}
737
738
impl<'a> FontRead<'a> for AlternateSubstFormat1 {
739
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
740
0
        <read_fonts::tables::gsub::AlternateSubstFormat1 as FontRead>::read(data)
741
0
            .map(|x| x.to_owned_table())
742
0
    }
743
}
744
745
/// Part of [AlternateSubstFormat1]
746
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
747
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
748
pub struct AlternateSet {
749
    /// Array of alternate glyph IDs, in arbitrary order
750
    pub alternate_glyph_ids: Vec<GlyphId16>,
751
}
752
753
impl AlternateSet {
754
    /// Construct a new `AlternateSet`
755
0
    pub fn new(alternate_glyph_ids: Vec<GlyphId16>) -> Self {
756
0
        Self {
757
0
            alternate_glyph_ids,
758
0
        }
759
0
    }
760
}
761
762
impl FontWrite for AlternateSet {
763
    #[allow(clippy::unnecessary_cast)]
764
0
    fn write_into(&self, writer: &mut TableWriter) {
765
0
        (u16::try_from(array_len(&self.alternate_glyph_ids)).unwrap()).write_into(writer);
766
0
        self.alternate_glyph_ids.write_into(writer);
767
0
    }
768
0
    fn table_type(&self) -> TableType {
769
0
        TableType::Named("AlternateSet")
770
0
    }
771
}
772
773
impl Validate for AlternateSet {
774
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
775
0
        ctx.in_table("AlternateSet", |ctx| {
776
0
            ctx.in_field("alternate_glyph_ids", |ctx| {
777
0
                if self.alternate_glyph_ids.len() > to_usize(u16::MAX) {
778
0
                    ctx.report("array exceeds max length");
779
0
                }
780
0
            });
781
0
        })
782
0
    }
783
}
784
785
impl<'a> FromObjRef<read_fonts::tables::gsub::AlternateSet<'a>> for AlternateSet {
786
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::AlternateSet<'a>, _: FontData) -> Self {
787
0
        let offset_data = obj.offset_data();
788
0
        AlternateSet {
789
0
            alternate_glyph_ids: obj.alternate_glyph_ids().to_owned_obj(offset_data),
790
0
        }
791
0
    }
792
}
793
794
#[allow(clippy::needless_lifetimes)]
795
impl<'a> FromTableRef<read_fonts::tables::gsub::AlternateSet<'a>> for AlternateSet {}
796
797
impl ReadArgs for AlternateSet {
798
    type Args = ();
799
}
800
801
impl<'a> FontRead<'a> for AlternateSet {
802
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
803
0
        <read_fonts::tables::gsub::AlternateSet as FontRead>::read(data).map(|x| x.to_owned_table())
804
0
    }
805
}
806
807
/// [Ligature Substitution Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#41-ligature-substitution-format-1)
808
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
809
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
810
pub struct LigatureSubstFormat1 {
811
    /// Offset to Coverage table, from beginning of substitution
812
    /// subtable
813
    pub coverage: OffsetMarker<CoverageTable>,
814
    /// Array of offsets to LigatureSet tables. Offsets are from
815
    /// beginning of substitution subtable, ordered by Coverage index
816
    pub ligature_sets: Vec<OffsetMarker<LigatureSet>>,
817
}
818
819
impl LigatureSubstFormat1 {
820
    /// Construct a new `LigatureSubstFormat1`
821
0
    pub fn new(coverage: CoverageTable, ligature_sets: Vec<LigatureSet>) -> Self {
822
0
        Self {
823
0
            coverage: coverage.into(),
824
0
            ligature_sets: ligature_sets.into_iter().map(Into::into).collect(),
825
0
        }
826
0
    }
827
}
828
829
impl FontWrite for LigatureSubstFormat1 {
830
    #[allow(clippy::unnecessary_cast)]
831
0
    fn write_into(&self, writer: &mut TableWriter) {
832
0
        (1 as u16).write_into(writer);
833
0
        self.coverage.write_into(writer);
834
0
        (u16::try_from(array_len(&self.ligature_sets)).unwrap()).write_into(writer);
835
0
        self.ligature_sets.write_into(writer);
836
0
    }
837
0
    fn table_type(&self) -> TableType {
838
0
        TableType::Named("LigatureSubstFormat1")
839
0
    }
840
}
841
842
impl Validate for LigatureSubstFormat1 {
843
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
844
0
        ctx.in_table("LigatureSubstFormat1", |ctx| {
845
0
            ctx.in_field("coverage", |ctx| {
846
0
                self.coverage.validate_impl(ctx);
847
0
            });
848
0
            ctx.in_field("ligature_sets", |ctx| {
849
0
                if self.ligature_sets.len() > to_usize(u16::MAX) {
850
0
                    ctx.report("array exceeds max length");
851
0
                }
852
0
                self.ligature_sets.validate_impl(ctx);
853
0
            });
854
0
        })
855
0
    }
856
}
857
858
impl<'a> FromObjRef<read_fonts::tables::gsub::LigatureSubstFormat1<'a>> for LigatureSubstFormat1 {
859
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::LigatureSubstFormat1<'a>, _: FontData) -> Self {
860
0
        LigatureSubstFormat1 {
861
0
            coverage: obj.coverage().to_owned_table(),
862
0
            ligature_sets: obj.ligature_sets().to_owned_table(),
863
0
        }
864
0
    }
865
}
866
867
#[allow(clippy::needless_lifetimes)]
868
impl<'a> FromTableRef<read_fonts::tables::gsub::LigatureSubstFormat1<'a>> for LigatureSubstFormat1 {}
869
870
impl ReadArgs for LigatureSubstFormat1 {
871
    type Args = ();
872
}
873
874
impl<'a> FontRead<'a> for LigatureSubstFormat1 {
875
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
876
0
        <read_fonts::tables::gsub::LigatureSubstFormat1 as FontRead>::read(data)
877
0
            .map(|x| x.to_owned_table())
878
0
    }
879
}
880
881
/// Part of [LigatureSubstFormat1]
882
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
883
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
884
pub struct LigatureSet {
885
    /// Array of offsets to Ligature tables. Offsets are from beginning
886
    /// of LigatureSet table, ordered by preference.
887
    pub ligatures: Vec<OffsetMarker<Ligature>>,
888
}
889
890
impl LigatureSet {
891
    /// Construct a new `LigatureSet`
892
0
    pub fn new(ligatures: Vec<Ligature>) -> Self {
893
0
        Self {
894
0
            ligatures: ligatures.into_iter().map(Into::into).collect(),
895
0
        }
896
0
    }
897
}
898
899
impl FontWrite for LigatureSet {
900
    #[allow(clippy::unnecessary_cast)]
901
0
    fn write_into(&self, writer: &mut TableWriter) {
902
0
        (u16::try_from(array_len(&self.ligatures)).unwrap()).write_into(writer);
903
0
        self.ligatures.write_into(writer);
904
0
    }
905
0
    fn table_type(&self) -> TableType {
906
0
        TableType::Named("LigatureSet")
907
0
    }
908
}
909
910
impl Validate for LigatureSet {
911
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
912
0
        ctx.in_table("LigatureSet", |ctx| {
913
0
            ctx.in_field("ligatures", |ctx| {
914
0
                if self.ligatures.len() > to_usize(u16::MAX) {
915
0
                    ctx.report("array exceeds max length");
916
0
                }
917
0
                self.ligatures.validate_impl(ctx);
918
0
            });
919
0
        })
920
0
    }
921
}
922
923
impl<'a> FromObjRef<read_fonts::tables::gsub::LigatureSet<'a>> for LigatureSet {
924
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::LigatureSet<'a>, _: FontData) -> Self {
925
0
        LigatureSet {
926
0
            ligatures: obj.ligatures().to_owned_table(),
927
0
        }
928
0
    }
929
}
930
931
#[allow(clippy::needless_lifetimes)]
932
impl<'a> FromTableRef<read_fonts::tables::gsub::LigatureSet<'a>> for LigatureSet {}
933
934
impl ReadArgs for LigatureSet {
935
    type Args = ();
936
}
937
938
impl<'a> FontRead<'a> for LigatureSet {
939
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
940
0
        <read_fonts::tables::gsub::LigatureSet as FontRead>::read(data).map(|x| x.to_owned_table())
941
0
    }
942
}
943
944
/// Part of [LigatureSubstFormat1]
945
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
946
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
947
pub struct Ligature {
948
    /// glyph ID of ligature to substitute
949
    pub ligature_glyph: GlyphId16,
950
    /// Array of component glyph IDs — start with the second
951
    /// component, ordered in writing direction
952
    pub component_glyph_ids: Vec<GlyphId16>,
953
}
954
955
impl Ligature {
956
    /// Construct a new `Ligature`
957
0
    pub fn new(ligature_glyph: GlyphId16, component_glyph_ids: Vec<GlyphId16>) -> Self {
958
0
        Self {
959
0
            ligature_glyph,
960
0
            component_glyph_ids,
961
0
        }
962
0
    }
963
}
964
965
impl FontWrite for Ligature {
966
    #[allow(clippy::unnecessary_cast)]
967
0
    fn write_into(&self, writer: &mut TableWriter) {
968
0
        self.ligature_glyph.write_into(writer);
969
0
        (u16::try_from(plus_one(&self.component_glyph_ids.len())).unwrap()).write_into(writer);
970
0
        self.component_glyph_ids.write_into(writer);
971
0
    }
972
0
    fn table_type(&self) -> TableType {
973
0
        TableType::Named("Ligature")
974
0
    }
975
}
976
977
impl Validate for Ligature {
978
0
    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
979
}
980
981
impl<'a> FromObjRef<read_fonts::tables::gsub::Ligature<'a>> for Ligature {
982
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::Ligature<'a>, _: FontData) -> Self {
983
0
        let offset_data = obj.offset_data();
984
0
        Ligature {
985
0
            ligature_glyph: obj.ligature_glyph(),
986
0
            component_glyph_ids: obj.component_glyph_ids().to_owned_obj(offset_data),
987
0
        }
988
0
    }
989
}
990
991
#[allow(clippy::needless_lifetimes)]
992
impl<'a> FromTableRef<read_fonts::tables::gsub::Ligature<'a>> for Ligature {}
993
994
impl ReadArgs for Ligature {
995
    type Args = ();
996
}
997
998
impl<'a> FontRead<'a> for Ligature {
999
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1000
0
        <read_fonts::tables::gsub::Ligature as FontRead>::read(data).map(|x| x.to_owned_table())
1001
0
    }
1002
}
1003
1004
/// [Extension Substitution Subtable Format 1](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#71-extension-substitution-subtable-format-1)
1005
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1006
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1007
pub struct ExtensionSubstFormat1<T> {
1008
    /// Lookup type of subtable referenced by extensionOffset (that is,
1009
    /// the extension subtable).
1010
    pub extension_lookup_type: u16,
1011
    /// Offset to the extension subtable, of lookup type
1012
    /// extensionLookupType, relative to the start of the
1013
    /// ExtensionSubstFormat1 subtable.
1014
    pub extension: OffsetMarker<T, WIDTH_32>,
1015
}
1016
1017
impl<T: Default> ExtensionSubstFormat1<T> {
1018
    /// Construct a new `ExtensionSubstFormat1`
1019
0
    pub fn new(extension_lookup_type: u16, extension: T) -> Self {
1020
0
        Self {
1021
0
            extension_lookup_type,
1022
0
            extension: extension.into(),
1023
0
        }
1024
0
    }
1025
}
1026
1027
impl<T: Validate> Validate for ExtensionSubstFormat1<T> {
1028
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1029
0
        ctx.in_table("ExtensionSubstFormat1", |ctx| {
1030
0
            ctx.in_field("extension", |ctx| {
1031
0
                self.extension.validate_impl(ctx);
1032
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::LigatureSubst> as write_fonts::validate::Validate>::validate_impl::{closure#0}::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::MultipleSubst> as write_fonts::validate::Validate>::validate_impl::{closure#0}::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::AlternateSubst> as write_fonts::validate::Validate>::validate_impl::{closure#0}::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::ReverseChainSingleSubst> 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}
1033
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::LigatureSubst> as write_fonts::validate::Validate>::validate_impl::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::MultipleSubst> as write_fonts::validate::Validate>::validate_impl::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::AlternateSubst> as write_fonts::validate::Validate>::validate_impl::{closure#0}
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::ReverseChainSingleSubst> 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}
1034
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::LigatureSubst> as write_fonts::validate::Validate>::validate_impl
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::MultipleSubst> as write_fonts::validate::Validate>::validate_impl
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::AlternateSubst> as write_fonts::validate::Validate>::validate_impl
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::ReverseChainSingleSubst> 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
1035
}
1036
1037
impl<'a, T, U> FromObjRef<read_fonts::tables::gsub::ExtensionSubstFormat1<'a, U>>
1038
    for ExtensionSubstFormat1<T>
1039
where
1040
    U: FontRead<'a, Args = ()>,
1041
    T: FromTableRef<U> + Default + 'static,
1042
{
1043
0
    fn from_obj_ref(
1044
0
        obj: &read_fonts::tables::gsub::ExtensionSubstFormat1<'a, U>,
1045
0
        _: FontData,
1046
0
    ) -> Self {
1047
0
        ExtensionSubstFormat1 {
1048
0
            extension_lookup_type: obj.extension_lookup_type(),
1049
0
            extension: obj.extension().to_owned_table(),
1050
0
        }
1051
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::LigatureSubst> as write_fonts::from_obj::FromObjRef<read_fonts::tables::gsub::ExtensionSubstFormat1<read_fonts::tables::gsub::LigatureSubst>>>::from_obj_ref
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::MultipleSubst> as write_fonts::from_obj::FromObjRef<read_fonts::tables::gsub::ExtensionSubstFormat1<read_fonts::tables::gsub::MultipleSubst>>>::from_obj_ref
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::AlternateSubst> as write_fonts::from_obj::FromObjRef<read_fonts::tables::gsub::ExtensionSubstFormat1<read_fonts::tables::gsub::AlternateSubst>>>::from_obj_ref
Unexecuted instantiation: <write_fonts::tables::gsub::ExtensionSubstFormat1<write_fonts::tables::gsub::ReverseChainSingleSubst> as write_fonts::from_obj::FromObjRef<read_fonts::tables::gsub::ExtensionSubstFormat1<read_fonts::tables::gsub::ReverseChainSingleSubst>>>::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
1052
}
1053
1054
#[allow(clippy::needless_lifetimes)]
1055
impl<'a, T, U> FromTableRef<read_fonts::tables::gsub::ExtensionSubstFormat1<'a, U>>
1056
    for ExtensionSubstFormat1<T>
1057
where
1058
    U: FontRead<'a, Args = ()>,
1059
    T: FromTableRef<U> + Default + 'static,
1060
{
1061
}
1062
1063
/// A [GSUB Extension Substitution](https://learn.microsoft.com/en-us/typography/opentype/spec/gsub#ES) subtable
1064
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1065
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1066
pub enum ExtensionSubtable {
1067
    Single(ExtensionSubstFormat1<SingleSubst>),
1068
    Multiple(ExtensionSubstFormat1<MultipleSubst>),
1069
    Alternate(ExtensionSubstFormat1<AlternateSubst>),
1070
    Ligature(ExtensionSubstFormat1<LigatureSubst>),
1071
    Contextual(ExtensionSubstFormat1<SubstitutionSequenceContext>),
1072
    ChainContextual(ExtensionSubstFormat1<SubstitutionChainContext>),
1073
    Reverse(ExtensionSubstFormat1<ReverseChainSingleSubst>),
1074
}
1075
1076
impl Default for ExtensionSubtable {
1077
0
    fn default() -> Self {
1078
0
        Self::Single(Default::default())
1079
0
    }
1080
}
1081
1082
impl FontWrite for ExtensionSubtable {
1083
0
    fn write_into(&self, writer: &mut TableWriter) {
1084
0
        match self {
1085
0
            Self::Single(table) => table.write_into(writer),
1086
0
            Self::Multiple(table) => table.write_into(writer),
1087
0
            Self::Alternate(table) => table.write_into(writer),
1088
0
            Self::Ligature(table) => table.write_into(writer),
1089
0
            Self::Contextual(table) => table.write_into(writer),
1090
0
            Self::ChainContextual(table) => table.write_into(writer),
1091
0
            Self::Reverse(table) => table.write_into(writer),
1092
        }
1093
0
    }
1094
0
    fn table_type(&self) -> TableType {
1095
0
        match self {
1096
0
            Self::Single(table) => table.table_type(),
1097
0
            Self::Multiple(table) => table.table_type(),
1098
0
            Self::Alternate(table) => table.table_type(),
1099
0
            Self::Ligature(table) => table.table_type(),
1100
0
            Self::Contextual(table) => table.table_type(),
1101
0
            Self::ChainContextual(table) => table.table_type(),
1102
0
            Self::Reverse(table) => table.table_type(),
1103
        }
1104
0
    }
1105
}
1106
1107
impl Validate for ExtensionSubtable {
1108
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1109
0
        match self {
1110
0
            Self::Single(table) => table.validate_impl(ctx),
1111
0
            Self::Multiple(table) => table.validate_impl(ctx),
1112
0
            Self::Alternate(table) => table.validate_impl(ctx),
1113
0
            Self::Ligature(table) => table.validate_impl(ctx),
1114
0
            Self::Contextual(table) => table.validate_impl(ctx),
1115
0
            Self::ChainContextual(table) => table.validate_impl(ctx),
1116
0
            Self::Reverse(table) => table.validate_impl(ctx),
1117
        }
1118
0
    }
1119
}
1120
1121
impl FromObjRef<read_fonts::tables::gsub::ExtensionSubtable<'_>> for ExtensionSubtable {
1122
0
    fn from_obj_ref(
1123
0
        from: &read_fonts::tables::gsub::ExtensionSubtable<'_>,
1124
0
        data: FontData,
1125
0
    ) -> Self {
1126
0
        match from {
1127
0
            read_fonts::tables::gsub::ExtensionSubtable::Single(table) => {
1128
0
                Self::Single(table.to_owned_obj(data))
1129
            }
1130
0
            read_fonts::tables::gsub::ExtensionSubtable::Multiple(table) => {
1131
0
                Self::Multiple(table.to_owned_obj(data))
1132
            }
1133
0
            read_fonts::tables::gsub::ExtensionSubtable::Alternate(table) => {
1134
0
                Self::Alternate(table.to_owned_obj(data))
1135
            }
1136
0
            read_fonts::tables::gsub::ExtensionSubtable::Ligature(table) => {
1137
0
                Self::Ligature(table.to_owned_obj(data))
1138
            }
1139
0
            read_fonts::tables::gsub::ExtensionSubtable::Contextual(table) => {
1140
0
                Self::Contextual(table.to_owned_obj(data))
1141
            }
1142
0
            read_fonts::tables::gsub::ExtensionSubtable::ChainContextual(table) => {
1143
0
                Self::ChainContextual(table.to_owned_obj(data))
1144
            }
1145
0
            read_fonts::tables::gsub::ExtensionSubtable::Reverse(table) => {
1146
0
                Self::Reverse(table.to_owned_obj(data))
1147
            }
1148
        }
1149
0
    }
1150
}
1151
1152
impl FromTableRef<read_fonts::tables::gsub::ExtensionSubtable<'_>> for ExtensionSubtable {}
1153
1154
impl From<ExtensionSubstFormat1<SingleSubst>> for ExtensionSubtable {
1155
0
    fn from(src: ExtensionSubstFormat1<SingleSubst>) -> ExtensionSubtable {
1156
0
        ExtensionSubtable::Single(src)
1157
0
    }
1158
}
1159
1160
impl From<ExtensionSubstFormat1<MultipleSubst>> for ExtensionSubtable {
1161
0
    fn from(src: ExtensionSubstFormat1<MultipleSubst>) -> ExtensionSubtable {
1162
0
        ExtensionSubtable::Multiple(src)
1163
0
    }
1164
}
1165
1166
impl From<ExtensionSubstFormat1<AlternateSubst>> for ExtensionSubtable {
1167
0
    fn from(src: ExtensionSubstFormat1<AlternateSubst>) -> ExtensionSubtable {
1168
0
        ExtensionSubtable::Alternate(src)
1169
0
    }
1170
}
1171
1172
impl From<ExtensionSubstFormat1<LigatureSubst>> for ExtensionSubtable {
1173
0
    fn from(src: ExtensionSubstFormat1<LigatureSubst>) -> ExtensionSubtable {
1174
0
        ExtensionSubtable::Ligature(src)
1175
0
    }
1176
}
1177
1178
impl From<ExtensionSubstFormat1<SubstitutionSequenceContext>> for ExtensionSubtable {
1179
0
    fn from(src: ExtensionSubstFormat1<SubstitutionSequenceContext>) -> ExtensionSubtable {
1180
0
        ExtensionSubtable::Contextual(src)
1181
0
    }
1182
}
1183
1184
impl From<ExtensionSubstFormat1<SubstitutionChainContext>> for ExtensionSubtable {
1185
0
    fn from(src: ExtensionSubstFormat1<SubstitutionChainContext>) -> ExtensionSubtable {
1186
0
        ExtensionSubtable::ChainContextual(src)
1187
0
    }
1188
}
1189
1190
impl From<ExtensionSubstFormat1<ReverseChainSingleSubst>> for ExtensionSubtable {
1191
0
    fn from(src: ExtensionSubstFormat1<ReverseChainSingleSubst>) -> ExtensionSubtable {
1192
0
        ExtensionSubtable::Reverse(src)
1193
0
    }
1194
}
1195
1196
/// [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)
1197
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1198
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1199
pub struct ReverseChainSingleSubstFormat1 {
1200
    /// Offset to Coverage table, from beginning of substitution
1201
    /// subtable.
1202
    pub coverage: OffsetMarker<CoverageTable>,
1203
    /// Array of offsets to coverage tables in backtrack sequence, in
1204
    /// glyph sequence order.
1205
    pub backtrack_coverages: Vec<OffsetMarker<CoverageTable>>,
1206
    /// Array of offsets to coverage tables in lookahead sequence, in
1207
    /// glyph sequence order.
1208
    pub lookahead_coverages: Vec<OffsetMarker<CoverageTable>>,
1209
    /// Array of substitute glyph IDs — ordered by Coverage index.
1210
    pub substitute_glyph_ids: Vec<GlyphId16>,
1211
}
1212
1213
impl ReverseChainSingleSubstFormat1 {
1214
    /// Construct a new `ReverseChainSingleSubstFormat1`
1215
0
    pub fn new(
1216
0
        coverage: CoverageTable,
1217
0
        backtrack_coverages: Vec<CoverageTable>,
1218
0
        lookahead_coverages: Vec<CoverageTable>,
1219
0
        substitute_glyph_ids: Vec<GlyphId16>,
1220
0
    ) -> Self {
1221
0
        Self {
1222
0
            coverage: coverage.into(),
1223
0
            backtrack_coverages: backtrack_coverages.into_iter().map(Into::into).collect(),
1224
0
            lookahead_coverages: lookahead_coverages.into_iter().map(Into::into).collect(),
1225
0
            substitute_glyph_ids,
1226
0
        }
1227
0
    }
1228
}
1229
1230
impl FontWrite for ReverseChainSingleSubstFormat1 {
1231
    #[allow(clippy::unnecessary_cast)]
1232
0
    fn write_into(&self, writer: &mut TableWriter) {
1233
0
        (1 as u16).write_into(writer);
1234
0
        self.coverage.write_into(writer);
1235
0
        (u16::try_from(array_len(&self.backtrack_coverages)).unwrap()).write_into(writer);
1236
0
        self.backtrack_coverages.write_into(writer);
1237
0
        (u16::try_from(array_len(&self.lookahead_coverages)).unwrap()).write_into(writer);
1238
0
        self.lookahead_coverages.write_into(writer);
1239
0
        (u16::try_from(array_len(&self.substitute_glyph_ids)).unwrap()).write_into(writer);
1240
0
        self.substitute_glyph_ids.write_into(writer);
1241
0
    }
1242
0
    fn table_type(&self) -> TableType {
1243
0
        TableType::Named("ReverseChainSingleSubstFormat1")
1244
0
    }
1245
}
1246
1247
impl Validate for ReverseChainSingleSubstFormat1 {
1248
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1249
0
        ctx.in_table("ReverseChainSingleSubstFormat1", |ctx| {
1250
0
            ctx.in_field("coverage", |ctx| {
1251
0
                self.coverage.validate_impl(ctx);
1252
0
            });
1253
0
            ctx.in_field("backtrack_coverages", |ctx| {
1254
0
                if self.backtrack_coverages.len() > to_usize(u16::MAX) {
1255
0
                    ctx.report("array exceeds max length");
1256
0
                }
1257
0
                self.backtrack_coverages.validate_impl(ctx);
1258
0
            });
1259
0
            ctx.in_field("lookahead_coverages", |ctx| {
1260
0
                if self.lookahead_coverages.len() > to_usize(u16::MAX) {
1261
0
                    ctx.report("array exceeds max length");
1262
0
                }
1263
0
                self.lookahead_coverages.validate_impl(ctx);
1264
0
            });
1265
0
            ctx.in_field("substitute_glyph_ids", |ctx| {
1266
0
                if self.substitute_glyph_ids.len() > to_usize(u16::MAX) {
1267
0
                    ctx.report("array exceeds max length");
1268
0
                }
1269
0
            });
1270
0
        })
1271
0
    }
1272
}
1273
1274
impl<'a> FromObjRef<read_fonts::tables::gsub::ReverseChainSingleSubstFormat1<'a>>
1275
    for ReverseChainSingleSubstFormat1
1276
{
1277
0
    fn from_obj_ref(
1278
0
        obj: &read_fonts::tables::gsub::ReverseChainSingleSubstFormat1<'a>,
1279
0
        _: FontData,
1280
0
    ) -> Self {
1281
0
        let offset_data = obj.offset_data();
1282
0
        ReverseChainSingleSubstFormat1 {
1283
0
            coverage: obj.coverage().to_owned_table(),
1284
0
            backtrack_coverages: obj.backtrack_coverages().to_owned_table(),
1285
0
            lookahead_coverages: obj.lookahead_coverages().to_owned_table(),
1286
0
            substitute_glyph_ids: obj.substitute_glyph_ids().to_owned_obj(offset_data),
1287
0
        }
1288
0
    }
1289
}
1290
1291
#[allow(clippy::needless_lifetimes)]
1292
impl<'a> FromTableRef<read_fonts::tables::gsub::ReverseChainSingleSubstFormat1<'a>>
1293
    for ReverseChainSingleSubstFormat1
1294
{
1295
}
1296
1297
impl ReadArgs for ReverseChainSingleSubstFormat1 {
1298
    type Args = ();
1299
}
1300
1301
impl<'a> FontRead<'a> for ReverseChainSingleSubstFormat1 {
1302
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1303
0
        <read_fonts::tables::gsub::ReverseChainSingleSubstFormat1 as FontRead>::read(data)
1304
0
            .map(|x| x.to_owned_table())
1305
0
    }
1306
}
1307
1308
/// SingleSubstFormat3 (ISO/IEC 14496-22:2026).
1309
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1310
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1311
pub struct SingleSubstFormat3 {
1312
    /// Offset to Coverage table, from beginning of substitution
1313
    /// subtable
1314
    pub coverage: OffsetMarker<CoverageTable, WIDTH_32>,
1315
    /// Add to original glyph ID to get substitute glyph ID
1316
    pub delta_glyph_id: Int24,
1317
}
1318
1319
impl SingleSubstFormat3 {
1320
    /// Construct a new `SingleSubstFormat3`
1321
0
    pub fn new(coverage: CoverageTable, delta_glyph_id: Int24) -> Self {
1322
0
        Self {
1323
0
            coverage: coverage.into(),
1324
0
            delta_glyph_id,
1325
0
        }
1326
0
    }
1327
}
1328
1329
impl FontWrite for SingleSubstFormat3 {
1330
    #[allow(clippy::unnecessary_cast)]
1331
0
    fn write_into(&self, writer: &mut TableWriter) {
1332
0
        (3 as u16).write_into(writer);
1333
0
        self.coverage.write_into(writer);
1334
0
        self.delta_glyph_id.write_into(writer);
1335
0
    }
1336
0
    fn table_type(&self) -> TableType {
1337
0
        TableType::Named("SingleSubstFormat3")
1338
0
    }
1339
}
1340
1341
impl Validate for SingleSubstFormat3 {
1342
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1343
0
        ctx.in_table("SingleSubstFormat3", |ctx| {
1344
0
            ctx.in_field("coverage", |ctx| {
1345
0
                self.coverage.validate_impl(ctx);
1346
0
            });
1347
0
        })
1348
0
    }
1349
}
1350
1351
impl<'a> FromObjRef<read_fonts::tables::gsub::SingleSubstFormat3<'a>> for SingleSubstFormat3 {
1352
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::SingleSubstFormat3<'a>, _: FontData) -> Self {
1353
0
        SingleSubstFormat3 {
1354
0
            coverage: obj.coverage().to_owned_table(),
1355
0
            delta_glyph_id: obj.delta_glyph_id(),
1356
0
        }
1357
0
    }
1358
}
1359
1360
#[allow(clippy::needless_lifetimes)]
1361
impl<'a> FromTableRef<read_fonts::tables::gsub::SingleSubstFormat3<'a>> for SingleSubstFormat3 {}
1362
1363
impl ReadArgs for SingleSubstFormat3 {
1364
    type Args = ();
1365
}
1366
1367
impl<'a> FontRead<'a> for SingleSubstFormat3 {
1368
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1369
0
        <read_fonts::tables::gsub::SingleSubstFormat3 as FontRead>::read(data)
1370
0
            .map(|x| x.to_owned_table())
1371
0
    }
1372
}
1373
1374
/// SingleSubstFormat4 (ISO/IEC 14496-22:2026).
1375
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1376
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1377
pub struct SingleSubstFormat4 {
1378
    /// Offset to Coverage table, from beginning of substitution
1379
    /// subtable
1380
    pub coverage: OffsetMarker<CoverageTable, WIDTH_32>,
1381
    /// Array of substitute glyph IDs — ordered by Coverage index
1382
    pub substitute_glyph_ids: Vec<GlyphId24>,
1383
}
1384
1385
impl SingleSubstFormat4 {
1386
    /// Construct a new `SingleSubstFormat4`
1387
0
    pub fn new(coverage: CoverageTable, substitute_glyph_ids: Vec<GlyphId24>) -> Self {
1388
0
        Self {
1389
0
            coverage: coverage.into(),
1390
0
            substitute_glyph_ids,
1391
0
        }
1392
0
    }
1393
}
1394
1395
impl FontWrite for SingleSubstFormat4 {
1396
    #[allow(clippy::unnecessary_cast)]
1397
0
    fn write_into(&self, writer: &mut TableWriter) {
1398
0
        (4 as u16).write_into(writer);
1399
0
        self.coverage.write_into(writer);
1400
0
        (Uint24::try_from(array_len(&self.substitute_glyph_ids)).unwrap()).write_into(writer);
1401
0
        self.substitute_glyph_ids.write_into(writer);
1402
0
    }
1403
0
    fn table_type(&self) -> TableType {
1404
0
        TableType::Named("SingleSubstFormat4")
1405
0
    }
1406
}
1407
1408
impl Validate for SingleSubstFormat4 {
1409
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1410
0
        ctx.in_table("SingleSubstFormat4", |ctx| {
1411
0
            ctx.in_field("coverage", |ctx| {
1412
0
                self.coverage.validate_impl(ctx);
1413
0
            });
1414
0
            ctx.in_field("substitute_glyph_ids", |ctx| {
1415
0
                if self.substitute_glyph_ids.len() > to_usize(Uint24::MAX) {
1416
0
                    ctx.report("array exceeds max length");
1417
0
                }
1418
0
            });
1419
0
        })
1420
0
    }
1421
}
1422
1423
impl<'a> FromObjRef<read_fonts::tables::gsub::SingleSubstFormat4<'a>> for SingleSubstFormat4 {
1424
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::SingleSubstFormat4<'a>, _: FontData) -> Self {
1425
0
        let offset_data = obj.offset_data();
1426
0
        SingleSubstFormat4 {
1427
0
            coverage: obj.coverage().to_owned_table(),
1428
0
            substitute_glyph_ids: obj.substitute_glyph_ids().to_owned_obj(offset_data),
1429
0
        }
1430
0
    }
1431
}
1432
1433
#[allow(clippy::needless_lifetimes)]
1434
impl<'a> FromTableRef<read_fonts::tables::gsub::SingleSubstFormat4<'a>> for SingleSubstFormat4 {}
1435
1436
impl ReadArgs for SingleSubstFormat4 {
1437
    type Args = ();
1438
}
1439
1440
impl<'a> FontRead<'a> for SingleSubstFormat4 {
1441
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1442
0
        <read_fonts::tables::gsub::SingleSubstFormat4 as FontRead>::read(data)
1443
0
            .map(|x| x.to_owned_table())
1444
0
    }
1445
}
1446
1447
/// MultipleSubstFormat2 (ISO/IEC 14496-22:2026).
1448
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1449
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1450
pub struct MultipleSubstFormat2 {
1451
    /// Offset to Coverage table, from beginning of substitution
1452
    /// subtable
1453
    pub coverage: OffsetMarker<CoverageTable, WIDTH_32>,
1454
    /// Array of offsets to Sequence tables. Offsets are from beginning
1455
    /// of substitution subtable, ordered by Coverage index
1456
    pub sequences: Vec<OffsetMarker<Sequence2, WIDTH_24>>,
1457
}
1458
1459
impl MultipleSubstFormat2 {
1460
    /// Construct a new `MultipleSubstFormat2`
1461
0
    pub fn new(coverage: CoverageTable, sequences: Vec<Sequence2>) -> Self {
1462
0
        Self {
1463
0
            coverage: coverage.into(),
1464
0
            sequences: sequences.into_iter().map(Into::into).collect(),
1465
0
        }
1466
0
    }
1467
}
1468
1469
impl FontWrite for MultipleSubstFormat2 {
1470
    #[allow(clippy::unnecessary_cast)]
1471
0
    fn write_into(&self, writer: &mut TableWriter) {
1472
0
        (2 as u16).write_into(writer);
1473
0
        self.coverage.write_into(writer);
1474
0
        (Uint24::try_from(array_len(&self.sequences)).unwrap()).write_into(writer);
1475
0
        self.sequences.write_into(writer);
1476
0
    }
1477
0
    fn table_type(&self) -> TableType {
1478
0
        TableType::Named("MultipleSubstFormat2")
1479
0
    }
1480
}
1481
1482
impl Validate for MultipleSubstFormat2 {
1483
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1484
0
        ctx.in_table("MultipleSubstFormat2", |ctx| {
1485
0
            ctx.in_field("coverage", |ctx| {
1486
0
                self.coverage.validate_impl(ctx);
1487
0
            });
1488
0
            ctx.in_field("sequences", |ctx| {
1489
0
                if self.sequences.len() > to_usize(Uint24::MAX) {
1490
0
                    ctx.report("array exceeds max length");
1491
0
                }
1492
0
                self.sequences.validate_impl(ctx);
1493
0
            });
1494
0
        })
1495
0
    }
1496
}
1497
1498
impl<'a> FromObjRef<read_fonts::tables::gsub::MultipleSubstFormat2<'a>> for MultipleSubstFormat2 {
1499
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::MultipleSubstFormat2<'a>, _: FontData) -> Self {
1500
0
        MultipleSubstFormat2 {
1501
0
            coverage: obj.coverage().to_owned_table(),
1502
0
            sequences: obj.sequences().to_owned_table(),
1503
0
        }
1504
0
    }
1505
}
1506
1507
#[allow(clippy::needless_lifetimes)]
1508
impl<'a> FromTableRef<read_fonts::tables::gsub::MultipleSubstFormat2<'a>> for MultipleSubstFormat2 {}
1509
1510
impl ReadArgs for MultipleSubstFormat2 {
1511
    type Args = ();
1512
}
1513
1514
impl<'a> FontRead<'a> for MultipleSubstFormat2 {
1515
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1516
0
        <read_fonts::tables::gsub::MultipleSubstFormat2 as FontRead>::read(data)
1517
0
            .map(|x| x.to_owned_table())
1518
0
    }
1519
}
1520
1521
/// AlternateSubstFormat2 (ISO/IEC 14496-22:2026).
1522
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1523
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1524
pub struct AlternateSubstFormat2 {
1525
    /// Offset to Coverage table, from beginning of substitution
1526
    /// subtable
1527
    pub coverage: OffsetMarker<CoverageTable, WIDTH_32>,
1528
    /// Array of offsets to AlternateSet tables. Offsets are from
1529
    /// beginning of substitution subtable, ordered by Coverage index
1530
    pub alternate_sets: Vec<OffsetMarker<AlternateSet2, WIDTH_24>>,
1531
}
1532
1533
impl AlternateSubstFormat2 {
1534
    /// Construct a new `AlternateSubstFormat2`
1535
0
    pub fn new(coverage: CoverageTable, alternate_sets: Vec<AlternateSet2>) -> Self {
1536
0
        Self {
1537
0
            coverage: coverage.into(),
1538
0
            alternate_sets: alternate_sets.into_iter().map(Into::into).collect(),
1539
0
        }
1540
0
    }
1541
}
1542
1543
impl FontWrite for AlternateSubstFormat2 {
1544
    #[allow(clippy::unnecessary_cast)]
1545
0
    fn write_into(&self, writer: &mut TableWriter) {
1546
0
        (2 as u16).write_into(writer);
1547
0
        self.coverage.write_into(writer);
1548
0
        (Uint24::try_from(array_len(&self.alternate_sets)).unwrap()).write_into(writer);
1549
0
        self.alternate_sets.write_into(writer);
1550
0
    }
1551
0
    fn table_type(&self) -> TableType {
1552
0
        TableType::Named("AlternateSubstFormat2")
1553
0
    }
1554
}
1555
1556
impl Validate for AlternateSubstFormat2 {
1557
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1558
0
        ctx.in_table("AlternateSubstFormat2", |ctx| {
1559
0
            ctx.in_field("coverage", |ctx| {
1560
0
                self.coverage.validate_impl(ctx);
1561
0
            });
1562
0
            ctx.in_field("alternate_sets", |ctx| {
1563
0
                if self.alternate_sets.len() > to_usize(Uint24::MAX) {
1564
0
                    ctx.report("array exceeds max length");
1565
0
                }
1566
0
                self.alternate_sets.validate_impl(ctx);
1567
0
            });
1568
0
        })
1569
0
    }
1570
}
1571
1572
impl<'a> FromObjRef<read_fonts::tables::gsub::AlternateSubstFormat2<'a>> for AlternateSubstFormat2 {
1573
0
    fn from_obj_ref(
1574
0
        obj: &read_fonts::tables::gsub::AlternateSubstFormat2<'a>,
1575
0
        _: FontData,
1576
0
    ) -> Self {
1577
0
        AlternateSubstFormat2 {
1578
0
            coverage: obj.coverage().to_owned_table(),
1579
0
            alternate_sets: obj.alternate_sets().to_owned_table(),
1580
0
        }
1581
0
    }
1582
}
1583
1584
#[allow(clippy::needless_lifetimes)]
1585
impl<'a> FromTableRef<read_fonts::tables::gsub::AlternateSubstFormat2<'a>>
1586
    for AlternateSubstFormat2
1587
{
1588
}
1589
1590
impl ReadArgs for AlternateSubstFormat2 {
1591
    type Args = ();
1592
}
1593
1594
impl<'a> FontRead<'a> for AlternateSubstFormat2 {
1595
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1596
0
        <read_fonts::tables::gsub::AlternateSubstFormat2 as FontRead>::read(data)
1597
0
            .map(|x| x.to_owned_table())
1598
0
    }
1599
}
1600
1601
/// LigatureSubstFormat2 (ISO/IEC 14496-22:2026).
1602
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1603
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1604
pub struct LigatureSubstFormat2 {
1605
    /// Offset to Coverage table, from beginning of substitution
1606
    /// subtable
1607
    pub coverage: OffsetMarker<CoverageTable, WIDTH_32>,
1608
    /// Array of offsets to LigatureSet tables. Offsets are from
1609
    /// beginning of substitution subtable, ordered by Coverage index
1610
    pub ligature_sets: Vec<OffsetMarker<LigatureSet2, WIDTH_24>>,
1611
}
1612
1613
impl LigatureSubstFormat2 {
1614
    /// Construct a new `LigatureSubstFormat2`
1615
0
    pub fn new(coverage: CoverageTable, ligature_sets: Vec<LigatureSet2>) -> Self {
1616
0
        Self {
1617
0
            coverage: coverage.into(),
1618
0
            ligature_sets: ligature_sets.into_iter().map(Into::into).collect(),
1619
0
        }
1620
0
    }
1621
}
1622
1623
impl FontWrite for LigatureSubstFormat2 {
1624
    #[allow(clippy::unnecessary_cast)]
1625
0
    fn write_into(&self, writer: &mut TableWriter) {
1626
0
        (2 as u16).write_into(writer);
1627
0
        self.coverage.write_into(writer);
1628
0
        (Uint24::try_from(array_len(&self.ligature_sets)).unwrap()).write_into(writer);
1629
0
        self.ligature_sets.write_into(writer);
1630
0
    }
1631
0
    fn table_type(&self) -> TableType {
1632
0
        TableType::Named("LigatureSubstFormat2")
1633
0
    }
1634
}
1635
1636
impl Validate for LigatureSubstFormat2 {
1637
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1638
0
        ctx.in_table("LigatureSubstFormat2", |ctx| {
1639
0
            ctx.in_field("coverage", |ctx| {
1640
0
                self.coverage.validate_impl(ctx);
1641
0
            });
1642
0
            ctx.in_field("ligature_sets", |ctx| {
1643
0
                if self.ligature_sets.len() > to_usize(Uint24::MAX) {
1644
0
                    ctx.report("array exceeds max length");
1645
0
                }
1646
0
                self.ligature_sets.validate_impl(ctx);
1647
0
            });
1648
0
        })
1649
0
    }
1650
}
1651
1652
impl<'a> FromObjRef<read_fonts::tables::gsub::LigatureSubstFormat2<'a>> for LigatureSubstFormat2 {
1653
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::LigatureSubstFormat2<'a>, _: FontData) -> Self {
1654
0
        LigatureSubstFormat2 {
1655
0
            coverage: obj.coverage().to_owned_table(),
1656
0
            ligature_sets: obj.ligature_sets().to_owned_table(),
1657
0
        }
1658
0
    }
1659
}
1660
1661
#[allow(clippy::needless_lifetimes)]
1662
impl<'a> FromTableRef<read_fonts::tables::gsub::LigatureSubstFormat2<'a>> for LigatureSubstFormat2 {}
1663
1664
impl ReadArgs for LigatureSubstFormat2 {
1665
    type Args = ();
1666
}
1667
1668
impl<'a> FontRead<'a> for LigatureSubstFormat2 {
1669
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1670
0
        <read_fonts::tables::gsub::LigatureSubstFormat2 as FontRead>::read(data)
1671
0
            .map(|x| x.to_owned_table())
1672
0
    }
1673
}
1674
1675
/// ReverseChainSingleSubstFormat2 (ISO/IEC 14496-22:2026).
1676
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1677
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1678
pub struct ReverseChainSingleSubstFormat2 {
1679
    /// Offset to Coverage table, from beginning of substitution
1680
    /// subtable.
1681
    pub coverage: OffsetMarker<CoverageTable, WIDTH_32>,
1682
    /// Array of offsets to coverage tables in backtrack sequence, in
1683
    /// glyph sequence order.
1684
    pub backtrack_coverages: Vec<OffsetMarker<CoverageTable, WIDTH_24>>,
1685
    /// Array of offsets to coverage tables in lookahead sequence, in
1686
    /// glyph sequence order.
1687
    pub lookahead_coverages: Vec<OffsetMarker<CoverageTable, WIDTH_24>>,
1688
    /// Array of substitute glyph IDs — ordered by Coverage index.
1689
    pub substitute_glyph_ids: Vec<GlyphId24>,
1690
}
1691
1692
impl ReverseChainSingleSubstFormat2 {
1693
    /// Construct a new `ReverseChainSingleSubstFormat2`
1694
0
    pub fn new(
1695
0
        coverage: CoverageTable,
1696
0
        backtrack_coverages: Vec<CoverageTable>,
1697
0
        lookahead_coverages: Vec<CoverageTable>,
1698
0
        substitute_glyph_ids: Vec<GlyphId24>,
1699
0
    ) -> Self {
1700
0
        Self {
1701
0
            coverage: coverage.into(),
1702
0
            backtrack_coverages: backtrack_coverages.into_iter().map(Into::into).collect(),
1703
0
            lookahead_coverages: lookahead_coverages.into_iter().map(Into::into).collect(),
1704
0
            substitute_glyph_ids,
1705
0
        }
1706
0
    }
1707
}
1708
1709
impl FontWrite for ReverseChainSingleSubstFormat2 {
1710
    #[allow(clippy::unnecessary_cast)]
1711
0
    fn write_into(&self, writer: &mut TableWriter) {
1712
0
        (2 as u16).write_into(writer);
1713
0
        self.coverage.write_into(writer);
1714
0
        (u16::try_from(array_len(&self.backtrack_coverages)).unwrap()).write_into(writer);
1715
0
        self.backtrack_coverages.write_into(writer);
1716
0
        (u16::try_from(array_len(&self.lookahead_coverages)).unwrap()).write_into(writer);
1717
0
        self.lookahead_coverages.write_into(writer);
1718
0
        (Uint24::try_from(array_len(&self.substitute_glyph_ids)).unwrap()).write_into(writer);
1719
0
        self.substitute_glyph_ids.write_into(writer);
1720
0
    }
1721
0
    fn table_type(&self) -> TableType {
1722
0
        TableType::Named("ReverseChainSingleSubstFormat2")
1723
0
    }
1724
}
1725
1726
impl Validate for ReverseChainSingleSubstFormat2 {
1727
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1728
0
        ctx.in_table("ReverseChainSingleSubstFormat2", |ctx| {
1729
0
            ctx.in_field("coverage", |ctx| {
1730
0
                self.coverage.validate_impl(ctx);
1731
0
            });
1732
0
            ctx.in_field("backtrack_coverages", |ctx| {
1733
0
                if self.backtrack_coverages.len() > to_usize(u16::MAX) {
1734
0
                    ctx.report("array exceeds max length");
1735
0
                }
1736
0
                self.backtrack_coverages.validate_impl(ctx);
1737
0
            });
1738
0
            ctx.in_field("lookahead_coverages", |ctx| {
1739
0
                if self.lookahead_coverages.len() > to_usize(u16::MAX) {
1740
0
                    ctx.report("array exceeds max length");
1741
0
                }
1742
0
                self.lookahead_coverages.validate_impl(ctx);
1743
0
            });
1744
0
            ctx.in_field("substitute_glyph_ids", |ctx| {
1745
0
                if self.substitute_glyph_ids.len() > to_usize(Uint24::MAX) {
1746
0
                    ctx.report("array exceeds max length");
1747
0
                }
1748
0
            });
1749
0
        })
1750
0
    }
1751
}
1752
1753
impl<'a> FromObjRef<read_fonts::tables::gsub::ReverseChainSingleSubstFormat2<'a>>
1754
    for ReverseChainSingleSubstFormat2
1755
{
1756
0
    fn from_obj_ref(
1757
0
        obj: &read_fonts::tables::gsub::ReverseChainSingleSubstFormat2<'a>,
1758
0
        _: FontData,
1759
0
    ) -> Self {
1760
0
        let offset_data = obj.offset_data();
1761
0
        ReverseChainSingleSubstFormat2 {
1762
0
            coverage: obj.coverage().to_owned_table(),
1763
0
            backtrack_coverages: obj.backtrack_coverages().to_owned_table(),
1764
0
            lookahead_coverages: obj.lookahead_coverages().to_owned_table(),
1765
0
            substitute_glyph_ids: obj.substitute_glyph_ids().to_owned_obj(offset_data),
1766
0
        }
1767
0
    }
1768
}
1769
1770
#[allow(clippy::needless_lifetimes)]
1771
impl<'a> FromTableRef<read_fonts::tables::gsub::ReverseChainSingleSubstFormat2<'a>>
1772
    for ReverseChainSingleSubstFormat2
1773
{
1774
}
1775
1776
impl ReadArgs for ReverseChainSingleSubstFormat2 {
1777
    type Args = ();
1778
}
1779
1780
impl<'a> FontRead<'a> for ReverseChainSingleSubstFormat2 {
1781
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1782
0
        <read_fonts::tables::gsub::ReverseChainSingleSubstFormat2 as FontRead>::read(data)
1783
0
            .map(|x| x.to_owned_table())
1784
0
    }
1785
}
1786
1787
/// Sequence2 (ISO/IEC 14496-22:2026).
1788
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1789
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1790
pub struct Sequence2 {
1791
    /// String of glyph IDs to substitute
1792
    pub substitute_glyph_ids: Vec<GlyphId24>,
1793
}
1794
1795
impl Sequence2 {
1796
    /// Construct a new `Sequence2`
1797
0
    pub fn new(substitute_glyph_ids: Vec<GlyphId24>) -> Self {
1798
0
        Self {
1799
0
            substitute_glyph_ids,
1800
0
        }
1801
0
    }
1802
}
1803
1804
impl FontWrite for Sequence2 {
1805
    #[allow(clippy::unnecessary_cast)]
1806
0
    fn write_into(&self, writer: &mut TableWriter) {
1807
0
        (u16::try_from(array_len(&self.substitute_glyph_ids)).unwrap()).write_into(writer);
1808
0
        self.substitute_glyph_ids.write_into(writer);
1809
0
    }
1810
0
    fn table_type(&self) -> TableType {
1811
0
        TableType::Named("Sequence2")
1812
0
    }
1813
}
1814
1815
impl Validate for Sequence2 {
1816
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1817
0
        ctx.in_table("Sequence2", |ctx| {
1818
0
            ctx.in_field("substitute_glyph_ids", |ctx| {
1819
0
                if self.substitute_glyph_ids.len() > to_usize(u16::MAX) {
1820
0
                    ctx.report("array exceeds max length");
1821
0
                }
1822
0
            });
1823
0
        })
1824
0
    }
1825
}
1826
1827
impl<'a> FromObjRef<read_fonts::tables::gsub::Sequence2<'a>> for Sequence2 {
1828
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::Sequence2<'a>, _: FontData) -> Self {
1829
0
        let offset_data = obj.offset_data();
1830
0
        Sequence2 {
1831
0
            substitute_glyph_ids: obj.substitute_glyph_ids().to_owned_obj(offset_data),
1832
0
        }
1833
0
    }
1834
}
1835
1836
#[allow(clippy::needless_lifetimes)]
1837
impl<'a> FromTableRef<read_fonts::tables::gsub::Sequence2<'a>> for Sequence2 {}
1838
1839
impl ReadArgs for Sequence2 {
1840
    type Args = ();
1841
}
1842
1843
impl<'a> FontRead<'a> for Sequence2 {
1844
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1845
0
        <read_fonts::tables::gsub::Sequence2 as FontRead>::read(data).map(|x| x.to_owned_table())
1846
0
    }
1847
}
1848
1849
/// AlternateSet2 (ISO/IEC 14496-22:2026).
1850
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1851
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1852
pub struct AlternateSet2 {
1853
    /// Array of alternate glyph IDs, in arbitrary order
1854
    pub alternate_glyph_ids: Vec<GlyphId24>,
1855
}
1856
1857
impl AlternateSet2 {
1858
    /// Construct a new `AlternateSet2`
1859
0
    pub fn new(alternate_glyph_ids: Vec<GlyphId24>) -> Self {
1860
0
        Self {
1861
0
            alternate_glyph_ids,
1862
0
        }
1863
0
    }
1864
}
1865
1866
impl FontWrite for AlternateSet2 {
1867
    #[allow(clippy::unnecessary_cast)]
1868
0
    fn write_into(&self, writer: &mut TableWriter) {
1869
0
        (u16::try_from(array_len(&self.alternate_glyph_ids)).unwrap()).write_into(writer);
1870
0
        self.alternate_glyph_ids.write_into(writer);
1871
0
    }
1872
0
    fn table_type(&self) -> TableType {
1873
0
        TableType::Named("AlternateSet2")
1874
0
    }
1875
}
1876
1877
impl Validate for AlternateSet2 {
1878
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1879
0
        ctx.in_table("AlternateSet2", |ctx| {
1880
0
            ctx.in_field("alternate_glyph_ids", |ctx| {
1881
0
                if self.alternate_glyph_ids.len() > to_usize(u16::MAX) {
1882
0
                    ctx.report("array exceeds max length");
1883
0
                }
1884
0
            });
1885
0
        })
1886
0
    }
1887
}
1888
1889
impl<'a> FromObjRef<read_fonts::tables::gsub::AlternateSet2<'a>> for AlternateSet2 {
1890
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::AlternateSet2<'a>, _: FontData) -> Self {
1891
0
        let offset_data = obj.offset_data();
1892
0
        AlternateSet2 {
1893
0
            alternate_glyph_ids: obj.alternate_glyph_ids().to_owned_obj(offset_data),
1894
0
        }
1895
0
    }
1896
}
1897
1898
#[allow(clippy::needless_lifetimes)]
1899
impl<'a> FromTableRef<read_fonts::tables::gsub::AlternateSet2<'a>> for AlternateSet2 {}
1900
1901
impl ReadArgs for AlternateSet2 {
1902
    type Args = ();
1903
}
1904
1905
impl<'a> FontRead<'a> for AlternateSet2 {
1906
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1907
0
        <read_fonts::tables::gsub::AlternateSet2 as FontRead>::read(data)
1908
0
            .map(|x| x.to_owned_table())
1909
0
    }
1910
}
1911
1912
/// LigatureSet2 (ISO/IEC 14496-22:2026).
1913
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1914
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1915
pub struct LigatureSet2 {
1916
    /// Array of offsets to Ligature tables. Offsets are from beginning
1917
    /// of LigatureSet2 table, ordered by preference.
1918
    pub ligatures: Vec<OffsetMarker<Ligature2, WIDTH_24>>,
1919
}
1920
1921
impl LigatureSet2 {
1922
    /// Construct a new `LigatureSet2`
1923
0
    pub fn new(ligatures: Vec<Ligature2>) -> Self {
1924
0
        Self {
1925
0
            ligatures: ligatures.into_iter().map(Into::into).collect(),
1926
0
        }
1927
0
    }
1928
}
1929
1930
impl FontWrite for LigatureSet2 {
1931
    #[allow(clippy::unnecessary_cast)]
1932
0
    fn write_into(&self, writer: &mut TableWriter) {
1933
0
        (u16::try_from(array_len(&self.ligatures)).unwrap()).write_into(writer);
1934
0
        self.ligatures.write_into(writer);
1935
0
    }
1936
0
    fn table_type(&self) -> TableType {
1937
0
        TableType::Named("LigatureSet2")
1938
0
    }
1939
}
1940
1941
impl Validate for LigatureSet2 {
1942
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1943
0
        ctx.in_table("LigatureSet2", |ctx| {
1944
0
            ctx.in_field("ligatures", |ctx| {
1945
0
                if self.ligatures.len() > to_usize(u16::MAX) {
1946
0
                    ctx.report("array exceeds max length");
1947
0
                }
1948
0
                self.ligatures.validate_impl(ctx);
1949
0
            });
1950
0
        })
1951
0
    }
1952
}
1953
1954
impl<'a> FromObjRef<read_fonts::tables::gsub::LigatureSet2<'a>> for LigatureSet2 {
1955
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::LigatureSet2<'a>, _: FontData) -> Self {
1956
0
        LigatureSet2 {
1957
0
            ligatures: obj.ligatures().to_owned_table(),
1958
0
        }
1959
0
    }
1960
}
1961
1962
#[allow(clippy::needless_lifetimes)]
1963
impl<'a> FromTableRef<read_fonts::tables::gsub::LigatureSet2<'a>> for LigatureSet2 {}
1964
1965
impl ReadArgs for LigatureSet2 {
1966
    type Args = ();
1967
}
1968
1969
impl<'a> FontRead<'a> for LigatureSet2 {
1970
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1971
0
        <read_fonts::tables::gsub::LigatureSet2 as FontRead>::read(data).map(|x| x.to_owned_table())
1972
0
    }
1973
}
1974
1975
/// Ligature2 (ISO/IEC 14496-22:2026).
1976
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1977
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1978
pub struct Ligature2 {
1979
    /// glyph ID of ligature to substitute
1980
    pub ligature_glyph: GlyphId24,
1981
    /// Array of component glyph IDs — start with the second
1982
    /// component, ordered in writing direction
1983
    pub component_glyph_ids: Vec<GlyphId24>,
1984
}
1985
1986
impl Ligature2 {
1987
    /// Construct a new `Ligature2`
1988
0
    pub fn new(ligature_glyph: GlyphId24, component_glyph_ids: Vec<GlyphId24>) -> Self {
1989
0
        Self {
1990
0
            ligature_glyph,
1991
0
            component_glyph_ids,
1992
0
        }
1993
0
    }
1994
}
1995
1996
impl FontWrite for Ligature2 {
1997
    #[allow(clippy::unnecessary_cast)]
1998
0
    fn write_into(&self, writer: &mut TableWriter) {
1999
0
        self.ligature_glyph.write_into(writer);
2000
0
        (u16::try_from(plus_one(&self.component_glyph_ids.len())).unwrap()).write_into(writer);
2001
0
        self.component_glyph_ids.write_into(writer);
2002
0
    }
2003
0
    fn table_type(&self) -> TableType {
2004
0
        TableType::Named("Ligature2")
2005
0
    }
2006
}
2007
2008
impl Validate for Ligature2 {
2009
0
    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
2010
}
2011
2012
impl<'a> FromObjRef<read_fonts::tables::gsub::Ligature2<'a>> for Ligature2 {
2013
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::Ligature2<'a>, _: FontData) -> Self {
2014
0
        let offset_data = obj.offset_data();
2015
0
        Ligature2 {
2016
0
            ligature_glyph: obj.ligature_glyph(),
2017
0
            component_glyph_ids: obj.component_glyph_ids().to_owned_obj(offset_data),
2018
0
        }
2019
0
    }
2020
}
2021
2022
#[allow(clippy::needless_lifetimes)]
2023
impl<'a> FromTableRef<read_fonts::tables::gsub::Ligature2<'a>> for Ligature2 {}
2024
2025
impl ReadArgs for Ligature2 {
2026
    type Args = ();
2027
}
2028
2029
impl<'a> FontRead<'a> for Ligature2 {
2030
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2031
0
        <read_fonts::tables::gsub::Ligature2 as FontRead>::read(data).map(|x| x.to_owned_table())
2032
0
    }
2033
}
2034
2035
/// MultipleSubst (ISO/IEC 14496-22:2026).
2036
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2037
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2038
pub enum MultipleSubst {
2039
    Format1(MultipleSubstFormat1),
2040
    Format2(MultipleSubstFormat2),
2041
}
2042
2043
impl MultipleSubst {
2044
    /// Construct a new `MultipleSubstFormat1` subtable
2045
0
    pub fn format_1(coverage: CoverageTable, sequences: Vec<Sequence>) -> Self {
2046
0
        Self::Format1(MultipleSubstFormat1::new(coverage, sequences))
2047
0
    }
2048
2049
    /// Construct a new `MultipleSubstFormat2` subtable
2050
0
    pub fn format_2(coverage: CoverageTable, sequences: Vec<Sequence2>) -> Self {
2051
0
        Self::Format2(MultipleSubstFormat2::new(coverage, sequences))
2052
0
    }
2053
}
2054
2055
impl Default for MultipleSubst {
2056
0
    fn default() -> Self {
2057
0
        Self::Format1(Default::default())
2058
0
    }
2059
}
2060
2061
impl FontWrite for MultipleSubst {
2062
0
    fn write_into(&self, writer: &mut TableWriter) {
2063
0
        match self {
2064
0
            Self::Format1(item) => item.write_into(writer),
2065
0
            Self::Format2(item) => item.write_into(writer),
2066
        }
2067
0
    }
2068
0
    fn table_type(&self) -> TableType {
2069
0
        match self {
2070
0
            Self::Format1(item) => item.table_type(),
2071
0
            Self::Format2(item) => item.table_type(),
2072
        }
2073
0
    }
2074
}
2075
2076
impl Validate for MultipleSubst {
2077
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
2078
0
        match self {
2079
0
            Self::Format1(item) => item.validate_impl(ctx),
2080
0
            Self::Format2(item) => item.validate_impl(ctx),
2081
        }
2082
0
    }
2083
}
2084
2085
impl FromObjRef<read_fonts::tables::gsub::MultipleSubst<'_>> for MultipleSubst {
2086
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::MultipleSubst, _: FontData) -> Self {
2087
        use read_fonts::tables::gsub::MultipleSubst as ObjRefType;
2088
0
        match obj {
2089
0
            ObjRefType::Format1(item) => MultipleSubst::Format1(item.to_owned_table()),
2090
0
            ObjRefType::Format2(item) => MultipleSubst::Format2(item.to_owned_table()),
2091
        }
2092
0
    }
2093
}
2094
2095
impl FromTableRef<read_fonts::tables::gsub::MultipleSubst<'_>> for MultipleSubst {}
2096
2097
impl ReadArgs for MultipleSubst {
2098
    type Args = ();
2099
}
2100
2101
impl<'a> FontRead<'a> for MultipleSubst {
2102
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2103
0
        <read_fonts::tables::gsub::MultipleSubst as FontRead>::read(data)
2104
0
            .map(|x| x.to_owned_table())
2105
0
    }
2106
}
2107
2108
impl From<MultipleSubstFormat1> for MultipleSubst {
2109
0
    fn from(src: MultipleSubstFormat1) -> MultipleSubst {
2110
0
        MultipleSubst::Format1(src)
2111
0
    }
2112
}
2113
2114
impl From<MultipleSubstFormat2> for MultipleSubst {
2115
0
    fn from(src: MultipleSubstFormat2) -> MultipleSubst {
2116
0
        MultipleSubst::Format2(src)
2117
0
    }
2118
}
2119
2120
/// AlternateSubst (ISO/IEC 14496-22:2026).
2121
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2122
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2123
pub enum AlternateSubst {
2124
    Format1(AlternateSubstFormat1),
2125
    Format2(AlternateSubstFormat2),
2126
}
2127
2128
impl AlternateSubst {
2129
    /// Construct a new `AlternateSubstFormat1` subtable
2130
0
    pub fn format_1(coverage: CoverageTable, alternate_sets: Vec<AlternateSet>) -> Self {
2131
0
        Self::Format1(AlternateSubstFormat1::new(coverage, alternate_sets))
2132
0
    }
2133
2134
    /// Construct a new `AlternateSubstFormat2` subtable
2135
0
    pub fn format_2(coverage: CoverageTable, alternate_sets: Vec<AlternateSet2>) -> Self {
2136
0
        Self::Format2(AlternateSubstFormat2::new(coverage, alternate_sets))
2137
0
    }
2138
}
2139
2140
impl Default for AlternateSubst {
2141
0
    fn default() -> Self {
2142
0
        Self::Format1(Default::default())
2143
0
    }
2144
}
2145
2146
impl FontWrite for AlternateSubst {
2147
0
    fn write_into(&self, writer: &mut TableWriter) {
2148
0
        match self {
2149
0
            Self::Format1(item) => item.write_into(writer),
2150
0
            Self::Format2(item) => item.write_into(writer),
2151
        }
2152
0
    }
2153
0
    fn table_type(&self) -> TableType {
2154
0
        match self {
2155
0
            Self::Format1(item) => item.table_type(),
2156
0
            Self::Format2(item) => item.table_type(),
2157
        }
2158
0
    }
2159
}
2160
2161
impl Validate for AlternateSubst {
2162
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
2163
0
        match self {
2164
0
            Self::Format1(item) => item.validate_impl(ctx),
2165
0
            Self::Format2(item) => item.validate_impl(ctx),
2166
        }
2167
0
    }
2168
}
2169
2170
impl FromObjRef<read_fonts::tables::gsub::AlternateSubst<'_>> for AlternateSubst {
2171
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::AlternateSubst, _: FontData) -> Self {
2172
        use read_fonts::tables::gsub::AlternateSubst as ObjRefType;
2173
0
        match obj {
2174
0
            ObjRefType::Format1(item) => AlternateSubst::Format1(item.to_owned_table()),
2175
0
            ObjRefType::Format2(item) => AlternateSubst::Format2(item.to_owned_table()),
2176
        }
2177
0
    }
2178
}
2179
2180
impl FromTableRef<read_fonts::tables::gsub::AlternateSubst<'_>> for AlternateSubst {}
2181
2182
impl ReadArgs for AlternateSubst {
2183
    type Args = ();
2184
}
2185
2186
impl<'a> FontRead<'a> for AlternateSubst {
2187
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2188
0
        <read_fonts::tables::gsub::AlternateSubst as FontRead>::read(data)
2189
0
            .map(|x| x.to_owned_table())
2190
0
    }
2191
}
2192
2193
impl From<AlternateSubstFormat1> for AlternateSubst {
2194
0
    fn from(src: AlternateSubstFormat1) -> AlternateSubst {
2195
0
        AlternateSubst::Format1(src)
2196
0
    }
2197
}
2198
2199
impl From<AlternateSubstFormat2> for AlternateSubst {
2200
0
    fn from(src: AlternateSubstFormat2) -> AlternateSubst {
2201
0
        AlternateSubst::Format2(src)
2202
0
    }
2203
}
2204
2205
/// LigatureSubst (ISO/IEC 14496-22:2026).
2206
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2207
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2208
pub enum LigatureSubst {
2209
    Format1(LigatureSubstFormat1),
2210
    Format2(LigatureSubstFormat2),
2211
}
2212
2213
impl LigatureSubst {
2214
    /// Construct a new `LigatureSubstFormat1` subtable
2215
0
    pub fn format_1(coverage: CoverageTable, ligature_sets: Vec<LigatureSet>) -> Self {
2216
0
        Self::Format1(LigatureSubstFormat1::new(coverage, ligature_sets))
2217
0
    }
2218
2219
    /// Construct a new `LigatureSubstFormat2` subtable
2220
0
    pub fn format_2(coverage: CoverageTable, ligature_sets: Vec<LigatureSet2>) -> Self {
2221
0
        Self::Format2(LigatureSubstFormat2::new(coverage, ligature_sets))
2222
0
    }
2223
}
2224
2225
impl Default for LigatureSubst {
2226
0
    fn default() -> Self {
2227
0
        Self::Format1(Default::default())
2228
0
    }
2229
}
2230
2231
impl FontWrite for LigatureSubst {
2232
0
    fn write_into(&self, writer: &mut TableWriter) {
2233
0
        match self {
2234
0
            Self::Format1(item) => item.write_into(writer),
2235
0
            Self::Format2(item) => item.write_into(writer),
2236
        }
2237
0
    }
2238
0
    fn table_type(&self) -> TableType {
2239
0
        match self {
2240
0
            Self::Format1(item) => item.table_type(),
2241
0
            Self::Format2(item) => item.table_type(),
2242
        }
2243
0
    }
2244
}
2245
2246
impl Validate for LigatureSubst {
2247
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
2248
0
        match self {
2249
0
            Self::Format1(item) => item.validate_impl(ctx),
2250
0
            Self::Format2(item) => item.validate_impl(ctx),
2251
        }
2252
0
    }
2253
}
2254
2255
impl FromObjRef<read_fonts::tables::gsub::LigatureSubst<'_>> for LigatureSubst {
2256
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::LigatureSubst, _: FontData) -> Self {
2257
        use read_fonts::tables::gsub::LigatureSubst as ObjRefType;
2258
0
        match obj {
2259
0
            ObjRefType::Format1(item) => LigatureSubst::Format1(item.to_owned_table()),
2260
0
            ObjRefType::Format2(item) => LigatureSubst::Format2(item.to_owned_table()),
2261
        }
2262
0
    }
2263
}
2264
2265
impl FromTableRef<read_fonts::tables::gsub::LigatureSubst<'_>> for LigatureSubst {}
2266
2267
impl ReadArgs for LigatureSubst {
2268
    type Args = ();
2269
}
2270
2271
impl<'a> FontRead<'a> for LigatureSubst {
2272
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2273
0
        <read_fonts::tables::gsub::LigatureSubst as FontRead>::read(data)
2274
0
            .map(|x| x.to_owned_table())
2275
0
    }
2276
}
2277
2278
impl From<LigatureSubstFormat1> for LigatureSubst {
2279
0
    fn from(src: LigatureSubstFormat1) -> LigatureSubst {
2280
0
        LigatureSubst::Format1(src)
2281
0
    }
2282
}
2283
2284
impl From<LigatureSubstFormat2> for LigatureSubst {
2285
0
    fn from(src: LigatureSubstFormat2) -> LigatureSubst {
2286
0
        LigatureSubst::Format2(src)
2287
0
    }
2288
}
2289
2290
/// ReverseChainSingleSubst (ISO/IEC 14496-22:2026).
2291
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2292
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2293
pub enum ReverseChainSingleSubst {
2294
    Format1(ReverseChainSingleSubstFormat1),
2295
    Format2(ReverseChainSingleSubstFormat2),
2296
}
2297
2298
impl ReverseChainSingleSubst {
2299
    /// Construct a new `ReverseChainSingleSubstFormat1` subtable
2300
0
    pub fn format_1(
2301
0
        coverage: CoverageTable,
2302
0
        backtrack_coverages: Vec<CoverageTable>,
2303
0
        lookahead_coverages: Vec<CoverageTable>,
2304
0
        substitute_glyph_ids: Vec<GlyphId16>,
2305
0
    ) -> Self {
2306
0
        Self::Format1(ReverseChainSingleSubstFormat1::new(
2307
0
            coverage,
2308
0
            backtrack_coverages,
2309
0
            lookahead_coverages,
2310
0
            substitute_glyph_ids,
2311
0
        ))
2312
0
    }
2313
2314
    /// Construct a new `ReverseChainSingleSubstFormat2` subtable
2315
0
    pub fn format_2(
2316
0
        coverage: CoverageTable,
2317
0
        backtrack_coverages: Vec<CoverageTable>,
2318
0
        lookahead_coverages: Vec<CoverageTable>,
2319
0
        substitute_glyph_ids: Vec<GlyphId24>,
2320
0
    ) -> Self {
2321
0
        Self::Format2(ReverseChainSingleSubstFormat2::new(
2322
0
            coverage,
2323
0
            backtrack_coverages,
2324
0
            lookahead_coverages,
2325
0
            substitute_glyph_ids,
2326
0
        ))
2327
0
    }
2328
}
2329
2330
impl Default for ReverseChainSingleSubst {
2331
0
    fn default() -> Self {
2332
0
        Self::Format1(Default::default())
2333
0
    }
2334
}
2335
2336
impl FontWrite for ReverseChainSingleSubst {
2337
0
    fn write_into(&self, writer: &mut TableWriter) {
2338
0
        match self {
2339
0
            Self::Format1(item) => item.write_into(writer),
2340
0
            Self::Format2(item) => item.write_into(writer),
2341
        }
2342
0
    }
2343
0
    fn table_type(&self) -> TableType {
2344
0
        match self {
2345
0
            Self::Format1(item) => item.table_type(),
2346
0
            Self::Format2(item) => item.table_type(),
2347
        }
2348
0
    }
2349
}
2350
2351
impl Validate for ReverseChainSingleSubst {
2352
0
    fn validate_impl(&self, ctx: &mut ValidationCtx) {
2353
0
        match self {
2354
0
            Self::Format1(item) => item.validate_impl(ctx),
2355
0
            Self::Format2(item) => item.validate_impl(ctx),
2356
        }
2357
0
    }
2358
}
2359
2360
impl FromObjRef<read_fonts::tables::gsub::ReverseChainSingleSubst<'_>> for ReverseChainSingleSubst {
2361
0
    fn from_obj_ref(obj: &read_fonts::tables::gsub::ReverseChainSingleSubst, _: FontData) -> Self {
2362
        use read_fonts::tables::gsub::ReverseChainSingleSubst as ObjRefType;
2363
0
        match obj {
2364
0
            ObjRefType::Format1(item) => ReverseChainSingleSubst::Format1(item.to_owned_table()),
2365
0
            ObjRefType::Format2(item) => ReverseChainSingleSubst::Format2(item.to_owned_table()),
2366
        }
2367
0
    }
2368
}
2369
2370
impl FromTableRef<read_fonts::tables::gsub::ReverseChainSingleSubst<'_>>
2371
    for ReverseChainSingleSubst
2372
{
2373
}
2374
2375
impl ReadArgs for ReverseChainSingleSubst {
2376
    type Args = ();
2377
}
2378
2379
impl<'a> FontRead<'a> for ReverseChainSingleSubst {
2380
0
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2381
0
        <read_fonts::tables::gsub::ReverseChainSingleSubst as FontRead>::read(data)
2382
0
            .map(|x| x.to_owned_table())
2383
0
    }
2384
}
2385
2386
impl From<ReverseChainSingleSubstFormat1> for ReverseChainSingleSubst {
2387
0
    fn from(src: ReverseChainSingleSubstFormat1) -> ReverseChainSingleSubst {
2388
0
        ReverseChainSingleSubst::Format1(src)
2389
0
    }
2390
}
2391
2392
impl From<ReverseChainSingleSubstFormat2> for ReverseChainSingleSubst {
2393
0
    fn from(src: ReverseChainSingleSubstFormat2) -> ReverseChainSingleSubst {
2394
0
        ReverseChainSingleSubst::Format2(src)
2395
0
    }
2396
}