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 EmptyExtension,
51}
52
53impl<'a> SubstitutionLookup<'a> {
54 pub fn lookup_flag(&self) -> LookupFlag {
55 self.of_unit_type().lookup_flag()
56 }
57
58 pub fn lookup_type(&self) -> u16 {
60 self.of_unit_type().lookup_type()
61 }
62
63 pub fn mark_filtering_set(&self) -> Option<u16> {
64 self.of_unit_type().mark_filtering_set()
65 }
66
67 pub fn subtables(&self) -> Result<SubstitutionSubtables<'a>, ReadError> {
72 let raw_lookup = self.of_unit_type();
73 let offsets = raw_lookup.subtable_offsets();
74 let data = raw_lookup.offset_data();
75 match raw_lookup.lookup_type() {
76 1 => Ok(SubstitutionSubtables::Single(Subtables::new(offsets, data))),
77 2 => Ok(SubstitutionSubtables::Multiple(Subtables::new(
78 offsets, data,
79 ))),
80 3 => Ok(SubstitutionSubtables::Alternate(Subtables::new(
81 offsets, data,
82 ))),
83 4 => Ok(SubstitutionSubtables::Ligature(Subtables::new(
84 offsets, data,
85 ))),
86 5 => Ok(SubstitutionSubtables::Contextual(Subtables::new(
87 offsets, data,
88 ))),
89 6 => Ok(SubstitutionSubtables::ChainContextual(Subtables::new(
90 offsets, data,
91 ))),
92 8 => Ok(SubstitutionSubtables::Reverse(Subtables::new(
93 offsets, data,
94 ))),
95 7 => {
96 let Some(lookup_type) = offsets.iter().find_map(|off| {
100 off.get()
101 .resolve::<ExtensionSubstFormat1<()>>(data)
102 .ok()
103 .map(|ext| ext.extension_lookup_type())
104 }) else {
105 return Ok(SubstitutionSubtables::EmptyExtension);
106 };
107
108 match lookup_type {
109 1 => Ok(SubstitutionSubtables::Single(Subtables::new_ext(
110 offsets, data,
111 ))),
112 2 => Ok(SubstitutionSubtables::Multiple(Subtables::new_ext(
113 offsets, data,
114 ))),
115 3 => Ok(SubstitutionSubtables::Alternate(Subtables::new_ext(
116 offsets, data,
117 ))),
118 4 => Ok(SubstitutionSubtables::Ligature(Subtables::new_ext(
119 offsets, data,
120 ))),
121 5 => Ok(SubstitutionSubtables::Contextual(Subtables::new_ext(
122 offsets, data,
123 ))),
124 6 => Ok(SubstitutionSubtables::ChainContextual(Subtables::new_ext(
125 offsets, data,
126 ))),
127 8 => Ok(SubstitutionSubtables::Reverse(Subtables::new_ext(
128 offsets, data,
129 ))),
130 other => Err(ReadError::InvalidFormat(other as _)),
131 }
132 }
133 other => Err(ReadError::InvalidFormat(other as _)),
134 }
135 }
136}