ttf_parser/tables/
hvar.rs
1use core::convert::TryFrom;
4
5use crate::{GlyphId, NormalizedCoordinate};
6use crate::parser::{Stream, Offset, Offset32};
7use crate::var_store::ItemVariationStore;
8
9#[derive(Clone, Copy)]
10pub struct Table<'a> {
11 data: &'a [u8],
12 variation_store: ItemVariationStore<'a>,
13 advance_width_mapping_offset: Option<Offset32>,
14 lsb_mapping_offset: Option<Offset32>,
15}
16
17impl<'a> Table<'a> {
18 pub fn parse(data: &'a [u8]) -> Option<Self> {
19 let mut s = Stream::new(data);
20
21 let version: u32 = s.read()?;
22 if version != 0x00010000 {
23 return None;
24 }
25
26 let variation_store_offset: Offset32 = s.read()?;
27 let var_store_s = Stream::new_at(data, variation_store_offset.to_usize())?;
28 let variation_store = ItemVariationStore::parse(var_store_s)?;
29
30 Some(Table {
31 data,
32 variation_store,
33 advance_width_mapping_offset: s.read::<Option<Offset32>>()?,
34 lsb_mapping_offset: s.read::<Option<Offset32>>()?,
35 })
36 }
37}
38
39
40pub struct DeltaSetIndexMap<'a> {
41 data: &'a [u8],
42}
43
44impl<'a> DeltaSetIndexMap<'a> {
45 #[inline]
46 pub fn new(data: &'a [u8]) -> Self {
47 DeltaSetIndexMap { data }
48 }
49
50 #[inline]
51 pub fn map(&self, glyph_id: GlyphId) -> Option<(u16, u16)> {
52 let mut idx = glyph_id.0;
53
54 let mut s = Stream::new(self.data);
55 let entry_format: u16 = s.read()?;
56 let map_count: u16 = s.read()?;
57
58 if map_count == 0 {
59 return None;
60 }
61
62 if idx >= map_count {
64 idx = map_count - 1;
65 }
66
67 let entry_size = ((entry_format >> 4) & 3) + 1;
68 let inner_index_bit_count = u32::from((entry_format & 0xF) + 1);
69
70 s.advance(usize::from(entry_size) * usize::from(idx));
71
72 let mut n = 0u32;
73 for b in s.read_bytes(usize::from(entry_size))? {
74 n = (n << 8) + u32::from(*b);
75 }
76
77 let outer_index = n >> inner_index_bit_count;
78 let inner_index = n & ((1 << inner_index_bit_count) - 1);
79 Some((
80 u16::try_from(outer_index).ok()?,
81 u16::try_from(inner_index).ok()?
82 ))
83 }
84}
85
86#[inline]
87pub(crate) fn glyph_advance_offset(
88 table: Table,
89 glyph_id: GlyphId,
90 coordinates: &[NormalizedCoordinate],
91) -> Option<f32> {
92 let (outer_idx, inner_idx) = if let Some(offset) = table.advance_width_mapping_offset {
93 DeltaSetIndexMap::new(table.data.get(offset.to_usize()..)?).map(glyph_id)?
94 } else {
95 (0, glyph_id.0)
100 };
101
102 table.variation_store.parse_delta(outer_idx, inner_idx, coordinates)
103}
104
105#[inline]
106pub(crate) fn glyph_side_bearing_offset(
107 table: Table,
108 glyph_id: GlyphId,
109 coordinates: &[NormalizedCoordinate],
110) -> Option<f32> {
111 let set_data = table.data.get(table.lsb_mapping_offset?.to_usize()..)?;
112 let (outer_idx, inner_idx) = DeltaSetIndexMap::new(set_data).map(glyph_id)?;
113 table.variation_store.parse_delta(outer_idx, inner_idx, coordinates)
114}