1 | use hashbrown::HashSet; |
2 | use ttf_parser::Face; |
3 | |
4 | pub fn load_gsub(face: &Face, indices_to_load: &mut HashSet<u16>) { |
5 | if let Some(subtable) = face.tables().gsub { |
6 | use ttf_parser::gsub::SubstitutionSubtable; |
7 | for lookup in subtable.lookups { |
8 | for table in lookup.subtables.into_iter::<SubstitutionSubtable>() { |
9 | match table { |
10 | SubstitutionSubtable::Single(ss) => { |
11 | use ttf_parser::gsub::SingleSubstitution; |
12 | use ttf_parser::opentype_layout::Coverage; |
13 | match ss { |
14 | SingleSubstitution::Format1 { |
15 | coverage, |
16 | delta, |
17 | } => match coverage { |
18 | Coverage::Format1 { |
19 | glyphs, |
20 | } => { |
21 | for glyph in glyphs { |
22 | indices_to_load.insert((glyph.0 as i32 + delta as i32) as u16); |
23 | } |
24 | } |
25 | Coverage::Format2 { |
26 | records, |
27 | } => { |
28 | for record in records { |
29 | for id in record.start.0..record.end.0 { |
30 | indices_to_load.insert((id as i32 + delta as i32) as u16); |
31 | } |
32 | } |
33 | } |
34 | }, |
35 | SingleSubstitution::Format2 { |
36 | coverage: _, |
37 | substitutes, |
38 | } => { |
39 | for g in substitutes { |
40 | indices_to_load.insert(g.0); |
41 | } |
42 | } |
43 | } |
44 | } |
45 | SubstitutionSubtable::Multiple(ms) => { |
46 | for seq in ms.sequences { |
47 | for g in seq.substitutes { |
48 | indices_to_load.insert(g.0); |
49 | } |
50 | } |
51 | } |
52 | SubstitutionSubtable::Alternate(als) => { |
53 | for alt in als.alternate_sets { |
54 | for g in alt.alternates { |
55 | indices_to_load.insert(g.0); |
56 | } |
57 | } |
58 | } |
59 | SubstitutionSubtable::Ligature(ls) => ls.ligature_sets.into_iter().for_each(|ls| { |
60 | for l in ls { |
61 | indices_to_load.insert(l.glyph.0); |
62 | } |
63 | }), |
64 | SubstitutionSubtable::ReverseChainSingle(rcsl) => { |
65 | for g in rcsl.substitutes { |
66 | indices_to_load.insert(g.0); |
67 | } |
68 | } |
69 | _ => {} |
70 | } |
71 | } |
72 | } |
73 | } |
74 | } |
75 | |