cn_font_split/pre_subset/
features.rs

1use 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
46/// 判断两个集合是否有交集
47fn 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    // println!("{:?}", subsets);
68    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}