From 5ca548f3563ad855be8f2c229f1f17b40fcd9e25 Mon Sep 17 00:00:00 2001 From: Fredrick Brennan Date: Mon, 13 Mar 2023 15:55:23 -0400 Subject: [PATCH] Load system fonts --- build.rs | 8 +++++ src/constants.rs | 11 ++++++ src/system_fonts.rs | 46 ++++++++++++++++++------ src/user_interface/egui_manager/fonts.rs | 24 +++++++++++++ src/user_interface/egui_manager/mod.rs | 6 ++++ src/user_interface/gui/mod.rs | 2 ++ src/user_interface/gui/tool_bar.rs | 8 ++--- 7 files changed, 91 insertions(+), 14 deletions(-) create mode 100644 src/user_interface/egui_manager/fonts.rs diff --git a/build.rs b/build.rs index d294cbdd..31516f56 100644 --- a/build.rs +++ b/build.rs @@ -40,6 +40,14 @@ fn main() { warning!("It is neither recommended nor supported to compile MFEKglif on Windows w/dynamic SDL2."); } } + cfg_if! { + if #[cfg(all(target_family = "unix", not(any(target_os = "macos", target_os = "android", target_os = "ios"))))] { + rustc_cfg!("is_free_software_os"); + rustc_env!("MFEK_FREE_OS_DETECTED", "{}", version); + } else { + warning!("MFEKglif works best on free software operating systems such as GNU/Linux and FreeBSD. Close Windows, open doors: "); + } + } } #[cfg(all(target_os = "macos", feature = "sdl2-dynamic"))] diff --git a/src/constants.rs b/src/constants.rs index 8201c99a..abdb9dd0 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -14,10 +14,21 @@ lazy_static! { pub static ref CONSOLE_FONTS: Vec = vec![ FKFamilyName::Title("Inconsolata".to_string()), FKFamilyName::Title("Consolas".to_string()), + FKFamilyName::Title("Unifont".to_string()), + FKFamilyName::Title("Courier New".to_string()), FKFamilyName::Monospace ]; } +/// TODO: Deprecate this hack. +/// See https://github.com/emilk/egui/issues/2639. +pub const FONT_SCALE_FACTOR: f32 = { + #[cfg(is_free_software_os)] + { 1.25 } + #[cfg(not(is_free_software_os))] + { 1.0 } +}; + // CONSOLE pub const CONSOLE_TEXT_SIZE: f32 = 14.; pub const CONSOLE_PADDING_X: f32 = CONSOLE_TEXT_SIZE - (CONSOLE_TEXT_SIZE / 3.); diff --git a/src/system_fonts.rs b/src/system_fonts.rs index c0d1440a..ea713873 100644 --- a/src/system_fonts.rs +++ b/src/system_fonts.rs @@ -1,6 +1,6 @@ use lazy_static::lazy_static; -//use crate::constants::CONSOLE_FONTS; +use crate::constants::CONSOLE_FONTS; use font_kit::{ error::SelectionError::NotFound as FKNotFoundError, family_name::FamilyName as FKFamilyName, @@ -11,12 +11,13 @@ use std::fs; use std::path::PathBuf; use std::sync::Arc; -pub struct Font { +#[derive(Clone, Debug)] +pub struct SystemFont { pub data: Vec, pub path: Option, } -fn load_font(family: &[FKFamilyName]) -> Font { +fn load_font(family: &[FKFamilyName]) -> SystemFont { log::debug!("Looking for a UI font to satisfy request for {:?}", family); let mut font = None; let source = SystemSource::new(); @@ -27,11 +28,20 @@ fn load_font(family: &[FKFamilyName]) -> Font { log::debug!("Skipped {:?}", fkfamname); } font = match best_match { - Ok(FKHandle::Path { path, .. }) => Some(Font { - path: Some(path.clone()), - data: fs::read(path).expect("Failed to open font path system specified"), - }), - Ok(FKHandle::Memory { bytes, .. }) => Some(Font { + Ok(FKHandle::Path { path, .. }) => { + let font_is_scalable = ["otf", "ttf"] + .into_iter() + .any(|e: &str| path.extension().map(|ee| ee == e).unwrap_or(false)); + // This is possible on GNU/Linux which has BDF fonts. + if !font_is_scalable { + continue; + } + Some(SystemFont { + path: Some(path.clone()), + data: fs::read(path).expect("Failed to open font path system specified"), + }) + } + Ok(FKHandle::Memory { bytes, .. }) => Some(SystemFont { path: None, data: Arc::try_unwrap(bytes).expect("Failed to load in-memory font"), }), @@ -70,7 +80,7 @@ lazy_static! { /// difficulty in deciding on a default font. I believe it works to try "Helvetica" and then /// ".SFUI-Text" (San Francisco UI Text); Apple does _NOT_ resolve `sans-serif` to anything, /// resulting in crash which became issue №220. - pub static ref SYSTEMSANS: Font = load_font(&[ + pub static ref SYSTEMSANS: SystemFont = load_font(&[ // Windows 10 FKFamilyName::Title("Segoe UI".to_string()), // Linux (fontconfig) @@ -79,6 +89,22 @@ lazy_static! { FKFamilyName::Title(".SFUIText".to_string()), // new macOS (≈2016+) FKFamilyName::Title("Helvetica".to_string()), + // Linux (fallback) + FKFamilyName::Title("Noto Sans".to_string()), + FKFamilyName::Title("Roboto".to_string()), + ]); + pub static ref SYSTEMSERIF: SystemFont = load_font(&[ + // Windows 10 + FKFamilyName::Title("Times New Roman".to_string()), + // Linux (fontconfig) + FKFamilyName::Serif, + // macOS + FKFamilyName::Title("Times".to_string()), + FKFamilyName::Title("TimesNewRomanPSMT".to_string()), + // Linux (fallback) + FKFamilyName::Title("FreeSerif".to_string()), + FKFamilyName::Title("Noto Serif".to_string()), + FKFamilyName::Title("Roboto Serif".to_string()), ]); - //pub static ref SYSTEMMONO: Font = load_font(CONSOLE_FONTS.as_slice()); + pub static ref SYSTEMMONO: SystemFont = load_font(CONSOLE_FONTS.as_slice()); } diff --git a/src/user_interface/egui_manager/fonts.rs b/src/user_interface/egui_manager/fonts.rs new file mode 100644 index 00000000..6e831274 --- /dev/null +++ b/src/user_interface/egui_manager/fonts.rs @@ -0,0 +1,24 @@ +use super::EguiManager; + +use egui::{FontData, FontDefinitions, FontTweak}; + +use crate::constants; +use crate::system_fonts::*; + +fn tweak(font: FontData) -> FontData { + font.tweak(FontTweak {scale: constants::FONT_SCALE_FACTOR, .. Default::default()}) +} + +impl EguiManager { + pub fn set_system_fonts(&mut self) { + let ctx = &self.egui.egui_ctx; + let mut fonts = egui::FontDefinitions::default(); + fonts.font_data.iter_mut().map(move |s|{let new = tweak((s.1).clone()); *s.1 = new;}).for_each(drop); + fonts.font_data.insert("sans".to_owned(), tweak(egui::FontData::from_static(&SYSTEMSANS.data))); + fonts.font_data.insert("serif".to_owned(), tweak(egui::FontData::from_static(&SYSTEMSERIF.data))); + fonts.font_data.insert("mono".to_owned(), tweak(egui::FontData::from_static(&SYSTEMMONO.data))); + fonts.families.get_mut(&egui::FontFamily::Proportional).unwrap().insert(0, "sans".to_owned()); + fonts.families.get_mut(&egui::FontFamily::Monospace).unwrap().insert(0, "mono".to_owned()); + ctx.set_fonts(fonts); + } +} diff --git a/src/user_interface/egui_manager/mod.rs b/src/user_interface/egui_manager/mod.rs index 3ca160f5..1ce9501c 100644 --- a/src/user_interface/egui_manager/mod.rs +++ b/src/user_interface/egui_manager/mod.rs @@ -1,3 +1,5 @@ +mod fonts; + use egui_skia::EguiSkia; use sdl2::{event::Event, video::Window}; @@ -25,6 +27,10 @@ impl EguiManager { }; } + pub fn init(&mut self) { + self.set_system_fonts(); + } + pub fn wants_event(&mut self, sdl_window: &Window, sdl_event: &Event) -> bool { self.egui_sdl2.sdl2_input_to_egui(sdl_window, sdl_event); diff --git a/src/user_interface/gui/mod.rs b/src/user_interface/gui/mod.rs index 3167336d..46869bc3 100644 --- a/src/user_interface/gui/mod.rs +++ b/src/user_interface/gui/mod.rs @@ -20,6 +20,8 @@ pub fn build_ui( i: &mut Interface, wm: &mut WindowManager, ) { + // initialization (so far just sets fonts to system fonts not included Ubuntu) + egui_manager.init(); let egui = &mut egui_manager.egui; let egsdl2 = &mut egui_manager.egui_sdl2; egui.run(egsdl2.take_egui_input(&i.sdl_window), |ctx| { diff --git a/src/user_interface/gui/tool_bar.rs b/src/user_interface/gui/tool_bar.rs index c94e7323..483c9f9b 100644 --- a/src/user_interface/gui/tool_bar.rs +++ b/src/user_interface/gui/tool_bar.rs @@ -1,6 +1,6 @@ use egui::{Align2, Color32, Context, Stroke, Ui}; -use crate::{editor::Editor, tools::ToolEnum, user_interface::Interface}; +use crate::{constants::*, editor::Editor, tools::ToolEnum, user_interface::Interface}; pub fn build_button(v: &mut Editor, ui: &mut Ui, text: &str, te: ToolEnum) { let stroke = if v.get_tool() == te { @@ -25,10 +25,10 @@ pub fn build_button(v: &mut Editor, ui: &mut Ui, text: &str, te: ToolEnum) { } pub fn tool_bar(ctx: &Context, v: &mut Editor, _i: &mut Interface) { egui::Window::new("Tools") - .anchor(Align2::LEFT_TOP, [0., 25.]) + .anchor(Align2::LEFT_TOP, [0., 25. * FONT_SCALE_FACTOR]) .title_bar(false) - .default_width(10.) - .min_width(15.) + .default_width(10. * FONT_SCALE_FACTOR) + .min_width(15. * FONT_SCALE_FACTOR) .resizable(false) .enabled(!v.is_modifying()) .show(ctx, |ui| {