1
//! `GDEF` font table parsing and glyph lookup and layout properties.
2

            
3
pub mod morx;
4

            
5
use std::borrow::Cow;
6
use std::collections::BTreeMap;
7
use std::marker::PhantomData;
8
use std::ops::RangeInclusive;
9
use std::sync::Arc;
10
use std::sync::Mutex;
11

            
12
use log::warn;
13

            
14
use crate::binary::read::{
15
    CheckIndex, ReadArray, ReadBinary, ReadBinaryDep, ReadCache, ReadCtxt, ReadFixedSizeDep,
16
    ReadFrom, ReadScope, ReadScopeOwned,
17
};
18
use crate::binary::{U16Be, U32Be};
19
use crate::context::{ContextLookupHelper, GlyphTable, LookupFlag, MatchContext};
20
use crate::error::ParseError;
21
use crate::tables::variable_fonts::{owned, ItemVariationStore, Tuple};
22
use crate::tables::F2Dot14;
23
use crate::{size, tag, GlyphId, SafeFrom};
24

            
25
pub enum GSUB {}
26
pub enum GPOS {}
27

            
28
pub struct GDEFTable {
29
    pub opt_glyph_classdef: Option<ClassDef>,
30
    // pub opt_attach_list: Option<ReadScope<'a>>,
31
    // pub opt_lig_caret_list: Option<ReadScope<'a>>,
32
    pub opt_mark_attach_classdef: Option<ClassDef>,
33
    // TODO read additional GDEF 1.2 fields
34
    pub opt_mark_glyph_sets: Option<MarkGlyphSets>,
35
    pub opt_item_variation_store: Option<owned::ItemVariationStore>,
36
}
37

            
38
// GSUB and GPOS tables have the same top-level structure
39
pub struct LayoutTable<T> {
40
    pub opt_script_list: Option<ScriptList>,
41
    pub opt_feature_list: Option<FeatureList>,
42
    pub opt_lookup_list: Option<LookupList<T>>,
43
    pub opt_feature_variations: Option<FeatureVariationsOwned>,
44
}
45

            
46
pub struct ScriptList {
47
    script_records: Vec<ScriptRecord>,
48
}
49

            
50
pub struct ScriptRecord {
51
    pub script_tag: u32,
52
    script_table: ScriptTable,
53
}
54

            
55
pub struct ScriptTable {
56
    opt_default_langsys: Option<LangSys>,
57
    langsys_records: Vec<LangSysRecord>,
58
}
59

            
60
pub struct LangSysRecord {
61
    pub langsys_tag: u32,
62
    langsys_table: LangSys,
63
}
64

            
65
pub struct LangSys {
66
    _required_feature_index: u16, // not used during shaping for now
67
    feature_indices: Vec<u16>,
68
}
69

            
70
pub struct FeatureList {
71
    feature_records: Vec<FeatureRecord>,
72
}
73

            
74
pub struct FeatureRecord {
75
    pub feature_tag: u32,
76
    feature_table: FeatureTable,
77
}
78

            
79
#[derive(Clone)]
80
pub struct FeatureTable {
81
    pub lookup_indices: Vec<u16>,
82
}
83

            
84
/// FeatureVariations table.
85
///
86
/// A feature variations table describes variations on the effects of features based on various
87
/// conditions. That is, it allows the default set of lookups for a given feature to be substituted
88
/// with alternates of lookups under particular conditions.
89
///
90
/// <https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#featurevariations-table>
91
pub struct FeatureVariations<'a> {
92
    record_scope: ReadScope<'a>,
93
    records: ReadArray<'a, FeatureVariationRecord>,
94
}
95

            
96
/// Owned version of [FeatureVariations].
97
pub struct FeatureVariationsOwned {
98
    record_scope: ReadScopeOwned,
99
    records: Vec<FeatureVariationRecord>,
100
}
101

            
102
/// A feature variation record containing conditions and substitute feature table.
103
struct FeatureVariationRecord {
104
    /// Offset to a condition set table, from beginning of FeatureVariations table.
105
    ///
106
    /// If the ConditionSet offset is 0, there is no condition set table. This is treated as the
107
    /// universal condition: all contexts are matched.
108
    condition_set_offset: u32,
109
    /// Offset to a feature table substitution table, from beginning of the FeatureVariations
110
    /// table.
111
    ///
112
    /// If the FeatureTableSubstitution offset is 0, there is no feature table substitution table,
113
    /// and no substitutions are made.
114
    feature_table_substitution_offset: u32,
115
}
116

            
117
enum ConditionSet<'a> {
118
    Universal,
119
    Set(ConditionSetTable<'a>),
120
}
121

            
122
struct ConditionSetTable<'a> {
123
    condition_scope: ReadScope<'a>,
124
    /// Array of offsets to condition tables, from beginning of the ConditionSet table.
125
    ///
126
    /// If a given condition set contains no conditions, then it matches all contexts, and the
127
    /// associated feature table substitution is always applied, unless there was a
128
    /// FeatureVariation record earlier in the array with a condition set matching the current
129
    /// context.
130
    condition_offsets: ReadArray<'a, U32Be>,
131
}
132

            
133
#[derive(Debug, Clone)]
134
enum ConditionTable {
135
    Unknown,
136
    /// Condition Table Format 1: Font Variation Axis Range
137
    Format1(ConditionFormat1),
138
}
139

            
140
#[derive(Debug, Copy, Clone)]
141
struct ConditionFormat1 {
142
    /// Index (zero-based) for the variation axis within the 'fvar' table.
143
    axis_index: u16,
144
    /// Minimum value of the font variation instances that satisfy this condition.
145
    filter_range_min_value: F2Dot14,
146
    /// Maximum value of the font variation instances that satisfy this condition.
147
    filter_range_max_value: F2Dot14,
148
}
149

            
150
/// A feature table substitution.
151
pub enum FeatureTableSubstitution<'a> {
152
    /// This substitution performs no substitution.
153
    NoSubstitution,
154
    /// The substitute feature table.
155
    Table(FeatureTableSubstitutionTable<'a>),
156
}
157

            
158
/// Substitute feature table.
159
pub struct FeatureTableSubstitutionTable<'a> {
160
    substitution_scope: ReadScope<'a>,
161
    substitutions: ReadArray<'a, FeatureTableSubstitutionRecord>,
162
}
163

            
164
/// A feature table substitution that indicates the alternate feature table for a feature index.
165
pub struct FeatureTableSubstitutionRecord {
166
    /// The feature table index to match.
167
    feature_index: u16,
168
    /// Offset to an alternate feature table, from start of the FeatureTableSubstitution table.
169
    alternate_feature_offset: u32,
170
}
171

            
172
pub struct LookupList<T> {
173
    scope_owned: ReadScopeOwned,
174
    lookup_offsets: Vec<u16>,
175
    phantom: PhantomData<T>,
176
}
177

            
178
pub struct Lookup<'a, T: LayoutTableType> {
179
    scope: ReadScope<'a>,
180
    lookup_type: LookupType<T>,
181
    pub lookup_flag: LookupFlag,
182
    subtable_offsets: ReadArray<'a, U16Be>,
183
    /// Index (base 0) into GDEF mark glyph sets structure.
184
    ///
185
    /// This field is only present if the USE_MARK_FILTERING_SET lookup flag is set.
186
    mark_filtering_set: Option<u16>,
187
    phantom: PhantomData<T>,
188
}
189

            
190
pub struct ExtensionSubst<'a, T: LayoutTableType> {
191
    scope: ReadScope<'a>,
192
    extension_lookup_type: T::BaseLookupType,
193
    extension_offset: u32,
194
}
195

            
196
pub struct LookupSubtableIter<'a, 'b, T: LayoutTableType> {
197
    lookup: &'b Lookup<'a, T>,
198
    index: usize,
199
}
200

            
201
pub struct ExtensionLookupSubtableIter<'a, 'b, T: LayoutTableType> {
202
    lookup_type: T::BaseLookupType,
203
    iter: LookupSubtableIter<'a, 'b, T>,
204
}
205

            
206
pub enum SmartLookupSubtableIter<'a, 'b, T: LayoutTableType> {
207
    Normal(T::BaseLookupType, LookupSubtableIter<'a, 'b, T>),
208
    Extension(ExtensionLookupSubtableIter<'a, 'b, T>),
209
}
210

            
211
pub enum LookupType<T: LayoutTableType> {
212
    Normal(T::BaseLookupType),
213
    Extension,
214
}
215

            
216
#[derive(Copy, Clone, PartialEq)]
217
pub enum SubstLookupType {
218
    SingleSubst,
219
    MultipleSubst,
220
    AlternateSubst,
221
    LigatureSubst,
222
    ContextSubst,
223
    ChainContextSubst,
224
    ReverseChainSingleSubst,
225
}
226

            
227
#[derive(Copy, Clone, PartialEq)]
228
pub enum PosLookupType {
229
    SinglePos,
230
    PairPos,
231
    CursivePos,
232
    MarkBasePos,
233
    MarkLigPos,
234
    MarkMarkPos,
235
    ContextPos,
236
    ChainContextPos,
237
}
238

            
239
pub enum SubstLookup {
240
    SingleSubst(Vec<SingleSubst>),
241
    MultipleSubst(Vec<MultipleSubst>),
242
    AlternateSubst(Vec<AlternateSubst>),
243
    LigatureSubst(Vec<LigatureSubst>),
244
    ContextSubst(Vec<ContextLookup<GSUB>>),
245
    ChainContextSubst(Vec<ChainContextLookup<GSUB>>),
246
    ReverseChainSingleSubst(Vec<ReverseChainSingleSubst>),
247
}
248

            
249
pub enum PosLookup {
250
    SinglePos(Vec<SinglePos>),
251
    PairPos(Vec<PairPos>),
252
    CursivePos(Vec<CursivePos>),
253
    MarkBasePos(Vec<MarkBasePos>),
254
    MarkLigPos(Vec<MarkLigPos>),
255
    MarkMarkPos(Vec<MarkBasePos>),
256
    ContextPos(Vec<ContextLookup<GPOS>>),
257
    ChainContextPos(Vec<ChainContextLookup<GPOS>>),
258
}
259

            
260
pub trait LayoutTableType: Sized {
261
    type LookupType;
262
    type BaseLookupType: Copy + PartialEq;
263
    fn check_lookup_type(lookup_type: u16) -> Result<LookupType<Self>, ParseError>;
264
}
265

            
266
impl ReadBinary for GDEFTable {
267
    type HostType<'a> = Self;
268

            
269
8208
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
270
8208
        let table = ctxt.scope();
271

            
272
8208
        let major_version = ctxt.read_u16be()?;
273
8208
        ctxt.check(major_version == 1)?;
274
8208
        let minor_version = ctxt.read_u16be()?;
275
8208
        let glyph_classdef_offset = usize::from(ctxt.read_u16be()?);
276
8208
        let _attach_list_offset = usize::from(ctxt.read_u16be()?);
277
8208
        let _lig_caret_list_offset = usize::from(ctxt.read_u16be()?);
278
        // MarkAttachClassDef was added to GDEF in OpenType 1.2 but they did not change the GDEF
279
        // version. This means that it's not possible to know from the version alone whether the
280
        // field should be read. Some implementations use GSUB/GPOS to determine if it should be
281
        // read, others use heuristics based on the offsets in the prior fields.  Based on testing
282
        // of this code and the fact that HarfBuzz _appears_ to always attempt to read the field we
283
        // do the same.
284
        //
285
        // See: https://github.com/yeslogic/prince/issues/297 for more detail.
286
8208
        let mark_attach_classdef_offset = usize::from(ctxt.read_u16be()?);
287

            
288
8208
        let gdef_header_size = match minor_version {
289
8208
            0 | 1 => 6 * size::U16,
290
            2 => 7 * size::U16,
291
            _ => 8 * size::U16,
292
        };
293

            
294
        // Offset to the table of mark glyph set definitions, from beginning of GDEF header (may be NULL).
295
8208
        let mark_glyph_sets_def_offset = if minor_version >= 2 {
296
            usize::from(ctxt.read_u16be()?)
297
        } else {
298
8208
            0
299
        };
300

            
301
        // Offset to the item variation store table, from beginning of GDEF header (may be NULL).
302
8208
        let item_var_store_offset = if minor_version >= 3 {
303
            usize::safe_from(ctxt.read_u32be()?)
304
        } else {
305
8208
            0
306
        };
307

            
308
8208
        let opt_glyph_classdef = if glyph_classdef_offset == 0 {
309
            None
310
8208
        } else if glyph_classdef_offset < gdef_header_size {
311
            None
312
        } else {
313
8208
            Some(table.offset(glyph_classdef_offset).read::<ClassDef>()?)
314
        };
315

            
316
        /*
317
                let opt_attach_list = if attach_list_offset >= table.data().len() {
318
                    return Err(ParseError::BadOffset);
319
                } else if attach_list_offset == 0 {
320
                    None
321
                } else if attach_list_offset < gdef_header_size {
322
                    return Err(ParseError::BadOffset);
323
                } else {
324
                    Some(table.offset(attach_list_offset))
325
                };
326

            
327
                let opt_lig_caret_list = if lig_caret_list_offset >= table.data().len() {
328
                    return Err(ParseError::BadOffset);
329
                } else if lig_caret_list_offset == 0 {
330
                    None
331
                } else if lig_caret_list_offset < gdef_header_size {
332
                    return Err(ParseError::BadOffset);
333
                } else {
334
                    Some(table.offset(lig_caret_list_offset))
335
                };
336
        */
337
8208
        let opt_mark_attach_classdef = if mark_attach_classdef_offset == 0 {
338
594
            None
339
7614
        } else if mark_attach_classdef_offset < gdef_header_size {
340
            None
341
        } else {
342
            Some(
343
7614
                table
344
7614
                    .offset(mark_attach_classdef_offset)
345
7614
                    .read::<ClassDef>()?,
346
            )
347
        };
348

            
349
8208
        let opt_mark_glyph_sets = if mark_glyph_sets_def_offset == 0 {
350
8208
            None
351
        } else if mark_glyph_sets_def_offset < gdef_header_size {
352
            None
353
        } else {
354
            Some(
355
                table
356
                    .offset(mark_glyph_sets_def_offset)
357
                    .read::<MarkGlyphSets>()?,
358
            )
359
        };
360

            
361
8208
        let opt_item_variation_store = (item_var_store_offset > gdef_header_size)
362
8208
            .then(|| {
363
                table
364
                    .offset(item_var_store_offset)
365
                    .read::<ItemVariationStore<'_>>()
366
                    .and_then(|store| store.try_to_owned())
367
            })
368
8208
            .transpose()?;
369

            
370
8208
        Ok(GDEFTable {
371
8208
            opt_glyph_classdef,
372
8208
            // opt_attach_list,
373
8208
            // opt_lig_caret_list,
374
8208
            opt_mark_attach_classdef,
375
8208
            opt_mark_glyph_sets,
376
8208
            opt_item_variation_store,
377
8208
        })
378
8208
    }
379
}
380

            
381
impl<T> ReadBinary for LayoutTable<T> {
382
    type HostType<'a> = Self;
383

            
384
10812
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
385
10812
        let table = ctxt.scope();
386

            
387
10812
        let major_version = ctxt.read_u16be()?;
388
10812
        let minor_version = ctxt.read_u16be()?;
389
10812
        let script_list_offset = usize::from(ctxt.read_u16be()?);
390
10812
        let feature_list_offset = usize::from(ctxt.read_u16be()?);
391
10812
        let lookup_list_offset = usize::from(ctxt.read_u16be()?);
392

            
393
        // We handle versions 1.x
394
10812
        if major_version != 1 {
395
            return Err(ParseError::BadVersion);
396
10812
        }
397

            
398
10812
        let opt_script_list = if script_list_offset >= table.data().len() {
399
            return Err(ParseError::BadOffset);
400
10812
        } else if script_list_offset == 0 {
401
            None
402
        } else {
403
10812
            Some(table.offset(script_list_offset).read::<ScriptList>()?)
404
        };
405

            
406
10812
        let opt_feature_list = if feature_list_offset >= table.data().len() {
407
            return Err(ParseError::BadOffset);
408
10812
        } else if feature_list_offset == 0 {
409
            None
410
        } else {
411
10812
            Some(table.offset(feature_list_offset).read::<FeatureList>()?)
412
        };
413

            
414
10812
        let opt_lookup_list = if lookup_list_offset >= table.data().len() {
415
            return Err(ParseError::BadOffset);
416
10812
        } else if lookup_list_offset == 0 {
417
            None
418
        } else {
419
10812
            Some(table.offset(lookup_list_offset).read::<LookupList<T>>()?)
420
        };
421

            
422
        // Version 1.1 also includes an offset to a FeatureVariations table.
423
10812
        let opt_feature_variations = (minor_version > 0)
424
10812
            .then(|| ctxt.read_u32be())
425
10812
            .transpose()?
426
10812
            .filter(|offset| *offset > 0)
427
10812
            .map(|offset| {
428
                table
429
                    .offset(usize::safe_from(offset))
430
                    .ctxt()
431
                    .read::<FeatureVariationsOwned>()
432
            })
433
10812
            .transpose()?;
434

            
435
10812
        Ok(LayoutTable {
436
10812
            opt_script_list,
437
10812
            opt_feature_list,
438
10812
            opt_lookup_list,
439
10812
            opt_feature_variations,
440
10812
        })
441
10812
    }
