1 | //! A [Horizontal/Vertical Metrics Variations Table]( |
2 | //! https://docs.microsoft.com/en-us/typography/opentype/spec/hvar) implementation. |
3 | |
4 | use core::convert::TryFrom; |
5 | |
6 | use crate::parser::{Offset, Offset32, Stream}; |
7 | use crate::var_store::ItemVariationStore; |
8 | use crate::{GlyphId, NormalizedCoordinate}; |
9 | |
10 | struct DeltaSetIndexMap<'a> { |
11 | data: &'a [u8], |
12 | } |
13 | |
14 | impl<'a> DeltaSetIndexMap<'a> { |
15 | #[inline ] |
16 | fn new(data: &'a [u8]) -> Self { |
17 | DeltaSetIndexMap { data } |
18 | } |
19 | |
20 | #[inline ] |
21 | fn map(&self, glyph_id: GlyphId) -> Option<(u16, u16)> { |
22 | let mut idx = glyph_id.0; |
23 | |
24 | let mut s = Stream::new(self.data); |
25 | let entry_format = s.read::<u16>()?; |
26 | let map_count = s.read::<u16>()?; |
27 | |
28 | if map_count == 0 { |
29 | return None; |
30 | } |
31 | |
32 | // 'If a given glyph ID is greater than mapCount-1, then the last entry is used.' |
33 | if idx >= map_count { |
34 | idx = map_count - 1; |
35 | } |
36 | |
37 | let entry_size = ((entry_format >> 4) & 3) + 1; |
38 | let inner_index_bit_count = u32::from((entry_format & 0xF) + 1); |
39 | |
40 | s.advance(usize::from(entry_size) * usize::from(idx)); |
41 | |
42 | let mut n = 0u32; |
43 | for b in s.read_bytes(usize::from(entry_size))? { |
44 | n = (n << 8) + u32::from(*b); |
45 | } |
46 | |
47 | let outer_index = n >> inner_index_bit_count; |
48 | let inner_index = n & ((1 << inner_index_bit_count) - 1); |
49 | Some(( |
50 | u16::try_from(outer_index).ok()?, |
51 | u16::try_from(inner_index).ok()?, |
52 | )) |
53 | } |
54 | } |
55 | |
56 | /// A [Horizontal/Vertical Metrics Variations Table]( |
57 | /// https://docs.microsoft.com/en-us/typography/opentype/spec/hvar). |
58 | #[derive (Clone, Copy)] |
59 | pub struct Table<'a> { |
60 | data: &'a [u8], |
61 | variation_store: ItemVariationStore<'a>, |
62 | advance_width_mapping_offset: Option<Offset32>, |
63 | lsb_mapping_offset: Option<Offset32>, |
64 | } |
65 | |
66 | impl<'a> Table<'a> { |
67 | /// Parses a table from raw data. |
68 | pub fn parse(data: &'a [u8]) -> Option<Self> { |
69 | let mut s = Stream::new(data); |
70 | |
71 | let version = s.read::<u32>()?; |
72 | if version != 0x00010000 { |
73 | return None; |
74 | } |
75 | |
76 | let variation_store_offset = s.read::<Offset32>()?; |
77 | let var_store_s = Stream::new_at(data, variation_store_offset.to_usize())?; |
78 | let variation_store = ItemVariationStore::parse(var_store_s)?; |
79 | |
80 | Some(Table { |
81 | data, |
82 | variation_store, |
83 | advance_width_mapping_offset: s.read::<Option<Offset32>>()?, |
84 | lsb_mapping_offset: s.read::<Option<Offset32>>()?, |
85 | }) |
86 | } |
87 | |
88 | /// Returns advance offset for a glyph. |
89 | #[inline ] |
90 | pub fn advance_offset( |
91 | &self, |
92 | glyph_id: GlyphId, |
93 | coordinates: &[NormalizedCoordinate], |
94 | ) -> Option<f32> { |
95 | let (outer_idx, inner_idx) = if let Some(offset) = self.advance_width_mapping_offset { |
96 | DeltaSetIndexMap::new(self.data.get(offset.to_usize()..)?).map(glyph_id)? |
97 | } else { |
98 | // 'If there is no delta-set index mapping table for advance widths, |
99 | // then glyph IDs implicitly provide the indices: |
100 | // for a given glyph ID, the delta-set outer-level index is zero, |
101 | // and the glyph ID is the delta-set inner-level index.' |
102 | (0, glyph_id.0) |
103 | }; |
104 | |
105 | self.variation_store |
106 | .parse_delta(outer_idx, inner_idx, coordinates) |
107 | } |
108 | |
109 | /// Returns side bearing offset for a glyph. |
110 | #[inline ] |
111 | pub fn side_bearing_offset( |
112 | &self, |
113 | glyph_id: GlyphId, |
114 | coordinates: &[NormalizedCoordinate], |
115 | ) -> Option<f32> { |
116 | let set_data = self.data.get(self.lsb_mapping_offset?.to_usize()..)?; |
117 | let (outer_idx, inner_idx) = DeltaSetIndexMap::new(set_data).map(glyph_id)?; |
118 | self.variation_store |
119 | .parse_delta(outer_idx, inner_idx, coordinates) |
120 | } |
121 | } |
122 | |
123 | impl core::fmt::Debug for Table<'_> { |
124 | fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { |
125 | write!(f, "Table {{ ... }}" ) |
126 | } |
127 | } |
128 | |