read_fonts/tables/
gsub.rs1pub use super::layout::{
6 ChainedSequenceContext, ClassDef, CoverageTable, Device, FeatureList, FeatureVariations,
7 Lookup, LookupList, ScriptList, SequenceContext,
8};
9use super::layout::{ExtensionLookup, LookupFlag, Subtables};
10
11#[cfg(feature = "std")]
12mod closure;
13#[cfg(test)]
14#[path = "../tests/test_gsub.rs"]
15mod tests;
16
17include!("../../generated/generated_gsub.rs");
18
19pub type SubstitutionLookupList<'a> = LookupList<'a, SubstitutionLookup<'a>>;
21
22pub type SubstitutionSequenceContext<'a> = super::layout::SequenceContext<'a>;
24
25pub type SubstitutionChainContext<'a> = super::layout::ChainedSequenceContext<'a>;
27
28impl<'a, T: FontRead<'a>> ExtensionLookup<'a, T> for ExtensionSubstFormat1<'a, T> {
29 fn extension(&self) -> Result<T, ReadError> {
30 self.extension()
31 }
32}
33
34type SubSubtables<'a, T> = Subtables<'a, T, ExtensionSubstFormat1<'a, T>>;
35
36pub enum SubstitutionSubtables<'a> {
42 Single(SubSubtables<'a, SingleSubst<'a>>),
43 Multiple(SubSubtables<'a, MultipleSubstFormat1<'a>>),
44 Alternate(SubSubtables<'a, AlternateSubstFormat1<'a>>),
45 Ligature(SubSubtables<'a, LigatureSubstFormat1<'a>>),
46 Contextual(SubSubtables<'a, SubstitutionSequenceContext<'a>>),
47 ChainContextual(SubSubtables<'a, SubstitutionChainContext<'a>>),
48 Reverse(SubSubtables<'a, ReverseChainSingleSubstFormat1<'a>>),
49}
50
51impl<'a> SubstitutionLookup<'a> {
52 pub fn lookup_flag(&self) -> LookupFlag {
53 self.of_unit_type().lookup_flag()
54 }
55
56 pub fn lookup_type(&self) -> u16 {
58 self.of_unit_type().lookup_type()
59 }
60
61 pub fn mark_filtering_set(&self) -> Option<u16> {
62 self.of_unit_type().mark_filtering_set()
63 }
64
65 pub fn subtables(&self) -> Result<SubstitutionSubtables<'a>, ReadError> {
70 let raw_lookup = self.of_unit_type();
71 let offsets = raw_lookup.subtable_offsets();
72 let data = raw_lookup.offset_data();
73 match raw_lookup.lookup_type() {
74 1 => Ok(SubstitutionSubtables::Single(Subtables::new(offsets, data))),
75 2 => Ok(SubstitutionSubtables::Multiple(Subtables::new(
76 offsets, data,
77 ))),
78 3 => Ok(SubstitutionSubtables::Alternate(Subtables::new(
79 offsets, data,
80 ))),
81 4 => Ok(SubstitutionSubtables::Ligature(Subtables::new(
82 offsets, data,
83 ))),
84 5 => Ok(SubstitutionSubtables::Contextual(Subtables::new(
85 offsets, data,
86 ))),
87 6 => Ok(SubstitutionSubtables::ChainContextual(Subtables::new(
88 offsets, data,
89 ))),
90 8 => Ok(SubstitutionSubtables::Reverse(Subtables::new(
91 offsets, data,
92 ))),
93 7 => {
94 let first = offsets.first().ok_or(ReadError::OutOfBounds)?.get();
95 let ext: ExtensionSubstFormat1<()> = first.resolve(data)?;
96 match ext.extension_lookup_type() {
97 1 => Ok(SubstitutionSubtables::Single(Subtables::new_ext(
98 offsets, data,
99 ))),
100 2 => Ok(SubstitutionSubtables::Multiple(Subtables::new_ext(
101 offsets, data,
102 ))),
103 3 => Ok(SubstitutionSubtables::Alternate(Subtables::new_ext(
104 offsets, data,
105 ))),
106 4 => Ok(SubstitutionSubtables::Ligature(Subtables::new_ext(
107 offsets, data,
108 ))),
109 5 => Ok(SubstitutionSubtables::Contextual(Subtables::new_ext(
110 offsets, data,
111 ))),
112 6 => Ok(SubstitutionSubtables::ChainContextual(Subtables::new_ext(
113 offsets, data,
114 ))),
115 8 => Ok(SubstitutionSubtables::Reverse(Subtables::new_ext(
116 offsets, data,
117 ))),
118 other => Err(ReadError::InvalidFormat(other as _)),
119 }
120 }
121 other => Err(ReadError::InvalidFormat(other as _)),
122 }
123 }
124}