442
}
443

            
444
impl ReadBinary for ScriptList {
445
    type HostType<'a> = Self;
446

            
447
11016
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
448
11016
        let scope = ctxt.scope();
449
11016
        let script_count = usize::from(ctxt.read_u16be()?);
450
11016
        let script_records = ctxt
451
11016
            .read_array_dep::<ScriptRecord>(script_count, scope)?
452
11016
            .read_to_vec()?;
453
11016
        Ok(ScriptList { script_records })
454
11016
    }
455
}
456

            
457
impl ReadBinaryDep for ScriptRecord {
458
    type Args<'a> = ReadScope<'a>;
459
    type HostType<'a> = ScriptRecord;
460

            
461
52812
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, scope: Self::Args<'a>) -> Result<Self, ParseError> {
462
52812
        let script_tag = ctxt.read_u32be()?;
463
52812
        let script_offset = ctxt.read_u16be()?;
464
52812
        let script_table = scope
465
52812
            .offset(usize::from(script_offset))
466
52812
            .read::<ScriptTable>()?;
467
52812
        Ok(ScriptRecord {
468
52812
            script_tag,
469
52812
            script_table,
470
52812
        })
471
52812
    }
472
}
473

            
474
impl ReadFixedSizeDep for ScriptRecord {
475
63828
    fn size(_scope: Self::Args<'_>) -> usize {
476
63828
        size::U32 + size::U16
477
63828
    }
478
}
479

            
480
impl ReadBinary for ScriptTable {
481
    type HostType<'a> = Self;
482

            
483
52812
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
484
52812
        let scope = ctxt.scope();
485
52812
        let default_langsys_offset = usize::from(ctxt.read_u16be()?);
486
52812
        let opt_default_langsys = if default_langsys_offset != 0 {
487
52812
            Some(scope.offset(default_langsys_offset).read::<LangSys>()?)
488
        } else {
489
            None
490
        };
491
52812
        let langsys_count = usize::from(ctxt.read_u16be()?);
492
52812
        let langsys_records = ctxt
493
52812
            .read_array_dep::<LangSysRecord>(langsys_count, scope)?
494
52812
            .read_to_vec()?;
495
52812
        Ok(ScriptTable {
496
52812
            opt_default_langsys,
497
52812
            langsys_records,
498
52812
        })
499
52812
    }
500
}
501

            
502
impl ReadBinary for FeatureList {
503
    type HostType<'a> = Self;
504

            
505
11016
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
506
11016
        let scope = ctxt.scope();
507
11016
        let feature_count = usize::from(ctxt.read_u16be()?);
508
11016
        let feature_records = ctxt
509
11016
            .read_array_dep::<FeatureRecord>(feature_count, scope)?
510
11016
            .read_to_vec()?;
511
11016
        Ok(FeatureList { feature_records })
512
11016
    }
513
}
514

            
515
impl FeatureList {
516
284148
    pub fn nth_feature_record(&self, index: usize) -> Result<&FeatureRecord, ParseError> {
517
284148
        self.feature_records.check_index(index)?;
518
284148
        Ok(&self.feature_records[index])
519
284148
    }
520
}
521

            
522
impl FeatureRecord {
523
    pub fn feature_table(&self) -> &FeatureTable {
524
        &self.feature_table
525
    }
526
}
527

            
528
impl ReadBinaryDep for FeatureRecord {
529
    type Args<'a> = ReadScope<'a>;
530
    type HostType<'a> = FeatureRecord;
531

            
532
745254
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, scope: Self::Args<'a>) -> Result<Self, ParseError> {
533
745254
        let feature_tag = ctxt.read_u32be()?;
534
745254
        let feature_offset = ctxt.read_u16be()?;
535
745254
        let feature_table = scope
536
745254
            .offset(usize::from(feature_offset))
537
745254
            .read::<FeatureTable>()?;
538
745254
        Ok(FeatureRecord {
539
745254
            feature_tag,
540
745254
            feature_table,
541
745254
        })
542
745254
    }
543
}
544

            
545
impl ReadFixedSizeDep for FeatureRecord {
546
756270
    fn size(_scope: Self::Args<'_>) -> usize {
547
756270
        size::U32 + size::U16
548
756270
    }
549
}
550

            
551
impl ReadBinary for FeatureTable {
552
    type HostType<'a> = Self;
553

            
554
745254
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
555
745254
        let _feature_params = ctxt.read_u16be()?;
556
745254
        let lookup_index_count = usize::from(ctxt.read_u16be()?);
557
745254
        let lookup_indices = ctxt.read_array::<U16Be>(lookup_index_count)?.to_vec();
558
745254
        Ok(FeatureTable { lookup_indices })
559
745254
    }
560
}
561

            
562
impl ReadBinary for FeatureVariations<'_> {
563
    type HostType<'a> = FeatureVariations<'a>;
564

            
565
    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
566
        let record_scope = ctxt.scope();
567
        let major_version = ctxt.read_u16be()?;
568
        ctxt.check_version(major_version == 1)?;
569
        let _minor_version = ctxt.read_u16be()?;
570
        let record_count = ctxt.read_u32be()?;
571
        let records = ctxt.read_array(usize::safe_from(record_count))?;
572

            
573
        Ok(FeatureVariations {
574
            record_scope,
575
            records,
576
        })
577
    }
578
}
579

            
580
impl FeatureVariationsOwned {
581
    /// Match this record against a variation tuple and return the feature table substitution if it matches.
582
    pub fn matches<'a>(
583
        &'a self,
584
        tuple: Tuple<'a>,
585
    ) -> Result<Option<FeatureTableSubstitution<'a>>, ParseError> {
586
        for rec in &self.records {
587
            // The first feature variation record for which the condition set matches the runtime
588
            // context will be considered as a candidate: if the version of the
589
            // FeatureTableSubstitution table is supported, then this feature variation record will
590
            // be used, and no additional feature variation records will be considered. If the
591
            // version of the FeatureTableSubstitution table is not supported, then this feature
592
            // variation record is rejected and processing will move to the next feature variation
593
            // record.
594
            //
595
            // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#featurevariations-table
596
            match rec.matches(self.record_scope.scope(), tuple) {
597
                substitution @ Ok(Some(_)) => return substitution,
598
                Ok(None) | Err(ParseError::BadVersion) => continue,
599
                err @ Err(_) => return err,
600
            }
601
        }
602

            
603
        Ok(None)
604
    }
605
}
606

            
607
impl ReadBinary for FeatureVariationsOwned {
608
    type HostType<'a> = FeatureVariationsOwned;
609

            
610
    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
611
        let feature_variations = ctxt.read::<FeatureVariations<'_>>()?;
612

            
613
        Ok(FeatureVariationsOwned {
614
            record_scope: ReadScopeOwned::new(feature_variations.record_scope),
615
            records: feature_variations.records.to_vec(),
616
        })
617
    }
618
}
619

            
620
impl FeatureVariationRecord {
621
    /// Match this record against a variation tuple and return the feature table substitution if it matches.
622
    pub fn matches<'a>(
623
        &self,
624
        scope: ReadScope<'a>,
625
        tuple: Tuple<'a>,
626
    ) -> Result<Option<FeatureTableSubstitution<'a>>, ParseError> {
627
        if self.condition_set(scope)?.matches(tuple) {
628
            self.feature_table_substitution(scope).map(Some)
629
        } else {
630
            Ok(None)
631
        }
632
    }
633

            
634
    fn condition_set<'a>(&self, scope: ReadScope<'a>) -> Result<ConditionSet<'a>, ParseError> {
635
        // If the ConditionSet offset is 0, there is no condition set table. This is treated as
636
        // the universal condition: all contexts are matched.
637
        if self.condition_set_offset == 0 {
638
            Ok(ConditionSet::Universal)
639
        } else {
640
            scope
641
                .offset(usize::safe_from(self.condition_set_offset))
642
                .read::<ConditionSetTable<'_>>()
643
                .map(ConditionSet::Set)
644
        }
645
    }
646

            
647
    fn feature_table_substitution<'a>(
648
        &self,
649
        scope: ReadScope<'a>,
650
    ) -> Result<FeatureTableSubstitution<'a>, ParseError> {
651
        // If the FeatureTableSubstitution offset is 0, there is no feature table substitution table,
652
        // and no substitutions are made.
653
        if self.feature_table_substitution_offset == 0 {
654
            Ok(FeatureTableSubstitution::NoSubstitution)
655
        } else {
656
            scope
657
                .offset(usize::safe_from(self.feature_table_substitution_offset))
658
                .read::<FeatureTableSubstitutionTable<'_>>()
659
                .map(FeatureTableSubstitution::Table)
660
        }
661
    }
662
}
663

            
664
impl ReadFrom for FeatureVariationRecord {
665
    type ReadType = (U32Be, U32Be);
666
    fn read_from((condition_set_offset, feature_table_substitution_offset): (u32, u32)) -> Self {
667
        FeatureVariationRecord {
668
            condition_set_offset,
669
            feature_table_substitution_offset,
670
        }
671
    }
672
}
673

            
674
impl FeatureTableSubstitution<'_> {
675
    /// Perform feature table substitution for the supplied `feature_index`.
676
50112
    pub fn substitute(&self, feature_index: u16) -> Option<FeatureTable> {
677
50112
        match self {
678
50112
            FeatureTableSubstitution::NoSubstitution => None,
679
            FeatureTableSubstitution::Table(table) => {
680
                let mut substitution_record = None;
681
                for rec in table.substitutions.iter() {
682
                    if rec.feature_index == feature_index {
683
                        substitution_record = Some(rec);
684
                        break;
685
                    } else if rec.feature_index > feature_index {
686
                        // "If a record is encountered with a higher feature index value,
687
                        // stop searching for that feature index; no substitution is made."
688
                        break;
689
                    }
690
                }
691
                let substitution_record = substitution_record?;
692

            
693
                table
694
                    .substitution_scope
695
                    .offset(usize::safe_from(
696
                        substitution_record.alternate_feature_offset,
697
                    ))
698
                    .read::<FeatureTable>()
699
                    .ok()
700
            }
701
        }
702
50112
    }
703
}
704

            
705
impl ReadBinary for FeatureTableSubstitutionTable<'_> {
706
    type HostType<'a> = FeatureTableSubstitutionTable<'a>;
707

            
708
    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
709
        let substitution_scope = ctxt.scope();
710
        let major_version = ctxt.read_u16be()?;
711
        ctxt.check_version(major_version == 1)?;
712
        let _minor_version = ctxt.read_u16be()?;
713
        let substitution_count = ctxt.read_u16be()?;
714
        let substitutions = ctxt.read_array(usize::from(substitution_count))?;
715

            
716
        Ok(FeatureTableSubstitutionTable {
717
            substitution_scope,
718
            substitutions,
719
        })
720
    }
721
}
722

            
723
impl ReadFrom for FeatureTableSubstitutionRecord {
724
    type ReadType = (U16Be, U32Be);
725
    fn read_from((feature_index, alternate_feature_offset): (u16, u32)) -> Self {
726
        FeatureTableSubstitutionRecord {
727
            feature_index,
728
            alternate_feature_offset,
729
        }
730
    }
731
}
732

            
733
impl ConditionSet<'_> {
734
    fn matches(&self, tuple: Tuple<'_>) -> bool {
735
        match self {
736
            ConditionSet::Universal => true,
737
            ConditionSet::Set(set) => set.matches(tuple),
738
        }
739
    }
740
}
741

            
742
impl ConditionSetTable<'_> {
743
    fn matches(&self, tuple: Tuple<'_>) -> bool {
744
        // For a given condition set, conditions are conjunctively related (boolean AND): all of
745
        // the specified conditions must be met in order for the associated feature table
746
        // substitution to be applied. A condition set does not need to specify conditional values
747
        // for all possible factors. If no values are specified for some factor, then the condition
748
        // set matches all runtime values for that factor.
749
        self.condition_offsets
750
            .iter()
751
            .map(|offset| {
752
                self.condition_scope
753
                    .offset(usize::safe_from(offset))
754
                    .read::<ConditionTable>()
755
            })
756
            .all(|table| table.map(|table| table.matches(tuple)).unwrap_or(false))
757
    }
758
}
759

            
760
impl ReadBinary for ConditionSetTable<'_> {
761
    type HostType<'a> = ConditionSetTable<'a>;
762

            
763
    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
764
        let condition_scope = ctxt.scope();
765
        let condition_count = ctxt.read_u16be()?;
766
        let conditions = ctxt.read_array(usize::from(condition_count))?;
767

            
768
        Ok(ConditionSetTable {
769
            condition_scope,
770
            condition_offsets: conditions,
771
        })
772
    }
773
}
774

            
775
impl ConditionTable {
776
    fn matches(&self, tuple: Tuple<'_>) -> bool {
777
        match self {
778
            // New condition table formats for other condition qualifiers may be added in the
779
            // future. If a layout engine encounters a condition table with an unrecognized format,
780
            // it should fail to match the condition set, but continue to test other condition
781
            // sets. In this way, new condition formats can be defined and used in fonts that can
782
            // work in a backward-compatible way in existing implementations.
783
            ConditionTable::Unknown => false,
784
            ConditionTable::Format1(condition_set) => {
785
                // A font variation axis range condition is met if the currently-selected variation
786
                // instance has a value for the given axis that is greater than or equal to the
787
                // filterRangeMinValue, and that is less than or equal to the filterRangeMaxValue.
788
                let axis_value = match tuple.get(condition_set.axis_index) {
789
                    Some(value) => value,
790
                    None => return false,
791
                };
792
                (condition_set.filter_range_min_value..=condition_set.filter_range_max_value)
793
                    .contains(&axis_value)
794
            }
795
        }
796
    }
797
}
798

            
799
impl ReadBinary for ConditionTable {
800
    type HostType<'a> = Self;
801

            
802
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
803
        let format = ctxt.read_u16be()?;
804

            
805
        match format {
806
            1 => Ok(ConditionTable::Format1(ctxt.read::<ConditionFormat1>()?)),
807
            _ => Ok(ConditionTable::Unknown),
808
        }
809
    }
810
}
811

            
812
impl ReadFrom for ConditionFormat1 {
813
    type ReadType = (U16Be, F2Dot14, F2Dot14);
814
    fn read_from(
815
        (axis_index, filter_range_min_value, filter_range_max_value): (u16, F2Dot14, F2Dot14),
816
    ) -> Self {
817
        ConditionFormat1 {
818
            axis_index,
819
            filter_range_min_value,
820
            filter_range_max_value,
821
        }
822
    }
823
}
824

            
825
impl<T> ReadBinary for LookupList<T> {
826
    type HostType<'a> = Self;
827

            
828
10812
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
829
10812
        let scope_owned = ReadScopeOwned::new(ctxt.scope());
830
10812
        let lookup_count = usize::from(ctxt.read_u16be()?);
831
10812
        let lookup_offsets = ctxt.read_array::<U16Be>(lookup_count)?.to_vec();
832
10812
        Ok(LookupList {
833
10812
            scope_owned,
834
10812
            lookup_offsets,
835
10812
            phantom: PhantomData,
836
10812
        })
837
10812
    }
838
}
839

            
840
impl ReadBinary for LangSys {
841
    type HostType<'a> = Self;
842

            
843
91692
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
844
91692
        let _reserved_lookup_order = ctxt.read_u16be()?;
845
91692
        let _required_feature_index = ctxt.read_u16be()?;
846
91692
        let feature_index_count = usize::from(ctxt.read_u16be()?);
847
91692
        let feature_indices = ctxt.read_array::<U16Be>(feature_index_count)?.to_vec();
848
91692
        Ok(LangSys {
849
91692
            _required_feature_index,
850
91692
            feature_indices,
851
91692
        })
852
91692
    }
