1use super::{CoverageArray, Covered, Subtable};
2use crate::parse_prelude::*;
3
4#[derive(Copy, Clone, Debug)]
8pub struct SingleSubst1<'a>(pub(super) Subtable<'a>);
9
10impl<'a> SingleSubst1<'a> {
11 pub fn get(&self, glyph_id: Covered) -> Option<u16> {
13 self.get_impl(glyph_id.glyph_id())
14 }
15
16 pub fn delta(&self) -> Option<i16> {
18 let (data, offset) = self.0.data_and_offset();
19 data.read_i16(offset + 4)
20 }
21
22 pub fn substs_with(&self, mut f: impl FnMut(GlyphId, GlyphId) -> bool) -> Option<bool> {
24 self.0.coverage().indices_with(|glyph_id, _| {
25 if let Some(subst) = self.get_impl(glyph_id) {
26 if !f(glyph_id, subst) {
27 return false;
28 }
29 }
30 true
31 })
32 }
33
34 fn get_impl(&self, glyph_id: u16) -> Option<u16> {
35 let delta = self.delta()? as i32;
36 Some((glyph_id as i32 + delta) as u16)
37 }
38}
39
40#[derive(Copy, Clone, Debug)]
44pub struct SingleSubst2<'a>(pub(super) Subtable<'a>);
45
46impl<'a> SingleSubst2<'a> {
47 pub fn get(&self, glyph_id: Covered) -> Option<u16> {
49 self.get_impl(glyph_id.coverage_index())
50 }
51
52 pub fn substs_with(&self, mut f: impl FnMut(GlyphId, GlyphId) -> bool) -> Option<bool> {
54 self.0.coverage().indices_with(|glyph_id, coverage| {
55 if let Some(subst) = self.get_impl(coverage) {
56 if !f(glyph_id, subst) {
57 return false;
58 }
59 }
60 true
61 })
62 }
63
64 fn get_impl(&self, coverage: u16) -> Option<u16> {
65 let array_base = self.0.record.offset as usize + 6;
66 self.0
67 .data()
68 .read::<u16>(array_base + coverage as usize * 2)
69 }
70}
71
72#[derive(Copy, Clone, Debug)]
76pub struct MultipleSubst1<'a>(pub(super) Subtable<'a>);
77
78impl<'a> MultipleSubst1<'a> {
79 pub fn get(&self, glyph_id: Covered) -> Option<Slice<'a, GlyphId>> {
81 self.get_impl(glyph_id.coverage_index())
82 }
83
84 pub fn substs_with(
86 &self,
87 mut f: impl FnMut(GlyphId, Slice<'a, GlyphId>) -> bool,
88 ) -> Option<bool> {
89 self.0.coverage().indices_with(|glyph_id, coverage| {
90 if let Some(subst) = self.get_impl(coverage) {
91 if !f(glyph_id, subst) {
92 return false;
93 }
94 }
95 true
96 })
97 }
98
99 fn get_impl(&self, coverage: u16) -> Option<Slice<'a, GlyphId>> {
100 let data = self.0.data();
101 let base = self.0.record.offset as usize;
102 let array_base = base + data.read::<u16>(base + 6 + coverage as usize * 2)? as usize;
103 let array_len = data.read::<u16>(array_base)? as usize;
104 data.read_slice::<u16>(array_base + 2, array_len)
105 }
106}
107
108#[derive(Copy, Clone, Debug)]
112pub struct AlternateSubst1<'a>(pub(super) Subtable<'a>);
113
114impl<'a> AlternateSubst1<'a> {
115 pub fn get(&self, glyph_id: Covered) -> Option<Slice<'a, GlyphId>> {
117 MultipleSubst1(self.0).get(glyph_id)
118 }
119
120 pub fn alternates_with(
122 &self,
123 f: impl FnMut(GlyphId, Slice<'a, GlyphId>) -> bool,
124 ) -> Option<bool> {
125 MultipleSubst1(self.0).substs_with(f)
126 }
127}
128
129#[derive(Copy, Clone, Debug)]
133pub struct LigatureSubst1<'a>(pub(super) Subtable<'a>);
134
135impl<'a> LigatureSubst1<'a> {
136 pub fn get(&self, covered: Covered) -> Option<Ligatures<'a>> {
138 self.get_impl(covered.glyph_id(), covered.coverage_index())
139 }
140
141 pub fn ligatures_with(&self, mut f: impl FnMut(Ligature<'a>) -> bool) -> Option<bool> {
143 self.0.coverage().indices_with(|glyph_id, coverage| {
144 if let Some(ligatures) = self.get_impl(glyph_id, coverage) {
145 for ligature in ligatures {
146 if !f(ligature) {
147 return false;
148 }
149 }
150 }
151 true
152 })
153 }
154
155 fn get_impl(&self, glyph_id: u16, coverage: u16) -> Option<Ligatures<'a>> {
156 let data = self.0.data();
157 let base = self.0.record.offset as usize;
158 let set_base = base + data.read::<u16>(base + 6 + coverage as usize * 2)? as usize;
159 let len = data.read::<u16>(set_base)? as usize;
160 Some(Ligatures {
161 data: Buffer::with_offset(data.data(), set_base)?,
162 first_component: glyph_id,
163 len,
164 pos: 0,
165 })
166 }
167}
168
169#[derive(Copy, Clone)]
171pub struct Ligatures<'a> {
172 data: Buffer<'a>,
173 first_component: u16,
174 len: usize,
175 pos: usize,
176}
177
178impl<'a> Iterator for Ligatures<'a> {
179 type Item = Ligature<'a>;
180
181 fn next(&mut self) -> Option<Self::Item> {
182 if self.pos >= self.len {
183 return None;
184 }
185 let pos = self.pos;
186 self.pos += 1;
187 let base = self.data.read::<u16>(2 + pos * 2)? as usize;
188 let ligature = self.data.read::<u16>(base)?;
189 let len = (self.data.read::<u16>(base + 2)? as usize).saturating_sub(1);
190 let trailing_components = self.data.read_slice::<u16>(base + 4, len)?;
191 Some(Ligature {
192 first_component: self.first_component,
193 trailing_components,
194 ligature,
195 })
196 }
197}
198
199#[derive(Copy, Clone)]
201pub struct Ligature<'a> {
202 pub first_component: GlyphId,
204 pub trailing_components: Slice<'a, GlyphId>,
206 pub ligature: GlyphId,
208}
209
210#[derive(Copy, Clone, Debug)]
214pub struct RevChainContext1<'a>(pub(super) Subtable<'a>);
215
216impl<'a> RevChainContext1<'a> {
217 pub fn rule(&self) -> Option<RevChainContextRule<'a>> {
218 let data = *self.0.data();
219 let base = self.0.record.offset;
220 let mut s = data.cursor_at(base as usize + 4)?;
221 let backtrack_count = s.read::<u16>()? as usize;
222 let backtrack = CoverageArray::new(data, base, s.read_slice::<u16>(backtrack_count)?);
223 let lookahead_count = s.read::<u16>()? as usize;
224 let lookahead = CoverageArray::new(data, base, s.read_slice::<u16>(lookahead_count)?);
225 let substitution_count = s.read::<u16>()? as usize;
226 let substitutions = s.read_slice::<u16>(substitution_count)?;
227 Some(RevChainContextRule {
228 backtrack,
229 lookahead,
230 substitutions,
231 })
232 }
233}
234
235#[derive(Copy, Clone)]
237pub struct RevChainContextRule<'a> {
238 pub backtrack: CoverageArray<'a>,
240 pub lookahead: CoverageArray<'a>,
242 pub substitutions: Slice<'a, GlyphId>,
244}