Skip to main content

diffenator3_lib/render/
encodedglyphs.rs

1/// Find and represent differences between encoded glyphs in the fonts.
2use std::fmt::Display;
3
4use super::{DEFAULT_GLYPHS_FONT_SIZE, DEFAULT_GLYPHS_THRESHOLD};
5pub use crate::structs::{CmapDiff, EncodedGlyph};
6use crate::{
7    dfont::DFont,
8    render::{diff_many_words, GlyphDiff},
9};
10pub use harfrust::Direction;
11use static_lang_word_lists::WordList;
12
13impl From<char> for EncodedGlyph {
14    fn from(c: char) -> Self {
15        EncodedGlyph {
16            string: c.to_string(),
17            name: unicode_names2::name(c).map(|s| s.to_string()),
18        }
19    }
20}
21
22impl From<u32> for EncodedGlyph {
23    fn from(c: u32) -> Self {
24        char::from_u32(c).unwrap().into()
25    }
26}
27
28impl Display for EncodedGlyph {
29    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30        write!(
31            f,
32            "{} (U+{:04X})",
33            self.string,
34            self.string.chars().next().unwrap() as u32
35        )?;
36        if let Some(name) = &self.name {
37            write!(f, " {}", name)
38        } else {
39            Ok(())
40        }
41    }
42}
43
44impl CmapDiff {
45    pub fn is_some(&self) -> bool {
46        !self.missing.is_empty() || !self.new.is_empty()
47    }
48
49    /// Compare the encoded codepoints from two fonts and return the differences
50    pub fn new(font_a: &DFont, font_b: &DFont) -> Self {
51        let cmap_a = &font_a.codepoints;
52        let cmap_b = &font_b.codepoints;
53        Self {
54            missing: cmap_a.difference(cmap_b).map(|&x| x.into()).collect(),
55            new: cmap_b.difference(cmap_a).map(|&x| x.into()).collect(),
56        }
57    }
58}
59
60/// Render the encoded glyphs common to both fonts, and return any differences
61pub fn modified_encoded_glyphs(font_a: &DFont, font_b: &DFont) -> Vec<GlyphDiff> {
62    let cmap_a = &font_a.codepoints;
63    let cmap_b = &font_b.codepoints;
64    let same_glyphs = cmap_a.intersection(cmap_b);
65    let word_list: Vec<String> = same_glyphs
66        .filter_map(|i| char::from_u32(*i))
67        .map(|c| c.to_string())
68        .collect();
69    let wl = WordList::define("Encoded glyphs", word_list);
70    let mut result: Vec<GlyphDiff> = diff_many_words(
71        font_a,
72        font_b,
73        DEFAULT_GLYPHS_FONT_SIZE,
74        &wl,
75        None,
76        DEFAULT_GLYPHS_THRESHOLD,
77    )
78    .into_iter()
79    .map(|x| x.into())
80    .collect();
81    result.sort_by_key(|x| -(x.differing_pixels as i32));
82    result
83}