From 4874b90e19c0bcbc0bdfac583b95d553decba54e Mon Sep 17 00:00:00 2001 From: Warpten Date: Sun, 9 Jun 2024 03:53:33 +0200 Subject: [PATCH] Try to improve support for .notdef glyphs through `FontTweak` --- crates/epaint/src/text/font.rs | 28 +++++++++++++++++----------- crates/epaint/src/text/fonts.rs | 5 +++++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/crates/epaint/src/text/font.rs b/crates/epaint/src/text/font.rs index 7520c971a89..296d8a96e46 100644 --- a/crates/epaint/src/text/font.rs +++ b/crates/epaint/src/text/font.rs @@ -78,6 +78,8 @@ pub struct FontImpl { pixels_per_point: f32, glyph_info_cache: RwLock>, // TODO(emilk): standard Mutex atlas: Arc>, + + fallbacks: [char; 2], } impl FontImpl { @@ -132,6 +134,7 @@ impl FontImpl { pixels_per_point, glyph_info_cache: Default::default(), atlas, + fallbacks: tweak.fallbacks.unwrap_or(['◻', '?']), } } @@ -363,20 +366,23 @@ impl Font { glyph_info_cache: Default::default(), }; - const PRIMARY_REPLACEMENT_CHAR: char = '◻'; // white medium square - const FALLBACK_REPLACEMENT_CHAR: char = '?'; // fallback for the fallback - - let replacement_glyph = slf - .glyph_info_no_cache_or_fallback(PRIMARY_REPLACEMENT_CHAR) - .or_else(|| slf.glyph_info_no_cache_or_fallback(FALLBACK_REPLACEMENT_CHAR)) + // For each font, find the first available fallback character + slf.replacement_glyph = slf + .fonts + .iter() + .enumerate() + .find_map(|(font_index, font_impl)| { + font_impl.fallbacks.iter().find_map(|chr| { + font_impl + .glyph_info(*chr) + .map(|glyph_info| (font_index, glyph_info)) + }) + }) .unwrap_or_else(|| { #[cfg(feature = "log")] - log::warn!( - "Failed to find replacement characters {PRIMARY_REPLACEMENT_CHAR:?} or {FALLBACK_REPLACEMENT_CHAR:?}. Will use empty glyph." - ); + log::warn!("Failed to find replacement characters. Will use empty glyph."); (0, GlyphInfo::default()) }); - slf.replacement_glyph = replacement_glyph; slf } @@ -434,7 +440,7 @@ impl Font { /// Can we display this glyph? pub fn has_glyph(&mut self, c: char) -> bool { - self.glyph_info(c) != self.replacement_glyph // TODO(emilk): this is a false negative if the user asks about the replacement character itself 🤦‍♂️ + self.glyph_info_no_cache_or_fallback(c).is_some() } /// Can we display all the glyphs in this text? diff --git a/crates/epaint/src/text/fonts.rs b/crates/epaint/src/text/fonts.rs index 394b898291e..e4dcab0390b 100644 --- a/crates/epaint/src/text/fonts.rs +++ b/crates/epaint/src/text/fonts.rs @@ -174,6 +174,10 @@ pub struct FontTweak { /// A positive value shifts the text downwards. /// A negative value shifts it upwards. pub baseline_offset_factor: f32, + + /// Fallback characters for this font + /// The default value is handled to be either the square character, or the question mark. + pub fallbacks: Option<[char; 2]>, } impl Default for FontTweak { @@ -183,6 +187,7 @@ impl Default for FontTweak { y_offset_factor: 0.0, y_offset: 0.0, baseline_offset_factor: -0.0333, // makes the default fonts look more centered in buttons and such + fallbacks: None, } } }