1use super::StringId;
2use crate::parser::{FromData, LazyArray16, Stream};
3use crate::GlyphId;
4
5/// The Expert Encoding conversion as defined in the Adobe Technical Note #5176 Appendix C.
6#[rustfmt::skip]
7#[cfg(feature = "glyph-names")]
8const EXPERT_ENCODING: &[u16] = &[
9 0, 1, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 13, 14, 15, 99,
10 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 252,
11 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110,
12 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282,
13 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
14 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
15 315, 316, 317, 318, 158, 155, 163, 319, 320, 321, 322, 323, 324, 325, 326, 150,
16 164, 169, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340,
17 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356,
18 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372,
19 373, 374, 375, 376, 377, 378,
20];
21
22/// The Expert Subset Encoding conversion as defined in the Adobe Technical Note #5176 Appendix C.
23#[rustfmt::skip]
24#[cfg(feature = "glyph-names")]
25const EXPERT_SUBSET_ENCODING: &[u16] = &[
26 0, 1, 231, 232, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240, 241, 242,
27 243, 244, 245, 246, 247, 248, 27, 28, 249, 250, 251, 253, 254, 255, 256, 257,
28 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110, 267, 268, 269, 270, 272,
29 300, 301, 302, 305, 314, 315, 158, 155, 163, 320, 321, 322, 323, 324, 325, 326,
30 150, 164, 169, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339,
31 340, 341, 342, 343, 344, 345, 346
32];
33
34#[derive(Clone, Copy, Debug)]
35pub(crate) struct Format1Range {
36 first: StringId,
37 left: u8,
38}
39
40impl FromData for Format1Range {
41 const SIZE: usize = 3;
42
43 #[inline]
44 fn parse(data: &[u8]) -> Option<Self> {
45 let mut s: Stream<'_> = Stream::new(data);
46 Some(Format1Range {
47 first: s.read::<StringId>()?,
48 left: s.read::<u8>()?,
49 })
50 }
51}
52
53#[derive(Clone, Copy, Debug)]
54pub(crate) struct Format2Range {
55 first: StringId,
56 left: u16,
57}
58
59impl FromData for Format2Range {
60 const SIZE: usize = 4;
61
62 #[inline]
63 fn parse(data: &[u8]) -> Option<Self> {
64 let mut s: Stream<'_> = Stream::new(data);
65 Some(Format2Range {
66 first: s.read::<StringId>()?,
67 left: s.read::<u16>()?,
68 })
69 }
70}
71
72#[derive(Clone, Copy, Debug)]
73pub(crate) enum Charset<'a> {
74 ISOAdobe,
75 Expert,
76 ExpertSubset,
77 Format0(LazyArray16<'a, StringId>),
78 Format1(LazyArray16<'a, Format1Range>),
79 Format2(LazyArray16<'a, Format2Range>),
80}
81
82impl Charset<'_> {
83 pub fn sid_to_gid(&self, sid: StringId) -> Option<GlyphId> {
84 if sid.0 == 0 {
85 return Some(GlyphId(0));
86 }
87
88 match self {
89 Charset::ISOAdobe | Charset::Expert | Charset::ExpertSubset => None,
90 Charset::Format0(ref array) => {
91 // First glyph is omitted, so we have to add 1.
92 array
93 .into_iter()
94 .position(|n| n == sid)
95 .map(|n| GlyphId(n as u16 + 1))
96 }
97 Charset::Format1(array) => {
98 let mut glyph_id = GlyphId(1);
99 for range in *array {
100 let last = u32::from(range.first.0) + u32::from(range.left);
101 if range.first <= sid && u32::from(sid.0) <= last {
102 glyph_id.0 += sid.0 - range.first.0;
103 return Some(glyph_id);
104 }
105
106 glyph_id.0 += u16::from(range.left) + 1;
107 }
108
109 None
110 }
111 Charset::Format2(array) => {
112 // The same as format 1, but Range::left is u16.
113 let mut glyph_id = GlyphId(1);
114 for range in *array {
115 let last = u32::from(range.first.0) + u32::from(range.left);
116 if sid >= range.first && u32::from(sid.0) <= last {
117 glyph_id.0 += sid.0 - range.first.0;
118 return Some(glyph_id);
119 }
120
121 glyph_id.0 += range.left + 1;
122 }
123
124 None
125 }
126 }
127 }
128
129 #[cfg(feature = "glyph-names")]
130 pub fn gid_to_sid(&self, gid: GlyphId) -> Option<StringId> {
131 match self {
132 Charset::ISOAdobe => {
133 if gid.0 <= 228 {
134 Some(StringId(gid.0))
135 } else {
136 None
137 }
138 }
139 Charset::Expert => EXPERT_ENCODING
140 .get(usize::from(gid.0))
141 .cloned()
142 .map(StringId),
143 Charset::ExpertSubset => EXPERT_SUBSET_ENCODING
144 .get(usize::from(gid.0))
145 .cloned()
146 .map(StringId),
147 Charset::Format0(ref array) => {
148 if gid.0 == 0 {
149 Some(StringId(0))
150 } else {
151 array.get(gid.0 - 1)
152 }
153 }
154 Charset::Format1(array) => {
155 if gid.0 == 0 {
156 Some(StringId(0))
157 } else {
158 let mut sid = gid.0 - 1;
159 for range in *array {
160 if sid <= u16::from(range.left) {
161 sid = sid.checked_add(range.first.0)?;
162 return Some(StringId(sid));
163 }
164
165 sid = sid.checked_sub(u16::from(range.left) + 1)?;
166 }
167
168 None
169 }
170 }
171 Charset::Format2(array) => {
172 if gid.0 == 0 {
173 Some(StringId(0))
174 } else {
175 let mut sid = gid.0 - 1;
176 for range in *array {
177 if sid <= range.left {
178 sid = sid.checked_add(range.first.0)?;
179 return Some(StringId(sid));
180 }
181
182 sid = sid.checked_sub(range.left.checked_add(1)?)?;
183 }
184
185 None
186 }
187 }
188 }
189 }
190}
191
192pub(crate) fn parse_charset<'a>(number_of_glyphs: u16, s: &mut Stream<'a>) -> Option<Charset<'a>> {
193 if number_of_glyphs < 2 {
194 return None;
195 }
196
197 // -1 everywhere, since `.notdef` is omitted.
198 let format = s.read::<u8>()?;
199 match format {
200 0 => Some(Charset::Format0(
201 s.read_array16::<StringId>(number_of_glyphs - 1)?,
202 )),
203 1 => {
204 // The number of ranges is not defined, so we have to
205 // read until no glyphs are left.
206 let mut count = 0;
207 {
208 let mut s = s.clone();
209 let mut total_left = number_of_glyphs - 1;
210 while total_left > 0 {
211 s.skip::<StringId>(); // first
212 let left = s.read::<u8>()?;
213 total_left = total_left.checked_sub(u16::from(left) + 1)?;
214 count += 1;
215 }
216 }
217
218 s.read_array16::<Format1Range>(count).map(Charset::Format1)
219 }
220 2 => {
221 // The same as format 1, but Range::left is u16.
222 let mut count = 0;
223 {
224 let mut s = s.clone();
225 let mut total_left = number_of_glyphs - 1;
226 while total_left > 0 {
227 s.skip::<StringId>(); // first
228 let left = s.read::<u16>()?.checked_add(1)?;
229 total_left = total_left.checked_sub(left)?;
230 count += 1;
231 }
232 }
233
234 s.read_array16::<Format2Range>(count).map(Charset::Format2)
235 }
236 _ => None,
237 }
238}
239