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