//! The interface fonts with and without the optional craft-fonts build input (`CRAFT_FONTS_DIR`). use egui::epaint::text::{Fonts, TextOptions}; use egui::{Color32, FontFamily, FontId}; use printcraft_ui_egui::theme; const JAPANESE: &str = "日本語の文字"; fn families() -> Vec { vec![FontId::proportional(13.0), FontId::monospace(13.0), theme::medium(13.0), theme::semibold(17.0)] } /// Lays `text` out in every interface family and returns each galley's width. fn layout_widths(fonts: &mut Fonts, text: &str) -> Vec { let mut view = fonts.with_pixels_per_point(2.0); families().into_iter().map(|id| view.layout_no_wrap(text.to_owned(), id, Color32::BLACK).size().x).collect() } /// Built with craft-fonts, Japanese text renders with real glyphs (no tofu) in every family, /// from a craft-fonts face placed after the app's own fonts. #[test] fn japanese_ui_text_uses_craft_fonts() { if printcraft_fonts::ui_japanese_fonts().is_empty() { eprintln!("skipping japanese_ui_text_uses_craft_fonts: built without craft-fonts (set CRAFT_FONTS_DIR to run it)"); return; } let defs = theme::font_definitions(); for family in [FontFamily::Proportional, FontFamily::Monospace] { let stack = &defs.families[&family]; let first_jp = stack.iter().position(|n| n.starts_with("BIZ UDPGothic")).expect("BIZ UDPGothic is a fallback"); let own = stack.iter().position(|n| n == "Inter" || n == "JetBrainsMono").expect("the app's own font"); assert!(own < first_jp, "{family:?}: {stack:?}"); assert!(stack[first_jp..].iter().all(|n| printcraft_fonts::CRAFT_FONTS.iter().any(|f| f.name() == *n)), "{stack:?}"); } let mut fonts = Fonts::new(TextOptions::default(), defs); for id in families() { assert!(fonts.has_glyphs(&id, JAPANESE), "{id:?} lacks {JAPANESE}"); } // Real glyphs are about a full em wide each; tofu boxes and missing glyphs are not. for w in layout_widths(&mut fonts, JAPANESE) { assert!(w > 13.0 * 0.8 * JAPANESE.chars().count() as f32, "{w}"); } } /// Without craft-fonts the interface fonts still install and lay out any text (Japanese falls /// back to egui's replacement glyph) without panicking; Latin text is unaffected. #[test] fn ui_fonts_work_without_craft_fonts() { let mut fonts = Fonts::new(TextOptions::default(), theme::font_definitions()); for id in families() { assert!(fonts.has_glyphs(&id, "PrintCraft"), "{id:?}"); assert_eq!(fonts.has_glyphs(&id, JAPANESE), !printcraft_fonts::ui_japanese_fonts().is_empty(), "{id:?}"); } assert!(layout_widths(&mut fonts, JAPANESE).iter().all(|w| w.is_finite() && *w > 0.0)); assert!(layout_widths(&mut fonts, "PrintCraft").iter().all(|w| *w > 20.0)); let ctx = egui::Context::default(); theme::install_fonts(&ctx); }