From ca961725522cc90d46d8ba44642846d45541eea7 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 31 Oct 2020 18:03:13 +0100 Subject: [PATCH] You can override the default Egui fonts Closes https://github.com/emilk/egui/issues/32 --- CHANGELOG.md | 1 + egui/src/app.rs | 5 +++++ egui/src/lib.rs | 5 ++++- egui/src/paint/fonts.rs | 39 +++++++++++++++++++++------------------ egui/src/paint/mod.rs | 2 +- egui_glium/src/backend.rs | 1 + egui_web/src/backend.rs | 3 ++- 7 files changed, 35 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d04daae2..3135943f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Demo App: Add slider to scale all of Egui * Windows are now constrained to the screen * Panels: you can now create panels using `SidePanel` and `TopPanel`. +* You can override the default Egui fonts * Fix a bug where some regions would slowly grow for non-integral scales (`pixels_per_point`). * You can no longer throw windows * `Context::begin_frame()` no longer returns anything. diff --git a/egui/src/app.rs b/egui/src/app.rs index 65e4fec5..aaf1a40d 100644 --- a/egui/src/app.rs +++ b/egui/src/app.rs @@ -12,6 +12,11 @@ use crate::Context; /// Implement this trait to write apps that can be compiled both natively using the [`egui_glium`](https://crates.io/crates/egui_glium) crate, /// and deployed as a web site using the [`egui_web`](https://crates.io/crates/egui_web) crate. pub trait App { + /// Called once before the first frame. + /// Allows you to do setup code and to call `ctx.set_fonts()`. + /// Optional. + fn setup(&mut self, _ctx: &std::sync::Arc) {} + /// Called each time the UI needs repainting, which may be many times per second. /// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`. fn ui( diff --git a/egui/src/lib.rs b/egui/src/lib.rs index 837d8d27..f31d1a12 100644 --- a/egui/src/lib.rs +++ b/egui/src/lib.rs @@ -92,7 +92,10 @@ pub use { layout::*, math::*, memory::Memory, - paint::{color, PaintCmd, PaintJobs, Rgba, Srgba, Stroke, TextStyle, Texture, TextureId}, + paint::{ + color, FontDefinitions, FontFamily, PaintCmd, PaintJobs, Rgba, Srgba, Stroke, TextStyle, + Texture, TextureId, + }, painter::Painter, style::Style, types::*, diff --git a/egui/src/paint/fonts.rs b/egui/src/paint/fonts.rs index 6971b4a3..4a982629 100644 --- a/egui/src/paint/fonts.rs +++ b/egui/src/paint/fonts.rs @@ -36,6 +36,11 @@ pub struct FontDefinitions { pub pixels_per_point: f32, pub fonts: BTreeMap, + + /// The TTF data for each font family. + /// Egui has built-in-default for these, + /// but you can override them if you like. + pub ttf_data: BTreeMap, } impl Default for FontDefinitions { @@ -51,11 +56,20 @@ impl FontDefinitions { fonts.insert(TextStyle::Body, (FontFamily::VariableWidth, 14.0)); fonts.insert(TextStyle::Button, (FontFamily::VariableWidth, 16.0)); fonts.insert(TextStyle::Heading, (FontFamily::VariableWidth, 24.0)); - fonts.insert(TextStyle::Monospace, (FontFamily::Monospace, 13.0)); + fonts.insert(TextStyle::Monospace, (FontFamily::Monospace, 13.0)); // 13 for `ProggyClean` + + // TODO: figure out a way to make the WASM smaller despite including a font. Zip it? + let monospace_typeface_data = include_bytes!("../../fonts/ProggyClean.ttf"); // Use 13 for this. NOTHING ELSE. + let variable_typeface_data = include_bytes!("../../fonts/Comfortaa-Regular.ttf"); // Funny, hard to read + + let mut ttf_data: BTreeMap = BTreeMap::new(); + ttf_data.insert(FontFamily::Monospace, monospace_typeface_data); + ttf_data.insert(FontFamily::VariableWidth, variable_typeface_data); Self { pixels_per_point, fonts, + ttf_data, } } } @@ -98,32 +112,21 @@ impl Fonts { let atlas = Arc::new(Mutex::new(atlas)); - // TODO: figure out a way to make the WASM smaller despite including a font. Zip it? - let monospace_typeface_data = include_bytes!("../../fonts/ProggyClean.ttf"); // Use 13 for this. NOTHING ELSE. - - // let monospace_typeface_data = include_bytes!("../../fonts/Roboto-Regular.ttf"); - - let variable_typeface_data = include_bytes!("../../fonts/Comfortaa-Regular.ttf"); // Funny, hard to read - - // let variable_typeface_data = include_bytes!("../../fonts/DejaVuSans.ttf"); // Basic, boring, takes up more space - self.definitions = definitions.clone(); let FontDefinitions { pixels_per_point, fonts, + ttf_data, } = definitions; self.fonts = fonts .into_iter() .map(|(text_style, (family, size))| { - let typeface_data: &[u8] = match family { - FontFamily::Monospace => monospace_typeface_data, - FontFamily::VariableWidth => variable_typeface_data, - }; + let typeface_data = ttf_data + .get(&family) + .unwrap_or_else(|| panic!("Missing TTF data for {:?}", family)); + let font = Font::new(atlas.clone(), typeface_data, size, pixels_per_point); - ( - text_style, - Font::new(atlas.clone(), typeface_data, size, pixels_per_point), - ) + (text_style, font) }) .collect(); diff --git a/egui/src/paint/mod.rs b/egui/src/paint/mod.rs index 32eaab09..39465431 100644 --- a/egui/src/paint/mod.rs +++ b/egui/src/paint/mod.rs @@ -13,7 +13,7 @@ mod texture_atlas; pub use { color::{Rgba, Srgba}, command::{PaintCmd, Stroke}, - fonts::{FontDefinitions, Fonts, TextStyle}, + fonts::{FontDefinitions, FontFamily, Fonts, TextStyle}, stats::PaintStats, tessellator::{PaintJob, PaintJobs, PaintOptions, TextureId, Triangles, Vertex, WHITE_UV}, texture_atlas::Texture, diff --git a/egui_glium/src/backend.rs b/egui_glium/src/backend.rs index 511c5d60..e077bf4a 100644 --- a/egui_glium/src/backend.rs +++ b/egui_glium/src/backend.rs @@ -57,6 +57,7 @@ pub fn run( let mut ctx = egui::Context::new(); *ctx.memory() = egui::app::get_value(storage.as_ref(), EGUI_MEMORY_KEY).unwrap_or_default(); + app.setup(&ctx); let mut raw_input = egui::RawInput { pixels_per_point: Some(native_pixels_per_point(&display)), diff --git a/egui_web/src/backend.rs b/egui_web/src/backend.rs index f3e16f4d..1e3bd7ae 100644 --- a/egui_web/src/backend.rs +++ b/egui_web/src/backend.rs @@ -132,7 +132,8 @@ pub struct AppRunner { } impl AppRunner { - pub fn new(web_backend: WebBackend, app: Box) -> Result { + pub fn new(web_backend: WebBackend, mut app: Box) -> Result { + app.setup(&web_backend.ctx); Ok(Self { pixels_per_point: native_pixels_per_point(), web_backend,