1use std::{fs::read, io::{Error, ErrorKind}, path::Path};
2
3use crate::fonts::parse::{constants::{ARG_1_AND_2_ARE_WORDS, MAC_ROMAN_LOOKUP, MAC_STANDARD_NAMES, MORE_COMPONENTS, REPEAT_FLAG, USE_MARK_FILTERING_SET, WE_HAVE_A_SCALE, WE_HAVE_A_TWO_BY_TWO, WE_HAVE_AN_X_AND_Y_SCALE, WE_HAVE_INSTRUCTIONS, X_ADVANCE, X_ADVANCE_DEVICE, X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR, X_PLACEMENT, X_PLACEMENT_DEVICE, X_SHORT_VECTOR, Y_ADVANCE, Y_ADVANCE_DEVICE, Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR, Y_PLACEMENT, Y_PLACEMENT_DEVICE, Y_SHORT_VECTOR}, structures::{AlternateSet, Anchor, BaseArray, BaseRecord, Class1Record, Class2Record, ClassDef, ClassRangeRecord, CmapSubtable, CmapTable, Component, ComponentRecord, Condition, ConditionSet, Coverage, CoverageRangeRecord, Device, DeviceOrVariationIndex, EncodingRecord, EntryExitRecord, Feature, FeatureList, FeatureParams, FeatureRecord, FeatureTableSubstitution, FeatureTableSubstitutionRecord, FeatureVariationRecord, FeatureVariations, FontFile, FontFileType, GaspRangeRecord, GaspTable, Glyph, GlyphHeader, GposChainSubClassRule, GposChainSubClassSet, GposChainSubRule, GposChainSubRuleSet, GposSubClassRule, GposSubClassSet, GposSubRule, GposSubRuleSet, GposSubtable, GposTable, GposType1Format, GposType2Format, GposType3Format, GposType4Format, GposType5Format, GposType6Format, GposType7Format, GposType8Format, GposType9Format, Group, GsubChainSubClassRule, GsubChainSubClassSet, GsubChainSubRule, GsubChainSubRuleSet, GsubSubClassRule, GsubSubClassSet, GsubSubRule, GsubSubRuleSet, GsubSubtable, GsubTable, GsubType1Format, GsubType2Format, GsubType3Format, GsubType4Format, GsubType5Format, GsubType6Format, GsubType7Format, GsubType8Format, HeadTable, HheaTable, HmtxEntry, HmtxTable, KernClassTable, KernPair, KernSubtable, KernTable, LangSys, LangSysRecord, LangTagRecord, Ligature, LigatureArray, LigatureAttach, LigatureSet, Lookup, LookupList, MacSubtable, Mark2Array, Mark2Record, MarkArray, MarkRecord, MaxpTable, NameRecord, NameTable, OS2Table, PairSet, PairValueRecord, PosLookupRecord, PostTable, Range, Script, ScriptList, ScriptRecord, Sequence, SubHeader, SubstLookupRecord, TableHeader, TableRecord, ValueRecord, VariationIndex, VariationSelectorRecord, VheaTable, VmtxEntry, VmtxTable, WindowsSubtable}};
4
5impl FontFile {
6 pub fn parse_font_file<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
7 let bytes = read(path)?;
8
9 let file_type = match bytes.get(0..4).ok_or(ErrorKind::UnexpectedEof)? {
10 [0x00, 0x01, 0x00, 0x00] => FontFileType::TrueType,
11 [0x4F, 0x54, 0x54, 0x4F] => FontFileType::OpenType,
12 _ => return Err(Error::new(ErrorKind::InvalidData, "Invalid Magic Number"))
13 };
14
15 let num_tables = u16::from_be_bytes(bytes.get(4..6).ok_or(ErrorKind::UnexpectedEof)?.try_into().unwrap());
16 let mut table_records: Vec<TableRecord> = Vec::new();
17 let mut current_offset = 12;
18 for _ in 0..num_tables {
19 let tag: [u8; 4] = bytes
20 .get(current_offset..current_offset + 4)
21 .ok_or(ErrorKind::UnexpectedEof)?
22 .try_into()
23 .unwrap();
24
25 let checksum = u32::from_be_bytes(
26 bytes
27 .get(current_offset + 4..current_offset + 8)
28 .ok_or(ErrorKind::UnexpectedEof)?
29 .try_into()
30 .unwrap()
31 );
32
33 let offset = u32::from_be_bytes(
34 bytes
35 .get(current_offset + 8..current_offset + 12)
36 .ok_or(ErrorKind::UnexpectedEof)?
37 .try_into()
38 .unwrap()
39 );
40
41 let length = u32::from_be_bytes(
42 bytes
43 .get(current_offset + 12..current_offset + 16)
44 .ok_or(ErrorKind::UnexpectedEof)?
45 .try_into()
46 .unwrap()
47 );
48
49 table_records.push(TableRecord::new(tag, checksum, offset, length));
50 current_offset += 16;
51 }
52
53 table_records.sort_by_key(|rec| rec.tag());
54
55 Ok(FontFile::new(file_type, bytes, table_records))
56 }
57
58 pub fn get_table(&self, tag: &[u8; 4]) -> Result<&[u8], Error> {
59 match self.table_records().binary_search_by_key(tag, |rec| rec.tag()) {
60 Ok(idx) => {
61 let table = self.table_records()[idx];
62 let offset = table.offset() as usize;
63 let length = table.length() as usize;
64
65 Ok(&self.bytes().get(offset..offset + length).ok_or(ErrorKind::UnexpectedEof)?)
66 },
67 Err(_) => Err(Error::new(ErrorKind::NotFound, "Given tag was not found in table records"))
68 }
69 }
70
71 pub fn parse_head(&self) -> Result<HeadTable, Error> {
72 let bytes = self.get_table(b"head")?;
73
74 if bytes[12..16] != [0x5F, 0x0F, 0x3C, 0xF5] {
75 return Err(Error::new(ErrorKind::InvalidData, "Head table doesn't contain correct magic number"));
76 }
77
78 let units_per_em = get_u16(bytes, 18)?;
79 let created = get_i64(bytes, 20)?;
80 let modified = get_i64(bytes, 28)?;
81 let x_min = get_i16(bytes, 36)?;
82 let y_min = get_i16(bytes, 38)?;
83 let x_max = get_i16(bytes, 40)?;
84 let y_max = get_i16(bytes, 42)?;
85 let mac_style = get_u16(bytes, 44)?;
86 let lowest_rec_ppem = get_u16(bytes, 46)?;
87 let font_direction_hint = get_i16(bytes, 48)?;
88 let index_to_loc_format = get_i16(bytes, 50)?;
89
90 Ok(HeadTable::new(
91 units_per_em,
92 created,
93 modified,
94 x_min,
95 y_min,
96 x_max,
97 y_max,
98 mac_style,
99 lowest_rec_ppem,
100 font_direction_hint,
101 index_to_loc_format
102 ))
103 }
104
105 pub fn parse_maxp(&self) -> Result<MaxpTable, Error> {
106 let bytes = self.get_table(b"maxp")?;
107
108 let version = get_u32(bytes, 0)?;
109 match version {
110 0x5000 => {
111 let num_glyphs = get_u16(bytes, 4)?;
112 let max_points = None;
113 let max_contours = None;
114 let max_composite_points = None;
115 let max_composite_contours = None;
116 let max_zones = None;
117 let max_twilight_points = None;
118 let max_storage = None;
119 let max_function_defs = None;
120 let max_instruction_defs = None;
121 let max_stack_elements = None;
122 let max_size_of_instructions = None;
123 let max_components_elements = None;
124 let max_component_depth = None;
125
126 Ok(MaxpTable::new(
127 version,
128 num_glyphs,
129 max_points,
130 max_contours,
131 max_composite_points,
132 max_composite_contours,
133 max_zones,
134 max_twilight_points,
135 max_storage,
136 max_function_defs,
137 max_instruction_defs,
138 max_stack_elements,
139 max_size_of_instructions,
140 max_components_elements,
141 max_component_depth
142 ))
143 }
144 0x10000 => {
145 let num_glyphs = get_u16(bytes, 4)?;
146 let max_points = get_u16(bytes, 6)?;
147 let max_contours = get_u16(bytes, 8)?;
148 let max_composite_points = get_u16(bytes, 10)?;
149 let max_composite_contours = get_u16(bytes, 12)?;
150 let max_zones = get_u16(bytes, 14)?;
151 let max_twilight_points = get_u16(bytes, 16)?;
152 let max_storage = get_u16(bytes, 18)?;
153 let max_function_defs = get_u16(bytes, 20)?;
154 let max_instruction_defs = get_u16(bytes, 22)?;
155 let max_stack_elements = get_u16(bytes, 24)?;
156 let max_size_of_instructions = get_u16(bytes, 26)?;
157 let max_component_elements = get_u16(bytes, 28)?;
158 let max_component_depth = get_u16(bytes, 30)?;
159
160 Ok(MaxpTable::new(
161 version,
162 num_glyphs,
163 Some(max_points),
164 Some(max_contours),
165 Some(max_composite_points),
166 Some(max_composite_contours),
167 Some(max_zones),
168 Some(max_twilight_points),
169 Some(max_storage),
170 Some(max_function_defs),
171 Some(max_instruction_defs),
172 Some(max_stack_elements),
173 Some(max_size_of_instructions),
174 Some(max_component_elements),
175 Some(max_component_depth)
176 ))
177 }
178 _ => Err(Error::new(ErrorKind::InvalidData, "Version number invalid"))
179 }
180 }
181
182 pub fn parse_cmap(&self) -> Result<CmapTable, Error> {
183 let bytes = self.get_table(b"cmap")?;
184
185 let version = get_u16(bytes, 0)?;
186 if version != 0 {
187 return Err(Error::new(ErrorKind::InvalidData, "Version number isn't zero"));
188 }
189 let num_tables = get_u16(bytes, 2)?;
190 let mut encoding_records: Vec<EncodingRecord> = Vec::new();
191 let mut count = 4;
192 for _ in 0..num_tables {
193 let platform_id = get_u16(bytes, count)?;
194 let encoding_id = get_u16(bytes, count + 2)?;
195 let offset = get_u32(bytes, count + 4)?;
196 encoding_records.push(EncodingRecord::new(platform_id, encoding_id, offset));
197 count += 8;
198 }
199
200 let mut subtables: Vec<CmapSubtable> = Vec::new();
201 for rec in encoding_records.iter() {
202 let mut offset = rec.offset() as usize;
203 let format = get_u16(bytes, offset)?;
204 offset += 2;
205 match format {
206 0 => {
207 let length = get_u16(bytes, offset)?;
208 let language = get_u16(bytes, offset + 2)?;
209 let glyph_id_array: [u8; 256] = bytes.get(offset + 4..offset + 260).ok_or(ErrorKind::UnexpectedEof)?.try_into().unwrap();
210
211 subtables.push(CmapSubtable::Format0 { length, language, glyph_id_array });
212 }
213 2 => {
214 let length = get_u16(bytes, offset)?;
215 let language = get_u16(bytes, offset + 2)?;
216 let sub_header_keys: [u16; 256] = bytes.get(offset + 4..offset + 516).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
217 u16::from_be_bytes(ch.try_into().unwrap())
218 }).collect::<Vec<u16>>().try_into().unwrap();
219 offset += 516;
220 let sub_headers_num = (sub_header_keys.iter().max().unwrap() / 8) + 1;
221 let sub_headers: Vec<SubHeader> = bytes.get(offset..offset + sub_headers_num as usize * 8).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(8).map(|ch| {
222 let first_code = u16::from_be_bytes(ch[0..2].try_into().unwrap());
223 let entry_count = u16::from_be_bytes(ch[2..4].try_into().unwrap());
224 let id_delta = i16::from_be_bytes(ch[4..6].try_into().unwrap());
225 let id_range_offset = u16::from_be_bytes(ch[6..8].try_into().unwrap());
226
227 SubHeader::new(first_code, entry_count, id_delta, id_range_offset)
228 }).collect();
229 offset += sub_headers_num as usize * 8;
230 let glyph_id_array: Vec<u16> = bytes.get(offset..).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
231 u16::from_be_bytes(ch.try_into().unwrap())
232 }).collect();
233
234 subtables.push(CmapSubtable::Format2 { length, language, sub_header_keys, sub_headers, glyph_id_array });
235 }
236 4 => {
237 let length = get_u16(bytes, offset)?;
238 let language = get_u16(bytes, offset + 2)?;
239 let seg_count_x2 = get_u16(bytes, offset + 4)?;
240 let search_range = get_u16(bytes, offset + 6)?;
241 let entry_selector = get_u16(bytes, offset + 8)?;
242 let range_shift = get_u16(bytes, offset + 10)?;
243 offset += 12;
244 let end_code: Vec<u16> = bytes.get(offset..offset + seg_count_x2 as usize).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
245 u16::from_be_bytes(ch.try_into().unwrap())
246 }).collect();
247 offset += seg_count_x2 as usize;
248 let _reserved_pad = get_u16(bytes, offset)?;
249 offset += 2;
250 let start_code: Vec<u16> = bytes.get(offset..offset + seg_count_x2 as usize).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
251 u16::from_be_bytes(ch.try_into().unwrap())
252 }).collect();
253 offset += seg_count_x2 as usize;
254 let id_delta: Vec<i16> = bytes.get(offset..offset + seg_count_x2 as usize).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
255 i16::from_be_bytes(ch.try_into().unwrap())
256 }).collect();
257 offset += seg_count_x2 as usize;
258 let id_range_offset: Vec<u16> = bytes.get(offset..offset + seg_count_x2 as usize).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
259 u16::from_be_bytes(ch.try_into().unwrap())
260 }).collect();
261 offset += seg_count_x2 as usize;
262 let glyph_id_array: Vec<u16> = bytes.get(offset..).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
263 u16::from_be_bytes(ch.try_into().unwrap())
264 }).collect();
265
266 subtables.push(CmapSubtable::Format4 { length, language, seg_count_x2, search_range, entry_selector, range_shift, end_code, _reserved_pad, start_code, id_delta, id_range_offset, glyph_id_array });
267 }
268 6 => {
269 let length = get_u16(bytes, offset)?;
270 let language = get_u16(bytes, offset + 2)?;
271 let first_code = get_u16(bytes, offset + 4)?;
272 let entry_count = get_u16(bytes, offset + 6)?;
273 offset += 8;
274 let glyph_id_array: Vec<u16> = bytes.get(offset..offset + entry_count as usize * 2).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(2).map(|ch| {
275 u16::from_be_bytes(ch.try_into().unwrap())
276 }).collect();
277
278 subtables.push(CmapSubtable::Format6 { length, language, first_code, entry_count, glyph_id_array });
279 }
280 12 => {
281 let _reserved = get_u16(bytes, offset)?;
282 let length = get_u32(bytes, offset + 2)?;
283 let language = get_u32(bytes, offset + 6)?;
284 let num_groups = get_u32(bytes, offset + 10)?;
285 let groups: Vec<Group> = bytes.get(offset + 14..).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(12).map(|ch| {
286 let start_char_code = u32::from_be_bytes(ch[0..4].try_into().unwrap());
287 let end_char_code = u32::from_be_bytes(ch[4..8].try_into().unwrap());
288 let start_glyph_id = u32::from_be_bytes(ch[8..].try_into().unwrap());
289
290 Group::new(start_char_code, end_char_code, start_glyph_id)
291 }).collect();
292
293 subtables.push(CmapSubtable::Format12 { _reserved, length, language, num_groups, groups });
294 }
295 13 => {
296 let _reserved = get_u16(bytes, offset)?;
297 let length = get_u32(bytes, offset + 2)?;
298 let language = get_u32(bytes, offset + 6)?;
299 let num_groups = get_u32(bytes, offset + 10)?;
300 let groups: Vec<Group> = bytes.get(offset + 14..).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(12).map(|ch| {
301 let start_char_code = u32::from_be_bytes(ch[0..4].try_into().unwrap());
302 let end_char_code = u32::from_be_bytes(ch[4..8].try_into().unwrap());
303 let start_glyph_id = u32::from_be_bytes(ch[8..].try_into().unwrap());
304
305 Group::new(start_char_code, end_char_code, start_glyph_id)
306 }).collect();
307
308 subtables.push(CmapSubtable::Format13 { _reserved, length, language, num_groups, groups });
309 }
310 14 => {
311 let length = get_u32(bytes, offset)?;
312 let num_var_selector_records = get_u32(bytes, offset + 4)?;
313 let var_selector: Vec<VariationSelectorRecord> = bytes.get(offset + 8..).ok_or(ErrorKind::UnexpectedEof)?.chunks_exact(11).map(|ch| {
314 let var_selector: [u8; 3] = ch[0..3].try_into().unwrap();
315 let default_uvs_offset = u32::from_be_bytes(ch[3..7].try_into().unwrap());
316 let non_default_uvs_offset = u32::from_be_bytes(ch[7..11].try_into().unwrap());
317
318 VariationSelectorRecord::new(var_selector, default_uvs_offset, non_default_uvs_offset)
319 }).collect();
320
321 subtables.push(CmapSubtable::Format14 { length, num_var_selector_records, var_selector });
322 }
323 8 | 10 => return Err(Error::new(ErrorKind::InvalidData, "Subtable formats 8 and 10 are considered deprecated")),
324 _ => return Err(Error::new(ErrorKind::InvalidData, ""))
325 }
326 }
327
328 Ok(CmapTable::new(version, num_tables, encoding_records, subtables))
329 }
330
331 pub fn parse_loca(&self, num_glyphs: u16, index_to_loc_format: i16) -> Result<Vec<u32>, Error> {
332 let bytes = self.get_table(b"loca")?;
333
334 let mut indices: Vec<u32> = Vec::new();
335 match index_to_loc_format {
336 0 => {
337 for i in (0..(num_glyphs as usize + 1) * 2).step_by(2) {
338 let offset = get_u16(bytes, i)?;
339 indices.push((offset * 2) as u32);
340 }
341 },
342 1 => {
343 for i in (0..(num_glyphs as usize + 1) * 4).step_by(4) {
344 let offset = get_u32(bytes, i)?;
345 indices.push(offset);
346 }
347 },
348 _ => return Err(Error::new(ErrorKind::InvalidInput, "index_to_loc_format was not 0 or 1"))
349 }
350
351 Ok(indices)
352 }
353
354 pub fn parse_glyf(&self, loca_offsets: Vec<u32>) -> Result<Vec<Option<Glyph>>, Error> {
355 let bytes = self.get_table(b"glyf")?;
356 let mut loca_iter = loca_offsets.iter().peekable();
357
358 let mut glyphs: Vec<Option<Glyph>> = Vec::new();
360
361 while let Some(offset) = loca_iter.next() {
362 if let Some(next_offset) = loca_iter.peek() {
363 if *next_offset - offset == 0 {
364 glyphs.push(None);
365 continue;
366 }
367
368 let current_glyph_bytes = bytes.get(*offset as usize..**next_offset as usize).ok_or(ErrorKind::UnexpectedEof)?;
369 let mut current_offset: usize = 0;
370 let number_of_contours = get_i16(current_glyph_bytes, 0)?;
371 let x_min = get_i16(current_glyph_bytes, 2)?;
372 let y_min = get_i16(current_glyph_bytes, 4)?;
373 let x_max = get_i16(current_glyph_bytes, 6)?;
374 let y_max = get_i16(current_glyph_bytes, 8)?;
375 current_offset += 10;
376 let header = GlyphHeader::new(number_of_contours, x_min, y_min, x_max, y_max);
377 let mut are_instructions;
378 if number_of_contours > 0 {
379 let end_pts_of_contours: Vec<u16> = current_glyph_bytes
380 .get(current_offset..current_offset + number_of_contours as usize * 2)
381 .ok_or(ErrorKind::UnexpectedEof)?
382 .chunks_exact(2)
383 .map(|ch| {
384 u16::from_be_bytes(ch.try_into().unwrap())
385 }).collect();
386 current_offset += number_of_contours as usize * 2;
387 let instruction_length = get_u16(current_glyph_bytes, current_offset)?;
388 current_offset += 2;
389 let instructions: Vec<u8> = current_glyph_bytes.get(current_offset..current_offset + instruction_length as usize).ok_or(ErrorKind::UnexpectedEof)?.to_vec();
390 current_offset += instruction_length as usize;
391 let total_points = end_pts_of_contours.last().unwrap() + 1;
392 let mut flags: Vec<u8> = Vec::with_capacity(total_points as usize);
393 while flags.len() < total_points as usize {
394 let flag = current_glyph_bytes.get(current_offset).ok_or(ErrorKind::UnexpectedEof)?;
395 if flag & REPEAT_FLAG != 0 {
396 let repeat_count = current_glyph_bytes.get(current_offset + 1).ok_or(ErrorKind::UnexpectedEof)?;
397 let flag_vec = vec![flag; *repeat_count as usize + 1];
398 flags.extend(flag_vec);
399 current_offset += 2;
400 }
401 else {
402 flags.push(*flag);
403 current_offset += 1;
404 }
405 }
406 let mut x_coordinates: Vec<i16> = Vec::with_capacity(total_points as usize);
407 let mut current_x: i16 = 0;
408 for flag in flags.iter() {
409 if flag & X_SHORT_VECTOR != 0 {
410 let x = current_glyph_bytes.get(current_offset).ok_or(ErrorKind::UnexpectedEof)?;
411 if flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR != 0 {
412 current_x += *x as i16;
413 }
414 else {
415 current_x -= *x as i16;
416 }
417 current_offset += 1;
418 }
419 else {
420 if flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR == 0 {
421 current_x += get_i16(current_glyph_bytes, current_offset)?;
422 current_offset += 2;
423 }
424 }
425
426 x_coordinates.push(current_x);
427 }
428 let mut y_coordinates: Vec<i16> = Vec::with_capacity(total_points as usize);
429 let mut current_y: i16 = 0;
430 for flag in flags.iter() {
431 if flag & Y_SHORT_VECTOR != 0 {
432 let y = current_glyph_bytes.get(current_offset).ok_or(ErrorKind::UnexpectedEof)?;
433 if flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR != 0 {
434 current_y += *y as i16;
435 }
436 else {
437 current_y -= *y as i16;
438 }
439 current_offset += 1;
440 }
441 else {
442 if flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR == 0 {
443 current_y += get_i16(current_glyph_bytes, current_offset)?;
444 current_offset += 2;
445 }
446 }
447
448 y_coordinates.push(current_y);
449 }
450
451 glyphs.push(Some(Glyph::Simple { header, end_pts_of_contours, instruction_length, instructions, flags, x_coordinates, y_coordinates }));
452 }
453 else if number_of_contours == -1 {
454 let mut components: Vec<Component> = Vec::new();
455 loop {
456 let flags = get_u16(current_glyph_bytes, current_offset)?;
457 let glyph_index = get_u16(current_glyph_bytes, current_offset + 2)?;
458 current_offset += 4;
459 let argument_1: i16;
460 let argument_2: i16;
461 if flags & ARG_1_AND_2_ARE_WORDS != 0 {
462 argument_1 = get_i16(current_glyph_bytes, current_offset)?;
463 argument_2 = get_i16(current_glyph_bytes, current_offset + 2)?;
464 current_offset += 4;
465 }
466 else {
467 argument_1 = *current_glyph_bytes
468 .get(current_offset)
469 .ok_or(ErrorKind::UnexpectedEof)? as i8 as i16;
470 argument_2 = *current_glyph_bytes
471 .get(current_offset + 1)
472 .ok_or(ErrorKind::UnexpectedEof)? as i8 as i16;
473 current_offset += 2;
474 }
475 let transformation: [i16; 4];
476 if flags & WE_HAVE_A_SCALE != 0 {
477 transformation = [get_i16(current_glyph_bytes, current_offset)?, 0, 0, 0];
478 current_offset += 2;
479 }
480 else if flags & WE_HAVE_AN_X_AND_Y_SCALE != 0 {
481 transformation = [
482 get_i16(current_glyph_bytes, current_offset)?,
483 get_i16(current_glyph_bytes, current_offset + 2)?,
484 0, 0
485 ];
486 current_offset += 4;
487 }
488 else if flags & WE_HAVE_A_TWO_BY_TWO != 0 {
489 transformation = [
490 get_i16(current_glyph_bytes, current_offset)?,
491 get_i16(current_glyph_bytes, current_offset + 2)?,
492 get_i16(current_glyph_bytes, current_offset + 4)?,
493 get_i16(current_glyph_bytes, current_offset + 6)?
494 ];
495 current_offset += 8;
496 }
497 else {
498 transformation = [0, 0, 0, 0];
499 }
500
501 components.push(Component::new(flags, glyph_index, argument_1, argument_2, transformation));
502
503 are_instructions = flags & WE_HAVE_INSTRUCTIONS != 0;
504
505 if flags & MORE_COMPONENTS == 0 { break; }
506 }
507 let mut instruction_length: Option<u16> = None;
508 let mut instructions: Option<Vec<u8>> = None;
509 if are_instructions {
510 instruction_length = Some(get_u16(current_glyph_bytes, current_offset)?);
511 current_offset += 2;
512 instructions = Some(
513 current_glyph_bytes
514 .get(current_offset..current_offset + instruction_length.unwrap() as usize)
515 .ok_or(ErrorKind::UnexpectedEof)?
516 .to_vec()
517 )
518 }
519
520 glyphs.push(Some(Glyph::Composite { header, components, instruction_length, instructions }));
521 }
522 else if number_of_contours == 0 {
523 glyphs.push(None);
524 }
525 }
526 }
527
528 Ok(glyphs)
529 }
530
531 pub fn parse_hhea(&self) -> Result<HheaTable, Error> {
532 let bytes = self.get_table(b"hhea")?;
533
534 let version = get_u32(bytes, 0)?;
535 if version != 0x00010000 {
536 return Err(Error::new(ErrorKind::InvalidData, "Version number for hhea table is incorrect"));
537 }
538 let ascender = get_i16(bytes, 4)?;
539 let descender = get_i16(bytes, 6)?;
540 let line_gap = get_i16(bytes, 8)?;
541 let advance_width_max = get_u16(bytes, 10)?;
542 let min_left_side_bearing = get_i16(bytes, 12)?;
543 let min_right_side_bearing = get_i16(bytes, 14)?;
544 let x_max_extent = get_i16(bytes, 16)?;
545 let caret_slope_rise = get_i16(bytes, 18)?;
546 let caret_slope_run = get_i16(bytes, 20)?;
547 let caret_offset = get_i16(bytes, 22)?;
548 let _reserved1 = 0;
549 let _reserved2 = 0;
550 let _reserved3 = 0;
551 let _reserved4 = 0;
552 let metric_data_format = get_i16(bytes, 32)?;
553 let number_of_h_metrics = get_u16(bytes, 34)?;
554
555 Ok(HheaTable::new(
556 version,
557 ascender,
558 descender,
559 line_gap,
560 advance_width_max,
561 min_left_side_bearing,
562 min_right_side_bearing,
563 x_max_extent,
564 caret_slope_rise,
565 caret_slope_run,
566 caret_offset,
567 _reserved1,
568 _reserved2,
569 _reserved3,
570 _reserved4,
571 metric_data_format,
572 number_of_h_metrics
573 ))
574 }
575
576 pub fn parse_hmtx(&self, num_glyphs: u16, number_of_h_metrics: u16) -> Result<HmtxTable, Error> {
577 let bytes = self.get_table(b"hmtx")?;
578
579 let mut entries: Vec<HmtxEntry> = bytes
580 .get(0..number_of_h_metrics as usize * 4)
581 .ok_or(ErrorKind::UnexpectedEof)?
582 .chunks_exact(4)
583 .map(|ch| {
584 let advance_width = u16::from_be_bytes(ch[0..2].try_into().unwrap());
585 let lsb = i16::from_be_bytes(ch[2..4].try_into().unwrap());
586
587 HmtxEntry::FullMetric { advance_width, lsb }
588 }).collect();
589
590 let shared_advance_var = entries.last().unwrap();
591 let shared_advance_width = match shared_advance_var {
592 HmtxEntry::FullMetric { advance_width, lsb: _ } => *advance_width,
593 _ => unreachable!()
594 };
595
596 let leftovers = num_glyphs - number_of_h_metrics;
597
598 entries.extend(
599 bytes
600 .get(number_of_h_metrics as usize * 4..(number_of_h_metrics as usize * 4) + (leftovers as usize * 2))
601 .ok_or(ErrorKind::UnexpectedEof)?
602 .chunks_exact(2)
603 .map(|ch| {
604 HmtxEntry::LeftoverBearing(i16::from_be_bytes(ch.try_into().unwrap()))
605 })
606 );
607
608 Ok(HmtxTable::new(entries, shared_advance_width))
609 }
610
611 pub fn parse_name(&self) -> Result<NameTable, Error> {
612 let bytes = self.get_table(b"name")?;
613 let mut offset = 0;
614
615 let version = get_u16(bytes, 0)?;
616 if version != 0 && version != 1 {
617 return Err(Error::new(ErrorKind::InvalidData, "Version number is not 0 or 1"));
618 }
619 let count = get_u16(bytes, 2)?;
620 let storage_offset = get_u16(bytes, 4)?;
621 offset += 6;
622 let records: Vec<NameRecord> = bytes.get(offset..offset + count as usize * 12)
623 .ok_or(ErrorKind::UnexpectedEof)?
624 .chunks_exact(12)
625 .map(|ch| {
626 let platform_id = u16::from_be_bytes(ch[0..2].try_into().unwrap());
627 let encoding_id = u16::from_be_bytes(ch[2..4].try_into().unwrap());
628 let language_id = u16::from_be_bytes(ch[4..6].try_into().unwrap());
629 let name_id = u16::from_be_bytes(ch[6..8].try_into().unwrap());
630 let length = u16::from_be_bytes(ch[8..10].try_into().unwrap());
631 let string_offset = u16::from_be_bytes(ch[10..12].try_into().unwrap());
632 let string_bytes = bytes.get(storage_offset as usize + string_offset as usize..storage_offset as usize + string_offset as usize + length as usize)
633 .ok_or(ErrorKind::UnexpectedEof)?;
634 let string = decode_name_bytes(string_bytes, platform_id, encoding_id)?;
635
636 Ok(NameRecord::new(platform_id, encoding_id, language_id, name_id, length, string_offset, string))
637 }).collect::<Result<Vec<_>, Error>>()?;
638 offset += count as usize * 12;
639 let mut lang_tag_count: Option<u16> = None;
640 let mut lang_tag_records: Option<Vec<LangTagRecord>> = None;
641 if version == 1 {
642 lang_tag_count = Some(get_u16(bytes, offset)?);
643 offset += 2;
644 lang_tag_records = Some(
645 bytes.get(offset..offset + lang_tag_count.unwrap() as usize * 4)
646 .ok_or(ErrorKind::UnexpectedEof)?
647 .chunks_exact(4)
648 .map(|ch| {
649 let length = u16::from_be_bytes(ch[0..2].try_into().unwrap());
650 let lang_tag_offset = u16::from_be_bytes(ch[2..4].try_into().unwrap());
651 let string_bytes: Vec<u16> = bytes.get(storage_offset as usize + lang_tag_offset as usize.. storage_offset as usize + lang_tag_offset as usize + length as usize)
652 .ok_or(ErrorKind::UnexpectedEof)?
653 .chunks_exact(2)
654 .map(|ch| {
655 u16::from_be_bytes(ch[0..2].try_into().unwrap())
656 }).collect();
657 let string = String::from_utf16(&string_bytes).map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
658
659 Ok(LangTagRecord::new(length, lang_tag_offset, string))
660 }).collect::<Result<Vec<_>, Error>>()?
661 );
662 }
663
664 Ok(NameTable::new(version, count, storage_offset, records, lang_tag_count, lang_tag_records))
665 }
666
667 pub fn parse_os2(&self) -> Result<OS2Table, Error> {
668 let bytes = self.get_table(b"OS/2")?;
669
670 let version = get_u16(bytes, 0)?;
671 let x_avg_char_width = get_i16(bytes, 2)?;
672 let us_weight_class = get_u16(bytes, 4)?;
673 let us_width_class = get_u16(bytes, 6)?;
674 let fs_type = get_u16(bytes, 8)?;
675 let y_subscript_x_size = get_i16(bytes, 10)?;
676 let y_subscript_y_size = get_i16(bytes, 12)?;
677 let y_subscript_x_offset = get_i16(bytes, 14)?;
678 let y_subscript_y_offset = get_i16(bytes, 16)?;
679 let y_superscript_x_size = get_i16(bytes, 18)?;
680 let y_superscript_y_size = get_i16(bytes, 20)?;
681 let y_superscript_x_offset = get_i16(bytes, 22)?;
682 let y_superscript_y_offset = get_i16(bytes, 24)?;
683 let y_strikeout_size = get_i16(bytes, 26)?;
684 let y_strikeout_position = get_i16(bytes, 28)?;
685 let s_family_class = get_i16(bytes, 30)?;
686 let panose: [u8; 10] = bytes.get(32..42)
687 .ok_or(ErrorKind::UnexpectedEof)?
688 .try_into()
689 .unwrap();
690 let ul_unicode_range_1 = get_u32(bytes, 42)?;
691 let ul_unicode_range_2 = get_u32(bytes, 46)?;
692 let ul_unicode_range_3 = get_u32(bytes, 50)?;
693 let ul_unicode_range_4 = get_u32(bytes, 54)?;
694 let ach_vend_id: [u8; 4] = bytes.get(58..62)
695 .ok_or(ErrorKind::UnexpectedEof)?
696 .try_into()
697 .unwrap();
698 let fs_selection = get_u16(bytes, 62)?;
699 let us_first_char_index = get_u16(bytes, 64)?;
700 let us_last_char_index = get_u16(bytes, 66)?;
701 let s_typo_ascender = get_i16(bytes, 68)?;
702 let s_typo_descender = get_i16(bytes, 70)?;
703 let s_typo_line_gap = get_i16(bytes, 72)?;
704 let us_win_ascent = get_u16(bytes, 74)?;
705 let us_win_descent = get_u16(bytes, 76)?;
706 let mut ul_code_page_range_1: Option<u32> = None;
707 let mut ul_code_page_range_2: Option<u32> = None;
708 if version >= 1 {
709 ul_code_page_range_1 = Some(get_u32(bytes, 78)?);
710 ul_code_page_range_2 = Some(get_u32(bytes, 82)?);
711 }
712 let mut sx_height: Option<i16> = None;
713 let mut s_cap_height: Option<i16> = None;
714 let mut us_default_char: Option<u16> = None;
715 let mut us_break_char: Option<u16> = None;
716 let mut us_max_context: Option<u16> = None;
717 if version >= 2 {
718 sx_height = Some(get_i16(bytes, 86)?);
719 s_cap_height = Some(get_i16(bytes, 88)?);
720 us_default_char = Some(get_u16(bytes, 90)?);
721 us_break_char = Some(get_u16(bytes, 92)?);
722 us_max_context = Some(get_u16(bytes, 94)?);
723 }
724 let mut us_lower_optical_point_size: Option<u16> = None;
725 let mut us_upper_optical_point_size: Option<u16> = None;
726 if version >= 5 {
727 us_lower_optical_point_size = Some(get_u16(bytes, 96)?);
728 us_upper_optical_point_size = Some(get_u16(bytes, 98)?);
729 }
730
731 Ok(OS2Table::new(
732 version,
733 x_avg_char_width,
734 us_weight_class,
735 us_width_class,
736 fs_type,
737 y_subscript_x_size,
738 y_subscript_y_size,
739 y_subscript_x_offset,
740 y_subscript_y_offset,
741 y_superscript_x_size,
742 y_superscript_y_size,
743 y_superscript_x_offset,
744 y_superscript_y_offset,
745 y_strikeout_size,
746 y_strikeout_position,
747 s_family_class,
748 panose,
749 ul_unicode_range_1,
750 ul_unicode_range_2,
751 ul_unicode_range_3,
752 ul_unicode_range_4,
753 ach_vend_id,
754 fs_selection,
755 us_first_char_index,
756 us_last_char_index,
757 s_typo_ascender,
758 s_typo_descender,
759 s_typo_line_gap,
760 us_win_ascent,
761 us_win_descent,
762 ul_code_page_range_1,
763 ul_code_page_range_2,
764 sx_height,
765 s_cap_height,
766 us_default_char,
767 us_break_char,
768 us_max_context,
769 us_lower_optical_point_size,
770 us_upper_optical_point_size
771 ))
772 }
773
774 pub fn parse_post(&self) -> Result<PostTable, Error> {
775 let bytes = self.get_table(b"post")?;
776
777 let version = get_u32(bytes, 0)?;
778 let italic_angle = get_i32(bytes, 4)?;
779 let underline_position = get_i16(bytes, 8)?;
780 let underline_thickness = get_i16(bytes, 10)?;
781 let is_fixed_pitch = get_u32(bytes, 12)?;
782 let min_mem_type_42 = get_u32(bytes, 16)?;
783 let max_mem_type_42 = get_u32(bytes, 20)?;
784 let min_mem_type_1 = get_u32(bytes, 24)?;
785 let max_mem_type_1 = get_u32(bytes, 28)?;
786 let mut num_glyphs: Option<u16> = None;
787 let mut glyph_name_index: Option<Vec<u16>> = None;
788 let mut names: Option<Vec<String>> = None;
789 if version == 0x00010000 {
790 names = Some(MAC_STANDARD_NAMES.iter().map(|s| s.to_string()).collect());
791 }
792 else if version == 0x00020000 {
793 let mut offset = 34;
794 num_glyphs = Some(get_u16(bytes, 32)?);
795 glyph_name_index = Some(
796 bytes.get(offset..offset + num_glyphs.unwrap() as usize * 2)
797 .ok_or(ErrorKind::UnexpectedEof)?
798 .chunks_exact(2)
799 .map(|ch| u16::from_be_bytes(ch[0..2].try_into().unwrap())).collect()
800 );
801 let max_idx = glyph_name_index.as_ref().unwrap().iter().max().unwrap();
802 let mut extra_names: Vec<String> = Vec::with_capacity(*max_idx as usize - 257);
803 if *max_idx >= 258 {
804 offset += num_glyphs.unwrap() as usize * 2;
805 for _ in 0..(max_idx - 257) {
806 let length = bytes.get(offset).ok_or(ErrorKind::UnexpectedEof)?;
807 offset += 1;
808 let string_bytes = bytes.get(offset..offset + *length as usize).ok_or(ErrorKind::UnexpectedEof)?;
809 offset += *length as usize;
810 extra_names.push(decode_name_bytes(string_bytes, 1, 0)?);
811 }
812 }
813 names = Some(Vec::with_capacity(num_glyphs.unwrap() as usize));
814 for idx in glyph_name_index.as_ref().unwrap() {
815 if *idx <= 257 {
816 names.as_mut().unwrap().push(MAC_STANDARD_NAMES[*idx as usize].to_string());
817 }
818 else {
819 names.as_mut().unwrap().push(extra_names[*idx as usize - 258].to_string());
820 }
821 }
822 }
823 else if version == 0x00025000 {
824 return Err(Error::new(ErrorKind::InvalidData, "Version 2.5 is deprecated"))
825 }
826 else if version != 0x00030000 {
827 return Err(Error::new(ErrorKind::InvalidData, format!("Version {} is not valid", version)))
828 }
829
830 Ok(PostTable::new(
831 version,
832 italic_angle,
833 underline_position,
834 underline_thickness,
835 is_fixed_pitch,
836 min_mem_type_42,
837 max_mem_type_42,
838 min_mem_type_1,
839 max_mem_type_1,
840 num_glyphs,
841 glyph_name_index,
842 names
843 ))
844 }
845
846 pub fn parse_vhea(&self) -> Result<VheaTable, Error> {
847 let vhea_bytes = self.get_table(b"vhea")?;
848
849 let version = get_u32(vhea_bytes, 0)?;
850 if version != 0x00010000 && version != 0x00011000 {
851 return Err(Error::new(ErrorKind::InvalidData, format!("Invalid version number: {}", version)))
852 }
853 let vert_typo_ascender = get_i16(vhea_bytes, 4)?;
854 let vert_typo_descender = get_i16(vhea_bytes, 6)?;
855 let vert_typo_line_gap = get_i16(vhea_bytes, 8)?;
856 let advance_height_max = get_u16(vhea_bytes, 10)?;
857 let min_top_side_bearing = get_i16(vhea_bytes, 12)?;
858 let min_bottom_side_bearing = get_i16(vhea_bytes, 14)?;
859 let y_max_extent = get_i16(vhea_bytes, 16)?;
860 let caret_slope_rise = get_i16(vhea_bytes, 18)?;
861 let caret_slope_run = get_i16(vhea_bytes, 20)?;
862 let caret_offset = get_i16(vhea_bytes, 22)?;
863 let _reserved1 = get_i16(vhea_bytes, 24)?;
864 let _reserved2 = get_i16(vhea_bytes, 26)?;
865 let _reserved3 = get_i16(vhea_bytes, 28)?;
866 let _reserved4 = get_i16(vhea_bytes, 30)?;
867 let metric_data_format = get_i16(vhea_bytes, 32)?;
868 let num_of_long_ver_metrics = get_u16(vhea_bytes, 34)?;
869
870 Ok(VheaTable::new(
871 version,
872 vert_typo_ascender,
873 vert_typo_descender,
874 vert_typo_line_gap,
875 advance_height_max,
876 min_top_side_bearing,
877 min_bottom_side_bearing,
878 y_max_extent,
879 caret_slope_rise,
880 caret_slope_run,
881 caret_offset,
882 _reserved1,
883 _reserved2,
884 _reserved3,
885 _reserved4,
886 metric_data_format,
887 num_of_long_ver_metrics
888 ))
889 }
890
891 pub fn parse_vmtx(&self, num_glyphs: u16, number_of_v_metrics: u16) -> Result<VmtxTable, Error> {
892 let bytes = self.get_table(b"vmtx")?;
893
894 let mut entries: Vec<VmtxEntry> = bytes
895 .get(0..number_of_v_metrics as usize * 4)
896 .ok_or(ErrorKind::UnexpectedEof)?
897 .chunks_exact(4)
898 .map(|ch| {
899 let advance_height = u16::from_be_bytes(ch[0..2].try_into().unwrap());
900 let tsb = i16::from_be_bytes(ch[2..4].try_into().unwrap());
901
902 VmtxEntry::FullMetric { advance_height, tsb }
903 }).collect();
904
905 let shared_advance_var = entries.last().unwrap();
906 let shared_advance_height = match shared_advance_var {
907 VmtxEntry::FullMetric { advance_height, tsb: _ } => *advance_height,
908 _ => unreachable!()
909 };
910
911 let leftovers = num_glyphs - number_of_v_metrics;
912
913 entries.extend(
914 bytes
915 .get(number_of_v_metrics as usize * 4..(number_of_v_metrics as usize * 4) + (leftovers as usize * 2))
916 .ok_or(ErrorKind::UnexpectedEof)?
917 .chunks_exact(2)
918 .map(|ch| {
919 VmtxEntry::LeftoverBearing(i16::from_be_bytes(ch.try_into().unwrap()))
920 })
921 );
922
923 Ok(VmtxTable::new(entries, shared_advance_height))
924 }
925
926 pub fn parse_kern(&self) -> Result<KernTable, Error> {
927 let bytes = self.get_table(b"kern")?;
928
929 let version_test = get_u16(bytes, 0)?;
930 match version_test {
931 0 => {
932 let version = get_u16(bytes, 0)?;
933 let n_tables = get_u16(bytes, 2)?;
934 let mut subtables: Vec<WindowsSubtable> = Vec::with_capacity(n_tables as usize);
935 let mut offset: usize = 4;
936 let mut subtable_start: usize;
937 for _ in 0..n_tables {
938 subtable_start = offset;
939 let version = get_u16(bytes, offset)?;
940 let length = get_u16(bytes, offset + 2)?;
941 let coverage = get_u16(bytes, offset + 4)?;
942 offset += 6;
943 let subtable = match coverage >> 8 {
944 0 => parse_kern_format0(&bytes[offset..]),
945 2 => parse_kern_format2(&bytes[offset..], subtable_start, length as usize),
946 _ => {
947 offset += length as usize - 6;
948 continue;
949 }
950 }?;
951
952 subtables.push(WindowsSubtable::new(version, length, coverage, subtable));
953 }
954
955 Ok(KernTable::Windows {
956 version,
957 n_tables,
958 subtables
959 })
960 }
961 1 => {
962 let version = get_u32(bytes, 0)?;
963 let n_tables = get_u32(bytes, 4)?;
964 let mut offset: usize = 8;
965 let mut subtable_start: usize;
966 let mut subtables: Vec<MacSubtable> = Vec::with_capacity(n_tables as usize);
967 for _ in 0..n_tables {
968 subtable_start = offset;
969 let length = get_u32(bytes, offset)?;
970 let coverage = get_u16(bytes, offset + 4)?;
971 let tuple_index = get_u16(bytes, offset + 6)?;
972 offset += 8;
973 let subtable = match coverage & 0xFF {
974 0 => parse_kern_format0(&bytes[offset..]),
975 2 => parse_kern_format2(&bytes[offset..], subtable_start, length as usize),
976 _ => {
977 offset += length as usize - 8;
978 continue;
979 }
980 }?;
981
982 subtables.push(MacSubtable::new(length, coverage, tuple_index, subtable));
983 }
984
985 Ok(KernTable::Mac {
986 version,
987 n_tables,
988 subtables
989 })
990 }
991 _ => Err(Error::new(ErrorKind::InvalidData, format!("Invalid version number: {}", version_test)))
992 }
993 }
994
995 pub fn parse_gasp(&self) -> Result<GaspTable, Error> {
996 let bytes = self.get_table(b"gasp")?;
997
998 let version = get_u16(bytes, 0)?;
999 if version != 0 && version != 1 {
1000 return Err(Error::new(ErrorKind::InvalidData, format!("Version number is not 0 or 1: {}", version)))
1001 }
1002 let num_ranges = get_u16(bytes, 2)?;
1003 let range_records: Vec<GaspRangeRecord> = bytes.get(4..4 + num_ranges as usize * 4)
1004 .ok_or(ErrorKind::UnexpectedEof)?
1005 .chunks_exact(4)
1006 .map(|ch| {
1007 let range_max_ppem = get_u16(ch, 0)?;
1008 let range_gasp_behavior = get_u16(ch, 2)?;
1009
1010 Ok(GaspRangeRecord::new(range_max_ppem, range_gasp_behavior))
1011 }).collect::<Result<Vec<_>, Error>>()?;
1012
1013 Ok(GaspTable::new(version, num_ranges, range_records))
1014 }
1015
1016 pub fn parse_cvt(&self) -> Result<Vec<i16>, Error> {
1017 let cvt_bytes = self.get_table(b"cvt ")?;
1018
1019 Ok(
1020 cvt_bytes.chunks_exact(2)
1021 .map(|ch| {
1022 i16::from_be_bytes(ch[0..2].try_into().unwrap())
1023 }).collect()
1024 )
1025 }
1026
1027 pub fn parse_fpgm(&self) -> Result<Vec<u8>, Error> {
1028 Ok(self.get_table(b"fpgm")?.to_vec())
1029 }
1030
1031 pub fn parse_prep(&self) -> Result<Vec<u8>, Error> {
1032 Ok(self.get_table(b"prep")?.to_vec())
1033 }
1034
1035 pub fn parse_gpos(&self) -> Result<GposTable<GposSubtable>, Error> {
1036 let bytes = self.get_table(b"GPOS")?;
1037 let mut offset: usize = 0;
1038
1039 let major_version = get_u16(bytes, 0)?;
1040 let minor_version = get_u16(bytes, 2)?;
1041 let script_list_offset = get_u16(bytes, 4)?;
1042 let feature_list_offset = get_u16(bytes, 6)?;
1043 let lookup_list_offset = get_u16(bytes, 8)?;
1044 offset += 10;
1045 let feature_variations_offset: Option<u32>;
1046 if minor_version >= 1 {
1047 feature_variations_offset = Some(get_u32(bytes, offset)?);
1048 }
1049 else {
1050 feature_variations_offset = None;
1051 }
1052 let header = TableHeader::new(
1053 major_version,
1054 minor_version,
1055 script_list_offset,
1056 feature_list_offset,
1057 lookup_list_offset,
1058 feature_variations_offset
1059 );
1060 let script_list = parse_script_list(bytes, script_list_offset)?;
1061 let feature_list = parse_feature_list(bytes, feature_list_offset)?;
1062 let lookup_list = parse_lookup_list(bytes, lookup_list_offset)?;
1063 let feature_variations: Option<FeatureVariations>;
1064 if feature_variations_offset != None {
1065 feature_variations = Some(parse_feature_variations(bytes, feature_variations_offset.unwrap(), feature_list.clone())?);
1066 }
1067 else {
1068 feature_variations = None;
1069 }
1070
1071 Ok(GposTable::new(
1072 header,
1073 script_list,
1074 feature_list,
1075 lookup_list,
1076 feature_variations
1077 ))
1078 }
1079
1080 pub fn parse_gsub(&self) -> Result<GsubTable<GsubSubtable>, Error> {
1081 let bytes = self.get_table(b"GSUB")?;
1082 let mut offset: usize = 0;
1083
1084 let major_version = get_u16(bytes, 0)?;
1085 let minor_version = get_u16(bytes, 2)?;
1086 let script_list_offset = get_u16(bytes, 4)?;
1087 let feature_list_offset = get_u16(bytes, 6)?;
1088 let lookup_list_offset = get_u16(bytes, 8)?;
1089 offset += 10;
1090 let feature_variations_offset: Option<u32>;
1091 if minor_version >= 1 {
1092 feature_variations_offset = Some(get_u32(bytes, offset)?);
1093 }
1094 else {
1095 feature_variations_offset = None;
1096 }
1097 let header = TableHeader::new(
1098 major_version,
1099 minor_version,
1100 script_list_offset,
1101 feature_list_offset,
1102 lookup_list_offset,
1103 feature_variations_offset
1104 );
1105 let script_list = parse_script_list(bytes, script_list_offset)?;
1106 let feature_list = parse_feature_list(bytes, feature_list_offset)?;
1107 let lookup_list = parse_lookup_list(bytes, lookup_list_offset)?;
1108 let feature_variations: Option<FeatureVariations>;
1109 if feature_variations_offset != None {
1110 feature_variations = Some(parse_feature_variations(bytes, feature_variations_offset.unwrap(), feature_list.clone())?);
1111 }
1112 else {
1113 feature_variations = None;
1114 }
1115
1116 Ok(GsubTable::new(
1117 header,
1118 script_list,
1119 feature_list,
1120 lookup_list,
1121 feature_variations
1122 ))
1123 }
1124}
1125
1126fn parse_kern_format0(bytes: &[u8]) -> Result<KernSubtable, Error> {
1127 let n_pairs = get_u16(bytes, 0)?;
1128 let search_range = get_u16(bytes, 2)?;
1129 let entry_selector = get_u16(bytes, 4)?;
1130 let range_shift = get_u16(bytes, 6)?;
1131 let pairs: Vec<KernPair> = bytes.get(8..8 + n_pairs as usize * 6)
1132 .ok_or(ErrorKind::UnexpectedEof)?
1133 .chunks_exact(6)
1134 .map(|ch| {
1135 let left = get_u16(ch, 0)?;
1136 let right = get_u16(ch, 2)?;
1137 let value = get_i16(ch, 4)?;
1138
1139 Ok(KernPair::new(left, right, value))
1140 }).collect::<Result<Vec<_>, Error>>()?;
1141
1142 Ok(KernSubtable::Format0 {
1143 n_pairs,
1144 search_range,
1145 entry_selector,
1146 range_shift,
1147 pairs
1148 })
1149}
1150
1151fn parse_kern_format2(bytes: &[u8], subtable_start: usize, length: usize) -> Result<KernSubtable, Error> {
1152 let mut offset = 0;
1153 let row_width = get_u16(bytes, offset)?;
1154 let left_offset = get_u16(bytes, offset + 2)?;
1155 let right_offset = get_u16(bytes, offset + 4)?;
1156 let array_offset = get_u16(bytes, offset + 6)?;
1157 offset = subtable_start + left_offset as usize;
1158 let left_class_format = get_u16(bytes, offset)?;
1159 let left_class_table = parse_kern_class(bytes, left_class_format, offset)?;
1160 offset = subtable_start + right_offset as usize;
1161 let right_class_format = get_u16(bytes, offset)?;
1162 let right_class_table = parse_kern_class(bytes, right_class_format, offset)?;
1163 offset = subtable_start + array_offset as usize;
1164 let kerning_array: Vec<i16> = bytes.get(offset..offset + length)
1165 .ok_or(ErrorKind::UnexpectedEof)?
1166 .chunks_exact(2)
1167 .map(|ch| Ok(get_i16(ch, 0)?))
1168 .collect::<Result<Vec<_>, Error>>()?;
1169
1170 Ok(KernSubtable::Format2 {
1171 row_width,
1172 left_offset,
1173 right_offset,
1174 array_offset,
1175 left_class_table,
1176 right_class_table,
1177 kerning_array
1178 })
1179}
1180
1181fn parse_kern_class(bytes: &[u8], class_format: u16, offset: usize) -> Result<KernClassTable, Error> {
1182 let mut offset = offset;
1183 match class_format {
1184 1 => {
1185 let start_glyph = get_u16(bytes, offset + 2)?;
1186 let glyph_count = get_u16(bytes, offset + 4)?;
1187 offset += 6;
1188 let class_ids: Vec<u16> = bytes.get(offset..offset + glyph_count as usize * 2)
1189 .ok_or(ErrorKind::UnexpectedEof)?
1190 .chunks_exact(2)
1191 .map(|ch| Ok(get_u16(ch, 0)?))
1192 .collect::<Result<Vec<_>, Error>>()?;
1193
1194 Ok(KernClassTable::Format1 { start_glyph, glyph_count, class_ids })
1195 }
1196 2 => {
1197 let range_count = get_u16(bytes, offset)?;
1198 offset += 2;
1199 let ranges: Vec<Range> = bytes.get(offset..offset + range_count as usize * 6)
1200 .ok_or(ErrorKind::UnexpectedEof)?
1201 .chunks_exact(6)
1202 .map(|ch| {
1203 let start_glyph = get_u16(ch, 0)?;
1204 let end_glyph = get_u16(ch, 2)?;
1205 let class = get_u16(ch, 4)?;
1206
1207 Ok(Range::new(start_glyph, end_glyph, class))
1208 }).collect::<Result<Vec<_>, Error>>()?;
1209
1210 Ok(KernClassTable::Format2 { range_count, ranges })
1211 }
1212 _ => Err(Error::new(ErrorKind::InvalidData, format!("Class table format invalid: {}", class_format)))
1213 }
1214}
1215
1216fn parse_script_list(bytes: &[u8], script_list_offset: u16) -> Result<ScriptList, Error> {
1217 let mut offset = script_list_offset as usize;
1218
1219 let script_count = get_u16(bytes, offset)?;
1220 offset += 2;
1221 let script_records: Vec<ScriptRecord> = bytes.get(offset..offset + script_count as usize * 6)
1222 .ok_or(ErrorKind::UnexpectedEof)?
1223 .chunks_exact(6)
1224 .map(|ch| {
1225 let script_tag: [u8; 4] = ch[0..4].try_into().unwrap();
1226 let script_offset = get_u16(ch, 4)?;
1227
1228 Ok(ScriptRecord::new(script_tag, script_offset))
1229 }).collect::<Result<Vec<_>, Error>>()?;
1230 let scripts: Vec<Script> = script_records.iter()
1231 .map(|sr| {
1232 let mut offset = (script_list_offset + sr.script_offset()) as usize;
1233 let test_offset = get_u16(bytes, offset)?;
1234 offset += 2;
1235 let default_lang_sys_offset = if test_offset != 0 {
1236 Some(test_offset)
1237 }
1238 else {
1239 None
1240 };
1241 let default_lang_sys = if default_lang_sys_offset != None {
1242 let mut offset = (script_list_offset + sr.script_offset() + default_lang_sys_offset.unwrap()) as usize;
1243 let _lookup_order_offset = get_u16(bytes, offset)?;
1244 let required_feature_index = get_u16(bytes, offset + 2)?;
1245 let feature_index_count = get_u16(bytes, offset + 4)?;
1246 offset += 6;
1247 let feature_indices = bytes.get(offset..offset + feature_index_count as usize * 2)
1248 .ok_or(ErrorKind::UnexpectedEof)?
1249 .chunks_exact(2)
1250 .map(|ch| {
1251 Ok(get_u16(ch, 0)?)
1252 }).collect::<Result<Vec<_>, Error>>()?;
1253
1254 Some(LangSys::new(
1255 _lookup_order_offset,
1256 required_feature_index,
1257 feature_index_count,
1258 feature_indices
1259 ))
1260 }
1261 else {
1262 None
1263 };
1264 let lang_sys_count = get_u16(bytes, offset)?;
1265 offset += 2;
1266 let lang_sys_records: Vec<LangSysRecord> = bytes.get(offset..offset + lang_sys_count as usize * 6)
1267 .ok_or(ErrorKind::UnexpectedEof)?
1268 .chunks_exact(6)
1269 .map(|ch| {
1270 let lang_sys_tag: [u8; 4] = ch.get(0..4)
1271 .ok_or(ErrorKind::UnexpectedEof)?
1272 .try_into()
1273 .unwrap();
1274 let lang_sys_offset = get_u16(ch, 4)?;
1275
1276 Ok(LangSysRecord::new(lang_sys_tag, lang_sys_offset))
1277 }).collect::<Result<Vec<_>, Error>>()?;
1278 let lang_syses: Vec<LangSys> = lang_sys_records.iter()
1279 .map(|lsr| {
1280 let mut offset = (script_list_offset + sr.script_offset() + lsr.lang_sys_offset()) as usize;
1281 let _lookup_order_offset = get_u16(bytes, offset)?;
1282 let required_feature_index = get_u16(bytes, offset + 2)?;
1283 let feature_index_count = get_u16(bytes, offset + 4)?;
1284 offset += 6;
1285 let feature_indices = bytes.get(offset..offset + feature_index_count as usize * 2)
1286 .ok_or(ErrorKind::UnexpectedEof)?
1287 .chunks_exact(2)
1288 .map(|ch| {
1289 Ok(get_u16(ch, 0)?)
1290 }).collect::<Result<Vec<_>, Error>>()?;
1291
1292 Ok(LangSys::new(
1293 _lookup_order_offset,
1294 required_feature_index,
1295 feature_index_count,
1296 feature_indices
1297 ))
1298 }).collect::<Result<Vec<_>, Error>>()?;
1299
1300 Ok(Script::new(
1301 default_lang_sys_offset,
1302 default_lang_sys,
1303 lang_sys_count,
1304 lang_sys_records,
1305 lang_syses
1306 ))
1307 }).collect::<Result<Vec<_>, Error>>()?;
1308
1309 Ok(ScriptList::new(
1310 script_count,
1311 script_records,
1312 scripts
1313 ))
1314}
1315
1316fn parse_feature_list(bytes: &[u8], feature_list_offset: u16) -> Result<FeatureList, Error> {
1317 let mut offset = feature_list_offset as usize;
1318
1319 let feature_count = get_u16(bytes, offset)?;
1320 offset += 2;
1321 let feature_records: Vec<FeatureRecord> = bytes.get(offset..offset + feature_count as usize * 6)
1322 .ok_or(ErrorKind::UnexpectedEof)?
1323 .chunks_exact(6)
1324 .map(|ch| {
1325 let feature_tag: [u8; 4] = ch[0..4].try_into().unwrap();
1326 let feature_offset = get_u16(ch, 4)?;
1327
1328 Ok(FeatureRecord::new(feature_tag, feature_offset))
1329 }).collect::<Result<Vec<_>, Error>>()?;
1330 let features: Vec<Feature> = feature_records.iter()
1331 .map(|fr| {
1332 let mut offset = (feature_list_offset + fr.feature_offset()) as usize;
1333 let test_offset = get_u16(bytes, offset)?;
1334 offset += 2;
1335 let feature_params_offset: Option<u16> = if test_offset != 0 {
1336 Some(test_offset)
1337 }
1338 else {
1339 None
1340 };
1341 let feature_params: Option<FeatureParams> = if feature_params_offset != None {
1342 let offset = (feature_list_offset + fr.feature_offset() + feature_params_offset.unwrap()) as usize;
1343 match &fr.feature_tag() {
1344 b"size" => {
1345 let design_size = get_u16(bytes, offset)?;
1346 let subfamily_id = get_u16(bytes, offset + 2)?;
1347 let subfamily_name_id = get_u16(bytes, offset + 4)?;
1348 let range_start = get_u16(bytes, offset + 6)?;
1349 let range_end = get_u16(bytes, offset + 8)?;
1350
1351 Some(FeatureParams::Size {
1352 design_size,
1353 subfamily_id,
1354 subfamily_name_id,
1355 range_start,
1356 range_end
1357 })
1358 },
1359 tag if tag.starts_with(b"ss") => {
1360 let version = get_u16(bytes, offset)?;
1361 let ui_name_id = get_u16(bytes, offset + 2)?;
1362
1363 Some(FeatureParams::StylisticSet {
1364 version,
1365 ui_name_id
1366 })
1367 },
1368 tag if tag.starts_with(b"cv") => {
1369 let format = get_u16(bytes, offset)?;
1370 let feat_ui_label_name_id = get_u16(bytes, offset + 2)?;
1371 let feat_tooltip_text_name_id = get_u16(bytes, offset + 4)?;
1372 let sample_text_name_id = get_u16(bytes, offset + 6)?;
1373 let num_named_parameters = get_u16(bytes, offset + 8)?;
1374 let first_param_ui_label_name_id = get_u16(bytes, offset + 10)?;
1375 let char_count = get_u16(bytes, offset + 12)?;
1376 let character: [u8; 3] = bytes.get(offset + 14..offset + 17)
1377 .ok_or(ErrorKind::UnexpectedEof)?
1378 .try_into()
1379 .unwrap();
1380
1381 Some(FeatureParams::CharacterVariant {
1382 format,
1383 feat_ui_label_name_id,
1384 feat_tooltip_text_name_id,
1385 sample_text_name_id,
1386 num_named_parameters,
1387 first_param_ui_label_name_id,
1388 char_count,
1389 character
1390 })
1391 }
1392 _ => return Err(Error::new(ErrorKind::InvalidData, format!("Feature tag is invalid: {:#?}", fr.feature_tag())))
1393 }
1394 }
1395 else {
1396 None
1397 };
1398 let lookup_index_count = get_u16(bytes, offset)?;
1399 offset += 2;
1400 let lookup_list_indices: Vec<u16> = bytes.get(offset..offset + lookup_index_count as usize * 2)
1401 .ok_or(ErrorKind::UnexpectedEof)?
1402 .chunks_exact(2)
1403 .map(|ch| {
1404 u16::from_be_bytes(ch.try_into().unwrap())
1405 }).collect();
1406
1407 Ok(Feature::new(
1408 feature_params_offset,
1409 feature_params,
1410 lookup_index_count,
1411 lookup_list_indices
1412 ))
1413 }).collect::<Result<Vec<_>, Error>>()?;
1414
1415 Ok(FeatureList::new(feature_count, feature_records, features))
1416}
1417
1418fn parse_lookup_list<T: SubtableParser>(bytes: &[u8], lookup_list_offset: u16) -> Result<LookupList<T>, Error> {
1419 let mut offset = lookup_list_offset as usize;
1420
1421 let lookup_count = get_u16(bytes, offset)?;
1422 offset += 2;
1423 let lookup_offsets: Vec<u16> = bytes.get(offset..offset + lookup_count as usize * 2)
1424 .ok_or(ErrorKind::UnexpectedEof)?
1425 .chunks_exact(2)
1426 .map(|ch| {
1427 u16::from_be_bytes(ch.try_into().unwrap())
1428 }).collect();
1429 let mut lookups: Vec<Lookup<T>> = Vec::with_capacity(lookup_offsets.len());
1430 for offset in lookup_offsets.iter() {
1431 let lookup_offset = lookup_list_offset as usize + *offset as usize;
1432 let mut offset = lookup_offset;
1433 let lookup_type = get_u16(bytes, offset)?;
1434 let lookup_flag = get_u16(bytes, offset + 2)?;
1435 let subtable_count = get_u16(bytes, offset + 4)?;
1436 offset += 6;
1437 let subtable_offsets: Vec<u16> = bytes.get(offset..offset + subtable_count as usize * 2)
1438 .ok_or(ErrorKind::UnexpectedEof)?
1439 .chunks_exact(2)
1440 .map(|ch| {
1441 u16::from_be_bytes(ch.try_into().unwrap())
1442 }).collect();
1443 offset += subtable_count as usize * 2;
1444 let subtables: Vec<T> = subtable_offsets.iter()
1445 .map(|offset| {
1446 Ok(T::parse(bytes, lookup_offset + *offset as usize, 0, lookup_type)?)
1447 }).collect::<Result<Vec<_>, Error>>()?;
1448 let mark_filtering_set = if lookup_flag & USE_MARK_FILTERING_SET != 0 {
1449 Some(get_u16(bytes, offset)?)
1450 }
1451 else {
1452 None
1453 };
1454
1455 lookups.push(Lookup::new(
1456 lookup_type,
1457 lookup_flag,
1458 subtable_count,
1459 subtable_offsets,
1460 subtables,
1461 mark_filtering_set
1462 ));
1463 }
1464
1465 Ok(LookupList::new(
1466 lookup_count,
1467 lookup_offsets,
1468 lookups
1469 ))
1470}
1471
1472trait SubtableParser: Sized {
1473 fn parse(bytes: &[u8], subtable_offset: usize, extension_offset: u32, lookup_type: u16) -> Result<Self, Error>;
1474}
1475
1476impl SubtableParser for GposSubtable {
1477 fn parse(bytes: &[u8], subtable_offset: usize, extension_offset: u32, lookup_type: u16) -> Result<Self, Error> {
1478 let mut offset = (subtable_offset as u32 + extension_offset) as usize;
1479 let format = get_u16(bytes, offset)?;
1480 offset += 2;
1481 match lookup_type {
1482 1 => {
1483 match format {
1484 1 => {
1485 let coverage_offset = get_u16(bytes, offset)?;
1486 offset += 2;
1487 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1488 let value_format = get_u16(bytes, offset)?;
1489 offset += 2;
1490 let value_record = parse_value_record(bytes, value_format, &mut offset, subtable_offset)?;
1491
1492 Ok(GposSubtable::Type1(GposType1Format::Format1 {
1493 coverage_offset,
1494 coverage,
1495 value_format,
1496 value_record
1497 }))
1498 }
1499 2 => {
1500 let coverage_offset = get_u16(bytes, offset)?;
1501 offset += 2;
1502 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1503 let value_format = get_u16(bytes, offset)?;
1504 let value_count = get_u16(bytes, offset + 2)?;
1505 offset += 4;
1506 let value_records: Vec<ValueRecord> = (0..value_count).map(|_| {
1507 Ok(parse_value_record(bytes, value_format, &mut offset, subtable_offset)?)
1508 }).collect::<Result<Vec<_>, Error>>()?;
1509
1510 Ok(GposSubtable::Type1(GposType1Format::Format2 {
1511 coverage_offset,
1512 coverage,
1513 value_format,
1514 value_count,
1515 value_records
1516 }))
1517 }
1518 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 1 is invalid: {}", format)))
1519 }
1520 }
1521 2 => {
1522 match format {
1523 1 => {
1524 let coverage_offset = get_u16(bytes, offset)?;
1525 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1526 let value_format1 = get_u16(bytes, offset + 2)?;
1527 let value_format2 = get_u16(bytes, offset + 4)?;
1528 let pair_set_count = get_u16(bytes, offset + 6)?;
1529 offset += 6;
1530 let pair_set_offsets: Vec<u16> = bytes.get(offset..offset + pair_set_count as usize * 2)
1531 .ok_or(ErrorKind::UnexpectedEof)?
1532 .chunks_exact(2)
1533 .map(|ch| {
1534 u16::from_be_bytes(ch.try_into().unwrap())
1535 }).collect();
1536 let pair_sets: Vec<PairSet> = pair_set_offsets.iter()
1537 .map(|offset| {
1538 let mut offset = subtable_offset + *offset as usize;
1539 let pair_value_count = get_u16(bytes, offset)?;
1540 offset += 2;
1541 let pair_value_records: Vec<PairValueRecord> = (0..pair_value_count).map(|_| {
1542 let second_glyph = get_u16(bytes, offset)?;
1543 offset += 2;
1544 let value_record1 = parse_value_record(bytes, value_format1, &mut offset, subtable_offset)?;
1545 let value_record2 = parse_value_record(bytes, value_format2, &mut offset, subtable_offset)?;
1546
1547 Ok(PairValueRecord::new(
1548 second_glyph,
1549 value_record1,
1550 value_record2
1551 ))
1552 }).collect::<Result<Vec<_>, Error>>()?;
1553
1554 Ok(PairSet::new(
1555 pair_value_count,
1556 pair_value_records
1557 ))
1558 }).collect::<Result<Vec<_>, Error>>()?;
1559
1560 Ok(GposSubtable::Type2(GposType2Format::Format1 {
1561 coverage_offset,
1562 coverage,
1563 value_format1,
1564 value_format2,
1565 pair_set_count,
1566 pair_set_offsets,
1567 pair_sets
1568 }))
1569 }
1570 2 => {
1571 let coverage_offset = get_u16(bytes, offset)?;
1572 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1573 let value_format1 = get_u16(bytes, offset + 2)?;
1574 let value_format2 = get_u16(bytes, offset + 4)?;
1575 let class_def1_offset = get_u16(bytes, offset + 6)?;
1576 let class_def1 = parse_class_def(bytes, subtable_offset, class_def1_offset)?;
1577 let class_def2_offset = get_u16(bytes, offset + 8)?;
1578 let class_def2 = parse_class_def(bytes, subtable_offset, class_def2_offset)?;
1579 let class1_count = get_u16(bytes, offset + 10)?;
1580 let class2_count = get_u16(bytes, offset + 12)?;
1581 offset += 12;
1582 let class1_records: Vec<Class1Record> = (0..class1_count).map(|_| {
1583 Ok(parse_class1_record(bytes, subtable_offset, value_format1, value_format2, class2_count, &mut offset)?)
1584 }).collect::<Result<Vec<_>, Error>>()?;
1585
1586 Ok(GposSubtable::Type2(GposType2Format::Format2 {
1587 coverage_offset,
1588 coverage,
1589 value_format1,
1590 value_format2,
1591 class_def1_offset,
1592 class_def1,
1593 class_def2_offset,
1594 class_def2,
1595 class1_count,
1596 class2_count,
1597 class1_records
1598 }))
1599 }
1600 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 2 is invalid: {}", format)))
1601 }
1602 }
1603 3 => {
1604 match format {
1605 1 => {
1606 let coverage_offset = get_u16(bytes, offset)?;
1607 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1608 let entry_exit_count = get_u16(bytes, offset + 2)?;
1609 offset += 4;
1610 let entry_exit_records: Vec<EntryExitRecord> = (0..entry_exit_count).map(|_| {
1611 Ok(parse_entry_exit_record(bytes, subtable_offset, &mut offset)?)
1612 }).collect::<Result<Vec<_>, Error>>()?;
1613
1614 Ok(GposSubtable::Type3(GposType3Format::Format1 {
1615 coverage_offset,
1616 coverage,
1617 entry_exit_count,
1618 entry_exit_records
1619 }))
1620 }
1621 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 3 is invalid: {}", format)))
1622 }
1623 }
1624 4 => {
1625 match format {
1626 1 => {
1627 let mark_coverage_offset = get_u16(bytes, offset)?;
1628 let mark_coverage = parse_coverage(bytes, subtable_offset, mark_coverage_offset)?;
1629 let base_coverage_offset = get_u16(bytes, offset + 2)?;
1630 let base_coverage = parse_coverage(bytes, subtable_offset, base_coverage_offset)?;
1631 let mark_class_count = get_u16(bytes, offset + 4)?;
1632 let mark_array_offset = get_u16(bytes, offset + 6)?;
1633 let mark_array = parse_mark_array(bytes, subtable_offset, mark_array_offset)?;
1634 let base_array_offset = get_u16(bytes, offset + 8)?;
1635 let base_array = parse_base_array(bytes, subtable_offset, base_array_offset)?;
1636
1637 Ok(GposSubtable::Type4(GposType4Format::Format1 {
1638 mark_coverage_offset,
1639 mark_coverage,
1640 base_coverage_offset,
1641 base_coverage,
1642 mark_class_count,
1643 mark_array_offset,
1644 mark_array,
1645 base_array_offset,
1646 base_array
1647 }))
1648 }
1649 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 4 is invalid: {}", format)))
1650 }
1651 }
1652 5 => {
1653 match format {
1654 1 => {
1655 let mark_coverage_offset = get_u16(bytes, offset)?;
1656 let mark_coverage = parse_coverage(bytes, subtable_offset, mark_coverage_offset)?;
1657 let ligature_coverage_offset = get_u16(bytes, offset + 2)?;
1658 let ligature_coverage = parse_coverage(bytes, subtable_offset, ligature_coverage_offset)?;
1659 let mark_class_count = get_u16(bytes, offset + 4)?;
1660 let mark_array_offset = get_u16(bytes, offset + 6)?;
1661 let mark_array = parse_mark_array(bytes, subtable_offset, mark_array_offset)?;
1662 let ligature_array_offset = get_u16(bytes, offset + 8)?;
1663 let ligature_array = parse_ligature_array(bytes, subtable_offset, ligature_array_offset, mark_class_count)?;
1664
1665 Ok(GposSubtable::Type5(GposType5Format::Format1 {
1666 mark_coverage_offset,
1667 mark_coverage,
1668 ligature_coverage_offset,
1669 ligature_coverage,
1670 mark_class_count,
1671 mark_array_offset,
1672 mark_array,
1673 ligature_array_offset,
1674 ligature_array
1675 }))
1676 }
1677 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 5 is invalid: {}", format)))
1678 }
1679 }
1680 6 => {
1681 match format {
1682 1 => {
1683 let mark1_coverage_offset = get_u16(bytes, offset)?;
1684 let mark1_coverage = parse_coverage(bytes, subtable_offset, mark1_coverage_offset)?;
1685 let mark2_coverage_offset = get_u16(bytes, offset + 2)?;
1686 let mark2_coverage = parse_coverage(bytes, subtable_offset, mark2_coverage_offset)?;
1687 let mark_class_count = get_u16(bytes, offset + 4)?;
1688 let mark1_array_offset = get_u16(bytes, offset + 6)?;
1689 let mark1_array = parse_mark_array(bytes, subtable_offset, mark1_array_offset)?;
1690 let mark2_array_offset = get_u16(bytes, offset + 8)?;
1691 let mark2_array = parse_mark2_array(bytes, subtable_offset, mark2_array_offset, mark_class_count)?;
1692
1693 Ok(GposSubtable::Type6(GposType6Format::Format1 {
1694 mark1_coverage_offset,
1695 mark1_coverage,
1696 mark2_coverage_offset,
1697 mark2_coverage,
1698 mark_class_count,
1699 mark1_array_offset,
1700 mark1_array,
1701 mark2_array_offset,
1702 mark2_array
1703 }))
1704 }
1705 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 6 is invalid: {}", format)))
1706 }
1707 }
1708 7 => {
1709 match format {
1710 1 => {
1711 let coverage_offset = get_u16(bytes, offset)?;
1712 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1713 let sub_rule_set_count = get_u16(bytes, offset + 2)?;
1714 offset += 2;
1715 let sub_rule_set_offsets: Vec<u16> = bytes.get(offset..offset + sub_rule_set_count as usize * 2)
1716 .ok_or(ErrorKind::UnexpectedEof)?
1717 .chunks_exact(2)
1718 .map(|ch| {
1719 u16::from_be_bytes(ch.try_into().unwrap())
1720 }).collect();
1721 let sub_rule_sets: Vec<GposSubRuleSet> = sub_rule_set_offsets.iter()
1722 .map(|offset| {
1723 Ok(parse_gpos_sub_rule_set(bytes, subtable_offset, *offset)?)
1724 }).collect::<Result<Vec<_>, Error>>()?;
1725
1726 Ok(GposSubtable::Type7(GposType7Format::Format1 {
1727 coverage_offset,
1728 coverage,
1729 sub_rule_set_count,
1730 sub_rule_set_offsets,
1731 sub_rule_sets
1732 }))
1733 }
1734 2 => {
1735 let coverage_offset = get_u16(bytes, offset)?;
1736 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1737 let class_def_offset = get_u16(bytes, offset + 2)?;
1738 let class_def = parse_class_def(bytes, subtable_offset, class_def_offset)?;
1739 let sub_class_set_count = get_u16(bytes, offset + 4)?;
1740 offset += 6;
1741 let sub_class_set_offsets: Vec<u16> = bytes.get(offset..offset + sub_class_set_count as usize * 2)
1742 .ok_or(ErrorKind::UnexpectedEof)?
1743 .chunks_exact(2)
1744 .map(|ch| {
1745 u16::from_be_bytes(ch.try_into().unwrap())
1746 }).collect();
1747 let sub_class_sets: Vec<GposSubClassSet> = sub_class_set_offsets.iter()
1748 .map(|offset| {
1749 Ok(parse_gpos_sub_class_set(bytes, subtable_offset, *offset)?)
1750 }).collect::<Result<Vec<_>, Error>>()?;
1751
1752 Ok(GposSubtable::Type7(GposType7Format::Format2 {
1753 coverage_offset,
1754 coverage,
1755 class_def_offset,
1756 class_def,
1757 sub_class_set_count,
1758 sub_class_set_offsets,
1759 sub_class_sets
1760 }))
1761 }
1762 3 => {
1763 let glyph_count = get_u16(bytes, offset)?;
1764 let sub_count = get_u16(bytes, offset + 2)?;
1765 offset += 4;
1766 let coverage_offsets: Vec<u16> = bytes.get(offset..offset + glyph_count as usize * 2)
1767 .ok_or(ErrorKind::UnexpectedEof)?
1768 .chunks_exact(2)
1769 .map(|ch| {
1770 u16::from_be_bytes(ch.try_into().unwrap())
1771 }).collect();
1772 offset += glyph_count as usize * 2;
1773 let coverages: Vec<Coverage> = coverage_offsets.iter()
1774 .map(|offset| {
1775 Ok(parse_coverage(bytes, subtable_offset, *offset)?)
1776 }).collect::<Result<Vec<_>, Error>>()?;
1777 let pos_lookup_records: Vec<PosLookupRecord> = (0..sub_count).map(|_| {
1778 Ok(parse_pos_lookup_record(bytes, &mut offset)?)
1779 }).collect::<Result<Vec<_>, Error>>()?;
1780
1781 Ok(GposSubtable::Type7(GposType7Format::Format3 {
1782 glyph_count,
1783 sub_count,
1784 coverage_offsets,
1785 coverages,
1786 pos_lookup_records
1787 }))
1788 }
1789 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 7 is invalid: {}", format)))
1790 }
1791 }
1792 8 => {
1793 match format {
1794 1 => {
1795 let coverage_offset = get_u16(bytes, offset)?;
1796 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1797 let chain_sub_rule_set_count = get_u16(bytes, offset + 2)?;
1798 offset += 4;
1799 let chain_sub_rule_set_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_rule_set_count as usize * 2)
1800 .ok_or(ErrorKind::UnexpectedEof)?
1801 .chunks_exact(2)
1802 .map(|ch| {
1803 u16::from_be_bytes(ch.try_into().unwrap())
1804 }).collect();
1805 let chain_sub_rule_sets: Vec<GposChainSubRuleSet> = chain_sub_rule_set_offsets.iter()
1806 .map(|offset| {
1807 Ok(parse_gpos_chain_sub_rule_set(bytes, subtable_offset, *offset)?)
1808 }).collect::<Result<Vec<_>, Error>>()?;
1809
1810 Ok(GposSubtable::Type8(GposType8Format::Format1 {
1811 coverage_offset,
1812 coverage,
1813 chain_sub_rule_set_count,
1814 chain_sub_rule_set_offsets,
1815 chain_sub_rule_sets
1816 }))
1817 }
1818 2 => {
1819 let coverage_offset = get_u16(bytes, offset)?;
1820 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1821 let backtrack_class_def_offset = get_u16(bytes, offset + 2)?;
1822 let backtrack_class_def = parse_class_def(bytes, subtable_offset, backtrack_class_def_offset)?;
1823 let input_class_def_offset = get_u16(bytes, offset + 4)?;
1824 let input_class_def = parse_class_def(bytes, subtable_offset, input_class_def_offset)?;
1825 let lookahead_class_def_offset = get_u16(bytes, offset + 6)?;
1826 let lookahead_class_def = parse_class_def(bytes, subtable_offset, lookahead_class_def_offset)?;
1827 let chain_sub_class_set_count = get_u16(bytes, offset + 8)?;
1828 offset += 8;
1829 let chain_sub_class_set_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_class_set_count as usize * 2)
1830 .ok_or(ErrorKind::UnexpectedEof)?
1831 .chunks_exact(2)
1832 .map(|ch| {
1833 u16::from_be_bytes(ch.try_into().unwrap())
1834 }).collect();
1835 let chain_sub_class_sets: Vec<GposChainSubClassSet> = chain_sub_class_set_offsets.iter()
1836 .map(|offset| {
1837 Ok(parse_gpos_chain_sub_class_set(bytes, subtable_offset, *offset)?)
1838 }).collect::<Result<Vec<_>, Error>>()?;
1839
1840 Ok(GposSubtable::Type8(GposType8Format::Format2 {
1841 coverage_offset,
1842 coverage,
1843 backtrack_class_def_offset,
1844 backtrack_class_def,
1845 input_class_def_offset,
1846 input_class_def,
1847 lookahead_class_def_offset,
1848 lookahead_class_def,
1849 chain_sub_class_set_count,
1850 chain_sub_class_set_offsets,
1851 chain_sub_class_sets
1852 }))
1853 }
1854 3 => {
1855 let backtrack_glyph_count = get_u16(bytes, offset)?;
1856 offset += 2;
1857 let backtrack_coverage_offsets: Vec<u16> = bytes.get(offset..offset + backtrack_glyph_count as usize * 2)
1858 .ok_or(ErrorKind::UnexpectedEof)?
1859 .chunks_exact(2)
1860 .map(|ch| {
1861 u16::from_be_bytes(ch.try_into().unwrap())
1862 }).collect();
1863 offset += backtrack_glyph_count as usize * 2;
1864 let backtrack_coverages: Vec<Coverage> = backtrack_coverage_offsets.iter()
1865 .map(|offset| {
1866 Ok(parse_coverage(bytes, subtable_offset, *offset)?)
1867 }).collect::<Result<Vec<_>, Error>>()?;
1868 let input_glyph_count = get_u16(bytes, offset)?;
1869 offset += 2;
1870 let input_coverage_offsets: Vec<u16> = bytes.get(offset..offset + input_glyph_count as usize * 2)
1871 .ok_or(ErrorKind::UnexpectedEof)?
1872 .chunks_exact(2)
1873 .map(|ch| {
1874 u16::from_be_bytes(ch.try_into().unwrap())
1875 }).collect();
1876 offset += input_glyph_count as usize * 2;
1877 let input_coverages: Vec<Coverage> = input_coverage_offsets.iter()
1878 .map(|offset| {
1879 Ok(parse_coverage(bytes, subtable_offset, *offset)?)
1880 }).collect::<Result<Vec<_>, Error>>()?;
1881 let lookahead_glyph_count = get_u16(bytes, offset)?;
1882 offset += 2;
1883 let lookahead_coverage_offsets: Vec<u16> = bytes.get(offset..offset + lookahead_glyph_count as usize * 2)
1884 .ok_or(ErrorKind::UnexpectedEof)?
1885 .chunks_exact(2)
1886 .map(|ch| {
1887 u16::from_be_bytes(ch.try_into().unwrap())
1888 }).collect();
1889 offset += lookahead_glyph_count as usize * 2;
1890 let lookahead_coverages: Vec<Coverage> = lookahead_coverage_offsets.iter()
1891 .map(|offset| {
1892 Ok(parse_coverage(bytes, subtable_offset, *offset)?)
1893 }).collect::<Result<Vec<_>, Error>>()?;
1894 let sub_count = get_u16(bytes, offset)?;
1895 offset += 2;
1896 let pos_lookup_records: Vec<PosLookupRecord> = (0..sub_count).map(|_| {
1897 Ok(parse_pos_lookup_record(bytes, &mut offset)?)
1898 }).collect::<Result<Vec<_>, Error>>()?;
1899
1900 Ok(GposSubtable::Type8(GposType8Format::Format3 {
1901 backtrack_glyph_count,
1902 backtrack_coverage_offsets,
1903 backtrack_coverages,
1904 input_glyph_count,
1905 input_coverage_offsets,
1906 input_coverages,
1907 lookahead_glyph_count,
1908 lookahead_coverage_offsets,
1909 lookahead_coverages,
1910 sub_count,
1911 pos_lookup_records
1912 }))
1913 }
1914 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 8 is invalid: {}", format)))
1915 }
1916 }
1917 9 => {
1918 match format {
1919 1 => {
1920 let extension_lookup_type = get_u16(bytes, offset)?;
1921 let extension_offset = get_u32(bytes, offset + 2)?;
1922 let extension = Box::new(GposSubtable::parse(bytes, subtable_offset, extension_offset, extension_lookup_type)?);
1923
1924 Ok(GposSubtable::Type9(GposType9Format::Format1 {
1925 extension_lookup_type,
1926 extension_offset,
1927 extension
1928 }))
1929 }
1930 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 9 is invalid: {}", format)))
1931 }
1932 }
1933 _ => Err(Error::new(ErrorKind::InvalidData, format!("Lookup Type is invalid: {}", lookup_type)))
1934 }
1935 }
1936}
1937
1938impl SubtableParser for GsubSubtable {
1939 fn parse(bytes: &[u8], subtable_offset: usize, extension_offset: u32, lookup_type: u16) -> Result<Self, Error> {
1940 let mut offset = (subtable_offset as u32 + extension_offset) as usize;
1941 let format = get_u16(bytes, offset)?;
1942 offset += 2;
1943 match lookup_type {
1944 1 => {
1945 match format {
1946 1 => {
1947 let coverage_offset = get_u16(bytes, offset)?;
1948 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1949 let delta_glyph_id = get_i16(bytes, offset + 2)?;
1950
1951 Ok(GsubSubtable::Type1(GsubType1Format::Format1 {
1952 coverage_offset,
1953 coverage,
1954 delta_glyph_id
1955 }))
1956 }
1957 2 => {
1958 let coverage_offset = get_u16(bytes, offset)?;
1959 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1960 let glyph_count = get_u16(bytes, offset + 2)?;
1961 offset += 4;
1962 let substitute_glyph_ids = bytes.get(offset..offset + glyph_count as usize * 2)
1963 .ok_or(ErrorKind::UnexpectedEof)?
1964 .chunks_exact(2)
1965 .map(|ch| {
1966 u16::from_be_bytes(ch.try_into().unwrap())
1967 }).collect();
1968
1969 Ok(GsubSubtable::Type1(GsubType1Format::Format2 {
1970 coverage_offset,
1971 coverage,
1972 glyph_count,
1973 substitute_glyph_ids
1974 }))
1975 }
1976 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 1 is invalid: {}", format)))
1977 }
1978 }
1979 2 => {
1980 match format {
1981 1 => {
1982 let coverage_offset = get_u16(bytes, offset)?;
1983 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
1984 let sequence_count = get_u16(bytes, offset + 2)?;
1985 offset += 4;
1986 let sequence_offsets: Vec<u16> = bytes.get(offset..offset + sequence_count as usize * 2)
1987 .ok_or(ErrorKind::UnexpectedEof)?
1988 .chunks_exact(2)
1989 .map(|ch| {
1990 u16::from_be_bytes(ch.try_into().unwrap())
1991 }).collect();
1992 let sequences: Vec<Sequence> = sequence_offsets.iter()
1993 .map(|offset| {
1994 Ok(parse_sequence(bytes, subtable_offset, *offset)?)
1995 }).collect::<Result<Vec<_>, Error>>()?;
1996
1997 Ok(GsubSubtable::Type2(GsubType2Format::Format1 {
1998 coverage_offset,
1999 coverage,
2000 sequence_count,
2001 sequence_offsets,
2002 sequences
2003 }))
2004 }
2005 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 2 is invalid: {}", format)))
2006 }
2007 }
2008 3 => {
2009 match format {
2010 1 => {
2011 let coverage_offset = get_u16(bytes, offset)?;
2012 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
2013 let alternate_set_count = get_u16(bytes, offset + 2)?;
2014 offset += 4;
2015 let alternate_set_offsets: Vec<u16> = bytes.get(offset..offset + alternate_set_count as usize * 2)
2016 .ok_or(ErrorKind::UnexpectedEof)?
2017 .chunks_exact(2)
2018 .map(|ch| {
2019 u16::from_be_bytes(ch.try_into().unwrap())
2020 }).collect();
2021 let alternate_sets: Vec<AlternateSet> = alternate_set_offsets.iter()
2022 .map(|offset| {
2023 Ok(parse_alternate_set(bytes, subtable_offset, *offset)?)
2024 }).collect::<Result<Vec<_>, Error>>()?;
2025
2026 Ok(GsubSubtable::Type3(GsubType3Format::Format1 {
2027 coverage_offset,
2028 coverage,
2029 alternate_set_count,
2030 alternate_set_offsets,
2031 alternate_sets
2032 }))
2033 }
2034 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 3 is invalid: {}", format)))
2035 }
2036 }
2037 4 => {
2038 match format {
2039 1 => {
2040 let coverage_offset = get_u16(bytes, offset)?;
2041 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
2042 let ligature_set_count = get_u16(bytes, offset + 2)?;
2043 offset += 4;
2044 let ligature_set_offsets: Vec<u16> = bytes.get(offset..offset + ligature_set_count as usize)
2045 .ok_or(ErrorKind::UnexpectedEof)?
2046 .chunks_exact(2)
2047 .map(|ch| {
2048 u16::from_be_bytes(ch.try_into().unwrap())
2049 }).collect();
2050 let ligature_sets: Vec<LigatureSet> = ligature_set_offsets.iter()
2051 .map(|offset| {
2052 Ok(parse_ligature_set(bytes, subtable_offset, *offset)?)
2053 }).collect::<Result<Vec<_>, Error>>()?;
2054
2055 Ok(GsubSubtable::Type4(GsubType4Format::Format1 {
2056 coverage_offset,
2057 coverage,
2058 ligature_set_count,
2059 ligature_set_offsets,
2060 ligature_sets
2061 }))
2062 }
2063 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 4 is invalid: {}", format)))
2064 }
2065 }
2066 5 => {
2067 match format {
2068 1 => {
2069 let coverage_offset = get_u16(bytes, offset)?;
2070 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
2071 let sub_rule_set_count = get_u16(bytes, offset + 2)?;
2072 offset += 4;
2073 let sub_rule_set_offsets: Vec<u16> = bytes.get(offset..offset + sub_rule_set_count as usize * 2)
2074 .ok_or(ErrorKind::UnexpectedEof)?
2075 .chunks_exact(2)
2076 .map(|ch| {
2077 u16::from_be_bytes(ch.try_into().unwrap())
2078 }).collect();
2079 let sub_rule_sets: Vec<GsubSubRuleSet> = sub_rule_set_offsets.iter()
2080 .map(|offset| {
2081 Ok(parse_gsub_sub_rule_set(bytes, subtable_offset, *offset)?)
2082 }).collect::<Result<Vec<_>, Error>>()?;
2083
2084 Ok(GsubSubtable::Type5(GsubType5Format::Format1 {
2085 coverage_offset,
2086 coverage,
2087 sub_rule_set_count,
2088 sub_rule_set_offsets,
2089 sub_rule_sets
2090 }))
2091 }
2092 2 => {
2093 let coverage_offset = get_u16(bytes, offset)?;
2094 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
2095 let class_def_offset = get_u16(bytes, offset + 2)?;
2096 let class_def = parse_class_def(bytes, subtable_offset, class_def_offset)?;
2097 let sub_class_set_count = get_u16(bytes, offset + 4)?;
2098 offset += 6;
2099 let sub_class_set_offsets: Vec<u16> = bytes.get(offset..offset + sub_class_set_count as usize * 2)
2100 .ok_or(ErrorKind::UnexpectedEof)?
2101 .chunks_exact(2)
2102 .map(|ch| {
2103 u16::from_be_bytes(ch.try_into().unwrap())
2104 }).collect();
2105 let sub_class_sets: Vec<GsubSubClassSet> = sub_class_set_offsets.iter()
2106 .map(|offset| {
2107 Ok(parse_gsub_sub_class_set(bytes, subtable_offset, *offset)?)
2108 }).collect::<Result<Vec<_>, Error>>()?;
2109
2110 Ok(GsubSubtable::Type5(GsubType5Format::Format2 {
2111 coverage_offset,
2112 coverage,
2113 class_def_offset,
2114 class_def,
2115 sub_class_set_count,
2116 sub_class_set_offsets,
2117 sub_class_sets
2118 }))
2119 }
2120 3 => {
2121 let glyph_count = get_u16(bytes, offset)?;
2122 let sub_count = get_u16(bytes, offset + 2)?;
2123 offset += 4;
2124 let coverage_offsets: Vec<u16> = bytes.get(offset..offset + glyph_count as usize * 2)
2125 .ok_or(ErrorKind::UnexpectedEof)?
2126 .chunks_exact(2)
2127 .map(|ch| {
2128 u16::from_be_bytes(ch.try_into().unwrap())
2129 }).collect();
2130 offset += glyph_count as usize * 2;
2131 let coverages: Vec<Coverage> = coverage_offsets.iter()
2132 .map(|offset| {
2133 Ok(parse_coverage(bytes, subtable_offset, *offset)?)
2134 }).collect::<Result<Vec<_>, Error>>()?;
2135 let subst_lookup_records: Vec<SubstLookupRecord> = (0..sub_count).map(|_| {
2136 Ok(parse_subst_lookup_record(bytes, &mut offset)?)
2137 }).collect::<Result<Vec<_>, Error>>()?;
2138
2139 Ok(GsubSubtable::Type5(GsubType5Format::Format3 {
2140 glyph_count,
2141 sub_count,
2142 coverage_offsets,
2143 coverages,
2144 subst_lookup_records
2145 }))
2146 }
2147 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 5 is invalid: {}", format)))
2148 }
2149 }
2150 6 => {
2151 match format {
2152 1 => {
2153 let coverage_offset = get_u16(bytes, offset)?;
2154 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
2155 let chain_sub_rule_set_count = get_u16(bytes, offset + 2)?;
2156 offset += 4;
2157 let chain_sub_rule_set_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_rule_set_count as usize * 2)
2158 .ok_or(ErrorKind::UnexpectedEof)?
2159 .chunks_exact(2)
2160 .map(|ch| {
2161 u16::from_be_bytes(ch.try_into().unwrap())
2162 }).collect();
2163 let chain_sub_rule_sets: Vec<GsubChainSubRuleSet> = chain_sub_rule_set_offsets.iter()
2164 .map(|offset| {
2165 Ok(parse_gsub_chain_sub_rule_set(bytes, subtable_offset, *offset)?)
2166 }).collect::<Result<Vec<_>, Error>>()?;
2167
2168 Ok(GsubSubtable::Type6(GsubType6Format::Format1 {
2169 coverage_offset,
2170 coverage,
2171 chain_sub_rule_set_count,
2172 chain_sub_rule_set_offsets,
2173 chain_sub_rule_sets
2174 }))
2175 }
2176 2 => {
2177 let coverage_offset = get_u16(bytes, offset)?;
2178 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
2179 let backtrack_class_def_offset = get_u16(bytes, offset + 2)?;
2180 let backtrack_class_def = parse_class_def(bytes, subtable_offset, backtrack_class_def_offset)?;
2181 let input_class_def_offset = get_u16(bytes, offset + 4)?;
2182 let input_class_def = parse_class_def(bytes, subtable_offset, input_class_def_offset)?;
2183 let lookahead_class_def_offset = get_u16(bytes, offset + 6)?;
2184 let lookahead_class_def = parse_class_def(bytes, subtable_offset, lookahead_class_def_offset)?;
2185 let chain_sub_class_set_count = get_u16(bytes, offset + 8)?;
2186 offset += 8;
2187 let chain_sub_class_set_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_class_set_count as usize * 2)
2188 .ok_or(ErrorKind::UnexpectedEof)?
2189 .chunks_exact(2)
2190 .map(|ch| {
2191 u16::from_be_bytes(ch.try_into().unwrap())
2192 }).collect();
2193 let chain_sub_class_sets: Vec<GsubChainSubClassSet> = chain_sub_class_set_offsets.iter()
2194 .map(|offset| {
2195 Ok(parse_gsub_chain_sub_class_set(bytes, subtable_offset, *offset)?)
2196 }).collect::<Result<Vec<_>, Error>>()?;
2197
2198 Ok(GsubSubtable::Type6(GsubType6Format::Format2 {
2199 coverage_offset,
2200 coverage,
2201 backtrack_class_def_offset,
2202 backtrack_class_def,
2203 input_class_def_offset,
2204 input_class_def,
2205 lookahead_class_def_offset,
2206 lookahead_class_def,
2207 chain_sub_class_set_count,
2208 chain_sub_class_set_offsets,
2209 chain_sub_class_sets
2210 }))
2211 }
2212 3 => {
2213 let backtrack_glyph_count = get_u16(bytes, offset)?;
2214 offset += 2;
2215 let backtrack_coverage_offsets: Vec<u16> = bytes.get(offset..offset + backtrack_glyph_count as usize * 2)
2216 .ok_or(ErrorKind::UnexpectedEof)?
2217 .chunks_exact(2)
2218 .map(|ch| {
2219 u16::from_be_bytes(ch.try_into().unwrap())
2220 }).collect();
2221 offset += backtrack_glyph_count as usize * 2;
2222 let backtrack_coverages: Vec<Coverage> = backtrack_coverage_offsets.iter()
2223 .map(|offset| {
2224 Ok(parse_coverage(bytes, subtable_offset, *offset)?)
2225 }).collect::<Result<Vec<_>, Error>>()?;
2226 let input_glyph_count = get_u16(bytes, offset)?;
2227 offset += 2;
2228 let input_coverage_offsets: Vec<u16> = bytes.get(offset..offset + input_glyph_count as usize * 2)
2229 .ok_or(ErrorKind::UnexpectedEof)?
2230 .chunks_exact(2)
2231 .map(|ch| {
2232 u16::from_be_bytes(ch.try_into().unwrap())
2233 }).collect();
2234 offset += input_glyph_count as usize * 2;
2235 let input_coverages: Vec<Coverage> = input_coverage_offsets.iter()
2236 .map(|offset| {
2237 Ok(parse_coverage(bytes, subtable_offset, *offset)?)
2238 }).collect::<Result<Vec<_>, Error>>()?;
2239 let lookahead_glyph_count = get_u16(bytes, offset)?;
2240 offset += 2;
2241 let lookahead_coverage_offsets: Vec<u16> = bytes.get(offset..offset + lookahead_glyph_count as usize * 2)
2242 .ok_or(ErrorKind::UnexpectedEof)?
2243 .chunks_exact(2)
2244 .map(|ch| {
2245 u16::from_be_bytes(ch.try_into().unwrap())
2246 }).collect();
2247 offset += lookahead_glyph_count as usize * 2;
2248 let lookahead_coverages: Vec<Coverage> = lookahead_coverage_offsets.iter()
2249 .map(|offset| {
2250 Ok(parse_coverage(bytes, subtable_offset, *offset)?)
2251 }).collect::<Result<Vec<_>, Error>>()?;
2252 let sub_count = get_u16(bytes, offset)?;
2253 offset += 2;
2254 let subst_lookup_records: Vec<SubstLookupRecord> = (0..sub_count).map(|_| {
2255 Ok(parse_subst_lookup_record(bytes, &mut offset)?)
2256 }).collect::<Result<Vec<_>, Error>>()?;
2257
2258 Ok(GsubSubtable::Type6(GsubType6Format::Format3 {
2259 backtrack_glyph_count,
2260 backtrack_coverage_offsets,
2261 backtrack_coverages,
2262 input_glyph_count,
2263 input_coverage_offsets,
2264 input_coverages,
2265 lookahead_glyph_count,
2266 lookahead_coverage_offsets,
2267 lookahead_coverages,
2268 sub_count,
2269 subst_lookup_records
2270 }))
2271 }
2272 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 6 is invalid: {}", format)))
2273 }
2274 }
2275 7 => {
2276 match format {
2277 1 => {
2278 let extension_lookup_type = get_u16(bytes, offset)?;
2279 let extension_offset = get_u32(bytes, offset + 2)?;
2280 let extension = Box::new(GsubSubtable::parse(bytes, subtable_offset, extension_offset, extension_lookup_type)?);
2281
2282 Ok(GsubSubtable::Type7(GsubType7Format::Format1 {
2283 extension_lookup_type,
2284 extension_offset,
2285 extension
2286 }))
2287 }
2288 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 7 is invalid: {}", format)))
2289 }
2290 }
2291 8 => {
2292 match format {
2293 1 => {
2294 let coverage_offset = get_u16(bytes, offset)?;
2295 let coverage = parse_coverage(bytes, subtable_offset, coverage_offset)?;
2296 let backtrack_glyph_count = get_u16(bytes, offset + 2)?;
2297 offset += 4;
2298 let backtrack_coverage_offsets: Vec<u16> = bytes.get(offset..offset + backtrack_glyph_count as usize * 2)
2299 .ok_or(ErrorKind::UnexpectedEof)?
2300 .chunks_exact(2)
2301 .map(|ch| {
2302 u16::from_be_bytes(ch.try_into().unwrap())
2303 }).collect();
2304 offset += backtrack_glyph_count as usize * 2;
2305 let backtrack_coverages: Vec<Coverage> = backtrack_coverage_offsets.iter()
2306 .map(|offset| {
2307 Ok(parse_coverage(bytes, subtable_offset, *offset)?)
2308 }).collect::<Result<Vec<_>, Error>>()?;
2309 let lookahead_glyph_count = get_u16(bytes, offset)?;
2310 offset += 2;
2311 let lookahead_coverage_offsets: Vec<u16> = bytes.get(offset..offset + lookahead_glyph_count as usize * 2)
2312 .ok_or(ErrorKind::UnexpectedEof)?
2313 .chunks_exact(2)
2314 .map(|ch| {
2315 u16::from_be_bytes(ch.try_into().unwrap())
2316 }).collect();
2317 offset += lookahead_glyph_count as usize * 2;
2318 let lookahead_coverages: Vec<Coverage> = lookahead_coverage_offsets.iter()
2319 .map(|offset| {
2320 Ok(parse_coverage(bytes, subtable_offset, *offset)?)
2321 }).collect::<Result<Vec<_>, Error>>()?;
2322 let glyph_count = get_u16(bytes, offset)?;
2323 offset += 2;
2324 let substitute_glyph_ids: Vec<u16> = bytes.get(offset..offset + glyph_count as usize * 2)
2325 .ok_or(ErrorKind::UnexpectedEof)?
2326 .chunks_exact(2)
2327 .map(|ch| {
2328 u16::from_be_bytes(ch.try_into().unwrap())
2329 }).collect();
2330
2331 Ok(GsubSubtable::Type8(GsubType8Format::Format1 {
2332 coverage_offset,
2333 coverage,
2334 backtrack_glyph_count,
2335 backtrack_coverage_offsets,
2336 backtrack_coverages,
2337 lookahead_glyph_count,
2338 lookahead_coverage_offsets,
2339 lookahead_coverages,
2340 glyph_count,
2341 substitute_glyph_ids
2342 }))
2343 }
2344 _ => Err(Error::new(ErrorKind::InvalidData, format!("Format for Lookup Type 8 is invalid: {}", format)))
2345 }
2346 }
2347 _ => Err(Error::new(ErrorKind::InvalidData, format!("Lookup Type is invalid: {}", lookup_type)))
2348 }
2349 }
2350}
2351
2352fn parse_feature_variations(bytes: &[u8], feature_variations_offset: u32, feature_list: FeatureList) -> Result<FeatureVariations, Error> {
2353 let mut offset = feature_variations_offset as usize;
2354
2355 let major_version = get_u16(bytes, offset)?;
2356 let minor_version = get_u16(bytes, offset + 2)?;
2357 let feature_variation_record_count = get_u32(bytes, offset + 4)?;
2358 offset += 8;
2359 let mut feature_variation_records: Vec<FeatureVariationRecord> = Vec::with_capacity(feature_variation_record_count as usize);
2360 for _ in 0..feature_variation_record_count {
2361 let condition_set_offset = get_u32(bytes, offset)?;
2362 offset += 4;
2363 let condition_set: ConditionSet = {
2364 let mut offset = (feature_variations_offset + condition_set_offset) as usize;
2365 let condition_count = get_u16(bytes, offset)?;
2366 offset += 2;
2367 let condition_offsets: Vec<u32> = bytes.get(offset..offset + condition_count as usize * 4)
2368 .ok_or(ErrorKind::UnexpectedEof)?
2369 .chunks_exact(4)
2370 .map(|ch| {
2371 u32::from_be_bytes(ch.try_into().unwrap())
2372 }).collect();
2373 let conditions: Vec<Condition> = condition_offsets.iter()
2374 .map(|off| {
2375 let offset = *off as usize;
2376 let format = get_u16(bytes, offset)?;
2377 match format {
2378 1 => {
2379 let axis_index = get_u16(bytes, offset)?;
2380 let filter_range_min_value = get_i16(bytes, offset + 2)?;
2381 let filter_range_max_value = get_i16(bytes, offset + 4)?;
2382
2383 Ok(Condition::Format1 {
2384 axis_index,
2385 filter_range_min_value,
2386 filter_range_max_value
2387 })
2388 }
2389 _ => return Err(Error::new(ErrorKind::InvalidData, format!("Condition format invalid: {}", format)))
2390 }
2391 }).collect::<Result<Vec<_>, Error>>()?;
2392
2393 ConditionSet::new(
2394 condition_count,
2395 condition_offsets,
2396 conditions
2397 )
2398 };
2399 let feature_table_substitution_offset = get_u32(bytes, offset)?;
2400 let feature_table_substitution: FeatureTableSubstitution = {
2401 let mut offset = (feature_variations_offset + feature_table_substitution_offset) as usize;
2402 let major_version = get_u16(bytes, offset)?;
2403 let minor_version = get_u16(bytes, offset + 2)?;
2404 let substitution_count = get_u16(bytes, offset + 4)?;
2405 offset += 4;
2406 let mut substitution_records: Vec<FeatureTableSubstitutionRecord> = Vec::with_capacity(substitution_count as usize);
2407 for _ in 0..substitution_count {
2408 let feature_index = get_u16(bytes, offset)?;
2409 let alternate_feature_table_offset = get_u32(bytes, offset + 2)?;
2410 offset += 6;
2411 let alternate_feature_table: Feature = {
2412 let mut offset = (feature_variations_offset + feature_table_substitution_offset + alternate_feature_table_offset) as usize;
2413 let test_offset = get_u16(bytes, offset)?;
2414 offset += 2;
2415 let feature_params_offset = if test_offset != 0 {
2416 Some(test_offset)
2417 }
2418 else {
2419 None
2420 };
2421 let feature_params = if feature_params_offset != None {
2422 let feature_tag = feature_list.feature_records()
2423 .get(feature_index as usize)
2424 .ok_or(ErrorKind::NotFound)?
2425 .feature_tag();
2426 match &feature_tag {
2427 b"size" => {
2428 let design_size = get_u16(bytes, offset)?;
2429 let subfamily_id = get_u16(bytes, offset + 2)?;
2430 let subfamily_name_id = get_u16(bytes, offset + 4)?;
2431 let range_start = get_u16(bytes, offset + 6)?;
2432 let range_end = get_u16(bytes, offset + 8)?;
2433
2434 Some(FeatureParams::Size {
2435 design_size,
2436 subfamily_id,
2437 subfamily_name_id,
2438 range_start,
2439 range_end
2440 })
2441 },
2442 tag if tag.starts_with(b"ss") => {
2443 let version = get_u16(bytes, offset)?;
2444 let ui_name_id = get_u16(bytes, offset + 2)?;
2445
2446 Some(FeatureParams::StylisticSet {
2447 version,
2448 ui_name_id
2449 })
2450 },
2451 tag if tag.starts_with(b"cv") => {
2452 let format = get_u16(bytes, offset)?;
2453 let feat_ui_label_name_id = get_u16(bytes, offset + 2)?;
2454 let feat_tooltip_text_name_id = get_u16(bytes, offset + 4)?;
2455 let sample_text_name_id = get_u16(bytes, offset + 6)?;
2456 let num_named_parameters = get_u16(bytes, offset + 8)?;
2457 let first_param_ui_label_name_id = get_u16(bytes, offset + 10)?;
2458 let char_count = get_u16(bytes, offset + 12)?;
2459 let character: [u8; 3] = bytes.get(offset + 14..offset + 17)
2460 .ok_or(ErrorKind::UnexpectedEof)?
2461 .try_into()
2462 .unwrap();
2463
2464 Some(FeatureParams::CharacterVariant {
2465 format,
2466 feat_ui_label_name_id,
2467 feat_tooltip_text_name_id,
2468 sample_text_name_id,
2469 num_named_parameters,
2470 first_param_ui_label_name_id,
2471 char_count,
2472 character
2473 })
2474 }
2475 _ => return Err(Error::new(ErrorKind::InvalidData, format!("Feature tag is invalid: {:#?}", feature_tag)))
2476 }
2477 }
2478 else {
2479 None
2480 };
2481 let lookup_index_count = get_u16(bytes, offset)?;
2482 offset += 2;
2483 let lookup_list_indices: Vec<u16> = bytes.get(offset..offset + lookup_index_count as usize * 2)
2484 .ok_or(ErrorKind::UnexpectedEof)?
2485 .chunks_exact(2)
2486 .map(|ch| {
2487 u16::from_be_bytes(ch.try_into().unwrap())
2488 }).collect();
2489
2490 Feature::new(
2491 feature_params_offset,
2492 feature_params,
2493 lookup_index_count,
2494 lookup_list_indices
2495 )
2496 };
2497
2498 substitution_records.push(FeatureTableSubstitutionRecord::new(
2499 feature_index,
2500 alternate_feature_table_offset,
2501 alternate_feature_table
2502 ))
2503 }
2504
2505 FeatureTableSubstitution::new(
2506 major_version,
2507 minor_version,
2508 substitution_count,
2509 substitution_records
2510 )
2511 };
2512
2513 feature_variation_records.push(FeatureVariationRecord::new(
2514 condition_set_offset,
2515 condition_set,
2516 feature_table_substitution_offset,
2517 feature_table_substitution
2518 ));
2519 }
2520
2521 Ok(FeatureVariations::new(
2522 major_version,
2523 minor_version,
2524 feature_variation_record_count,
2525 feature_variation_records
2526 ))
2527}
2528
2529fn parse_coverage(bytes: &[u8], subtable_offset: usize, coverage_offset: u16) -> Result<Coverage, Error> {
2530 let mut offset = subtable_offset + coverage_offset as usize;
2531 let format = get_u16(bytes, offset)?;
2532 offset += 2;
2533 match format {
2534 1 => {
2535 let glyph_count = get_u16(bytes, offset)?;
2536 offset += 2;
2537 let glyph_array = bytes.get(offset..offset + glyph_count as usize * 2)
2538 .ok_or(ErrorKind::UnexpectedEof)?
2539 .chunks_exact(2)
2540 .map(|ch| {
2541 u16::from_be_bytes(ch.try_into().unwrap())
2542 }).collect();
2543
2544 Ok(Coverage::Format1 {
2545 glyph_count,
2546 glyph_array
2547 })
2548 }
2549 2 => {
2550 let range_count = get_u16(bytes, offset)?;
2551 offset += 2;
2552 let range_records: Vec<CoverageRangeRecord> = bytes.get(offset..offset + range_count as usize * 6)
2553 .ok_or(ErrorKind::UnexpectedEof)?
2554 .chunks_exact(6)
2555 .map(|ch| {
2556 let start_glyph_id = u16::from_be_bytes(ch[0..2].try_into().unwrap());
2557 let end_glyph_id = u16::from_be_bytes(ch[2..4].try_into().unwrap());
2558 let start_coverage_index = u16::from_be_bytes(ch[4..6].try_into().unwrap());
2559
2560 CoverageRangeRecord::new(
2561 start_glyph_id,
2562 end_glyph_id,
2563 start_coverage_index
2564 )
2565 }).collect();
2566
2567 Ok(Coverage::Format2 {
2568 range_count,
2569 range_records
2570 })
2571 }
2572 _ => return Err(Error::new(ErrorKind::InvalidData, format!("Coverage format invalid: {}", format)))
2573 }
2574}
2575
2576fn parse_value_record(bytes: &[u8], value_format: u16, offset: &mut usize, subtable_offset: usize) -> Result<ValueRecord, Error> {
2577 let x_placement = if value_format & X_PLACEMENT != 0 {
2578 *offset += 2;
2579 Some(get_i16(bytes, *offset - 2)?)
2580 }
2581 else { None };
2582 let y_placement = if value_format & Y_PLACEMENT != 0 {
2583 *offset += 2;
2584 Some(get_i16(bytes, *offset - 2)?)
2585 }
2586 else { None };
2587 let x_advance = if value_format & X_ADVANCE != 0 {
2588 *offset += 2;
2589 Some(get_i16(bytes, *offset - 2)?)
2590 }
2591 else { None };
2592 let y_advance = if value_format & Y_ADVANCE != 0 {
2593 *offset += 2;
2594 Some(get_i16(bytes, *offset - 2)?)
2595 }
2596 else { None };
2597 let x_pla_device_offset = if value_format & X_PLACEMENT_DEVICE != 0 {
2598 *offset += 2;
2599 Some(get_u16(bytes, *offset - 2)?)
2600 }
2601 else { None };
2602 let x_pla_device = if x_pla_device_offset != None {
2603 Some(parse_device_or_variation_index(bytes, subtable_offset, x_pla_device_offset.unwrap())?)
2604 }
2605 else { None };
2606 let y_pla_device_offset = if value_format & Y_PLACEMENT_DEVICE != 0 {
2607 *offset += 2;
2608 Some(get_u16(bytes, *offset - 2)?)
2609 }
2610 else { None };
2611 let y_pla_device = if y_pla_device_offset != None {
2612 Some(parse_device_or_variation_index(bytes, subtable_offset, y_pla_device_offset.unwrap())?)
2613 }
2614 else { None };
2615 let x_adv_device_offset = if value_format & X_ADVANCE_DEVICE != 0 {
2616 *offset += 2;
2617 Some(get_u16(bytes, *offset - 2)?)
2618 }
2619 else { None };
2620 let x_adv_device = if x_adv_device_offset != None {
2621 Some(parse_device_or_variation_index(bytes, subtable_offset, x_adv_device_offset.unwrap())?)
2622 }
2623 else { None };
2624 let y_adv_device_offset = if value_format & Y_ADVANCE_DEVICE != 0 {
2625 *offset += 2;
2626 Some(get_u16(bytes, *offset - 2)?)
2627 }
2628 else { None };
2629 let y_adv_device = if y_adv_device_offset != None {
2630 Some(parse_device_or_variation_index(bytes, subtable_offset, y_adv_device_offset.unwrap())?)
2631 }
2632 else { None };
2633
2634 Ok(ValueRecord::new(
2635 x_placement,
2636 y_placement,
2637 x_advance,
2638 y_advance,
2639 x_pla_device_offset,
2640 x_pla_device,
2641 y_pla_device_offset,
2642 y_pla_device,
2643 x_adv_device_offset,
2644 x_adv_device,
2645 y_adv_device_offset,
2646 y_adv_device
2647 ))
2648}
2649
2650fn parse_device_or_variation_index(bytes: &[u8], subtable_offset: usize, device_offset: u16) -> Result<DeviceOrVariationIndex, Error> {
2651 let offset = subtable_offset + device_offset as usize;
2652 let delta_format = get_u16(bytes, offset + 4)?;
2653 if delta_format == 1 || delta_format == 2 || delta_format == 3 {
2654 Ok(parse_device(bytes, subtable_offset, device_offset)?)
2655 }
2656 else if delta_format == 0x8000 {
2657 Ok(parse_variation_index(bytes, subtable_offset, device_offset)?)
2658 }
2659 else {
2660 Err(Error::new(ErrorKind::InvalidData, "DeltaFormat value invalid: {}".to_string()))
2661 }
2662}
2663
2664fn parse_device(bytes: &[u8], subtable_offset: usize, device_offset: u16) -> Result<DeviceOrVariationIndex, Error> {
2665 let offset = subtable_offset + device_offset as usize;
2666 let start_size = get_u16(bytes, offset)?;
2667 let end_size = get_u16(bytes, offset + 2)?;
2668 let delta_format = get_u16(bytes, offset + 4)?;
2669 let count = end_size - start_size + 1;
2670 let length = match delta_format {
2671 1 => (count * 2).div_ceil(16),
2672 2 => (count * 4).div_ceil(16),
2673 3 => (count * 8).div_ceil(16),
2674 _ => return Err(Error::new(ErrorKind::InvalidData, format!("DeltaFormat value invalid: {}", delta_format)))
2675 };
2676 let delta_values: Vec<u16> = bytes.get(offset..offset + length as usize * 2)
2677 .ok_or(ErrorKind::UnexpectedEof)?
2678 .chunks_exact(2)
2679 .map(|ch| {
2680 u16::from_be_bytes(ch.try_into().unwrap())
2681 }).collect();
2682
2683 Ok(DeviceOrVariationIndex::Device(
2684 Device::new(
2685 start_size,
2686 end_size,
2687 delta_format,
2688 delta_values
2689 )
2690 ))
2691}
2692
2693fn parse_variation_index(bytes: &[u8], subtable_offset: usize, device_offset: u16) -> Result<DeviceOrVariationIndex, Error> {
2694 let offset = subtable_offset + device_offset as usize;
2695 let delta_set_outer_index = get_u16(bytes, offset)?;
2696 let delta_set_inner_index = get_u16(bytes, offset + 2)?;
2697 let delta_format = get_u16(bytes, offset + 4)?;
2698
2699 Ok(DeviceOrVariationIndex::VariationIndex(
2700 VariationIndex::new(
2701 delta_set_outer_index,
2702 delta_set_inner_index,
2703 delta_format
2704 )
2705 ))
2706}
2707
2708fn parse_class_def(bytes: &[u8], subtable_offset: usize, class_def_offset: u16) -> Result<ClassDef, Error> {
2709 let mut offset = subtable_offset + class_def_offset as usize;
2710 let format = get_u16(bytes, offset)?;
2711 offset += 2;
2712 match format {
2713 1 => {
2714 let start_glyph_id = get_u16(bytes, offset)?;
2715 let glyph_count = get_u16(bytes, offset + 2)?;
2716 offset += 4;
2717 let class_value_array: Vec<u16> = bytes.get(offset..offset + glyph_count as usize * 2)
2718 .ok_or(ErrorKind::UnexpectedEof)?
2719 .chunks_exact(2)
2720 .map(|ch| {
2721 u16::from_be_bytes(ch.try_into().unwrap())
2722 }).collect();
2723
2724 Ok(ClassDef::Format1 {
2725 start_glyph_id,
2726 glyph_count,
2727 class_value_array
2728 })
2729 }
2730 2 => {
2731 let class_range_count = get_u16(bytes, offset)?;
2732 offset += 2;
2733 let class_range_records: Vec<ClassRangeRecord> = bytes.get(offset..offset + class_range_count as usize * 6)
2734 .ok_or(ErrorKind::UnexpectedEof)?
2735 .chunks_exact(6)
2736 .map(|ch| {
2737 let start_glyph_id = u16::from_be_bytes(ch[0..2].try_into().unwrap());
2738 let end_glyph_id = u16::from_be_bytes(ch[2..4].try_into().unwrap());
2739 let class = u16::from_be_bytes(ch[4..6].try_into().unwrap());
2740
2741 ClassRangeRecord::new(
2742 start_glyph_id,
2743 end_glyph_id,
2744 class
2745 )
2746 }).collect();
2747
2748 Ok(ClassDef::Format2 {
2749 class_range_count,
2750 class_range_records
2751 })
2752 }
2753 _ => return Err(Error::new(ErrorKind::InvalidData, format!("ClassDef format invalid: {}", format)))
2754 }
2755}
2756
2757fn parse_class1_record(
2758 bytes: &[u8],
2759 subtable_offset: usize,
2760 value_format1: u16,
2761 value_format2: u16,
2762 class2_count: u16,
2763 offset: &mut usize
2764) -> Result<Class1Record, Error> {
2765 let class2_records: Vec<Class2Record> = (0..class2_count).map(|_| {
2766 let value_record1 = parse_value_record(bytes, value_format1, offset, subtable_offset)?;
2767 let value_record2 = parse_value_record(bytes, value_format2, offset, subtable_offset)?;
2768
2769 Ok(Class2Record::new(value_record1, value_record2))
2770 }).collect::<Result<Vec<_>, Error>>()?;
2771
2772 Ok(Class1Record::new(class2_records))
2773}
2774
2775fn parse_entry_exit_record(bytes: &[u8], subtable_offset: usize, offset: &mut usize) -> Result<EntryExitRecord, Error> {
2776 let test_offset = get_u16(bytes, *offset)?;
2777 let entry_anchor_offset = if test_offset != 0 {
2778 Some(test_offset)
2779 }
2780 else { None };
2781 let entry_anchor = if entry_anchor_offset != None {
2782 Some(parse_anchor(bytes, subtable_offset, entry_anchor_offset.unwrap())?)
2783 }
2784 else { None };
2785 let test_offset = get_u16(bytes, *offset + 2)?;
2786 let exit_anchor_offset = if test_offset != 0 {
2787 Some(test_offset)
2788 }
2789 else { None };
2790 let exit_anchor = if exit_anchor_offset != None {
2791 Some(parse_anchor(bytes, subtable_offset, exit_anchor_offset.unwrap())?)
2792 }
2793 else { None };
2794 *offset += 4;
2795
2796 Ok(EntryExitRecord::new(
2797 entry_anchor_offset,
2798 entry_anchor,
2799 exit_anchor_offset,
2800 exit_anchor
2801 ))
2802}
2803
2804fn parse_anchor(bytes: &[u8], subtable_offset: usize, anchor_offset: u16) -> Result<Anchor, Error> {
2805 let mut offset = subtable_offset + anchor_offset as usize;
2806 let format = get_u16(bytes, offset)?;
2807 offset += 2;
2808 match format {
2809 1 => {
2810 let x_coordinate = get_i16(bytes, offset)?;
2811 let y_coordinate = get_i16(bytes, offset + 2)?;
2812
2813 Ok(Anchor::Format1 {
2814 x_coordinate,
2815 y_coordinate
2816 })
2817 }
2818 2 => {
2819 let x_coordinate = get_i16(bytes, offset)?;
2820 let y_coordinate = get_i16(bytes, offset + 2)?;
2821 let anchor_point = get_u16(bytes, offset + 4)?;
2822
2823 Ok(Anchor::Format2 {
2824 x_coordinate,
2825 y_coordinate,
2826 anchor_point
2827 })
2828 }
2829 3 => {
2830 let x_coordinate = get_i16(bytes, offset)?;
2831 let y_coordinate = get_i16(bytes, offset + 2)?;
2832 let x_device_offset = get_u16(bytes, offset + 4)?;
2833 let x_device = parse_device_or_variation_index(bytes, subtable_offset, x_device_offset)?;
2834 let y_device_offset = get_u16(bytes, offset + 6)?;
2835 let y_device = parse_device_or_variation_index(bytes, subtable_offset, y_device_offset)?;
2836
2837 Ok(Anchor::Format3 {
2838 x_coordinate,
2839 y_coordinate,
2840 x_device_offset,
2841 x_device,
2842 y_device_offset,
2843 y_device
2844 })
2845 }
2846 _ => Err(Error::new(ErrorKind::InvalidData, format!("Anchor invalid format: {}", format)))
2847 }
2848}
2849
2850fn parse_mark_array(bytes: &[u8], subtable_offset: usize, mark_array_offset: u16) -> Result<MarkArray, Error> {
2851 let mut offset = subtable_offset + mark_array_offset as usize;
2852 let mark_count = get_u16(bytes, offset)?;
2853 offset += 2;
2854 let mark_records: Vec<MarkRecord> = (0..mark_count).map(|_| {
2855 let mark_class = get_u16(bytes, offset)?;
2856 let mark_anchor_offset = get_u16(bytes, offset + 2)?;
2857 offset += 4;
2858 let mark_anchor = parse_anchor(bytes, subtable_offset, mark_anchor_offset)?;
2859
2860 Ok(MarkRecord::new(
2861 mark_class,
2862 mark_anchor_offset,
2863 mark_anchor
2864 ))
2865 }).collect::<Result<Vec<_>, Error>>()?;
2866
2867 Ok(MarkArray::new(
2868 mark_count,
2869 mark_records
2870 ))
2871}
2872
2873fn parse_base_array(bytes: &[u8], subtable_offset: usize, base_array_offset: u16) -> Result<BaseArray, Error> {
2874 let mut offset = subtable_offset + base_array_offset as usize;
2875 let base_count = get_u16(bytes, offset)?;
2876 offset += 2;
2877 let base_records: Vec<BaseRecord> = (0..base_count).map(|_| {
2878 let base_anchor_offsets: Vec<u16> = bytes.get(offset..offset + base_count as usize * 2)
2879 .ok_or(ErrorKind::UnexpectedEof)?
2880 .chunks_exact(2)
2881 .map(|ch| {
2882 u16::from_be_bytes(ch.try_into().unwrap())
2883 }).collect();
2884 offset += base_count as usize * 2;
2885 let base_anchors: Vec<Anchor> = base_anchor_offsets.iter()
2886 .map(|offset| {
2887 Ok(parse_anchor(bytes, subtable_offset, *offset)?)
2888 }).collect::<Result<Vec<_>, Error>>()?;
2889
2890 Ok(BaseRecord::new(base_anchor_offsets, base_anchors))
2891 }).collect::<Result<Vec<_>, Error>>()?;
2892
2893 Ok(BaseArray::new(
2894 base_count,
2895 base_records
2896 ))
2897}
2898
2899fn parse_ligature_array(bytes: &[u8], subtable_offset: usize, ligature_array_offset: u16, mark_class_count: u16) -> Result<LigatureArray, Error> {
2900 let mut offset = subtable_offset + ligature_array_offset as usize;
2901 let ligature_count = get_u16(bytes, offset)?;
2902 offset += 2;
2903 let ligature_attach_offsets: Vec<u16> = bytes.get(offset..offset + ligature_count as usize * 2)
2904 .ok_or(ErrorKind::UnexpectedEof)?
2905 .chunks_exact(2)
2906 .map(|ch| {
2907 u16::from_be_bytes(ch.try_into().unwrap())
2908 }).collect();
2909 let ligature_attaches: Vec<LigatureAttach> = ligature_attach_offsets.iter()
2910 .map(|offset| {
2911 Ok(parse_ligature_attach(bytes, subtable_offset, *offset, mark_class_count)?)
2912 }).collect::<Result<Vec<_>, Error>>()?;
2913
2914 Ok(LigatureArray::new(
2915 ligature_count,
2916 ligature_attach_offsets,
2917 ligature_attaches
2918 ))
2919}
2920
2921fn parse_ligature_attach(
2922 bytes: &[u8],
2923 subtable_offset: usize,
2924 ligature_attach_offset: u16,
2925 mark_class_count: u16
2926) -> Result<LigatureAttach, Error> {
2927 let mut offset = subtable_offset + ligature_attach_offset as usize;
2928 let component_count = get_u16(bytes, offset)?;
2929 offset += 2;
2930 let component_records: Vec<ComponentRecord> = (0..component_count).map(|_| {
2931 Ok(parse_component_record(bytes, subtable_offset, offset, mark_class_count)?)
2932 }).collect::<Result<Vec<_>, Error>>()?;
2933
2934 Ok(LigatureAttach::new(
2935 component_count,
2936 component_records
2937 ))
2938}
2939
2940fn parse_component_record(
2941 bytes: &[u8],
2942 subtable_offset: usize,
2943 offset: usize,
2944 mark_class_count: u16
2945) -> Result<ComponentRecord, Error> {
2946 let ligature_anchor_offsets: Vec<u16> = bytes.get(offset..offset + mark_class_count as usize * 2)
2947 .ok_or(ErrorKind::UnexpectedEof)?
2948 .chunks_exact(2)
2949 .map(|ch| {
2950 u16::from_be_bytes(ch.try_into().unwrap())
2951 }).collect();
2952 let ligature_anchors: Vec<Anchor> = ligature_anchor_offsets.iter()
2953 .map(|offset| {
2954 Ok(parse_anchor(bytes, subtable_offset, *offset)?)
2955 }).collect::<Result<Vec<_>, Error>>()?;
2956
2957 Ok(ComponentRecord::new(
2958 ligature_anchor_offsets,
2959 ligature_anchors
2960 ))
2961}
2962
2963fn parse_mark2_array(bytes: &[u8], subtable_offset: usize, mark2_array_offset: u16, mark_class_count: u16) -> Result<Mark2Array, Error> {
2964 let mut offset = subtable_offset + mark2_array_offset as usize;
2965 let mark2_count = get_u16(bytes, offset)?;
2966 offset += 2;
2967 let mark2_records: Vec<Mark2Record> = (0..mark2_count).map(|_| {
2968 Ok(parse_mark2_record(bytes, subtable_offset, &mut offset, mark_class_count)?)
2969 }).collect::<Result<Vec<_>, Error>>()?;
2970
2971 Ok(Mark2Array::new(
2972 mark2_count,
2973 mark2_records
2974 ))
2975}
2976
2977fn parse_mark2_record(bytes: &[u8], subtable_offset: usize, offset: &mut usize, mark_class_count: u16) -> Result<Mark2Record, Error> {
2978 let mark2_anchor_offsets: Vec<u16> = bytes.get(*offset..*offset + mark_class_count as usize * 2)
2979 .ok_or(ErrorKind::UnexpectedEof)?
2980 .chunks_exact(2)
2981 .map(|ch| {
2982 u16::from_be_bytes(ch.try_into().unwrap())
2983 }).collect();
2984 *offset += mark_class_count as usize * 2;
2985 let mark2_anchors: Vec<Anchor> = mark2_anchor_offsets.iter()
2986 .map(|offset| {
2987 Ok(parse_anchor(bytes, subtable_offset, *offset)?)
2988 }).collect::<Result<Vec<_>, Error>>()?;
2989
2990 Ok(Mark2Record::new(
2991 mark2_anchor_offsets,
2992 mark2_anchors
2993 ))
2994}
2995
2996fn parse_gpos_sub_rule_set(bytes: &[u8], subtable_offset: usize, sub_rule_set_offset: u16) -> Result<GposSubRuleSet, Error> {
2997 let mut offset = subtable_offset + sub_rule_set_offset as usize;
2998 let sub_rule_count = get_u16(bytes, offset)?;
2999 offset += 2;
3000 let sub_rule_offsets: Vec<u16> = bytes.get(offset..offset + sub_rule_count as usize * 2)
3001 .ok_or(ErrorKind::UnexpectedEof)?
3002 .chunks_exact(2)
3003 .map(|ch| {
3004 u16::from_be_bytes(ch.try_into().unwrap())
3005 }).collect();
3006 let sub_rules: Vec<GposSubRule> = sub_rule_offsets.iter()
3007 .map(|offset| {
3008 Ok(parse_gpos_sub_rule(bytes, subtable_offset, *offset)?)
3009 }).collect::<Result<Vec<_>, Error>>()?;
3010
3011 Ok(GposSubRuleSet::new(
3012 sub_rule_count,
3013 sub_rule_offsets,
3014 sub_rules
3015 ))
3016}
3017
3018fn parse_gpos_sub_rule(bytes: &[u8], subtable_offset: usize, sub_rule_offset: u16) -> Result<GposSubRule, Error> {
3019 let mut offset = subtable_offset + sub_rule_offset as usize;
3020 let glyph_count = get_u16(bytes, offset)?;
3021 let sub_count = get_u16(bytes, offset + 2)?;
3022 offset += 4;
3023 let input_glyph_ids: Vec<u16> = bytes.get(offset..offset + (glyph_count as usize - 1) * 2)
3024 .ok_or(ErrorKind::UnexpectedEof)?
3025 .chunks_exact(2)
3026 .map(|ch| {
3027 u16::from_be_bytes(ch.try_into().unwrap())
3028 }).collect();
3029 offset += glyph_count as usize * 2;
3030 let pos_lookup_records: Vec<PosLookupRecord> = (0..sub_count).map(|_| {
3031 Ok(parse_pos_lookup_record(bytes, &mut offset)?)
3032 }).collect::<Result<Vec<_>, Error>>()?;
3033
3034 Ok(GposSubRule::new(
3035 glyph_count,
3036 sub_count,
3037 input_glyph_ids,
3038 pos_lookup_records
3039 ))
3040}
3041
3042fn parse_pos_lookup_record(bytes: &[u8], offset: &mut usize) -> Result<PosLookupRecord, Error> {
3043 let glyph_sequence_index = get_u16(bytes, *offset)?;
3044 let lookup_list_index = get_u16(bytes, *offset + 2)?;
3045 *offset += 4;
3046
3047 Ok(PosLookupRecord::new(
3048 glyph_sequence_index,
3049 lookup_list_index
3050 ))
3051}
3052
3053fn parse_gpos_sub_class_set(bytes: &[u8], subtable_offset: usize, sub_class_set_offset: u16) -> Result<GposSubClassSet, Error> {
3054 let mut offset = subtable_offset + sub_class_set_offset as usize;
3055 let sub_class_rule_count = get_u16(bytes, offset)?;
3056 offset += 2;
3057 let sub_class_rule_offsets: Vec<u16> = bytes.get(offset..offset + sub_class_rule_count as usize * 2)
3058 .ok_or(ErrorKind::UnexpectedEof)?
3059 .chunks_exact(2)
3060 .map(|ch| {
3061 u16::from_be_bytes(ch.try_into().unwrap())
3062 }).collect();
3063 let sub_class_rules: Vec<GposSubClassRule> = sub_class_rule_offsets.iter()
3064 .map(|offset| {
3065 Ok(parse_gpos_sub_class_rule(bytes, subtable_offset, *offset)?)
3066 }).collect::<Result<Vec<_>, Error>>()?;
3067
3068 Ok(GposSubClassSet::new(
3069 sub_class_rule_count,
3070 sub_class_rule_offsets,
3071 sub_class_rules
3072 ))
3073}
3074
3075fn parse_gpos_sub_class_rule(bytes: &[u8], subtable_offset: usize, sub_class_rule_offset: u16) -> Result<GposSubClassRule, Error> {
3076 let mut offset = subtable_offset + sub_class_rule_offset as usize;
3077 let glyph_count = get_u16(bytes, offset)?;
3078 let sub_count = get_u16(bytes, offset + 2)?;
3079 offset += 4;
3080 let class_ids = bytes.get(offset..offset + glyph_count as usize * 2)
3081 .ok_or(ErrorKind::UnexpectedEof)?
3082 .chunks_exact(2)
3083 .map(|ch| {
3084 u16::from_be_bytes(ch.try_into().unwrap())
3085 }).collect();
3086 offset += glyph_count as usize * 2;
3087 let pos_lookup_records: Vec<PosLookupRecord> = (0..sub_count).map(|_| {
3088 Ok(parse_pos_lookup_record(bytes, &mut offset)?)
3089 }).collect::<Result<Vec<_>, Error>>()?;
3090
3091 Ok(GposSubClassRule::new(
3092 glyph_count,
3093 sub_count,
3094 class_ids,
3095 pos_lookup_records
3096 ))
3097}
3098
3099fn parse_gpos_chain_sub_rule_set(bytes: &[u8], subtable_offset: usize, chain_sub_rule_set_offset: u16) -> Result<GposChainSubRuleSet, Error> {
3100 let mut offset = subtable_offset + chain_sub_rule_set_offset as usize;
3101 let chain_sub_rule_count = get_u16(bytes, offset)?;
3102 offset += 2;
3103 let chain_sub_rule_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_rule_count as usize * 2)
3104 .ok_or(ErrorKind::UnexpectedEof)?
3105 .chunks_exact(2)
3106 .map(|ch| {
3107 u16::from_be_bytes(ch.try_into().unwrap())
3108 }).collect();
3109 let chain_sub_rules: Vec<GposChainSubRule> = chain_sub_rule_offsets.iter()
3110 .map(|offset| {
3111 Ok(parse_gpos_chain_sub_rule(bytes, subtable_offset, *offset)?)
3112 }).collect::<Result<Vec<_>, Error>>()?;
3113
3114 Ok(GposChainSubRuleSet::new(
3115 chain_sub_rule_count,
3116 chain_sub_rule_offsets,
3117 chain_sub_rules
3118 ))
3119}
3120
3121fn parse_gpos_chain_sub_class_set(bytes: &[u8], subtable_offset: usize, chain_sub_class_set_offset: u16) -> Result<GposChainSubClassSet, Error> {
3122 let mut offset = subtable_offset + chain_sub_class_set_offset as usize;
3123 let chain_sub_class_rule_count = get_u16(bytes, offset)?;
3124 offset += 2;
3125 let chain_sub_class_rule_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_class_rule_count as usize * 2)
3126 .ok_or(ErrorKind::UnexpectedEof)?
3127 .chunks_exact(2)
3128 .map(|ch| {
3129 u16::from_be_bytes(ch.try_into().unwrap())
3130 }).collect();
3131 let chain_sub_class_rules: Vec<GposChainSubClassRule> = chain_sub_class_rule_offsets.iter()
3132 .map(|offset| {
3133 Ok(parse_gpos_chain_sub_class_rule(bytes, subtable_offset, *offset)?)
3134 }).collect::<Result<Vec<_>, Error>>()?;
3135
3136 Ok(GposChainSubClassSet::new(
3137 chain_sub_class_rule_count,
3138 chain_sub_class_rule_offsets,
3139 chain_sub_class_rules
3140 ))
3141}
3142
3143fn parse_gpos_chain_sub_class_rule(bytes: &[u8], subtable_offset: usize, chain_sub_class_rule_offset: u16) -> Result<GposChainSubClassRule, Error> {
3144 let mut offset = subtable_offset + chain_sub_class_rule_offset as usize;
3145 let backtrack_glyph_count = get_u16(bytes, offset)?;
3146 offset += 2;
3147 let backtrack_class_ids = bytes.get(offset..offset + backtrack_glyph_count as usize * 2)
3148 .ok_or(ErrorKind::UnexpectedEof)?
3149 .chunks_exact(2)
3150 .map(|ch| {
3151 u16::from_be_bytes(ch.try_into().unwrap())
3152 }).collect();
3153 offset += backtrack_glyph_count as usize * 2;
3154 let input_glyph_count = get_u16(bytes, offset)?;
3155 offset += 2;
3156 let input_class_ids = bytes.get(offset..offset + input_glyph_count as usize * 2)
3157 .ok_or(ErrorKind::UnexpectedEof)?
3158 .chunks_exact(2)
3159 .map(|ch| {
3160 u16::from_be_bytes(ch.try_into().unwrap())
3161 }).collect();
3162 offset += input_glyph_count as usize * 2;
3163 let lookahead_glyph_count = get_u16(bytes, offset)?;
3164 offset += 2;
3165 let lookahead_class_ids = bytes.get(offset..offset + lookahead_glyph_count as usize * 2)
3166 .ok_or(ErrorKind::UnexpectedEof)?
3167 .chunks_exact(2)
3168 .map(|ch| {
3169 u16::from_be_bytes(ch.try_into().unwrap())
3170 }).collect();
3171 offset += lookahead_glyph_count as usize * 2;
3172 let sub_count = get_u16(bytes, offset)?;
3173 offset += 2;
3174 let pos_lookup_records = (0..sub_count).map(|_| {
3175 Ok(parse_pos_lookup_record(bytes, &mut offset)?)
3176 }).collect::<Result<Vec<_>, Error>>()?;
3177
3178 Ok(GposChainSubClassRule::new(
3179 backtrack_glyph_count,
3180 backtrack_class_ids,
3181 input_glyph_count,
3182 input_class_ids,
3183 lookahead_glyph_count,
3184 lookahead_class_ids,
3185 sub_count,
3186 pos_lookup_records
3187 ))
3188}
3189
3190fn parse_gpos_chain_sub_rule(bytes: &[u8], subtable_offset: usize, chain_sub_rule_offset: u16) -> Result<GposChainSubRule, Error> {
3191 let mut offset = subtable_offset + chain_sub_rule_offset as usize;
3192 let backtrack_glyph_count = get_u16(bytes, offset)?;
3193 offset += 2;
3194 let backtrack_glyph_ids = bytes.get(offset..offset + backtrack_glyph_count as usize * 2)
3195 .ok_or(ErrorKind::UnexpectedEof)?
3196 .chunks_exact(2)
3197 .map(|ch| {
3198 u16::from_be_bytes(ch.try_into().unwrap())
3199 }).collect();
3200 offset += backtrack_glyph_count as usize * 2;
3201 let input_glyph_count = get_u16(bytes, offset)?;
3202 offset += 2;
3203 let input_glyph_ids = bytes.get(offset..offset + input_glyph_count as usize * 2)
3204 .ok_or(ErrorKind::UnexpectedEof)?
3205 .chunks_exact(2)
3206 .map(|ch| {
3207 u16::from_be_bytes(ch.try_into().unwrap())
3208 }).collect();
3209 offset += input_glyph_count as usize * 2;
3210 let lookahead_glyph_count = get_u16(bytes, offset)?;
3211 offset += 2;
3212 let lookahead_glyph_ids = bytes.get(offset..offset + lookahead_glyph_count as usize * 2)
3213 .ok_or(ErrorKind::UnexpectedEof)?
3214 .chunks_exact(2)
3215 .map(|ch| {
3216 u16::from_be_bytes(ch.try_into().unwrap())
3217 }).collect();
3218 offset += lookahead_glyph_count as usize * 2;
3219 let sub_count = get_u16(bytes, offset)?;
3220 offset += 2;
3221 let pos_lookup_records: Vec<PosLookupRecord> = (0..sub_count).map(|_| {
3222 Ok(parse_pos_lookup_record(bytes, &mut offset)?)
3223 }).collect::<Result<Vec<_>, Error>>()?;
3224
3225 Ok(GposChainSubRule::new(
3226 backtrack_glyph_count,
3227 backtrack_glyph_ids,
3228 input_glyph_count,
3229 input_glyph_ids,
3230 lookahead_glyph_count,
3231 lookahead_glyph_ids,
3232 sub_count,
3233 pos_lookup_records
3234 ))
3235}
3236
3237fn parse_sequence(bytes: &[u8], subtable_offset: usize, sequence_offset: u16) -> Result<Sequence, Error> {
3238 let mut offset = subtable_offset + sequence_offset as usize;
3239 let glyph_count = get_u16(bytes, offset)?;
3240 offset += 2;
3241 let substitute_glyph_ids: Vec<u16> = bytes.get(offset..offset + glyph_count as usize * 2)
3242 .ok_or(ErrorKind::UnexpectedEof)?
3243 .chunks_exact(2)
3244 .map(|ch| {
3245 u16::from_be_bytes(ch.try_into().unwrap())
3246 }).collect();
3247
3248 Ok(Sequence::new(
3249 glyph_count,
3250 substitute_glyph_ids
3251 ))
3252}
3253
3254fn parse_alternate_set(bytes: &[u8], subtable_offset: usize, alternate_set_offset: u16) -> Result<AlternateSet, Error> {
3255 let mut offset = subtable_offset + alternate_set_offset as usize;
3256 let glyph_count = get_u16(bytes, offset)?;
3257 offset += 2;
3258 let alternate_glyph_ids = bytes.get(offset..offset + glyph_count as usize * 2)
3259 .ok_or(ErrorKind::UnexpectedEof)?
3260 .chunks_exact(2)
3261 .map(|ch| {
3262 u16::from_be_bytes(ch.try_into().unwrap())
3263 }).collect();
3264
3265 Ok(AlternateSet::new(
3266 glyph_count,
3267 alternate_glyph_ids
3268 ))
3269}
3270
3271fn parse_ligature_set(bytes: &[u8], subtable_offset: usize, ligature_set_offset: u16) -> Result<LigatureSet, Error> {
3272 let mut offset = subtable_offset + ligature_set_offset as usize;
3273 let ligature_count = get_u16(bytes, offset)?;
3274 offset += 2;
3275 let ligature_offsets: Vec<u16> = bytes.get(offset..offset + ligature_count as usize * 2)
3276 .ok_or(ErrorKind::UnexpectedEof)?
3277 .chunks_exact(2)
3278 .map(|ch| {
3279 u16::from_be_bytes(ch.try_into().unwrap())
3280 }).collect();
3281 let ligatures: Vec<Ligature> = ligature_offsets.iter()
3282 .map(|offset| {
3283 Ok(parse_ligature(bytes, subtable_offset, *offset)?)
3284 }).collect::<Result<Vec<_>, Error>>()?;
3285
3286 Ok(LigatureSet::new(
3287 ligature_count,
3288 ligature_offsets,
3289 ligatures
3290 ))
3291}
3292
3293fn parse_ligature(bytes: &[u8], subtable_offset: usize, ligature_offset: u16) -> Result<Ligature, Error> {
3294 let mut offset = subtable_offset + ligature_offset as usize;
3295 let ligature_glyph_id = get_u16(bytes, offset)?;
3296 let component_count = get_u16(bytes, offset + 2)?;
3297 offset += 4;
3298 let component_glyph_ids: Vec<u16> = bytes.get(offset..offset + component_count as usize * 2)
3299 .ok_or(ErrorKind::UnexpectedEof)?
3300 .chunks_exact(2)
3301 .map(|ch| {
3302 u16::from_be_bytes(ch.try_into().unwrap())
3303 }).collect();
3304
3305 Ok(Ligature::new(
3306 ligature_glyph_id,
3307 component_count,
3308 component_glyph_ids
3309 ))
3310}
3311
3312fn parse_gsub_sub_rule_set(bytes: &[u8], subtable_offset: usize, sub_rule_set_offset: u16) -> Result<GsubSubRuleSet, Error> {
3313 let mut offset = subtable_offset + sub_rule_set_offset as usize;
3314 let sub_rule_count = get_u16(bytes, offset)?;
3315 offset += 2;
3316 let sub_rule_offsets: Vec<u16> = bytes.get(offset..offset + sub_rule_count as usize * 2)
3317 .ok_or(ErrorKind::UnexpectedEof)?
3318 .chunks_exact(2)
3319 .map(|ch| {
3320 u16::from_be_bytes(ch.try_into().unwrap())
3321 }).collect();
3322 let sub_rules: Vec<GsubSubRule> = sub_rule_offsets.iter()
3323 .map(|offset| {
3324 Ok(parse_gsub_sub_rule(bytes, subtable_offset, *offset)?)
3325 }).collect::<Result<Vec<_>, Error>>()?;
3326
3327 Ok(GsubSubRuleSet::new(
3328 sub_rule_count,
3329 sub_rule_offsets,
3330 sub_rules
3331 ))
3332}
3333
3334fn parse_gsub_sub_rule(bytes: &[u8], subtable_offset: usize, sub_rule_offset: u16) -> Result<GsubSubRule, Error> {
3335 let mut offset = subtable_offset + sub_rule_offset as usize;
3336 let glyph_count = get_u16(bytes, offset)?;
3337 let sub_count = get_u16(bytes, offset + 2)?;
3338 offset += 4;
3339 let input_glyph_ids: Vec<u16> = bytes.get(offset..offset + (glyph_count as usize - 1) * 2)
3340 .ok_or(ErrorKind::UnexpectedEof)?
3341 .chunks_exact(2)
3342 .map(|ch| {
3343 u16::from_be_bytes(ch.try_into().unwrap())
3344 }).collect();
3345 offset += glyph_count as usize * 2;
3346 let subst_lookup_records: Vec<SubstLookupRecord> = (0..sub_count).map(|_| {
3347 Ok(parse_subst_lookup_record(bytes, &mut offset)?)
3348 }).collect::<Result<Vec<_>, Error>>()?;
3349
3350 Ok(GsubSubRule::new(
3351 glyph_count,
3352 sub_count,
3353 input_glyph_ids,
3354 subst_lookup_records
3355 ))
3356}
3357
3358fn parse_subst_lookup_record(bytes: &[u8], offset: &mut usize) -> Result<SubstLookupRecord, Error> {
3359 let glyph_sequence_index = get_u16(bytes, *offset)?;
3360 let lookup_list_index = get_u16(bytes, *offset + 2)?;
3361 *offset += 4;
3362
3363 Ok(SubstLookupRecord::new(
3364 glyph_sequence_index,
3365 lookup_list_index
3366 ))
3367}
3368
3369fn parse_gsub_sub_class_set(bytes: &[u8], subtable_offset: usize, sub_class_set_offset: u16) -> Result<GsubSubClassSet, Error> {
3370 let mut offset = subtable_offset + sub_class_set_offset as usize;
3371 let sub_class_rule_count = get_u16(bytes, offset)?;
3372 offset += 2;
3373 let sub_class_rule_offsets: Vec<u16> = bytes.get(offset..offset + sub_class_rule_count as usize * 2)
3374 .ok_or(ErrorKind::UnexpectedEof)?
3375 .chunks_exact(2)
3376 .map(|ch| {
3377 u16::from_be_bytes(ch.try_into().unwrap())
3378 }).collect();
3379 let sub_class_rules: Vec<GsubSubClassRule> = sub_class_rule_offsets.iter()
3380 .map(|offset| {
3381 Ok(parse_gsub_sub_class_rule(bytes, subtable_offset, *offset)?)
3382 }).collect::<Result<Vec<_>, Error>>()?;
3383
3384 Ok(GsubSubClassSet::new(
3385 sub_class_rule_count,
3386 sub_class_rule_offsets,
3387 sub_class_rules
3388 ))
3389}
3390
3391fn parse_gsub_sub_class_rule(bytes: &[u8], subtable_offset: usize, sub_class_rule_offset: u16) -> Result<GsubSubClassRule, Error> {
3392 let mut offset = subtable_offset + sub_class_rule_offset as usize;
3393 let glyph_count = get_u16(bytes, offset)?;
3394 let sub_count = get_u16(bytes, offset + 2)?;
3395 offset += 4;
3396 let class_ids = bytes.get(offset..offset + glyph_count as usize * 2)
3397 .ok_or(ErrorKind::UnexpectedEof)?
3398 .chunks_exact(2)
3399 .map(|ch| {
3400 u16::from_be_bytes(ch.try_into().unwrap())
3401 }).collect();
3402 offset += glyph_count as usize * 2;
3403 let subst_lookup_records: Vec<SubstLookupRecord> = (0..sub_count).map(|_| {
3404 Ok(parse_subst_lookup_record(bytes, &mut offset)?)
3405 }).collect::<Result<Vec<_>, Error>>()?;
3406
3407 Ok(GsubSubClassRule::new(
3408 glyph_count,
3409 sub_count,
3410 class_ids,
3411 subst_lookup_records
3412 ))
3413}
3414
3415fn parse_gsub_chain_sub_rule_set(bytes: &[u8], subtable_offset: usize, chain_sub_rule_set_offset: u16) -> Result<GsubChainSubRuleSet, Error> {
3416 let mut offset = subtable_offset + chain_sub_rule_set_offset as usize;
3417 let chain_sub_rule_count = get_u16(bytes, offset)?;
3418 offset += 2;
3419 let chain_sub_rule_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_rule_count as usize * 2)
3420 .ok_or(ErrorKind::UnexpectedEof)?
3421 .chunks_exact(2)
3422 .map(|ch| {
3423 u16::from_be_bytes(ch.try_into().unwrap())
3424 }).collect();
3425 let chain_sub_rules: Vec<GsubChainSubRule> = chain_sub_rule_offsets.iter()
3426 .map(|offset| {
3427 Ok(parse_gsub_chain_sub_rule(bytes, subtable_offset, *offset)?)
3428 }).collect::<Result<Vec<_>, Error>>()?;
3429
3430 Ok(GsubChainSubRuleSet::new(
3431 chain_sub_rule_count,
3432 chain_sub_rule_offsets,
3433 chain_sub_rules
3434 ))
3435}
3436
3437fn parse_gsub_chain_sub_class_set(bytes: &[u8], subtable_offset: usize, chain_sub_class_set_offset: u16) -> Result<GsubChainSubClassSet, Error> {
3438 let mut offset = subtable_offset + chain_sub_class_set_offset as usize;
3439 let chain_sub_class_rule_count = get_u16(bytes, offset)?;
3440 offset += 2;
3441 let chain_sub_class_rule_offsets: Vec<u16> = bytes.get(offset..offset + chain_sub_class_rule_count as usize * 2)
3442 .ok_or(ErrorKind::UnexpectedEof)?
3443 .chunks_exact(2)
3444 .map(|ch| {
3445 u16::from_be_bytes(ch.try_into().unwrap())
3446 }).collect();
3447 let chain_sub_class_rules: Vec<GsubChainSubClassRule> = chain_sub_class_rule_offsets.iter()
3448 .map(|offset| {
3449 Ok(parse_gsub_chain_sub_class_rule(bytes, subtable_offset, *offset)?)
3450 }).collect::<Result<Vec<_>, Error>>()?;
3451
3452 Ok(GsubChainSubClassSet::new(
3453 chain_sub_class_rule_count,
3454 chain_sub_class_rule_offsets,
3455 chain_sub_class_rules
3456 ))
3457}
3458
3459fn parse_gsub_chain_sub_class_rule(bytes: &[u8], subtable_offset: usize, chain_sub_class_rule_offset: u16) -> Result<GsubChainSubClassRule, Error> {
3460 let mut offset = subtable_offset + chain_sub_class_rule_offset as usize;
3461 let backtrack_glyph_count = get_u16(bytes, offset)?;
3462 offset += 2;
3463 let backtrack_class_ids = bytes.get(offset..offset + backtrack_glyph_count as usize * 2)
3464 .ok_or(ErrorKind::UnexpectedEof)?
3465 .chunks_exact(2)
3466 .map(|ch| {
3467 u16::from_be_bytes(ch.try_into().unwrap())
3468 }).collect();
3469 offset += backtrack_glyph_count as usize * 2;
3470 let input_glyph_count = get_u16(bytes, offset)?;
3471 offset += 2;
3472 let input_class_ids = bytes.get(offset..offset + input_glyph_count as usize * 2)
3473 .ok_or(ErrorKind::UnexpectedEof)?
3474 .chunks_exact(2)
3475 .map(|ch| {
3476 u16::from_be_bytes(ch.try_into().unwrap())
3477 }).collect();
3478 offset += input_glyph_count as usize * 2;
3479 let lookahead_glyph_count = get_u16(bytes, offset)?;
3480 offset += 2;
3481 let lookahead_class_ids = bytes.get(offset..offset + lookahead_glyph_count as usize * 2)
3482 .ok_or(ErrorKind::UnexpectedEof)?
3483 .chunks_exact(2)
3484 .map(|ch| {
3485 u16::from_be_bytes(ch.try_into().unwrap())
3486 }).collect();
3487 offset += lookahead_glyph_count as usize * 2;
3488 let sub_count = get_u16(bytes, offset)?;
3489 offset += 2;
3490 let subst_lookup_records = (0..sub_count).map(|_| {
3491 Ok(parse_subst_lookup_record(bytes, &mut offset)?)
3492 }).collect::<Result<Vec<_>, Error>>()?;
3493
3494 Ok(GsubChainSubClassRule::new(
3495 backtrack_glyph_count,
3496 backtrack_class_ids,
3497 input_glyph_count,
3498 input_class_ids,
3499 lookahead_glyph_count,
3500 lookahead_class_ids,
3501 sub_count,
3502 subst_lookup_records
3503 ))
3504}
3505
3506fn parse_gsub_chain_sub_rule(bytes: &[u8], subtable_offset: usize, chain_sub_rule_offset: u16) -> Result<GsubChainSubRule, Error> {
3507 let mut offset = subtable_offset + chain_sub_rule_offset as usize;
3508 let backtrack_glyph_count = get_u16(bytes, offset)?;
3509 offset += 2;
3510 let backtrack_glyph_ids = bytes.get(offset..offset + backtrack_glyph_count as usize * 2)
3511 .ok_or(ErrorKind::UnexpectedEof)?
3512 .chunks_exact(2)
3513 .map(|ch| {
3514 u16::from_be_bytes(ch.try_into().unwrap())
3515 }).collect();
3516 offset += backtrack_glyph_count as usize * 2;
3517 let input_glyph_count = get_u16(bytes, offset)?;
3518 offset += 2;
3519 let input_glyph_ids = bytes.get(offset..offset + input_glyph_count as usize * 2)
3520 .ok_or(ErrorKind::UnexpectedEof)?
3521 .chunks_exact(2)
3522 .map(|ch| {
3523 u16::from_be_bytes(ch.try_into().unwrap())
3524 }).collect();
3525 offset += input_glyph_count as usize * 2;
3526 let lookahead_glyph_count = get_u16(bytes, offset)?;
3527 offset += 2;
3528 let lookahead_glyph_ids = bytes.get(offset..offset + lookahead_glyph_count as usize * 2)
3529 .ok_or(ErrorKind::UnexpectedEof)?
3530 .chunks_exact(2)
3531 .map(|ch| {
3532 u16::from_be_bytes(ch.try_into().unwrap())
3533 }).collect();
3534 offset += lookahead_glyph_count as usize * 2;
3535 let sub_count = get_u16(bytes, offset)?;
3536 offset += 2;
3537 let subst_lookup_records: Vec<SubstLookupRecord> = (0..sub_count).map(|_| {
3538 Ok(parse_subst_lookup_record(bytes, &mut offset)?)
3539 }).collect::<Result<Vec<_>, Error>>()?;
3540
3541 Ok(GsubChainSubRule::new(
3542 backtrack_glyph_count,
3543 backtrack_glyph_ids,
3544 input_glyph_count,
3545 input_glyph_ids,
3546 lookahead_glyph_count,
3547 lookahead_glyph_ids,
3548 sub_count,
3549 subst_lookup_records
3550 ))
3551}
3552
3553fn get_u16(bytes: &[u8], start: usize) -> Result<u16, Error> {
3554 Ok(
3555 u16::from_be_bytes(
3556 bytes.get(start..start + 2)
3557 .ok_or(ErrorKind::UnexpectedEof)?
3558 .try_into()
3559 .unwrap()
3560 )
3561 )
3562}
3563
3564fn get_u32(bytes: &[u8], start: usize) -> Result<u32, Error> {
3565 Ok(
3566 u32::from_be_bytes(
3567 bytes.get(start..start + 4)
3568 .ok_or(ErrorKind::UnexpectedEof)?
3569 .try_into()
3570 .unwrap()
3571 )
3572 )
3573}
3574
3575fn get_i16(bytes: &[u8], start: usize) -> Result<i16, Error> {
3576 Ok(
3577 i16::from_be_bytes(
3578 bytes.get(start..start + 2)
3579 .ok_or(ErrorKind::UnexpectedEof)?
3580 .try_into()
3581 .unwrap()
3582 )
3583 )
3584}
3585
3586fn get_i32(bytes: &[u8], start: usize) -> Result<i32, Error> {
3587 Ok(
3588 i32::from_be_bytes(
3589 bytes.get(start..start + 4)
3590 .ok_or(ErrorKind::UnexpectedEof)?
3591 .try_into()
3592 .unwrap()
3593 )
3594 )
3595}
3596
3597fn get_i64(bytes: &[u8], start: usize) -> Result<i64, Error> {
3598 Ok(
3599 i64::from_be_bytes(
3600 bytes.get(start..start + 8)
3601 .ok_or(ErrorKind::UnexpectedEof)?
3602 .try_into()
3603 .unwrap()
3604 )
3605 )
3606}
3607
3608fn decode_name_bytes(bytes: &[u8], platform_id: u16, encoding_id: u16) -> Result<String, Error> {
3610 match platform_id {
3611 0 => {
3612 let name_bytes: Vec<u16> = bytes.chunks_exact(2)
3613 .map(|ch| u16::from_be_bytes(ch[0..2].try_into().unwrap()))
3614 .collect();
3615
3616 Ok(String::from_utf16(&name_bytes).map_err(|e| Error::new(ErrorKind::InvalidData, e))?)
3617 }
3618 1 => {
3619 match encoding_id {
3620 0 => {
3621 Ok(
3622 bytes.iter()
3623 .map(|idx| MAC_ROMAN_LOOKUP[*idx as usize])
3624 .collect::<String>()
3625 )
3626 }
3627 _ => Err(Error::new(ErrorKind::Unsupported, "Only encoding 0 (Mac Roman) currently supported for platform 1"))
3628 }
3629 }
3630 3 => {
3631 match encoding_id {
3632 0 | 1 | 10 => {
3633 let name_bytes: Vec<u16> = bytes.chunks_exact(2)
3634 .map(|ch| u16::from_be_bytes(ch[0..2].try_into().unwrap()))
3635 .collect();
3636
3637 Ok(String::from_utf16(&name_bytes).map_err(|e| Error::new(ErrorKind::InvalidData, e))?)
3638 }
3639 _ => Err(Error::new(ErrorKind::Unsupported, "Platform 3, Encodings 2 - 9 decoding currently unsupported"))
3640 }
3641 }
3642 _ => Err(Error::new(ErrorKind::Unsupported, "Platform 2 and 4 decoding currently unsupported"))
3643 }
3644}