853
}
854

            
855
impl LangSysRecord {
856
    pub fn langsys_table(&self) -> &LangSys {
857
        &self.langsys_table
858
    }
859
}
860

            
861
impl LangSys {
862
5238
    pub fn feature_indices_iter(&self) -> impl Iterator<Item = &u16> {
863
5238
        self.feature_indices.iter()
864
5238
    }
865
}
866

            
867
impl<T> LayoutTable<T> {
868
    pub fn find_script(&self, script_tag: u32) -> Result<Option<&ScriptTable>, ParseError> {
869
        if let Some(ref script_list) = self.opt_script_list {
870
            if let Some(script_table) = script_list.find_script(script_tag)? {
871
                return Ok(Some(script_table));
872
            }
873
        }
874
        Ok(None)
875
    }
876

            
877
35640
    pub fn find_script_or_default(
878
35640
        &self,
879
35640
        script_tag: u32,
880
35640
    ) -> Result<Option<&ScriptTable>, ParseError> {
881
35640
        if let Some(ref script_list) = self.opt_script_list {
882
35640
            if let Some(script_table) = script_list.find_script(script_tag)? {
883
33750
                return Ok(Some(script_table));
884
            } else {
885
1890
                return script_list.find_script(tag::DFLT);
886
            }
887
        }
888
        Ok(None)
889
35640
    }
890

            
891
108486
    pub fn find_langsys_feature(
892
108486
        &self,
893
108486
        langsys: &LangSys,
894
108486
        feature_tag: u32,
895
108486
        feature_variations: Option<&FeatureTableSubstitution<'_>>,
896
108486
    ) -> Result<Option<Cow<'_, FeatureTable>>, ParseError> {
897
108486
        let feature_variations =
898
108486
            feature_variations.unwrap_or(&FeatureTableSubstitution::NoSubstitution);
899
108486
        if let Some(ref feature_list) = self.opt_feature_list {
900
178686
            for feature_index in langsys.feature_indices.iter().copied() {
901
178686
                let feature_record = feature_list.nth_feature_record(usize::from(feature_index))?;
902
178686
                if feature_record.feature_tag == feature_tag {
903
                    // see if feature index is in feature_variations
904
50112
                    let feature_table = feature_variations
905
50112
                        .substitute(feature_index)
906
50112
                        .map(Cow::Owned)
907
50112
                        .unwrap_or(Cow::Borrowed(&feature_record.feature_table));
908

            
909
50112
                    return Ok(Some(feature_table));
910
128574
                }
911
            }
912
        }
913
58374
        Ok(None)
914
108486
    }
915

            
916
105462
    pub fn feature_by_index(&self, feature_index: u16) -> Result<&FeatureRecord, ParseError> {
917
105462
        if let Some(ref feature_list) = self.opt_feature_list {
918
105462
            let feature_record = feature_list.nth_feature_record(usize::from(feature_index))?;
919
105462
            Ok(feature_record)
920
        } else {
921
            Err(ParseError::BadIndex)
922
        }
923
105462
    }
924

            
925
71172
    pub fn feature_variations<'a>(
926
71172
        &'a self,
927
71172
        tuple: Option<Tuple<'a>>,
928
71172
    ) -> Result<Option<FeatureTableSubstitution<'a>>, ParseError> {
929
71172
        match (tuple, self.opt_feature_variations.as_ref()) {
930
            (Some(tuple), Some(feature_variations)) => feature_variations.matches(tuple),
931
71172
            _ => Ok(None),
932
        }
933
71172
    }
934
}
935

            
936
impl ScriptList {
937
    pub fn script_records(&self) -> &[ScriptRecord] {
938
        &self.script_records
939
    }
940

            
941
37530
    pub fn find_script(&self, script_tag: u32) -> Result<Option<&ScriptTable>, ParseError> {
942
206280
        for script_record in &self.script_records {
943
202500
            if script_record.script_tag == script_tag {
944
33750
                return Ok(Some(&script_record.script_table));
945
168750
            }
946
        }
947
3780
        Ok(None)
948
37530
    }
949
}
950

            
951
impl ScriptRecord {
952
    pub fn script_table(&self) -> &ScriptTable {
953
        &self.script_table
954
    }
955
}
956

            
957
impl ScriptTable {
958
33750
    pub fn default_langsys_record(&self) -> Option<&LangSys> {
959
33750
        self.opt_default_langsys.as_ref()
960
33750
    }
961

            
962
    pub fn langsys_records(&self) -> &[LangSysRecord] {
963
        &self.langsys_records
964
    }
965

            
966
33750
    pub fn find_langsys(&self, langsys_tag: u32) -> Result<Option<&LangSys>, ParseError> {
967
141426
        for langsys_record in &self.langsys_records {
968
107676
            if langsys_record.langsys_tag == langsys_tag {
969
                return Ok(Some(&langsys_record.langsys_table));
970
107676
            }
971
        }
972
33750
        Ok(None)
973
33750
    }
974

            
975
33750
    pub fn find_langsys_or_default(
976
33750
        &self,
977
33750
        opt_lang_tag: Option<u32>,
978
33750
    ) -> Result<Option<&LangSys>, ParseError> {
979
33750
        match opt_lang_tag {
980
33750
            Some(lang_tag) => match self.find_langsys(lang_tag)? {
981
                Some(langsys_record) => Ok(Some(langsys_record)),
982
33750
                None => Ok(self.default_langsys_record()),
983
            },
984
            None => Ok(self.default_langsys_record()),
985
        }
986
33750
    }
987
}
988

            
989
impl ReadBinaryDep for LangSysRecord {
990
    type Args<'a> = ReadScope<'a>;
991
    type HostType<'a> = LangSysRecord;
992

            
993
38880
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, scope: Self::Args<'a>) -> Result<Self, ParseError> {
994
38880
        let langsys_tag = ctxt.read_u32be()?;
995
38880
        let langsys_offset = ctxt.read_u16be()?;
996
38880
        let langsys_table = scope
997
38880
            .offset(usize::from(langsys_offset))
998
38880
            .read::<LangSys>()?;
999
38880
        Ok(LangSysRecord {
38880
            langsys_tag,
38880
            langsys_table,
38880
        })
38880
    }
}
impl ReadFixedSizeDep for LangSysRecord {
91692
    fn size(_scope: Self::Args<'_>) -> usize {
91692
        size::U32 + size::U16
91692
    }
}
impl<T: LayoutTableType> LookupList<T> {
61506
    pub fn lookup(&self, lookup_index: usize) -> Result<Lookup<'_, T>, ParseError> {
61506
        self.lookup_offsets.check_index(lookup_index)?;
61506
        let lookup_table_offset = self.lookup_offsets[lookup_index];
61506
        self.scope_owned
61506
            .scope()
61506
            .offset(usize::from(lookup_table_offset))
61506
            .read::<Lookup<'_, T>>()
61506
    }
}
impl LookupList<GSUB> {
175122
    pub fn lookup_cache_gsub(
175122
        &self,
175122
        cache: &LayoutCache<GSUB>,
175122
        lookup_index: usize,
175122
    ) -> Result<Arc<LookupCacheItem<SubstLookup>>, ParseError> {
175122
        if let Some(Some(cached)) = cache.lookup_cache.lock().unwrap().get(lookup_index) {
129924
            return Ok(Arc::clone(cached));
45198
        }
45198
        let lookup_cache_item = Arc::new(self.read_lookup_gsub(cache, lookup_index)?);
45198
        let mut lookup_vec = cache.lookup_cache.lock().unwrap();
45198
        if lookup_index >= lookup_vec.len() {
45198
            lookup_vec.resize(lookup_index + 1, None);
45198
        }
45198
        Ok(Arc::clone(
45198
            lookup_vec[lookup_index].get_or_insert(lookup_cache_item),
45198
        ))
175122
    }
45198
    fn read_lookup_gsub(
45198
        &self,
45198
        cache: &LayoutCache<GSUB>,
45198
        lookup_index: usize,
45198
    ) -> Result<LookupCacheItem<SubstLookup>, ParseError> {
45198
        let lookup = self.lookup(lookup_index)?;
45198
        let lookup_flag = lookup.lookup_flag;
45198
        let lookup_type = lookup.get_lookup_type()?;
45198
        let lookup_subtables = match lookup_type {
            SubstLookupType::SingleSubst => {
                SubstLookup::SingleSubst(lookup.read_subtables::<SingleSubst>(cache)?)
            }
            SubstLookupType::MultipleSubst => {
                SubstLookup::MultipleSubst(lookup.read_subtables::<MultipleSubst>(cache)?)
            }
            SubstLookupType::AlternateSubst => {
                SubstLookup::AlternateSubst(lookup.read_subtables::<AlternateSubst>(cache)?)
            }
            SubstLookupType::LigatureSubst => {
19980
                SubstLookup::LigatureSubst(lookup.read_subtables::<LigatureSubst>(cache)?)
            }
            SubstLookupType::ContextSubst => {
                SubstLookup::ContextSubst(lookup.read_subtables::<ContextLookup<GSUB>>(cache)?)
            }
            SubstLookupType::ChainContextSubst => SubstLookup::ChainContextSubst(
25218
                lookup.read_subtables::<ChainContextLookup<GSUB>>(cache)?,
            ),
            SubstLookupType::ReverseChainSingleSubst => SubstLookup::ReverseChainSingleSubst(
                lookup.read_subtables::<ReverseChainSingleSubst>(cache)?,
            ),
        };
45198
        Ok(LookupCacheItem {
45198
            lookup_flag,
45198
            mark_filtering_set: lookup.mark_filtering_set,
45198
            lookup_subtables,
45198
        })
45198
    }
}
impl LookupList<GPOS> {
81216
    pub fn lookup_cache_gpos(
81216
        &self,
81216
        cache: &LayoutCache<GPOS>,
81216
        lookup_index: usize,
81216
    ) -> Result<Arc<LookupCacheItem<PosLookup>>, ParseError> {
81216
        if let Some(Some(cached)) = cache.lookup_cache.lock().unwrap().get(lookup_index) {
64908
            return Ok(Arc::clone(cached));
16308
        }
16308
        let lookup_cache_item = Arc::new(self.read_lookup_gpos(cache, lookup_index)?);
16308
        let mut lookup_vec = cache.lookup_cache.lock().unwrap();
16308
        if lookup_index >= lookup_vec.len() {
16308
            lookup_vec.resize(lookup_index + 1, None);
16308
        }
16308
        Ok(Arc::clone(
16308
            lookup_vec[lookup_index].get_or_insert(lookup_cache_item),
16308
        ))
81216
    }
16308
    fn read_lookup_gpos(
16308
        &self,
16308
        cache: &LayoutCache<GPOS>,
16308
        lookup_index: usize,
16308
    ) -> Result<LookupCacheItem<PosLookup>, ParseError> {
16308
        let lookup = self.lookup(lookup_index)?;
16308
        let lookup_flag = lookup.lookup_flag;
16308
        let lookup_type = lookup.get_lookup_type()?;
16308
        let lookup_subtables = match lookup_type {
            PosLookupType::SinglePos => {
                PosLookup::SinglePos(lookup.read_subtables::<SinglePos>(cache)?)
            }
15390
            PosLookupType::PairPos => PosLookup::PairPos(lookup.read_subtables::<PairPos>(cache)?),
            PosLookupType::CursivePos => {
                PosLookup::CursivePos(lookup.read_subtables::<CursivePos>(cache)?)
            }
            PosLookupType::MarkBasePos => {
324
                PosLookup::MarkBasePos(lookup.read_subtables::<MarkBasePos>(cache)?)
            }
            PosLookupType::MarkLigPos => {
270
                PosLookup::MarkLigPos(lookup.read_subtables::<MarkLigPos>(cache)?)
            }
            PosLookupType::MarkMarkPos => {
324
                PosLookup::MarkMarkPos(lookup.read_subtables::<MarkBasePos>(cache)?)
            }
            PosLookupType::ContextPos => {
                PosLookup::ContextPos(lookup.read_subtables::<ContextLookup<GPOS>>(cache)?)
            }
            PosLookupType::ChainContextPos => PosLookup::ChainContextPos(
                lookup.read_subtables::<ChainContextLookup<GPOS>>(cache)?,
            ),
        };
16308
        Ok(LookupCacheItem {
16308
            lookup_flag,
16308
            mark_filtering_set: lookup.mark_filtering_set,
16308
            lookup_subtables,
16308
        })
16308
    }
}
impl<'a, T: LayoutTableType + 'static> Lookup<'a, T> {
123012
    fn subtable_iter<'b>(&'b self) -> LookupSubtableIter<'a, 'b, T> {
123012
        LookupSubtableIter {
123012
            lookup: self,
123012
            index: 0,
123012
        }
123012
    }
123012
    pub fn smart_subtable_iter<'b>(
123012
        &'b self,
123012
    ) -> Result<SmartLookupSubtableIter<'a, 'b, T>, ParseError> {
123012
        match self.lookup_type {
123012
            LookupType::Normal(lookup_type) => {
123012
                let iter = self.subtable_iter();
123012
                Ok(SmartLookupSubtableIter::Normal(lookup_type, iter))
            }
            LookupType::Extension => {
                if let Some(subtable) = self.subtable_iter().next() {
                    let ext_subtable = subtable.read::<ExtensionSubst<'_, T>>()?;
                    let lookup_type = ext_subtable.extension_lookup_type;
                    let iter = ExtensionLookupSubtableIter {
                        lookup_type,
                        iter: self.subtable_iter(),
                    };
                    Ok(SmartLookupSubtableIter::Extension(iter))
                } else {
                    Err(ParseError::BadValue)
                }
            }
        }
123012
    }
61506
    pub fn get_lookup_type(&self) -> Result<T::BaseLookupType, ParseError> {
61506
        let mut subtables = self.smart_subtable_iter()?;
61506
        let lookup_type = subtables.get_lookup_type();
61506
        Ok(lookup_type)
61506
    }
    pub fn find_subtable<S>(
        &self,
        f: impl Fn(ReadScope<'a>) -> Result<Option<S>, ParseError>,
    ) -> Result<Option<S>, ParseError> {
        let subtable_iter = self.smart_subtable_iter()?;
        for subtable_result in subtable_iter {
            let subtable = subtable_result?;
            match f(subtable) {
                Ok(Some(t)) => return Ok(Some(t)),
                Ok(None) => {}
                Err(err) => warn!("skipping invalid subtable: {}", err),
            }
        }
        Ok(None)
    }
61506
    pub fn read_subtables<S: ReadBinaryDep>(
61506
        &self,
61506
        args: S::Args<'a>,
61506
    ) -> Result<Vec<S::HostType<'a>>, ParseError> {
61506
        let mut subtables = Vec::new();
61506
        let subtable_iter = self.smart_subtable_iter()?;
270378
        for subtable_result in subtable_iter {
208872
            match subtable_result?.read_dep::<S>(args) {
208872
                Ok(subtable) => subtables.push(subtable),
                Err(err) => warn!("skipping invalid subtable: {}", err),
            }
        }
61506
        Ok(subtables)
61506
    }
}
impl<T: LayoutTableType> ReadBinary for Lookup<'_, T> {
    type HostType<'a> = Lookup<'a, T>;
61506
    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
61506
        let scope = ctxt.scope();
61506
        let lookup_type = ctxt.read_u16be()?;
61506
        let lookup_type = T::check_lookup_type(lookup_type)?;
61506
        let lookup_flag = LookupFlag(ctxt.read_u16be()?);
61506
        let subtable_count = usize::from(ctxt.read_u16be()?);
61506
        let subtable_offsets = ctxt.read_array::<U16Be>(subtable_count)?;
61506
        let mark_filtering_set = if lookup_flag.use_mark_filtering_set() {
            Some(ctxt.read_u16be()?)
        } else {
61506
            None
        };
61506
        Ok(Lookup {
61506
            scope,
61506
            lookup_type,
61506
            lookup_flag,
61506
            subtable_offsets,
61506
            phantom: PhantomData,
61506
            mark_filtering_set,
61506
        })
61506
    }
}
impl<T: LayoutTableType> ReadBinary for ExtensionSubst<'_, T> {
    type HostType<'a> = ExtensionSubst<'a, T>;
    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
        let scope = ctxt.scope();
        let subst_format = ctxt.read_u16be()?;
        match subst_format {
            1 => {
                let extension_lookup_type = ctxt.read_u16be()?;
                let extension_lookup_type = match T::check_lookup_type(extension_lookup_type)? {
                    LookupType::Normal(lookup_type) => lookup_type,
                    LookupType::Extension => return Err(ParseError::BadVersion),
                };
                let extension_offset = ctxt.read_u32be()?;
                Ok(ExtensionSubst {
                    scope,
                    extension_lookup_type,
                    extension_offset,
                })
            }
            _ => Err(ParseError::BadVersion),
        }
    }
}
impl<'a, T: LayoutTableType> Iterator for LookupSubtableIter<'a, '_, T> {
    type Item = ReadScope<'a>;
270378
    fn next(&mut self) -> Option<ReadScope<'a>> {
270378
        let subtable_offset = self.lookup.subtable_offsets.get_item(self.index)?;
208872
        let subtable = self.lookup.scope.offset(usize::from(subtable_offset));
208872
        self.index += 1;
208872
        Some(subtable)
