Skip to main content

blockworx/
font.rs

1//! Installing the bundled UI fonts with egui.
2//!
3//! The faces themselves are [`blockworx_paint::FontChoice`]'s; this is the one
4//! place their bytes are handed to a toolkit.
5
6use blockworx_paint::{CANVAS_FAMILY, FontChoice};
7
8/// Build the egui [`FontDefinitions`](egui::FontDefinitions) for the `active`
9/// font choice. Every selectable font is registered under its own family name so
10/// the preferences menu can preview each entry in its own typeface.
11///
12/// The UI chrome (nav tree, toolbar, menus, overlays) always renders in Basic
13/// (Roboto): it is pinned first in the `Proportional` family regardless of the
14/// choice. The *canvas* renders in the selected font via the dedicated
15/// [`CANVAS_FAMILY`], which is repointed here — so switching fonts restyles only
16/// the drawn diagram, never the chrome.
17pub fn build_fonts(active: FontChoice) -> egui::FontDefinitions {
18    let mut fonts = egui::FontDefinitions::default();
19    for choice in FontChoice::ALL {
20        let name = choice.family_name().to_owned();
21        fonts.font_data.insert(
22            name.clone(),
23            egui::FontData::from_static(choice.bytes()).into(),
24        );
25        fonts
26            .families
27            .insert(egui::FontFamily::Name(name.clone().into()), vec![name]);
28    }
29    fonts
30        .families
31        .entry(egui::FontFamily::Proportional)
32        .or_default()
33        .insert(0, FontChoice::Basic.family_name().to_owned());
34    fonts.families.insert(
35        egui::FontFamily::Name(CANVAS_FAMILY.into()),
36        vec![active.family_name().to_owned()],
37    );
38    fonts
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44    use egui::FontFamily;
45
46    #[test]
47    fn chrome_stays_basic_and_canvas_follows_the_choice() {
48        for choice in FontChoice::ALL {
49            let fonts = build_fonts(choice);
50            assert_eq!(
51                fonts.families[&FontFamily::Proportional][0].as_str(),
52                FontChoice::Basic.family_name(),
53                "UI chrome must stay Basic regardless of the choice ({choice:?})",
54            );
55            assert_eq!(
56                fonts.families[&FontFamily::Name(CANVAS_FAMILY.into())],
57                vec![choice.family_name().to_owned()],
58                "the canvas family follows the selected font ({choice:?})",
59            );
60        }
61    }
62}