diff --git a/crates/egui_demo_lib/src/demo/font_book.rs b/crates/egui_demo_lib/src/demo/font_book.rs index a5e8eb13829c..e2310f8a1e3c 100644 --- a/crates/egui_demo_lib/src/demo/font_book.rs +++ b/crates/egui_demo_lib/src/demo/font_book.rs @@ -1,9 +1,16 @@ use std::collections::BTreeMap; +struct GlyphInfo { + name: String, + + // What fonts it is available in + fonts: Vec, +} + pub struct FontBook { filter: String, font_id: egui::FontId, - named_chars: BTreeMap>, + available_glyphs: BTreeMap>, } impl Default for FontBook { @@ -11,7 +18,7 @@ impl Default for FontBook { Self { filter: Default::default(), font_id: egui::FontId::proportional(18.0), - named_chars: Default::default(), + available_glyphs: Default::default(), } } } @@ -37,7 +44,7 @@ impl crate::View for FontBook { ui.label(format!( "The selected font supports {} characters.", - self.named_chars + self.available_glyphs .get(&self.font_id.family) .map(|map| map.len()) .unwrap_or_default() @@ -67,8 +74,8 @@ impl crate::View for FontBook { }); let filter = &self.filter; - let named_chars = self - .named_chars + let available_glyphs = self + .available_glyphs .entry(self.font_id.family.clone()) .or_insert_with(|| available_characters(ui, self.font_id.family.clone())); @@ -78,8 +85,11 @@ impl crate::View for FontBook { ui.horizontal_wrapped(|ui| { ui.spacing_mut().item_spacing = egui::Vec2::splat(2.0); - for (&chr, name) in named_chars { - if filter.is_empty() || name.contains(filter) || *filter == chr.to_string() { + for (&chr, glyph_info) in available_glyphs { + if filter.is_empty() + || glyph_info.name.contains(filter) + || *filter == chr.to_string() + { let button = egui::Button::new( egui::RichText::new(chr.to_string()).font(self.font_id.clone()), ) @@ -89,7 +99,10 @@ impl crate::View for FontBook { ui.label( egui::RichText::new(chr.to_string()).font(self.font_id.clone()), ); - ui.label(format!("{}\nU+{:X}\n\nClick to copy", name, chr as u32)); + ui.label(format!( + "{}\nU+{:X}\n\nFound in: {:?}\n\nClick to copy", + glyph_info.name, chr as u32, glyph_info.fonts + )); }; if ui.add(button).on_hover_ui(tooltip_ui).clicked() { @@ -102,15 +115,23 @@ impl crate::View for FontBook { } } -fn available_characters(ui: &egui::Ui, family: egui::FontFamily) -> BTreeMap { +fn available_characters(ui: &egui::Ui, family: egui::FontFamily) -> BTreeMap { ui.fonts(|f| { f.lock() .fonts .font(&egui::FontId::new(10.0, family)) // size is arbitrary for getting the characters .characters() .iter() - .filter(|chr| !chr.is_whitespace() && !chr.is_ascii_control()) - .map(|&chr| (chr, char_name(chr))) + .filter(|(chr, _fonts)| !chr.is_whitespace() && !chr.is_ascii_control()) + .map(|(chr, fonts)| { + ( + *chr, + GlyphInfo { + name: char_name(*chr), + fonts: fonts.clone(), + }, + ) + }) .collect() }) } diff --git a/crates/epaint/src/text/font.rs b/crates/epaint/src/text/font.rs index 5a119cdc1f8f..8fc6e9efc6d7 100644 --- a/crates/epaint/src/text/font.rs +++ b/crates/epaint/src/text/font.rs @@ -1,11 +1,13 @@ +use std::collections::BTreeMap; +use std::sync::Arc; + +use emath::{vec2, Vec2}; + use crate::{ mutex::{Mutex, RwLock}, text::FontTweak, TextureAtlas, }; -use emath::{vec2, Vec2}; -use std::collections::BTreeSet; -use std::sync::Arc; // ---------------------------------------------------------------------------- @@ -330,7 +332,7 @@ pub struct Font { fonts: Vec>, /// Lazily calculated. - characters: Option>, + characters: Option>>, replacement_glyph: (FontIndex, GlyphInfo), pixels_per_point: f32, @@ -398,12 +400,14 @@ impl Font { self.glyph_info(crate::text::PASSWORD_REPLACEMENT_CHAR); } - /// All supported characters. - pub fn characters(&mut self) -> &BTreeSet { + /// All supported characters, and in which font they are available in. + pub fn characters(&mut self) -> &BTreeMap> { self.characters.get_or_insert_with(|| { - let mut characters = BTreeSet::new(); + let mut characters: BTreeMap> = Default::default(); for font in &self.fonts { - characters.extend(font.characters()); + for chr in font.characters() { + characters.entry(chr).or_default().push(font.name.clone()); + } } characters })