270378
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.lookup.subtable_offsets.len();
        if self.index < len {
            let upper = len - self.index;
            (upper, Some(upper))
        } else {
            (0, Some(0))
        }
    }
}
impl<'a, T: LayoutTableType> Iterator for ExtensionLookupSubtableIter<'a, '_, T> {
    type Item = Result<ReadScope<'a>, ParseError>;
    fn next(&mut self) -> Option<Result<ReadScope<'a>, ParseError>> {
        if let Some(subtable) = self.iter.next() {
            match subtable.read::<ExtensionSubst<'_, T>>() {
                Ok(ext_subtable) => {
                    if ext_subtable.extension_lookup_type != self.lookup_type {
                        return Some(Err(ParseError::BadVersion));
                    }
                    let subtable = ext_subtable
                        .scope
                        .offset(ext_subtable.extension_offset as usize);
                    Some(Ok(subtable))
                }
                Err(err) => Some(Err(err)),
            }
        } else {
            None
        }
    }
}
impl<'a, T: LayoutTableType> Iterator for SmartLookupSubtableIter<'a, '_, T> {
    type Item = Result<ReadScope<'a>, ParseError>;
270378
    fn next(&mut self) -> Option<Result<ReadScope<'a>, ParseError>> {
270378
        match *self {
270378
            SmartLookupSubtableIter::Normal(_, ref mut iter) => iter.next().map(Ok),
            SmartLookupSubtableIter::Extension(ref mut iter) => iter.next(),
        }
270378
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        match self {
            SmartLookupSubtableIter::Normal(_lookup_type, iter) => iter.size_hint(),
            SmartLookupSubtableIter::Extension(iter) => iter.size_hint(),
        }
    }
}
impl<T: LayoutTableType> SmartLookupSubtableIter<'_, '_, T> {
61506
    pub fn get_lookup_type(&mut self) -> T::BaseLookupType {
61506
        match *self {
61506
            SmartLookupSubtableIter::Normal(lookup_type, _) => lookup_type,
            SmartLookupSubtableIter::Extension(ref mut iter) => iter.lookup_type,
        }
61506
    }
}
impl LayoutTableType for GSUB {
    type LookupType = SubstLookup;
    type BaseLookupType = SubstLookupType;
45198
    fn check_lookup_type(lookup_type: u16) -> Result<LookupType<GSUB>, ParseError> {
45198
        match lookup_type {
            1 => Ok(LookupType::Normal(SubstLookupType::SingleSubst)),
            2 => Ok(LookupType::Normal(SubstLookupType::MultipleSubst)),
            3 => Ok(LookupType::Normal(SubstLookupType::AlternateSubst)),
19980
            4 => Ok(LookupType::Normal(SubstLookupType::LigatureSubst)),
            5 => Ok(LookupType::Normal(SubstLookupType::ContextSubst)),
25218
            6 => Ok(LookupType::Normal(SubstLookupType::ChainContextSubst)),
            7 => Ok(LookupType::Extension),
            8 => Ok(LookupType::Normal(SubstLookupType::ReverseChainSingleSubst)),
            _ => Err(ParseError::BadVersion),
        }
45198
    }
}
impl LayoutTableType for GPOS {
    type LookupType = PosLookup;
    type BaseLookupType = PosLookupType;
16308
    fn check_lookup_type(lookup_type: u16) -> Result<LookupType<GPOS>, ParseError> {
16308
        match lookup_type {
            1 => Ok(LookupType::Normal(PosLookupType::SinglePos)),
15390
            2 => Ok(LookupType::Normal(PosLookupType::PairPos)),
            3 => Ok(LookupType::Normal(PosLookupType::CursivePos)),
324
            4 => Ok(LookupType::Normal(PosLookupType::MarkBasePos)),
270
            5 => Ok(LookupType::Normal(PosLookupType::MarkLigPos)),
324
            6 => Ok(LookupType::Normal(PosLookupType::MarkMarkPos)),
            7 => Ok(LookupType::Normal(PosLookupType::ContextPos)),
            8 => Ok(LookupType::Normal(PosLookupType::ChainContextPos)),
            9 => Ok(LookupType::Extension),
            _ => Err(ParseError::BadVersion),
        }
16308
    }
}
pub enum SingleSubst {
    Format1 {
        coverage: Arc<Coverage>,
        delta_glyph_index: i16,
    },
    Format2 {
        coverage: Arc<Coverage>,
        substitute_glyph_array: Vec<u16>,
    },
}
impl ReadBinaryDep for SingleSubst {
    type HostType<'a> = Self;
    type Args<'a> = &'a LayoutCache<GSUB>;
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, cache: Self::Args<'a>) -> Result<Self, ParseError> {
        let subtable = ctxt.scope();
        match ctxt.read_u16be()? {
            1 => {
                let coverage_offset = usize::from(ctxt.read_u16be()?);
                let coverage = subtable
                    .offset(coverage_offset)
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
                let delta_glyph_index = ctxt.read_i16be()?;
                Ok(SingleSubst::Format1 {
                    coverage,
                    delta_glyph_index,
                })
            }
            2 => {
                let coverage_offset = usize::from(ctxt.read_u16be()?);
                let coverage = subtable
                    .offset(coverage_offset)
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
                let glyph_count = ctxt.read_u16be()?;
                let substitute_glyph_array =
                    ctxt.read_array::<U16Be>(usize::from(glyph_count))?.to_vec();
                Ok(SingleSubst::Format2 {
                    coverage,
                    substitute_glyph_array,
                })
            }
            _ => Err(ParseError::BadVersion),
        }
    }
}
impl SingleSubst {
    pub fn apply_glyph(&self, glyph: u16) -> Result<Option<u16>, ParseError> {
        match *self {
            SingleSubst::Format1 {
                ref coverage,
                delta_glyph_index,
            } => {
                if coverage.glyph_coverage_value(glyph).is_some() {
                    let new_glyph_index = glyph as isize + delta_glyph_index as isize;
                    // Addition of deltaGlyphID is modulo 65536, which is why the mask is used.
                    Ok(Some((new_glyph_index & 0xffff) as u16)) // Cast safe due to mask
                } else {
                    Ok(None)
                }
            }
            SingleSubst::Format2 {
                ref coverage,
                ref substitute_glyph_array,
            } => match coverage.glyph_coverage_value(glyph) {
                Some(coverage_index) => {
                    let coverage_index = usize::from(coverage_index);
                    substitute_glyph_array.check_index(coverage_index)?;
                    let new_glyph_index = substitute_glyph_array[coverage_index];
                    Ok(Some(new_glyph_index))
                }
                None => Ok(None),
            },
        }
    }
}
pub struct MultipleSubst {
    coverage: Arc<Coverage>,
    sequences: Vec<SequenceTable>,
}
pub struct SequenceTable {
    pub substitute_glyphs: Vec<GlyphId>,
}
impl ReadBinaryDep for MultipleSubst {
    type HostType<'a> = Self;
    type Args<'a> = &'a LayoutCache<GSUB>;
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, cache: Self::Args<'a>) -> Result<Self, ParseError> {
        let scope = ctxt.scope();
        match ctxt.read_u16be()? {
            1 => {
                let coverage_offset = usize::from(ctxt.read_u16be()?);
                let coverage = scope
                    .offset(coverage_offset)
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
                let sequence_count = usize::from(ctxt.read_u16be()?);
                let sequence_offsets = ctxt.read_array::<U16Be>(sequence_count)?;
                let sequences = read_objects::<SequenceTable>(&scope, sequence_offsets)?;
                Ok(MultipleSubst {
                    coverage,
                    sequences,
                })
            }
            _ => Err(ParseError::BadVersion),
        }
    }
}
impl MultipleSubst {
    pub fn apply_glyph(&self, glyph: GlyphId) -> Result<Option<&SequenceTable>, ParseError> {
        match self.coverage.glyph_coverage_value(glyph) {
            Some(coverage_index) => {
                let coverage_index = usize::from(coverage_index);
                self.sequences.check_index(coverage_index)?;
                let sequence = &self.sequences[coverage_index];
                Ok(Some(sequence))
            }
            None => Ok(None),
        }
    }
}
impl ReadBinary for SequenceTable {
    type HostType<'a> = Self;
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
        let glyph_count = usize::from(ctxt.read_u16be()?);
        // The spec requires this, but implementations do not follow it.
        // ctxt.check(glyph_count > 0)?;
        let substitute_glyphs = ctxt.read_array::<U16Be>(glyph_count)?.to_vec();
        Ok(SequenceTable { substitute_glyphs })
    }
}
pub struct AlternateSubst {
    coverage: Arc<Coverage>,
    alternatesets: Vec<AlternateSet>,
}
pub struct AlternateSet {
    pub alternate_glyphs: Vec<u16>,
}
impl ReadBinaryDep for AlternateSubst {
    type HostType<'a> = Self;
    type Args<'a> = &'a LayoutCache<GSUB>;
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, cache: Self::Args<'a>) -> Result<Self, ParseError> {
        let scope = ctxt.scope();
        match ctxt.read_u16be()? {
            1 => {
                let coverage_offset = usize::from(ctxt.read_u16be()?);
                let coverage = scope
                    .offset(coverage_offset)
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
                let alternateset_count = usize::from(ctxt.read_u16be()?);
                let alternateset_offsets = ctxt.read_array::<U16Be>(alternateset_count)?;
                let alternatesets = read_objects::<AlternateSet>(&scope, alternateset_offsets)?;
                Ok(AlternateSubst {
                    coverage,
                    alternatesets,
                })
            }
            _ => Err(ParseError::BadVersion),
        }
    }
}
impl AlternateSubst {
    pub fn apply_glyph(&self, glyph: GlyphId) -> Result<Option<&AlternateSet>, ParseError> {
        match self.coverage.glyph_coverage_value(glyph) {
            Some(coverage_index) => {
                let coverage_index = usize::from(coverage_index);
                self.alternatesets.check_index(coverage_index)?;
                let alternateset = &self.alternatesets[coverage_index];
                Ok(Some(alternateset))
            }
            None => Ok(None),
        }
    }
}
impl ReadBinary for AlternateSet {
    type HostType<'a> = Self;
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
        let glyph_count = usize::from(ctxt.read_u16be()?);
        ctxt.check(glyph_count > 0)?;
        let alternate_glyphs = ctxt.read_array::<U16Be>(glyph_count)?.to_vec();
        Ok(AlternateSet { alternate_glyphs })
    }
}
pub struct LigatureSubst {
    coverage: Arc<Coverage>,
    ligaturesets: Vec<LigatureSet>,
}
pub struct LigatureSet {
    pub ligatures: Vec<Ligature>,
}
#[derive(Debug)]
pub struct Ligature {
    pub ligature_glyph: GlyphId,
    pub component_glyphs: Vec<GlyphId>,
}
impl ReadBinaryDep for LigatureSubst {
    type HostType<'a> = Self;
    type Args<'a> = &'a LayoutCache<GSUB>;
19980
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, cache: Self::Args<'a>) -> Result<Self, ParseError> {
19980
        let scope = ctxt.scope();
19980
        match ctxt.read_u16be()? {
            1 => {
19980
                let coverage_offset = usize::from(ctxt.read_u16be()?);
19980
                let coverage = scope
19980
                    .offset(coverage_offset)
19980
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
19980
                let ligatureset_count = usize::from(ctxt.read_u16be()?);
19980
                let ligatureset_offsets = ctxt.read_array::<U16Be>(ligatureset_count)?;
19980
                let ligaturesets = read_objects::<LigatureSet>(&scope, ligatureset_offsets)?;
19980
                Ok(LigatureSubst {
19980
                    coverage,
19980
                    ligaturesets,
19980
                })
            }
            _ => Err(ParseError::BadVersion),
        }
19980
    }
}
impl LigatureSubst {
665982
    pub fn apply_glyph(&self, glyph: GlyphId) -> Result<Option<&LigatureSet>, ParseError> {
665982
        match self.coverage.glyph_coverage_value(glyph) {
11448
            Some(coverage_index) => {
11448
                let coverage_index = usize::from(coverage_index);
11448
                self.ligaturesets.check_index(coverage_index)?;
11448
                let ligatureset = &self.ligaturesets[coverage_index];
11448
                Ok(Some(ligatureset))
            }
654534
            None => Ok(None),
        }
665982
    }
}
impl ReadBinary for LigatureSet {
    type HostType<'a> = Self;
78948
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
78948
        let scope = ctxt.scope();
78948
        let ligature_count = usize::from(ctxt.read_u16be()?);
78948
        let ligature_offsets = ctxt.read_array::<U16Be>(ligature_count)?;
78948
        let ligatures = read_objects::<Ligature>(&scope, ligature_offsets)?;
78948
        Ok(LigatureSet { ligatures })
78948
    }
}
impl ReadBinary for Ligature {
    type HostType<'a> = Self;
1357884
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
1357884
        let ligature_glyph = ctxt.read_u16be()?;
1357884
        let component_count = usize::from(ctxt.read_u16be()?);
1357884
        ctxt.check(component_count > 0)?;
1357884
        let component_glyphs = ctxt.read_array::<U16Be>(component_count - 1)?.to_vec();
1357884
        Ok(Ligature {
1357884
            ligature_glyph,
1357884
            component_glyphs,
1357884
        })
1357884
    }
}
#[derive(Clone, Copy)]
pub struct ValueFormat(u16);
impl ReadBinary for ValueFormat {
    type HostType<'a> = Self;
276480
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
276480
        let value_format = ctxt.read_u16be()?;
276480
        if value_format <= 0xFF {
276480
            Ok(ValueFormat(value_format))
        } else {
            Err(ParseError::BadValue)
        }
276480
    }
}
impl ValueFormat {
242002944
    pub fn size(self) -> usize {
242002944
        let mut num_fields = 0;
2178026496
        for i in 0..8 {
1936023552
            if ith_bit_set(self.0, i) {
121001472
                num_fields += 1;
1815022080
            }
        }
242002944
        num_fields * size::U16
242002944
    }
227875896
    fn is_zero(self) -> bool {
227875896
        self.0 == 0
227875896
    }
113937948
    fn has_x_placement(self) -> bool {
113937948
        ith_bit_set(self.0, 0)
113937948
    }
113937948
    fn has_y_placement(self) -> bool {
113937948
        ith_bit_set(self.0, 1)
113937948
    }
113937948
    fn has_x_advance(self) -> bool {
113937948
        ith_bit_set(self.0, 2)
113937948
    }
113937948
    fn has_y_advance(self) -> bool {
113937948
        ith_bit_set(self.0, 3)
113937948
    }
113937948
    fn has_x_placement_device(self) -> bool {
113937948
        ith_bit_set(self.0, 4)
113937948
    }
113937948
    fn has_y_placement_device(self) -> bool {
113937948
        ith_bit_set(self.0, 5)
113937948
    }
113937948
    fn has_x_advance_device(self) -> bool {
113937948
        ith_bit_set(self.0, 6)
113937948
    }
113937948
    fn has_y_advance_device(self) -> bool {
113937948
        ith_bit_set(self.0, 7)
113937948
    }
}
2847527136
fn ith_bit_set(flags: u16, i: u16) -> bool {
2847527136
    (flags & (1 << i)) != 0
2847527136
}
pub(crate) type VariationIndex = crate::tables::variable_fonts::DeltaSetIndexMapEntry;
impl ReadBinary for Option<VariationIndex> {
    type HostType<'a> = Option<VariationIndex>;
    fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
        let start_size = ctxt.read_u16be()?;
        let end_size = ctxt.read_u16be()?;
        let delta_format = ctxt.read_u16be()?;
        match delta_format {
            // Valid, but currently unused DeviceTable
            1 | 2 | 3 => Ok(None),
            0x8000 => Ok(Some(VariationIndex {
                outer_index: start_size,
                inner_index: end_size,
            })),
            _ => {
                // It appears there are some fonts in the wild that use delta formats not described
                // by the specification. E.g. the Samanata Devanagari font contains several non-standard values.
                // Given how we are using the VariationIndex it makes sense to ignore these as opposed to
                // reporting an error.
                Ok(None)
            }
        }
    }
}
fn read_variation_index_at_offset(
    scope: ReadScope<'_>,
    offset: u16,
) -> Result<Option<VariationIndex>, ParseError> {
    // Offsets are relative to the beginning of the immediate parent table (SinglePos or
    // PairPosFormat2 lookup subtable, PairSet table within a PairPosFormat1 lookup subtable)
    // — may be NULL (0).
    if offset > 0 {
        scope
            .offset(usize::from(offset))
            .ctxt()
            .read::<Option<VariationIndex>>()
    } else {
        Ok(None)
    }
}
pub type ValueRecord = Option<Adjust>;
#[derive(Debug, Copy, Clone)]
pub struct Adjust {
    pub x_placement: i16,
    pub y_placement: i16,
    pub x_advance: i16,
    pub y_advance: i16,
    pub x_placement_variation: Option<VariationIndex>,
    pub y_placement_variation: Option<VariationIndex>,
    pub x_advance_variation: Option<VariationIndex>,
    pub y_advance_variation: Option<VariationIndex>,
}
impl ReadBinaryDep for ValueRecord {
    type Args<'a> = (ReadScope<'a>, ValueFormat);
    type HostType<'a> = Self;
