1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use egui::{FontDefinitions, Style};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;

const DEFAULT_FONTS: [&str; 4] = [
    "ProggyClean",
    "Ubuntu-Light",
    "NotoEmoji-Regular",
    "emoji-icon-font",
];

/// The EguiTheme is the serializable contents of the relevant font information. this is only useful for writing and reading the Style and FontDefinitions from disk.
/// This is essentially a container for `Style` and `FontDefinitions`
/// In addition, it will also serialize the `egui::FontData` into `base64` format to encode the font data directly into the theme
#[derive(Serialize, Deserialize)]
pub struct EguiTheme {
    style: Style,
    font_definitions: FontDefinitions,
    // Need to hold a reference to the font data as FontDefinitions does not serialize it automatically.
    font_data: BTreeMap<String, String>,
}

impl EguiTheme {
    /// Create a new style from
    /// `style` the egui style information
    /// `font_definitions` the current font definitions.
    pub fn new(style: Style, font_definitions: FontDefinitions) -> Self {
        println!("new egui theme!");
        // TODO: Determine if there is a better way to exclude the defaults.
        let mut font_data = BTreeMap::new();
        for (name, data) in font_definitions.font_data.iter() {
            if !DEFAULT_FONTS.contains(&name.as_str()) {
                font_data.insert(name.clone(), base64::encode(data));
            }
        }
        Self {
            style,
            font_definitions,
            font_data,
        }
    }

    /// Extracts the file information  and consumes the theme to retreive the `Style` and `FontDefinitions`
    /// This is the only supported way to move the style and font data into Egui.
    /// This should only be used when loading the theme from disk for the first time.
    pub fn extract(mut self) -> (Style, FontDefinitions) {
        // This is a workaround since the font_data is not automatically serialized.
        // If the keys are not found in the font data, we need to add them before allowing the data to be extracted
        println!("extract!");
        for (key, value) in self.font_data.iter() {
            println!("{}", key);
            if !self.font_definitions.font_data.contains_key(key) {
                println!("data len: {}", value.len());
                let data = base64::decode(value).expect("this should work");
                self.font_definitions
                    .font_data
                    .insert(key.to_owned(), std::borrow::Cow::Owned(data));
            }
        }
        (self.style, self.font_definitions)
    }
}