1use core::num::NonZeroU16;
9
10use crate::{aat, GlyphId};
11use crate::kern::KerningPair;
12use crate::parser::{Stream, FromData, NumFrom, Offset32, Offset, LazyArray32};
13
14const HEADER_SIZE: usize = 12;
15
16#[derive(Clone, Copy, Debug)]
22pub struct Subtable0<'a> {
23 pub pairs: LazyArray32<'a, KerningPair>,
25}
26
27impl<'a> Subtable0<'a> {
28 fn parse(data: &'a [u8]) -> Option<Self> {
30 let mut s = Stream::new(data);
31 let number_of_pairs = s.read::<u32>()?;
32 s.advance(12); let pairs = s.read_array32::<KerningPair>(number_of_pairs)?;
34 Some(Self { pairs })
35 }
36
37 #[inline]
39 pub fn glyphs_kerning(&self, left: GlyphId, right: GlyphId) -> Option<i16> {
40 let needle = u32::from(left.0) << 16 | u32::from(right.0);
41 self.pairs.binary_search_by(|v| v.pair.cmp(&needle)).map(|(_, v)| v.value)
42 }
43}
44
45
46#[derive(Clone, Copy, Debug)]
48pub struct EntryData {
49 pub action_index: u16,
51}
52
53impl FromData for EntryData {
54 const SIZE: usize = 2;
55
56 #[inline]
57 fn parse(data: &[u8]) -> Option<Self> {
58 let mut s = Stream::new(data);
59 Some(EntryData {
60 action_index: s.read::<u16>()?,
61 })
62 }
63}
64
65#[derive(Clone)]
69pub struct Subtable1<'a> {
70 pub state_table: aat::ExtendedStateTable<'a, EntryData>,
72 actions_data: &'a [u8],
73}
74
75impl<'a> Subtable1<'a> {
76 fn parse(number_of_glyphs: NonZeroU16, data: &'a [u8]) -> Option<Self> {
77 let mut s = Stream::new(data);
78 let state_table = aat::ExtendedStateTable::parse(number_of_glyphs, &mut s)?;
79
80 let actions_offset = s.read::<Offset32>()?;
82 let actions_data = data.get(actions_offset.to_usize()..)?;
86
87 Some(Subtable1 {
88 state_table,
89 actions_data,
90 })
91 }
92
93 #[inline]
95 pub fn glyphs_kerning(&self, action_index: u16) -> Option<i16> {
96 Stream::read_at(self.actions_data, usize::from(action_index) * i16::SIZE)
97 }
98}
99
100impl<'a> core::ops::Deref for Subtable1<'a> {
101 type Target = aat::ExtendedStateTable<'a, EntryData>;
102
103 fn deref(&self) -> &Self::Target {
104 &self.state_table
105 }
106}
107
108impl core::fmt::Debug for Subtable1<'_> {
109 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
110 write!(f, "Subtable1 {{ ... }}")
111 }
112}
113
114
115#[derive(Clone, Copy)]
121pub struct Subtable2<'a>(&'a [u8]); impl<'a> Subtable2<'a> {
124 pub fn glyphs_kerning(&self, left: GlyphId, right: GlyphId) -> Option<i16> {
126 let mut s = Stream::new(self.0);
127 s.skip::<u32>(); let left_hand_table_offset = s.read::<Offset32>()?.to_usize().checked_sub(HEADER_SIZE)?;
132 let right_hand_table_offset = s.read::<Offset32>()?.to_usize().checked_sub(HEADER_SIZE)?;
133 let array_offset = s.read::<Offset32>()?.to_usize().checked_sub(HEADER_SIZE)?;
134
135 let left_class = crate::kern::get_format2_class(left.0, left_hand_table_offset, self.0).unwrap_or(0);
140 let right_class = crate::kern::get_format2_class(right.0, right_hand_table_offset, self.0).unwrap_or(0);
141
142 if usize::from(left_class) < array_offset {
144 return None;
145 }
146
147 let index = usize::from(left_class) + usize::from(right_class);
149 let value_offset = index.checked_sub(HEADER_SIZE)?;
150 Stream::read_at::<i16>(self.0, value_offset)
151 }
152}
153
154impl core::fmt::Debug for Subtable2<'_> {
155 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
156 write!(f, "Subtable2 {{ ... }}")
157 }
158}
159
160
161#[derive(Clone, Copy)]
163pub struct AnchorPoints<'a>(&'a [u8]);
164
165impl AnchorPoints<'_> {
166 pub fn get(&self, action_index: u16) -> Option<(u16, u16)> {
168 let offset = usize::from(action_index) * u16::SIZE;
169 let mut s = Stream::new_at(self.0, offset)?;
170 Some((s.read::<u16>()?, s.read::<u16>()?))
171 }
172}
173
174impl core::fmt::Debug for AnchorPoints<'_> {
175 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
176 write!(f, "AnchorPoints {{ ... }}")
177 }
178}
179
180#[derive(Clone)]
188pub struct Subtable4<'a> {
189 pub state_table: aat::ExtendedStateTable<'a, EntryData>,
191 pub anchor_points: AnchorPoints<'a>,
193}
194
195impl<'a> Subtable4<'a> {
196 fn parse(number_of_glyphs: NonZeroU16, data: &'a [u8]) -> Option<Self> {
197 let mut s = Stream::new(data);
198 let state_table = aat::ExtendedStateTable::parse(number_of_glyphs, &mut s)?;
199 let flags = s.read::<u32>()?;
200 let action_type = ((flags & 0xC0000000) >> 30) as u8;
201 let points_offset = usize::num_from(flags & 0x00FFFFFF);
202
203 if action_type != 1 {
205 return None;
206 }
207
208 Some(Self {
209 state_table,
210 anchor_points: AnchorPoints(data.get(points_offset..)?),
211 })
212 }
213}
214
215impl<'a> core::ops::Deref for Subtable4<'a> {
216 type Target = aat::ExtendedStateTable<'a, EntryData>;
217
218 fn deref(&self) -> &Self::Target {
219 &self.state_table
220 }
221}
222
223impl core::fmt::Debug for Subtable4<'_> {
224 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
225 write!(f, "Subtable4 {{ ... }}")
226 }
227}
228
229
230#[derive(Clone, Copy)]
234pub struct Subtable6<'a>{
235 data: &'a [u8],
236 number_of_glyphs: NonZeroU16,
237}
238
239impl<'a> Subtable6<'a> {
240 fn parse(number_of_glyphs: NonZeroU16, data: &'a [u8]) -> Self {
242 Subtable6 { number_of_glyphs, data }
243 }
244
245 pub fn glyphs_kerning(&self, left: GlyphId, right: GlyphId) -> Option<i16> {
247 use core::convert::TryFrom;
248
249 let mut s = Stream::new(self.data);
250 let flags = s.read::<u32>()?;
251 s.skip::<u16>(); s.skip::<u16>(); let row_index_table_offset = s.read::<Offset32>()?.to_usize().checked_sub(HEADER_SIZE)?;
255 let column_index_table_offset = s.read::<Offset32>()?.to_usize().checked_sub(HEADER_SIZE)?;
256 let kerning_array_offset = s.read::<Offset32>()?.to_usize().checked_sub(HEADER_SIZE)?;
257 let kerning_vector_offset = s.read::<Offset32>()?.to_usize().checked_sub(HEADER_SIZE)?;
258
259 let row_index_table_data = self.data.get(row_index_table_offset..)?;
260 let column_index_table_data = self.data.get(column_index_table_offset..)?;
261 let kerning_array_data = self.data.get(kerning_array_offset..)?;
262 let kerning_vector_data = self.data.get(kerning_vector_offset..)?;
263
264 let has_long_values = flags & 0x00000001 != 0;
265 if has_long_values {
266 let l: u32 = aat::Lookup::parse(self.number_of_glyphs, row_index_table_data)?
267 .value(left).unwrap_or(0) as u32;
268
269 let r: u32 = aat::Lookup::parse(self.number_of_glyphs, column_index_table_data)?
270 .value(right).unwrap_or(0) as u32;
271
272 let array_offset = usize::try_from(l + r).ok()?.checked_mul(i32::SIZE)?;
273 let vector_offset: u32 = Stream::read_at(kerning_array_data, array_offset)?;
274
275 Stream::read_at(kerning_vector_data, usize::num_from(vector_offset))
276 } else {
277 let l: u16 = aat::Lookup::parse(self.number_of_glyphs, row_index_table_data)?
278 .value(left).unwrap_or(0);
279
280 let r: u16 = aat::Lookup::parse(self.number_of_glyphs, column_index_table_data)?
281 .value(right).unwrap_or(0);
282
283 let array_offset = usize::try_from(l + r).ok()?.checked_mul(i16::SIZE)?;
284 let vector_offset: u16 = Stream::read_at(kerning_array_data, array_offset)?;
285
286 Stream::read_at(kerning_vector_data, usize::from(vector_offset))
287 }
288 }
289}
290
291impl core::fmt::Debug for Subtable6<'_> {
292 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
293 write!(f, "Subtable6 {{ ... }}")
294 }
295}
296
297
298#[allow(missing_docs)]
300#[derive(Clone, Debug)]
301pub enum Format<'a> {
302 Format0(Subtable0<'a>),
303 Format1(Subtable1<'a>),
304 Format2(Subtable2<'a>),
305 Format4(Subtable4<'a>),
306 Format6(Subtable6<'a>),
307}
308
309#[derive(Clone, Debug)]
311pub struct Subtable<'a> {
312 pub horizontal: bool,
314 pub variable: bool,
316 pub has_cross_stream: bool,
318 pub has_state_machine: bool,
322 pub tuple_count: u32,
326 pub format: Format<'a>,
328}
329
330impl<'a> Subtable<'a> {
331 #[inline]
335 pub fn glyphs_kerning(&self, left: GlyphId, right: GlyphId) -> Option<i16> {
336 match self.format {
337 Format::Format0(ref subtable) => subtable.glyphs_kerning(left, right),
338 Format::Format1(_) => None,
339 Format::Format2(ref subtable) => subtable.glyphs_kerning(left, right),
340 Format::Format4(_) => None,
341 Format::Format6(ref subtable) => subtable.glyphs_kerning(left, right),
342 }
343 }
344}
345
346
347#[derive(Clone, Copy, Debug)]
348struct Coverage(u8);
349
350impl Coverage {
351 #[inline] pub fn is_horizontal(self) -> bool { self.0 & (1 << 7) == 0 }
353 #[inline] pub fn has_cross_stream(self) -> bool { self.0 & (1 << 6) != 0 }
354 #[inline] pub fn is_variable(self) -> bool { self.0 & (1 << 5) != 0 }
355}
356
357
358#[derive(Clone, Copy)]
363pub struct Subtables<'a> {
364 number_of_glyphs: NonZeroU16,
366 number_of_tables: u32,
368 data: &'a [u8],
370}
371
372impl core::fmt::Debug for Subtables<'_> {
373 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
374 write!(f, "Subtables {{ ... }}")
375 }
376}
377
378impl<'a> IntoIterator for Subtables<'a> {
379 type Item = Subtable<'a>;
380 type IntoIter = SubtablesIter<'a>;
381
382 #[inline]
383 fn into_iter(self) -> Self::IntoIter {
384 SubtablesIter {
385 number_of_glyphs: self.number_of_glyphs,
386 table_index: 0,
387 number_of_tables: self.number_of_tables,
388 stream: Stream::new(self.data),
389 }
390 }
391}
392
393#[allow(missing_debug_implementations)]
395#[derive(Clone, Copy)]
396pub struct SubtablesIter<'a> {
397 number_of_glyphs: NonZeroU16,
399 table_index: u32,
401 number_of_tables: u32,
403 stream: Stream<'a>,
405}
406
407impl<'a> Iterator for SubtablesIter<'a> {
408 type Item = Subtable<'a>;
409
410 fn next(&mut self) -> Option<Self::Item> {
411 if self.table_index == self.number_of_tables {
412 return None;
413 }
414
415 if self.stream.at_end() {
416 return None;
417 }
418
419 let s = &mut self.stream;
420
421 let table_len = s.read::<u32>()?;
422 let coverage = Coverage(s.read::<u8>()?);
423 s.skip::<u16>(); let raw_format = s.read::<u8>()?;
425 let tuple_count = s.read::<u32>()?;
426
427 let data_len = usize::num_from(table_len).checked_sub(HEADER_SIZE)?;
429 let data = s.read_bytes(data_len)?;
430
431 let format = match raw_format {
432 0 => Subtable0::parse(data).map(Format::Format0)?,
433 1 => Subtable1::parse(self.number_of_glyphs, data).map(Format::Format1)?,
434 2 => Format::Format2(Subtable2(data)),
435 4 => Subtable4::parse(self.number_of_glyphs, data).map(Format::Format4)?,
436 6 => Format::Format6(Subtable6::parse(self.number_of_glyphs, data)),
437 _ => {
438 return None;
440 }
441 };
442
443 Some(Subtable {
444 horizontal: coverage.is_horizontal(),
445 variable: coverage.is_variable(),
446 has_cross_stream: coverage.has_cross_stream(),
447 has_state_machine: raw_format == 1 || raw_format == 4,
448 tuple_count,
449 format,
450 })
451 }
452}
453
454
455#[derive(Clone, Copy, Debug)]
458pub struct Table<'a> {
459 pub subtables: Subtables<'a>,
461}
462
463impl<'a> Table<'a> {
464 pub fn parse(number_of_glyphs: NonZeroU16, data: &'a [u8]) -> Option<Self> {
468 let mut s = Stream::new(data);
469 s.skip::<u16>(); s.skip::<u16>(); let number_of_tables = s.read::<u32>()?;
472 let subtables = Subtables {
473 number_of_glyphs,
474 number_of_tables,
475 data: s.tail()?,
476 };
477
478 Some(Table { subtables })
479 }
480}