227875896
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, args: Self::Args<'a>) -> Result<Self, ParseError> {
227875896
        let (table_scope, value_format) = args;
227875896
        if value_format.is_zero() {
113937948
            return Ok(None);
113937948
        }
113937948
        let x_pla = if value_format.has_x_placement() {
            ctxt.read_i16be()?
        } else {
113937948
            0
        };
113937948
        let y_pla = if value_format.has_y_placement() {
            ctxt.read_i16be()?
        } else {
113937948
            0
        };
113937948
        let x_adv = if value_format.has_x_advance() {
113937948
            ctxt.read_i16be()?
        } else {
            0
        };
113937948
        let y_adv = if value_format.has_y_advance() {
            ctxt.read_i16be()?
        } else {
113937948
            0
        };
113937948
        let x_placement_variation = if value_format.has_x_placement_device() {
            let offset = ctxt.read_u16be()?;
            read_variation_index_at_offset(table_scope, offset)?
        } else {
113937948
            None
        };
113937948
        let y_placement_variation = if value_format.has_y_placement_device() {
            let offset = ctxt.read_u16be()?;
            read_variation_index_at_offset(table_scope, offset)?
        } else {
113937948
            None
        };
113937948
        let x_advance_variation = if value_format.has_x_advance_device() {
            let offset = ctxt.read_u16be()?;
            read_variation_index_at_offset(table_scope, offset)?
        } else {
113937948
            None
        };
113937948
        let y_advance_variation = if value_format.has_y_advance_device() {
            let offset = ctxt.read_u16be()?;
            read_variation_index_at_offset(table_scope, offset)?
        } else {
113937948
            None
        };
113937948
        Ok(Some(Adjust {
113937948
            x_placement: x_pla,
113937948
            y_placement: y_pla,
113937948
            x_advance: x_adv,
113937948
            y_advance: y_adv,
113937948
            x_placement_variation,
113937948
            y_placement_variation,
113937948
            x_advance_variation,
113937948
            y_advance_variation,
113937948
        }))
227875896
    }
}
impl ReadFixedSizeDep for ValueRecord {
    fn size((_scope, value_format): Self::Args<'_>) -> usize {
        value_format.size()
    }
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct Anchor {
    pub x: i16,
    pub y: i16,
}
impl ReadBinary for Anchor {
    type HostType<'a> = Self;
533250
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
533250
        match ctxt.read_u16be()? {
            1 | 2 | 3 => {
533250
                let x = ctxt.read_i16be()?;
533250
                let y = ctxt.read_i16be()?;
                // Doesn't read other fields because we don't use them
533250
                Ok(Anchor { x, y })
            }
            _ => Err(ParseError::BadVersion),
        }
533250
    }
}
pub enum SinglePos {
    Format1 {
        coverage: Arc<Coverage>,
        value_record: ValueRecord,
    },
    Format2 {
        coverage: Arc<Coverage>,
        value_records: Vec<ValueRecord>,
    },
}
impl ReadBinaryDep for SinglePos {
    type HostType<'a> = Self;
    type Args<'a> = &'a LayoutCache<GPOS>;
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, cache: Self::Args<'a>) -> Result<Self, ParseError> {
        let scope = ctxt.scope();
        match ctxt.read_u16be()? {
            1 => {
                let coverage_offset = usize::from(ctxt.read_u16be()?);
                let coverage = scope
                    .offset(coverage_offset)
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
                let value_format = ctxt.read::<ValueFormat>()?;
                let value_record = ctxt.read_dep::<ValueRecord>((scope, value_format))?;
                Ok(SinglePos::Format1 {
                    coverage,
                    value_record,
                })
            }
            2 => {
                let coverage_offset = usize::from(ctxt.read_u16be()?);
                let coverage = scope
                    .offset(coverage_offset)
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
                let value_format = ctxt.read::<ValueFormat>()?;
                let value_count = usize::from(ctxt.read_u16be()?);
                let value_records = ctxt
                    .read_array_dep::<ValueRecord>(value_count, (scope, value_format))?
                    .read_to_vec()?;
                Ok(SinglePos::Format2 {
                    coverage,
                    value_records,
                })
            }
            _ => Err(ParseError::BadVersion),
        }
    }
}
impl SinglePos {
    pub fn apply(&self, glyph: GlyphId) -> Result<ValueRecord, ParseError> {
        match *self {
            SinglePos::Format1 {
                ref coverage,
                value_record,
            } => {
                if coverage.glyph_coverage_value(glyph).is_some() {
                    Ok(value_record)
                } else {
                    Ok(None)
                }
            }
            SinglePos::Format2 {
                ref coverage,
                ref value_records,
            } => {
                if let Some(coverage_index) = coverage.glyph_coverage_value(glyph) {
                    let coverage_index = usize::from(coverage_index);
                    value_records.check_index(coverage_index)?;
                    Ok(value_records[coverage_index])
                } else {
                    Ok(None)
                }
            }
        }
    }
}
pub enum PairPos {
    Format1 {
        coverage: Arc<Coverage>,
        pairsets: Vec<PairSet>,
    },
    Format2 {
        coverage: Arc<Coverage>,
        classdef1: Arc<ClassDef>,
        classdef2: Arc<ClassDef>,
        class2_count: usize,
        class1_records: Vec<Class1Record>,
    },
}
impl ReadBinaryDep for PairPos {
    type HostType<'a> = Self;
    type Args<'a> = &'a LayoutCache<GPOS>;
138240
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, cache: Self::Args<'a>) -> Result<Self, ParseError> {
138240
        let scope = ctxt.scope();
138240
        match ctxt.read_u16be()? {
            1 => {
19656
                let coverage_offset = usize::from(ctxt.read_u16be()?);
19656
                let coverage = scope
19656
                    .offset(coverage_offset)
19656
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
19656
                let value_format1 = ctxt.read::<ValueFormat>()?;
19656
                let value_format2 = ctxt.read::<ValueFormat>()?;
19656
                let pairset_count = usize::from(ctxt.read_u16be()?);
19656
                let pairset_offsets = ctxt.read_array::<U16Be>(pairset_count)?;
19656
                let pairsets = read_objects_dep::<PairSet>(
19656
                    &scope,
19656
                    pairset_offsets,
19656
                    (value_format1, value_format2),
                )?;
19656
                Ok(PairPos::Format1 { coverage, pairsets })
            }
            2 => {
118584
                let coverage_offset = usize::from(ctxt.read_u16be()?);
118584
                let coverage = scope
118584
                    .offset(coverage_offset)
118584
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
118584
                let value_format1 = ctxt.read::<ValueFormat>()?;
118584
                let value_format2 = ctxt.read::<ValueFormat>()?;
118584
                let classdef1_offset = usize::from(ctxt.read_u16be()?);
118584
                let classdef2_offset = usize::from(ctxt.read_u16be()?);
118584
                let classdef1 = scope
118584
                    .offset(classdef1_offset)
118584
                    .read_cache::<ClassDef>(&mut cache.classdefs.lock().unwrap())?;
118584
                let classdef2 = scope
118584
                    .offset(classdef2_offset)
118584
                    .read_cache::<ClassDef>(&mut cache.classdefs.lock().unwrap())?;
118584
                let class1_count = usize::from(ctxt.read_u16be()?);
118584
                let class2_count = usize::from(ctxt.read_u16be()?);
118584
                let class1_records = ctxt
118584
                    .read_array_dep::<Class1Record>(
118584
                        class1_count,
118584
                        (scope, class2_count, value_format1, value_format2),
                    )?
118584
                    .read_to_vec()?;
118584
                Ok(PairPos::Format2 {
118584
                    coverage,
118584
                    classdef1,
118584
                    classdef2,
118584
                    class2_count,
118584
                    class1_records,
118584
                })
            }
            _ => Err(ParseError::BadVersion),
        }
138240
    }
}
pub struct PairSet {
    pair_value_records: Vec<PairValueRecord>,
}
impl ReadBinaryDep for PairSet {
    type Args<'a> = (ValueFormat, ValueFormat);
    type HostType<'a> = Self;
3636360
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, args: Self::Args<'a>) -> Result<Self, ParseError> {
3636360
        let scope = ctxt.scope();
3636360
        let (value_format1, value_format2) = args;
3636360
        let pair_value_count = usize::from(ctxt.read_u16be()?);
3636360
        let pair_value_records = ctxt
3636360
            .read_array_dep::<PairValueRecord>(
3636360
                pair_value_count,
3636360
                (scope, value_format1, value_format2),
            )?
3636360
            .read_to_vec()?;
3636360
        Ok(PairSet { pair_value_records })
3636360
    }
}
pub struct PairValueRecord {
    second_glyph: u16,
    value_record1: ValueRecord,
    value_record2: ValueRecord,
}
impl ReadBinaryDep for PairValueRecord {
    type Args<'a> = (ReadScope<'a>, ValueFormat, ValueFormat);
    type HostType<'a> = Self;
32402916
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, args: Self::Args<'a>) -> Result<Self, ParseError> {
32402916
        let (table_scope, value_format1, value_format2) = args;
32402916
        let second_glyph = ctxt.read_u16be()?;
32402916
        let value_record1 = ctxt.read_dep::<ValueRecord>((table_scope, value_format1))?;
32402916
        let value_record2 = ctxt.read_dep::<ValueRecord>((table_scope, value_format2))?;
32402916
        Ok(PairValueRecord {
32402916
            second_glyph,
32402916
            value_record1,
32402916
            value_record2,
32402916
        })
32402916
    }
}
impl ReadFixedSizeDep for PairValueRecord {
36039276
    fn size((_scope, value_format1, value_format2): Self::Args<'_>) -> usize {
36039276
        size::U16 + value_format1.size() + value_format2.size()
36039276
    }
}
pub struct Class1Record {
    class2_records: Vec<Class2Record>,
}
impl ReadBinaryDep for Class1Record {
    type Args<'a> = (ReadScope<'a>, usize, ValueFormat, ValueFormat);
    type HostType<'a> = Self;
1654290
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, args: Self::Args<'a>) -> Result<Self, ParseError> {
1654290
        let (scope, class2_count, value_format1, value_format2) = args;
1654290
        let class2_records = ctxt
1654290
            .read_array_dep::<Class2Record>(class2_count, (scope, value_format1, value_format2))?
1654290
            .read_to_vec()?;
1654290
        Ok(Class1Record { class2_records })
1654290
    }
}
impl ReadFixedSizeDep for Class1Record {
1772874
    fn size((scope, class2_count, value_format1, value_format2): Self::Args<'_>) -> usize {
1772874
        class2_count * Class2Record::size((scope, value_format1, value_format2))
1772874
    }
}
pub struct Class2Record {
    value_record1: ValueRecord,
    value_record2: ValueRecord,
}
impl ReadBinaryDep for Class2Record {
    type Args<'a> = (ReadScope<'a>, ValueFormat, ValueFormat);
    type HostType<'a> = Self;
81535032
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, args: Self::Args<'a>) -> Result<Self, ParseError> {
81535032
        let (table_scope, value_format1, value_format2) = args;
81535032
        let value_record1 = ctxt.read_dep::<ValueRecord>((table_scope, value_format1))?;
81535032
        let value_record2 = ctxt.read_dep::<ValueRecord>((table_scope, value_format2))?;
81535032
        Ok(Class2Record {
81535032
            value_record1,
81535032
            value_record2,
81535032
        })
81535032
    }
}
impl ReadFixedSizeDep for Class2Record {
84962196
    fn size((_scope, value_format1, value_format2): Self::Args<'_>) -> usize {
84962196
        value_format1.size() + value_format2.size()
84962196
    }
}
impl PairPos {
2931552
    pub fn apply(
2931552
        &self,
2931552
        glyph1: GlyphId,
2931552
        glyph2: GlyphId,
2931552
    ) -> Result<Option<(ValueRecord, ValueRecord)>, ParseError> {
2931552
        match *self {
            PairPos::Format1 {
586440
                ref coverage,
586440
                ref pairsets,
            } => {
586440
                if let Some(coverage_index) = coverage.glyph_coverage_value(glyph1) {
155844
                    let coverage_index = usize::from(coverage_index);
155844
                    pairsets.check_index(coverage_index)?;
155844
                    let pairset = &pairsets[coverage_index];
4204602
                    for pair_value_record in &pairset.pair_value_records {
4048758
                        if pair_value_record.second_glyph == glyph2 {
                            return Ok(Some((
                                pair_value_record.value_record1,
                                pair_value_record.value_record2,
                            )));
4048758
                        }
                    }
155844
                    Ok(None)
                } else {
430596
                    Ok(None)
                }
            }
            PairPos::Format2 {
2345112
                ref coverage,
2345112
                ref classdef1,
2345112
                ref classdef2,
2345112
                class2_count,
2345112
                ref class1_records,
            } => {
2345112
                if coverage.glyph_coverage_value(glyph1).is_some() {
175284
                    let class1_value = usize::from(classdef1.glyph_class_value(glyph1));
175284
                    let class2_value = usize::from(classdef2.glyph_class_value(glyph2));
175284
                    if class1_value < class1_records.len() && class2_value < class2_count {
175284
                        let class1_record = &class1_records[class1_value];
175284
                        let class2_record = &class1_record.class2_records[class2_value];
175284
                        let adj1 = class2_record.value_record1;
175284
                        let adj2 = class2_record.value_record2;
175284
                        Ok(Some((adj1, adj2)))
                    } else {
                        Err(ParseError::BadIndex)
                    }
                } else {
2169828
                    Ok(None)
                }
            }
        }
2931552
    }
}
pub struct CursivePos {
    coverage: Arc<Coverage>,
    entry_exit_records: Vec<EntryExitRecord>,
}
impl ReadBinaryDep for CursivePos {
    type HostType<'a> = Self;
    type Args<'a> = &'a LayoutCache<GPOS>;
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, cache: Self::Args<'a>) -> Result<Self, ParseError> {
        let scope = ctxt.scope();
        match ctxt.read_u16be()? {
            1 => {
                let coverage_offset = usize::from(ctxt.read_u16be()?);
                let coverage = scope
                    .offset(coverage_offset)
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
                let entry_exit_count = usize::from(ctxt.read_u16be()?);
                let entry_exit_records = ctxt
                    .read_array_dep::<EntryExitRecord>(entry_exit_count, scope)?
                    .read_to_vec()?;
                Ok(CursivePos {
                    coverage,
                    entry_exit_records,
                })
            }
            _ => Err(ParseError::BadVersion),
        }
    }
}
struct EntryExitRecord {
    entry_anchor: Option<Anchor>,
    exit_anchor: Option<Anchor>,
}
impl ReadBinaryDep for EntryExitRecord {
    type Args<'a> = ReadScope<'a>;
    type HostType<'a> = Self;
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, scope: Self::Args<'a>) -> Result<Self, ParseError> {
        let entry_anchor_offset = ctxt.read_u16be()?;
        let exit_anchor_offset = ctxt.read_u16be()?;
        let entry_anchor = if entry_anchor_offset != 0 {
            Some(
                scope
                    .offset(usize::from(entry_anchor_offset))
                    .read::<Anchor>()?,
            )
        } else {
            None
        };
        let exit_anchor = if exit_anchor_offset != 0 {
            Some(
                scope
                    .offset(usize::from(exit_anchor_offset))
                    .read::<Anchor>()?,
            )
        } else {
            None
        };
        Ok(EntryExitRecord {
            entry_anchor,
            exit_anchor,
        })
    }
}
impl ReadFixedSizeDep for EntryExitRecord {
    fn size(_scope: Self::Args<'_>) -> usize {
        2 * size::U16
    }
}
impl CursivePos {
    pub fn apply(
        &self,
        glyph1: GlyphId,
        glyph2: GlyphId,
    ) -> Result<Option<(Anchor, Anchor)>, ParseError> {
        let coverage_value1 = self.coverage.glyph_coverage_value(glyph1);
        let coverage_value2 = self.coverage.glyph_coverage_value(glyph2);
        match (coverage_value1, coverage_value2) {
            (Some(coverage_index1), Some(coverage_index2)) => {
                let coverage_index1 = usize::from(coverage_index1);
                let coverage_index2 = usize::from(coverage_index2);
                self.entry_exit_records.check_index(coverage_index1)?;
                self.entry_exit_records.check_index(coverage_index2)?;
                let entry_exit1 = &self.entry_exit_records[coverage_index1];
                let entry_exit2 = &self.entry_exit_records[coverage_index2];
                match (entry_exit1.exit_anchor, entry_exit2.entry_anchor) {
                    (Some(glyph1_exit), Some(glyph2_entry)) => {
                        Ok(Some((glyph1_exit, glyph2_entry)))
                    }
                    _ => Ok(None),
                }
            }
            _ => Ok(None),
        }
    }
}
// also used for MarkToMark tables
pub struct MarkBasePos {
    mark_coverage: Arc<Coverage>,
    base_coverage: Arc<Coverage>,
    mark_class_count: usize,
    mark_array: MarkArray,
    base_array: BaseArray,
}
impl ReadBinaryDep for MarkBasePos {
    type HostType<'a> = Self;
    type Args<'a> = &'a LayoutCache<GPOS>;
2592
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, cache: Self::Args<'a>) -> Result<Self, ParseError> {
2592
        let scope = ctxt.scope();
2592
        match ctxt.read_u16be()? {
            1 => {
2592
                let mark_coverage_offset = usize::from(ctxt.read_u16be()?);
2592
                let base_coverage_offset = usize::from(ctxt.read_u16be()?);
2592
                let mark_class_count = usize::from(ctxt.read_u16be()?);
2592
                let mark_array_offset = usize::from(ctxt.read_u16be()?);
2592
                let base_array_offset = usize::from(ctxt.read_u16be()?);
2592
                let mark_coverage = scope
2592
                    .offset(mark_coverage_offset)
2592
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
2592
                let base_coverage = scope
2592
                    .offset(base_coverage_offset)
2592
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
2592
                let mark_array = scope.offset(mark_array_offset).read::<MarkArray>()?;
2592
                let base_array = scope
2592
                    .offset(base_array_offset)
2592
                    .read_dep::<BaseArray>(mark_class_count)?;
2592
                Ok(MarkBasePos {
2592
                    mark_coverage,
2592
                    base_coverage,
2592
                    mark_class_count,
2592
                    mark_array,
2592
                    base_array,
2592
                })
            }
            _ => Err(ParseError::BadVersion),
        }
2592
    }
}
struct BaseArray {
    base_records: Vec<BaseRecord>,
}
impl ReadBinaryDep for BaseArray {
    type Args<'a> = usize;
    type HostType<'a> = Self;
2592
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, args: Self::Args<'a>) -> Result<Self, ParseError> {
2592
        let mark_class_count = args;
2592
        let scope = ctxt.scope();
2592
        let base_count = usize::from(ctxt.read_u16be()?);
2592
        let base_records = ctxt
2592
            .read_array_dep::<BaseRecord>(base_count, (scope, mark_class_count))?
2592
            .read_to_vec()?;
2592
        Ok(BaseArray { base_records })
2592
    }
}
struct BaseRecord {
    base_anchors: Vec<Option<Anchor>>,
}
impl ReadBinaryDep for BaseRecord {
    type Args<'a> = (ReadScope<'a>, usize);
    type HostType<'a> = Self;
