cn_font_split/pre_subset/
features.rs1use cmap::analyze_cmap;
2use gpos::analyze_gpos;
3use gsub::analyze_gsub;
4use indexmap::IndexSet;
5use std::collections::HashMap;
6
7use super::PreSubsetContext;
8pub mod cmap;
9pub mod gpos;
10pub mod gsub;
11pub fn features_plugin(
12 subsets: &mut Vec<IndexSet<u32>>,
13 _remaining_chars_set: &mut IndexSet<u32>,
14 ctx: &mut PreSubsetContext,
15) {
16 let cmap = analyze_cmap(ctx.font, ctx.font_file);
17 let sub_map = analyze_gsub(ctx.font, ctx.font_file);
18 let sub_map = turn_indics_to_unicode_set(sub_map, &cmap);
19 move_feature_set_to_front(&sub_map, subsets);
20
21 let pos_map = analyze_gpos(ctx.font, ctx.font_file);
22 let pos_map = turn_indics_to_unicode_set(pos_map, &cmap);
23 move_feature_set_to_front(&pos_map, subsets);
24 ()
25}
26
27fn move_feature_set_to_front(
28 feature_map: &Vec<IndexSet<u32>>,
29 subsets: &mut Vec<IndexSet<u32>>,
30) {
31 for feature_set in feature_map {
32 let mut have_coverage = false;
33 for subset in subsets.into_iter() {
34 if have_coverage {
35 subset.retain(|x| !feature_set.contains(x));
36 } else if has_intersection(feature_set, subset) {
37 for x in feature_set.iter() {
38 subset.insert(x.clone());
39 }
40 have_coverage = true;
41 }
42 }
43 }
44}
45
46fn has_intersection(a: &IndexSet<u32>, b: &IndexSet<u32>) -> bool {
48 for i in a {
49 if b.contains(i) {
50 return true;
51 }
52 }
53 return false;
54}
55
56#[test]
57fn test_move_feature_set_to_front() {
58 let mut feature_map = vec![IndexSet::from([1, 2]), IndexSet::from([3, 4])];
59 let mut subsets = vec![
60 IndexSet::from([2, 3]),
61 IndexSet::from([4, 5]),
62 IndexSet::from([1]),
63 ];
64
65 move_feature_set_to_front(&mut feature_map, &mut subsets);
66
67 assert!(subsets[0].contains(&1));
69 assert!(subsets[0].contains(&2));
70 assert!(subsets[0].contains(&3));
71 assert!(subsets[0].contains(&4));
72 assert!(subsets[1].contains(&5));
73 assert!(subsets[2].is_empty());
74}
75
76pub fn turn_indics_to_unicode_set(
77 all_maybe_relative_glyph: Vec<Vec<u16>>,
78 cmap: &HashMap<u16, u32>,
79) -> Vec<IndexSet<u32>> {
80 all_maybe_relative_glyph
81 .iter()
82 .map(|r| {
83 IndexSet::from_iter(
84 r.iter().map(|gid| cmap.get(gid).unwrap_or(&0_u32).clone()),
85 )
86 })
87 .collect::<Vec<IndexSet<u32>>>()
88}