460188
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, args: Self::Args<'a>) -> Result<Self, ParseError> {
460188
        let (scope, mark_class_count) = args;
460188
        let base_anchor_offsets = ctxt.read_array::<U16Be>(mark_class_count)?;
460188
        let base_anchors = read_objects_nullable::<Anchor>(&scope, base_anchor_offsets)?;
460188
        Ok(BaseRecord { base_anchors })
460188
    }
}
impl ReadFixedSizeDep for BaseRecord {
462780
    fn size((_scope, mark_class_count): Self::Args<'_>) -> usize {
462780
        mark_class_count * size::U16
462780
    }
}
struct MarkArray {
    mark_records: Vec<MarkRecord>,
}
impl ReadBinary for MarkArray {
    type HostType<'a> = Self;
2862
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
2862
        let scope = ctxt.scope();
2862
        let mark_count = usize::from(ctxt.read_u16be()?);
2862
        let mark_records = ctxt
2862
            .read_array_dep::<MarkRecord>(mark_count, scope)?
2862
            .read_to_vec()?;
2862
        Ok(MarkArray { mark_records })
2862
    }
}
struct MarkRecord {
    mark_class: u16,
    mark_anchor: Anchor,
}
impl ReadBinaryDep for MarkRecord {
    type Args<'a> = ReadScope<'a>;
    type HostType<'a> = Self;
72792
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, scope: Self::Args<'a>) -> Result<Self, ParseError> {
72792
        let mark_class = ctxt.read_u16be()?;
72792
        let mark_anchor_offset = ctxt.read_u16be()?;
72792
        let mark_anchor = scope
72792
            .offset(usize::from(mark_anchor_offset))
72792
            .read::<Anchor>()?;
72792
        Ok(MarkRecord {
72792
            mark_class,
72792
            mark_anchor,
72792
        })
72792
    }
}
impl ReadFixedSizeDep for MarkRecord {
75654
    fn size(_scope: Self::Args<'_>) -> usize {
75654
        2 * size::U16
75654
    }
}
impl MarkBasePos {
1944
    pub fn apply(
1944
        &self,
1944
        glyph1: GlyphId,
1944
        glyph2: GlyphId,
1944
    ) -> Result<Option<(Anchor, Anchor)>, ParseError> {
1944
        let base_coverage_value = self.base_coverage.glyph_coverage_value(glyph1);
1944
        let mark_coverage_value = self.mark_coverage.glyph_coverage_value(glyph2);
1944
        match (base_coverage_value, mark_coverage_value) {
            (Some(base_coverage_index), Some(mark_coverage_index)) => {
                let base_coverage_index = usize::from(base_coverage_index);
                let mark_coverage_index = usize::from(mark_coverage_index);
                self.base_array
                    .base_records
                    .check_index(base_coverage_index)?;
                self.mark_array
                    .mark_records
                    .check_index(mark_coverage_index)?;
                let mark_record = &self.mark_array.mark_records[mark_coverage_index];
                let mark_class = usize::from(mark_record.mark_class);
                if mark_class < self.mark_class_count {
                    let mark_anchor = mark_record.mark_anchor;
                    let base_record = &self.base_array.base_records[base_coverage_index];
                    if let Some(base_anchor) = base_record.base_anchors[mark_class] {
                        Ok(Some((base_anchor, mark_anchor)))
                    } else {
                        Ok(None)
                    }
                } else {
                    Err(ParseError::BadIndex)
                }
            }
1944
            _ => Ok(None),
        }
1944
    }
}
pub struct MarkLigPos {
    mark_coverage: Arc<Coverage>,
    liga_coverage: Arc<Coverage>,
    mark_class_count: usize,
    mark_array: MarkArray,
    ligature_array: LigatureArray,
}
impl ReadBinaryDep for MarkLigPos {
    type HostType<'a> = Self;
    type Args<'a> = &'a LayoutCache<GPOS>;
270
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, cache: Self::Args<'a>) -> Result<Self, ParseError> {
270
        let scope = ctxt.scope();
270
        match ctxt.read_u16be()? {
            1 => {
270
                let mark_coverage_offset = usize::from(ctxt.read_u16be()?);
270
                let liga_coverage_offset = usize::from(ctxt.read_u16be()?);
270
                let mark_class_count = usize::from(ctxt.read_u16be()?);
270
                let mark_array_offset = usize::from(ctxt.read_u16be()?);
270
                let liga_array_offset = usize::from(ctxt.read_u16be()?);
270
                let mark_coverage = scope
270
                    .offset(mark_coverage_offset)
270
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
270
                let liga_coverage = scope
270
                    .offset(liga_coverage_offset)
270
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
270
                let mark_array = scope.offset(mark_array_offset).read::<MarkArray>()?;
270
                let ligature_array = scope
270
                    .offset(liga_array_offset)
270
                    .read_dep::<LigatureArray>(mark_class_count)?;
270
                Ok(MarkLigPos {
270
                    mark_coverage,
270
                    liga_coverage,
270
                    mark_class_count,
270
                    mark_array,
270
                    ligature_array,
270
                })
            }
            _ => Err(ParseError::BadVersion),
        }
270
    }
}
struct LigatureArray {
    ligature_attaches: Vec<LigatureAttach>,
}
impl ReadBinaryDep for LigatureArray {
    type Args<'a> = usize;
    type HostType<'a> = Self;
270
    fn read_dep(ctxt: &mut ReadCtxt<'_>, mark_class_count: usize) -> Result<Self, ParseError> {
270
        let scope = ctxt.scope();
270
        let ligature_count = usize::from(ctxt.read_u16be()?);
270
        let ligature_attach_offsets = ctxt.read_array::<U16Be>(ligature_count)?;
270
        let ligature_attaches =
270
            read_objects_dep::<LigatureAttach>(&scope, ligature_attach_offsets, mark_class_count)?;
270
        Ok(LigatureArray { ligature_attaches })
270
    }
}
struct LigatureAttach {
    component_records: Vec<ComponentRecord>,
}
impl ReadBinaryDep for LigatureAttach {
    type Args<'a> = usize;
    type HostType<'a> = Self;
270
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, args: Self::Args<'a>) -> Result<Self, ParseError> {
270
        let mark_class_count = args;
270
        let scope = ctxt.scope();
270
        let component_count = usize::from(ctxt.read_u16be()?);
270
        let component_records = ctxt
270
            .read_array_dep::<ComponentRecord>(component_count, (scope, mark_class_count))?
270
            .read_to_vec()?;
270
        Ok(LigatureAttach { component_records })
270
    }
}
struct ComponentRecord {
    ligature_anchors: Vec<Option<Anchor>>,
}
impl ReadBinaryDep for ComponentRecord {
    type Args<'a> = (ReadScope<'a>, usize);
    type HostType<'a> = Self;
270
    fn read_dep<'a>(
270
        ctxt: &mut ReadCtxt<'a>,
270
        args: Self::Args<'a>,
270
    ) -> Result<Self::HostType<'a>, ParseError> {
270
        let (scope, mark_class_count) = args;
270
        let ligature_anchor_offsets = ctxt.read_array::<U16Be>(mark_class_count)?;
270
        let ligature_anchors = read_objects_nullable::<Anchor>(&scope, ligature_anchor_offsets)?;
270
        Ok(ComponentRecord { ligature_anchors })
270
    }
}
impl ReadFixedSizeDep for ComponentRecord {
540
    fn size((_scope, mark_class_count): Self::Args<'_>) -> usize {
540
        mark_class_count * size::U16
540
    }
}
impl MarkLigPos {
    pub fn apply(
        &self,
        glyph1: GlyphId,
        glyph2: GlyphId,
        liga_component_index: usize,
    ) -> Result<Option<(Anchor, Anchor)>, ParseError> {
        let liga_coverage_value = self.liga_coverage.glyph_coverage_value(glyph1);
        let mark_coverage_value = self.mark_coverage.glyph_coverage_value(glyph2);
        match (liga_coverage_value, mark_coverage_value) {
            (Some(liga_coverage_index), Some(mark_coverage_index)) => {
                let liga_coverage_index = usize::from(liga_coverage_index);
                let mark_coverage_index = usize::from(mark_coverage_index);
                self.mark_array
                    .mark_records
                    .check_index(mark_coverage_index)?;
                let mark_record = &self.mark_array.mark_records[mark_coverage_index];
                let mark_class = usize::from(mark_record.mark_class);
                if mark_class < self.mark_class_count {
                    self.ligature_array
                        .ligature_attaches
                        .check_index(liga_coverage_index)?;
                    let liga_attach = &self.ligature_array.ligature_attaches[liga_coverage_index];
                    if liga_component_index < liga_attach.component_records.len() {
                        let component_record = &liga_attach.component_records[liga_component_index];
                        if let Some(liga_anchor) = component_record.ligature_anchors[mark_class] {
                            Ok(Some((liga_anchor, mark_record.mark_anchor)))
                        } else {
                            Ok(None)
                        }
                    } else {
                        Ok(None)
                    }
                } else {
                    Err(ParseError::BadIndex)
                }
            }
            _ => Ok(None),
        }
    }
}
pub enum ContextLookup<T: LayoutTableType + 'static> {
    Format1 {
        coverage: Arc<Coverage>,
        subrulesets: Vec<Option<SubRuleSet>>,
        phantom: PhantomData<T>,
    },
    Format2 {
        coverage: Arc<Coverage>,
        classdef: Arc<ClassDef>,
        subclasssets: Vec<Option<SubClassSet>>,
        phantom: PhantomData<T>,
    },
    Format3 {
        coverages: Vec<Arc<Coverage>>,
        lookup_records: Vec<(u16, u16)>,
        phantom: PhantomData<T>,
    },
}
pub struct SubRuleSet {
    subrules: Vec<SubRule>,
}
pub struct SubRule {
    input_sequence: Vec<u16>,
    lookup_records: Vec<(u16, u16)>,
}
pub struct SubClassSet {
    subclassrules: Vec<SubClassRule>,
}
pub struct SubClassRule {
    input_sequence: Vec<u16>,
    lookup_records: Vec<(u16, u16)>,
}
pub enum ChainContextLookup<T: LayoutTableType + 'static> {
    Format1 {
        coverage: Arc<Coverage>,
        chainsubrulesets: Vec<Option<ChainSubRuleSet>>,
        phantom: PhantomData<T>,
    },
    Format2 {
        coverage: Arc<Coverage>,
        backtrack_classdef: Arc<ClassDef>,
        input_classdef: Arc<ClassDef>,
        lookahead_classdef: Arc<ClassDef>,
        chainsubclasssets: Vec<Option<ChainSubClassSet>>,
        phantom: PhantomData<T>,
    },
    Format3 {
        backtrack_coverages: Vec<Arc<Coverage>>,
        input_coverages: Vec<Arc<Coverage>>,
        lookahead_coverages: Vec<Arc<Coverage>>,
        lookup_records: Vec<(u16, u16)>,
        phantom: PhantomData<T>,
    },
}
pub struct ChainSubRuleSet {
    chainsubrules: Vec<ChainSubRule>,
}
pub struct ChainSubRule {
    backtrack_sequence: Vec<u16>,
    input_sequence: Vec<u16>,
    lookahead_sequence: Vec<u16>,
    lookup_records: Vec<(u16, u16)>,
}
pub struct ChainSubClassSet {
    chainsubclassrules: Vec<ChainSubClassRule>,
}
pub struct ChainSubClassRule {
    backtrack_sequence: Vec<u16>,
    input_sequence: Vec<u16>,
    lookahead_sequence: Vec<u16>,
    lookup_records: Vec<(u16, u16)>,
}
impl<T: LayoutTableType> ReadBinaryDep for ContextLookup<T> {
    type HostType<'a> = Self;
    type Args<'a> = &'a LayoutCache<T>;
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, cache: Self::Args<'a>) -> Result<Self, ParseError> {
        let scope = ctxt.scope();
        match ctxt.read_u16be()? {
            1 => {
                let coverage_offset = usize::from(ctxt.read_u16be()?);
                let subruleset_count = ctxt.read_u16be()?;
                let subruleset_offsets = ctxt.read_array::<U16Be>(usize::from(subruleset_count))?;
                let subrulesets = read_objects_nullable::<SubRuleSet>(&scope, subruleset_offsets)?;
                let coverage = scope
                    .offset(coverage_offset)
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
                Ok(ContextLookup::Format1 {
                    coverage,
                    subrulesets,
                    phantom: PhantomData,
                })
            }
            2 => {
                let coverage_offset = usize::from(ctxt.read_u16be()?);
                let classdef_offset = usize::from(ctxt.read_u16be()?);
                let subclassset_count = ctxt.read_u16be()?;
                let subclassset_offsets =
                    ctxt.read_array::<U16Be>(usize::from(subclassset_count))?;
                let subclasssets =
                    read_objects_nullable::<SubClassSet>(&scope, subclassset_offsets)?;
                let coverage = scope
                    .offset(coverage_offset)
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
                let classdef = scope
                    .offset(classdef_offset)
                    .read_cache::<ClassDef>(&mut cache.classdefs.lock().unwrap())?;
                Ok(ContextLookup::Format2 {
                    coverage,
                    classdef,
                    subclasssets,
                    phantom: PhantomData,
                })
            }
            3 => {
                let glyph_count = usize::from(ctxt.read_u16be()?);
                ctxt.check(glyph_count > 0)?;
                let lookup_count = usize::from(ctxt.read_u16be()?);
                let coverage_offsets = ctxt.read_array::<U16Be>(glyph_count)?;
                let coverages = read_coverages(&scope, cache, coverage_offsets)?;
                let lookup_records = ctxt.read_array::<(U16Be, U16Be)>(lookup_count)?.to_vec();
                Ok(ContextLookup::Format3 {
                    coverages,
                    lookup_records,
                    phantom: PhantomData,
                })
            }
            _ => Err(ParseError::BadVersion),
        }
    }
}
/// GSUB Lookup Type 8 Subtable Formats
pub enum ReverseChainSingleSubst {
    /// Format 1
    Format1 {
        /// Coverage table for the single input glyph
        coverage: Arc<Coverage>,
        /// Array of backtrack sequence coverages, ordered by glyph sequence
        backtrack_coverages: Vec<Arc<Coverage>>,
        /// Array of lookahead sequence coverages, ordered by glyph sequence
        lookahead_coverages: Vec<Arc<Coverage>>,
        /// Array of substitute glyphs, ordered by coverage index
        substitute_glyphs: Vec<GlyphId>,
    },
}
impl ReadBinaryDep for ReverseChainSingleSubst {
    type HostType<'a> = Self;
    type Args<'a> = &'a LayoutCache<GSUB>;
    /// Parse a GSUB Lookup Type 8 Subtable from the given read context
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, cache: Self::Args<'a>) -> Result<Self, ParseError> {
        let scope = ctxt.scope();
        match ctxt.read_u16be()? {
            1 => {
                let coverage_offset = usize::from(ctxt.read_u16be()?);
                let backtrack_count = usize::from(ctxt.read_u16be()?);
                let backtrack_coverage_offsets = ctxt.read_array::<U16Be>(backtrack_count)?;
                let lookahead_count = usize::from(ctxt.read_u16be()?);
                let lookahead_coverage_offsets = ctxt.read_array::<U16Be>(lookahead_count)?;
                let glyph_count = usize::from(ctxt.read_u16be()?);
                let substitute_glyphs = ctxt.read_array::<U16Be>(glyph_count)?.to_vec();
                let coverage = scope
                    .offset(coverage_offset)
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
                let backtrack_coverages =
                    read_coverages(&scope, cache, backtrack_coverage_offsets)?;
                let lookahead_coverages =
                    read_coverages(&scope, cache, lookahead_coverage_offsets)?;
                ctxt.check(coverage.glyph_count() == glyph_count)?;
                Ok(ReverseChainSingleSubst::Format1 {
                    coverage,
                    backtrack_coverages,
                    lookahead_coverages,
                    substitute_glyphs,
                })
            }
            _ => Err(ParseError::BadVersion),
        }
    }
}
104436
fn read_objects<'a, T: ReadBinary<HostType<'a> = T>>(
104436
    scope: &ReadScope<'a>,
104436
    offsets: ReadArray<'a, U16Be>,
104436
) -> Result<Vec<T::HostType<'a>>, ParseError> {
104436
    let mut objects = Vec::with_capacity(offsets.len());
1548072
    for offset in &offsets {
1443636
        let object = scope.offset(usize::from(offset)).read::<T>()?;
1443636
        objects.push(object);
    }
104436
    Ok(objects)
104436
}
19926
fn read_objects_dep<'a, T: ReadBinaryDep<HostType<'a> = T>>(
19926
    scope: &ReadScope<'a>,
19926
    offsets: ReadArray<'a, U16Be>,
19926
    args: T::Args<'a>,
19926
) -> Result<Vec<T::HostType<'a>>, ParseError> {
19926
    let mut objects = Vec::with_capacity(offsets.len());
3656556
    for offset in &offsets {
3636630
        let object = scope.offset(usize::from(offset)).read_dep::<T>(args)?;
3636630
        objects.push(object);
    }
19926
    Ok(objects)
19926
}
464022
fn read_objects_nullable<'a, T: ReadBinary<HostType<'a> = T>>(
464022
    scope: &ReadScope<'a>,
464022
    offsets: ReadArray<'a, U16Be>,
464022
) -> Result<Vec<Option<T::HostType<'a>>>, ParseError> {
464022
    let mut objects = Vec::with_capacity(offsets.len());
935820
    for offset in &offsets {
471798
        if offset != 0 {
465966
            let object = scope.offset(usize::from(offset)).read::<T>()?;
465966
            objects.push(Some(object));
5832
        } else {
5832
            objects.push(None);
5832
        }
    }
464022
    Ok(objects)
464022
}
132678
fn read_coverages<'a, T: LayoutTableType>(
132678
    scope: &ReadScope<'a>,
132678
    cache: &LayoutCache<T>,
132678
    offsets: ReadArray<'a, U16Be>,
132678
) -> Result<Vec<Arc<Coverage>>, ParseError> {
132678
    let mut coverages = Vec::with_capacity(offsets.len());
230958
    for coverage_offset in &offsets {
98280
        let coverage = scope
98280
            .offset(usize::from(coverage_offset))
98280
            .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
98280
        coverages.push(coverage);
    }
132678
    Ok(coverages)
132678
}
impl ReadBinary for SubRuleSet {
    type HostType<'a> = Self;
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
        let scope = ctxt.scope();
        let subrule_count = usize::from(ctxt.read_u16be()?);
        let subrule_offsets = ctxt.read_array::<U16Be>(subrule_count)?;
        let subrules = read_objects::<SubRule>(&scope, subrule_offsets)?;
        Ok(SubRuleSet { subrules })
    }
}
impl ReadBinary for SubRule {
    type HostType<'a> = Self;
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
        let glyph_count = usize::from(ctxt.read_u16be()?);
        ctxt.check(glyph_count > 0)?;
        let lookup_count = usize::from(ctxt.read_u16be()?);
        let input_sequence = ctxt.read_array::<U16Be>(glyph_count - 1)?.to_vec();
        let lookup_records = ctxt.read_array::<(U16Be, U16Be)>(lookup_count)?.to_vec();
        Ok(SubRule {
            input_sequence,
            lookup_records,
        })
    }
}
impl ReadBinary for SubClassSet {
    type HostType<'a> = Self;
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
        let scope = ctxt.scope();
        let subclassrule_count = usize::from(ctxt.read_u16be()?);
        let subclassrule_offsets = ctxt.read_array::<U16Be>(subclassrule_count)?;
        let subclassrules = read_objects::<SubClassRule>(&scope, subclassrule_offsets)?;
        Ok(SubClassSet { subclassrules })
    }
}
impl ReadBinary for SubClassRule {
    type HostType<'a> = Self;
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
        let glyph_count = usize::from(ctxt.read_u16be()?);
        ctxt.check(glyph_count > 0)?;
        let lookup_count = usize::from(ctxt.read_u16be()?);
        let input_sequence = ctxt.read_array::<U16Be>(glyph_count - 1)?.to_vec();
        let lookup_records = ctxt.read_array::<(U16Be, U16Be)>(lookup_count)?.to_vec();
        Ok(SubClassRule {
            input_sequence,
            lookup_records,
        })
    }
}
impl<T: LayoutTableType> ReadBinaryDep for ChainContextLookup<T> {
    type HostType<'a> = Self;
    type Args<'a> = &'a LayoutCache<T>;
47790
    fn read_dep<'a>(ctxt: &mut ReadCtxt<'a>, cache: Self::Args<'a>) -> Result<Self, ParseError> {
47790
        let scope = ctxt.scope();
47790
        match ctxt.read_u16be()? {
            1 => {
                let coverage_offset = usize::from(ctxt.read_u16be()?);
                let chainsubruleset_count = ctxt.read_u16be()?;
                let chainsubruleset_offsets =
                    ctxt.read_array::<U16Be>(usize::from(chainsubruleset_count))?;
                let chainsubrulesets =
                    read_objects_nullable::<ChainSubRuleSet>(&scope, chainsubruleset_offsets)?;
                let coverage = scope
                    .offset(coverage_offset)
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
                Ok(ChainContextLookup::Format1 {
                    coverage,
                    chainsubrulesets,
                    phantom: PhantomData,
                })
            }
            2 => {
3564
                let coverage_offset = usize::from(ctxt.read_u16be()?);
3564
                let backtrack_classdef_offset = usize::from(ctxt.read_u16be()?);
3564
                let input_classdef_offset = usize::from(ctxt.read_u16be()?);
3564
                let lookahead_classdef_offset = usize::from(ctxt.read_u16be()?);
3564
                let chainsubclassset_count = ctxt.read_u16be()?;
3564
                let chainsubclassset_offsets =
3564
                    ctxt.read_array::<U16Be>(usize::from(chainsubclassset_count))?;
3564
                let chainsubclasssets =
3564
                    read_objects_nullable::<ChainSubClassSet>(&scope, chainsubclassset_offsets)?;
3564
                let coverage = scope
3564
                    .offset(coverage_offset)
3564
                    .read_cache::<Coverage>(&mut cache.coverages.lock().unwrap())?;
3564
                let backtrack_classdef = scope
3564
                    .offset(backtrack_classdef_offset)
3564
                    .read_cache::<ClassDef>(&mut cache.classdefs.lock().unwrap())?;
3564
                let input_classdef = scope
3564
                    .offset(input_classdef_offset)
3564
                    .read_cache::<ClassDef>(&mut cache.classdefs.lock().unwrap())?;
3564
                let lookahead_classdef = scope
3564
                    .offset(lookahead_classdef_offset)
3564
                    .read_cache::<ClassDef>(&mut cache.classdefs.lock().unwrap())?;
3564
                Ok(ChainContextLookup::Format2 {
3564
                    coverage,
3564
                    backtrack_classdef,
3564
                    input_classdef,
3564
                    lookahead_classdef,
3564
                    chainsubclasssets,
3564
                    phantom: PhantomData,
3564
                })
            }
            3 => {
44226
                let backtrack_count = usize::from(ctxt.read_u16be()?);
44226
                let backtrack_coverage_offsets = ctxt.read_array::<U16Be>(backtrack_count)?;
44226
                let input_count = usize::from(ctxt.read_u16be()?);
44226
                ctxt.check(input_count > 0)?;
44226
                let input_coverage_offsets = ctxt.read_array::<U16Be>(input_count)?;
44226
                let lookahead_count = usize::from(ctxt.read_u16be()?);
44226
                let lookahead_coverage_offsets = ctxt.read_array::<U16Be>(lookahead_count)?;
44226
                let lookup_count = usize::from(ctxt.read_u16be()?);
44226
                let lookup_records = ctxt.read_array::<(U16Be, U16Be)>(lookup_count)?.to_vec();
44226
                let backtrack_coverages =
44226
                    read_coverages(&scope, cache, backtrack_coverage_offsets)?;
44226
                let input_coverages = read_coverages(&scope, cache, input_coverage_offsets)?;
44226
                let lookahead_coverages =
44226
                    read_coverages(&scope, cache, lookahead_coverage_offsets)?;
44226
                Ok(ChainContextLookup::Format3 {
44226
                    backtrack_coverages,
44226
                    input_coverages,
44226
                    lookahead_coverages,
44226
                    lookup_records,
44226
                    phantom: PhantomData,
44226
                })
            }
            _ => Err(ParseError::BadVersion),
        }
47790
    }
}
impl ReadBinary for ChainSubRuleSet {
    type HostType<'a> = Self;
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
        let scope = ctxt.scope();
        let chainsubrule_count = usize::from(ctxt.read_u16be()?);
        let chainsubrule_offsets = ctxt.read_array::<U16Be>(chainsubrule_count)?;
        let chainsubrules = read_objects::<ChainSubRule>(&scope, chainsubrule_offsets)?;
        Ok(ChainSubRuleSet { chainsubrules })
    }
}
impl ReadBinary for ChainSubRule {
    type HostType<'a> = Self;
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
        let backtrack_count = usize::from(ctxt.read_u16be()?);
        let backtrack_sequence = ctxt.read_array::<U16Be>(backtrack_count)?.to_vec();
        let input_count = usize::from(ctxt.read_u16be()?);
        ctxt.check(input_count > 0)?;
        let input_sequence = ctxt.read_array::<U16Be>(input_count - 1)?.to_vec();
        let lookahead_count = usize::from(ctxt.read_u16be()?);
        let lookahead_sequence = ctxt.read_array::<U16Be>(lookahead_count)?.to_vec();
        let lookup_count = usize::from(ctxt.read_u16be()?);
        let lookup_records = ctxt.read_array::<(U16Be, U16Be)>(lookup_count)?.to_vec();
        Ok(ChainSubRule {
            backtrack_sequence,
            input_sequence,
            lookahead_sequence,
            lookup_records,
        })
    }
}
impl ReadBinary for ChainSubClassSet {
    type HostType<'a> = Self;
5508
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
5508
        let scope = ctxt.scope();
5508
        let chainsubclassrule_count = usize::from(ctxt.read_u16be()?);
5508
        let chainsubclassrule_offsets = ctxt.read_array::<U16Be>(chainsubclassrule_count)?;
5508
        let chainsubclassrules =
5508
            read_objects::<ChainSubClassRule>(&scope, chainsubclassrule_offsets)?;
5508
        Ok(ChainSubClassSet { chainsubclassrules })
5508
    }
}
impl ReadBinary for ChainSubClassRule {
    type HostType<'a> = Self;
6804
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
6804
        let backtrack_count = usize::from(ctxt.read_u16be()?);
6804
        let backtrack_sequence = ctxt.read_array::<U16Be>(backtrack_count)?.to_vec();
6804
        let input_count = usize::from(ctxt.read_u16be()?);
6804
        ctxt.check(input_count > 0)?;
6804
        let input_sequence = ctxt.read_array::<U16Be>(input_count - 1)?.to_vec();
6804
        let lookahead_count = usize::from(ctxt.read_u16be()?);
6804
        let lookahead_sequence = ctxt.read_array::<U16Be>(lookahead_count)?.to_vec();
6804
        let lookup_count = usize::from(ctxt.read_u16be()?);
6804
        let lookup_records = ctxt.read_array::<(U16Be, U16Be)>(lookup_count)?.to_vec();
6804
        Ok(ChainSubClassRule {
6804
            backtrack_sequence,
6804
            input_sequence,
6804
            lookahead_sequence,
6804
            lookup_records,
6804
        })
6804
    }
}
pub fn context_lookup_info<'a, T, Table: LayoutTableType>(
    context_lookup: &'a ContextLookup<Table>,
    glyph: GlyphId,
    f: impl Fn(&MatchContext<'a>) -> Option<RangeInclusive<usize>>,
) -> Result<Option<Box<ContextLookupHelper<'a, T>>>, ParseError> {
    match context_lookup {
        ContextLookup::Format1 {
            coverage,
            subrulesets,
            phantom: _,
        } => match coverage.glyph_coverage_value(glyph) {
            Some(coverage_index) => {
                let coverage_index = usize::from(coverage_index);
                subrulesets.check_index(coverage_index)?;
                if let Some(ref subruleset) = subrulesets[coverage_index] {
                    for subrule in &subruleset.subrules {
                        let match_context = MatchContext {
                            backtrack_table: GlyphTable::Empty,
                            input_table: GlyphTable::ById(&subrule.input_sequence),
                            lookahead_table: GlyphTable::Empty,
                        };
                        if let Some(input_seq) = f(&match_context) {
                            let lookup = ContextLookupHelper::new(
                                match_context,
                                &subrule.lookup_records,
                                input_seq,
                            );
                            return Ok(Some(Box::new(lookup)));
                        }
                    }
                    Ok(None)
                } else {
                    Ok(None)
                }
            }
            None => Ok(None),
        },
        ContextLookup::Format2 {
            coverage,
            classdef,
            subclasssets,
            phantom: _,
        } => match coverage.glyph_coverage_value(glyph) {
            Some(_coverage_index) => {
                let class_value = usize::from(classdef.glyph_class_value(glyph));
                subclasssets.check_index(class_value)?;
                if let Some(ref subclassset) = subclasssets[class_value] {
                    for subclassrule in &subclassset.subclassrules {
                        let match_context = MatchContext {
                            backtrack_table: GlyphTable::Empty,
                            input_table: GlyphTable::ByClassDef(
                                Arc::clone(classdef),
                                &subclassrule.input_sequence,
                            ),
                            lookahead_table: GlyphTable::Empty,
                        };
                        if let Some(input_seq) = f(&match_context) {
                            let lookup = ContextLookupHelper::new(
                                match_context,
                                &subclassrule.lookup_records,
                                input_seq,
                            );
                            return Ok(Some(Box::new(lookup)));
                        }
                    }
                    Ok(None)
                } else {
                    Ok(None)
                }
            }
            None => Ok(None),
        },
        ContextLookup::Format3 {
            coverages,
            lookup_records,
            phantom: _,
        } => {
            if !coverages.is_empty() {
                match coverages[0].glyph_coverage_value(glyph) {
                    Some(_coverage_index) => {
                        let match_context = MatchContext {
                            backtrack_table: GlyphTable::Empty,
                            input_table: GlyphTable::ByCoverage(&coverages[1..]),
                            lookahead_table: GlyphTable::Empty,
                        };
                        if let Some(input_seq) = f(&match_context) {
                            let lookup =
                                ContextLookupHelper::new(match_context, lookup_records, input_seq);
                            Ok(Some(Box::new(lookup)))
                        } else {
                            Ok(None)
                        }
                    }
                    None => Ok(None),
                }
            } else {
                Ok(None)
            }
        }
    }
}
1554660
pub fn chain_context_lookup_info<'a, T, Table: LayoutTableType>(
1554660
    chain_context_lookup: &'a ChainContextLookup<Table>,
1554660
    glyph: GlyphId,
1554660
    f: impl Fn(&MatchContext<'a>) -> Option<RangeInclusive<usize>>,
1554660
) -> Result<Option<Box<ContextLookupHelper<'a, T>>>, ParseError> {
1554660
    match chain_context_lookup {
        ChainContextLookup::Format1 {
            coverage,
            ref chainsubrulesets,
            phantom: _,
        } => match coverage.glyph_coverage_value(glyph) {
            Some(coverage_index) => {
                let coverage_index = usize::from(coverage_index);
                chainsubrulesets.check_index(coverage_index)?;
                if let Some(ref chainsubruleset) = chainsubrulesets[coverage_index] {
                    for chainsubrule in &chainsubruleset.chainsubrules {
                        let match_context = MatchContext {
                            backtrack_table: GlyphTable::ById(&chainsubrule.backtrack_sequence),
                            input_table: GlyphTable::ById(&chainsubrule.input_sequence),
                            lookahead_table: GlyphTable::ById(&chainsubrule.lookahead_sequence),
                        };
                        if let Some(input_seq) = f(&match_context) {
                            let lookup = ContextLookupHelper::new(
                                match_context,
                                &chainsubrule.lookup_records,
                                input_seq,
                            );
                            return Ok(Some(Box::new(lookup)));
                        }
                    }
                    Ok(None)
                } else {
                    Ok(None)
                }
            }
            None => Ok(None),
        },
        ChainContextLookup::Format2 {
66528
            coverage,
66528
            backtrack_classdef,
66528
            input_classdef,
66528
            lookahead_classdef,
66528
            chainsubclasssets,
            phantom: _,
66528
        } => match coverage.glyph_coverage_value(glyph) {
54
            Some(_coverage_index) => {
54
                let class_value = usize::from(input_classdef.glyph_class_value(glyph));
54
                chainsubclasssets.check_index(class_value)?;
54
                if let Some(ref chainsubclassset) = chainsubclasssets[class_value] {
216
                    for chainsubclassrule in &chainsubclassset.chainsubclassrules {
162
                        let match_context = MatchContext {
162
                            backtrack_table: GlyphTable::ByClassDef(
162
                                Arc::clone(backtrack_classdef),
162
                                &chainsubclassrule.backtrack_sequence,
162
                            ),
162
                            input_table: GlyphTable::ByClassDef(
162
                                Arc::clone(input_classdef),
162
                                &chainsubclassrule.input_sequence,
162
                            ),
162
                            lookahead_table: GlyphTable::ByClassDef(
162
                                Arc::clone(lookahead_classdef),
162
                                &chainsubclassrule.lookahead_sequence,
162
                            ),
162
                        };
162
                        if let Some(input_seq) = f(&match_context) {
                            let lookup = ContextLookupHelper::new(
                                match_context,
                                &chainsubclassrule.lookup_records,
                                input_seq,
                            );
                            return Ok(Some(Box::new(lookup)));
162
                        }
                    }
54
                    Ok(None)
                } else {
                    Ok(None)
                }
            }
66474
            None => Ok(None),
        },
        ChainContextLookup::Format3 {
1488132
            backtrack_coverages,
1488132
            input_coverages,
1488132
            lookahead_coverages,
1488132
            lookup_records,
            phantom: _,
1488132
        } => match input_coverages[0].glyph_coverage_value(glyph) {
6696
            Some(_coverage_index) => {
6696
                let match_context = MatchContext {
6696
                    backtrack_table: GlyphTable::ByCoverage(backtrack_coverages),
6696
                    input_table: GlyphTable::ByCoverage(&input_coverages[1..]),
6696
                    lookahead_table: GlyphTable::ByCoverage(lookahead_coverages),
6696
                };
6696
                if let Some(input_seq) = f(&match_context) {
                    let lookup = ContextLookupHelper::new(match_context, lookup_records, input_seq);
                    Ok(Some(Box::new(lookup)))
                } else {
6696
                    Ok(None)
                }
            }
1481436
            None => Ok(None),
        },
    }
1554660
}
impl ReverseChainSingleSubst {
    /// Apply the substitution to the supplied glyph
    pub fn apply_glyph(
        &self,
        glyph: GlyphId,
        f: impl Fn(&MatchContext<'_>) -> bool,
    ) -> Result<Option<GlyphId>, ParseError> {
        match self {
            ReverseChainSingleSubst::Format1 {
                coverage,
                backtrack_coverages,
                lookahead_coverages,
                substitute_glyphs,
            } => match coverage.glyph_coverage_value(glyph) {
                Some(coverage_index) => {
                    let match_context = MatchContext {
                        backtrack_table: GlyphTable::ByCoverage(backtrack_coverages),
                        input_table: GlyphTable::Empty,
                        lookahead_table: GlyphTable::ByCoverage(lookahead_coverages),
                    };
                    if f(&match_context) {
                        let coverage_index = usize::from(coverage_index);
                        substitute_glyphs.check_index(coverage_index)?;
                        Ok(Some(substitute_glyphs[coverage_index]))
                    } else {
                        Ok(None)
                    }
                }
                None => Ok(None),
            },
        }
    }
}
pub enum Coverage {
    Format1 {
        glyph_array: Vec<GlyphId>,
    },
    Format2 {
        coverage_range_array: Vec<CoverageRangeRecord>,
    },
}
pub struct CoverageRangeRecord {
    start_glyph: GlyphId,
    end_glyph: GlyphId,
    start_coverage_index: u16,
}
impl ReadFrom for CoverageRangeRecord {
    type ReadType = (U16Be, U16Be, U16Be);
2158812
    fn read_from((start_glyph, end_glyph, start_coverage_index): (u16, u16, u16)) -> Self {
2158812
        CoverageRangeRecord {
2158812
            start_glyph,
2158812
            end_glyph,
2158812
            start_coverage_index,
2158812
        }
2158812
    }
}
impl ReadBinary for Coverage {
    type HostType<'a> = Self;
211734
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
211734
        match ctxt.read_u16be()? {
            1 => {
157464
                let glyph_count = ctxt.read_u16be()?;
157464
                let glyph_array = ctxt.read_array::<U16Be>(usize::from(glyph_count))?;
157464
                let glyph_vec = glyph_array.to_vec();
                // TODO consider verifying glyph_vec is sorted when is_sorted is stabilised
                // The glyph indices must be in numerical order for binary searching of the list.
                // https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-1
                // https://doc.rust-lang.org/std/primitive.slice.html#method.is_sorted
157464
                Ok(Coverage::Format1 {
157464
                    glyph_array: glyph_vec,
157464
                })
            }
            2 => {
54270
                let coverage_range_count = ctxt.read_u16be()?;
54270
                let coverage_range_array =
54270
                    ctxt.read_array::<CoverageRangeRecord>(usize::from(coverage_range_count))?;
54270
                let coverage_range_vec = coverage_range_array.to_vec();
2213082
                for coverage_range_record in &coverage_range_vec {
2158812
                    ctxt.check(
2158812
                        coverage_range_record.start_glyph <= coverage_range_record.end_glyph,
                    )?
                }
54270
                Ok(Coverage::Format2 {
54270
                    coverage_range_array: coverage_range_vec,
54270
                })
            }
            _ => Err(ParseError::BadVersion),
        }
211734
    }
}
impl Coverage {
5162616
    pub fn glyph_coverage_value(&self, glyph: GlyphId) -> Option<u16> {
5162616
        match *self {
3582846
            Coverage::Format1 { ref glyph_array } => {
                // The glyph indices must be in numerical order for binary searching of the list.
                // https://docs.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-1
3582846
                if let Ok(index) = glyph_array.binary_search(&glyph) {
252180
                    Some(index as u16)
                } else {
3330666
                    None
                }
            }
            Coverage::Format2 {
1579770
                ref coverage_range_array,
            } => {
35423460
                for coverage_range in coverage_range_array {
33942294
                    if (glyph >= coverage_range.start_glyph) && (glyph <= coverage_range.end_glyph)
                    {
98604
                        return Some(
98604
                            coverage_range.start_coverage_index
98604
                                + (glyph - coverage_range.start_glyph),
98604
                        );
33843690
                    }
                }
1481166
                None
            }
        }
5162616
    }
    /// Convenience method to count the total number of glyphs covered
    pub fn glyph_count(&self) -> usize {
        match self {
            Coverage::Format1 { glyph_array } => glyph_array.len(),
            Coverage::Format2 {
                coverage_range_array,
            } => coverage_range_array
                .iter()
                .fold(0, |acc, coverage_range_record| {
                    acc + (usize::from(coverage_range_record.end_glyph))
                        - (usize::from(coverage_range_record.start_glyph))
                        + 1
                }),
        }
    }
}
pub enum ClassDef {
    Format1 {
        start_glyph: u16,
        class_value_array: Vec<u16>,
    },
    Format2 {
        class_range_array: Vec<ClassRangeRecord>,
    },
}
pub struct ClassRangeRecord {
    start_glyph: u16,
    end_glyph: u16,
    class_value: u16,
}
impl ReadFrom for ClassRangeRecord {
    type ReadType = (U16Be, U16Be, U16Be);
15435360
    fn read_from((start_glyph, end_glyph, class_value): (u16, u16, u16)) -> Self {
15435360
        ClassRangeRecord {
15435360
            start_glyph,
15435360
            end_glyph,
15435360
            class_value,
15435360
        }
15435360
    }
}
impl ReadBinary for ClassDef {
    type HostType<'a> = Self;
225396
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
225396
        match ctxt.read_u16be()? {
            1 => {
16848
                let start_glyph = ctxt.read_u16be()?;
16848
                let glyph_count = ctxt.read_u16be()?;
16848
                let class_value_array =
16848
                    ctxt.read_array::<U16Be>(usize::from(glyph_count))?.to_vec();
16848
                Ok(ClassDef::Format1 {
16848
                    start_glyph,
16848
                    class_value_array,
16848
                })
            }
            2 => {
208548
                let class_range_count = usize::from(ctxt.read_u16be()?);
208548
                let class_range_array = ctxt
208548
                    .read_array::<ClassRangeRecord>(class_range_count)
                    // In the lookahead classdef table for a chaining context substitution
                    // (Format 2; PSTS feature), the Mangal font specifies a class_range_count that
                    // exceeds the number of elements that can be contained in the class_range_array.
                    // We use this hack as a fallback to cap the length based on available bytes
208548
                    .or_else(|_| ctxt.read_array_upto_hack::<ClassRangeRecord>(class_range_count))?
208548
                    .to_vec();
208548
                Ok(ClassDef::Format2 { class_range_array })
            }
            _ => Err(ParseError::BadVersion),
        }
225396
    }
}
impl ClassDef {
356832
    pub fn glyph_class_value(&self, glyph: GlyphId) -> u16 {
356832
        match *self {
            ClassDef::Format1 {
2484
                start_glyph,
2484
                ref class_value_array,
            } => {
2484
                if (glyph >= start_glyph)
1728
                    && (usize::from(glyph - start_glyph) < class_value_array.len())
                {
1728
                    let class_index = glyph - start_glyph;
1728
                    class_value_array[usize::from(class_index)]
                } else {
756
                    0
                }
            }
            ClassDef::Format2 {
354348
                ref class_range_array,
            } => {
21392640
                for class_range in class_range_array {
21255750
                    if (glyph >= class_range.start_glyph) && (glyph <= class_range.end_glyph) {
217458
                        return class_range.class_value;
21038292
                    }
                }
136890
                0
            }
        }
356832
    }
}
pub struct MarkGlyphSets {
    sets: Vec<Coverage>,
}
impl MarkGlyphSets {
    pub fn get(&self, index: usize) -> Option<&Coverage> {
        self.sets.get(index)
    }
}
impl ReadBinary for MarkGlyphSets {
    type HostType<'a> = Self;
    fn read(ctxt: &mut ReadCtxt<'_>) -> Result<Self, ParseError> {
        let start = ctxt.scope();
        let format = ctxt.read_u16be()?;
        ctxt.check_version(format == 1)?;
        let mark_glyph_set_count = ctxt.read_u16be()?;
        let offsets = ctxt.read_array::<U32Be>(usize::from(mark_glyph_set_count))?;
        let sets = offsets
            .iter()
            .map(|offset| start.offset(usize::safe_from(offset)).read::<Coverage>())
            .collect::<Result<_, _>>()?;
        Ok(MarkGlyphSets { sets })
    }
}
pub type LayoutCache<T> = Arc<LayoutCacheData<T>>;
pub type LookupCache<T> = Vec<Option<Arc<LookupCacheItem<T>>>>;
pub struct LookupCacheItem<T> {
    pub lookup_flag: LookupFlag,
    pub mark_filtering_set: Option<u16>,
    pub lookup_subtables: T,
}
pub struct LayoutCacheData<T: LayoutTableType> {
    pub layout_table: LayoutTable<T>,
    coverages: Mutex<ReadCache<Coverage>>,
    classdefs: Mutex<ReadCache<ClassDef>>,
    lookup_cache: Mutex<LookupCache<T::LookupType>>,
    /// maps (script_tag, opt_lang_tag) to FeatureMask
    /// opt_lang_tag = None is represented as `DFLT`
    // [azul web-lift] BTreeMap not HashMap: these caches start EMPTY (cap-0) and the FIRST insert at
    // shape time triggers the lifted hashbrown EMPTY-INSERT mis-lift (reserve_rehash-from-0) → the
    // web/remill backend HANGS in shape_text. BTreeMap has no ctrl-group/empty-static → immune.
    pub supported_features: Mutex<BTreeMap<(u32, u32), u64>>,
    /// maps (script_tag, lang_tag, FeatureMask) to cached_lookups index
    pub lookups_index: Mutex<BTreeMap<(u32, u32, u64), usize>>,
    pub cached_lookups: Mutex<Vec<Vec<(usize, u32)>>>,
}
10812
pub fn new_layout_cache<T: LayoutTableType>(layout_table: LayoutTable<T>) -> LayoutCache<T> {
10812
    let coverages = Mutex::new(ReadCache::new());
10812
    let classdefs = Mutex::new(ReadCache::new());
10812
    let lookup_cache = Mutex::new(Vec::new());
10812
    let supported_features = Mutex::new(BTreeMap::new());
10812
    let lookups_index = Mutex::new(BTreeMap::new());
10812
    let cached_lookups = Mutex::new(vec![Vec::new()]);
10812
    Arc::new(LayoutCacheData {
10812
        layout_table,
10812
        coverages,
10812
        classdefs,
10812
        lookup_cache,
10812
        supported_features,
10812
        lookups_index,
10812
        cached_lookups,
10812
    })
10812
}
#[cfg(test)]
mod tests {
    use super::*;
    use crate::binary::write::{WriteBinary, WriteBuffer};
    fn make_gdef_header(glyph_classdef_offset: u16) -> Vec<u8> {
        let mut data = vec![
            0x00, 0x01, // major version
            0x00, 0x00, // minor version
        ];
        data.extend_from_slice(&glyph_classdef_offset.to_be_bytes());
        data.extend_from_slice(&[
            0x00, 0x00, // glyph classdef offset
            0x00, 0x00, // attach list offset
            0x00, 0x00, // lig caret list offset
            0x00, 0x00, // mark attach classdef offset
        ]);
        data
    }
    #[test]
    fn test_read_gdef_zero_classdef_offset() {
        let data = make_gdef_header(0);
        let gdef = ReadScope::new(&data).read::<GDEFTable>().unwrap();
        assert!(gdef.opt_glyph_classdef.is_none());
    }
    #[test]
    fn test_read_gdef_too_small_classdef_offset() {
        // Offset is not past the end of the header
        let data = make_gdef_header(1);
        let gdef = ReadScope::new(&data).read::<GDEFTable>().unwrap();
        assert!(gdef.opt_glyph_classdef.is_none());
    }
    #[test]
    fn test_read_gdef_too_big_classdef_offset() {
        // Offset past the end of the table
        let data = make_gdef_header(1000);
        match ReadScope::new(&data).read::<GDEFTable>() {
            Ok(_) => panic!("expected error got success"),
            Err(ParseError::BadEof) => {}
            Err(err) => panic!("expeceted ParseError::BadEof got {:?}", err),
        }
    }
    #[test]
    fn read_gpos_v1_x() {
        let mut w = WriteBuffer::new();
        U16Be::write(&mut w, 1u16).unwrap(); // major version
        U16Be::write(&mut w, 2u16).unwrap(); // minor version
        U16Be::write(&mut w, 0u16).unwrap(); // script_list_offset
        U16Be::write(&mut w, 0u16).unwrap(); // feature_list_offset
        U16Be::write(&mut w, 0u16).unwrap(); // lookup_list_offset
        U32Be::write(&mut w, 0u32).unwrap(); // feature_variations_offset
        let data = w.into_inner();
        assert!(ReadScope::new(&data).read::<LayoutTable<GPOS>>().is_ok())
    }
}