egui/egui_demo_lib/src/apps/demo/font_book.rs
Emil Ernerfeldt fa43d16c41
Choose your own font and size (#1154)
* Refactor text layout: don't need &Fonts in all functions
* Replace indexing in Fonts with member function
* Wrap Fonts in a Mutex
* Remove mutex for Font::glyph_info_cache
* Remove RwLock around Font::characters
* Put FontsImpl and GalleyCache behind the same Mutex
* Round font sizes to whole pixels before deduplicating them
* Make TextStyle !Copy
* Implement user-named TextStyle:s
* round font size earlier
* Cache fonts based on family and size
* Move TextStyle into egui and Style
* Remove body_text_style
* Query graphics about max texture size and use that as font atlas size
* Recreate texture atlas when it is getting full
2022-01-24 14:32:36 +01:00

257 lines
9.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use std::collections::BTreeMap;
pub struct FontBook {
filter: String,
font_id: egui::FontId,
named_chars: BTreeMap<egui::FontFamily, BTreeMap<char, String>>,
}
impl Default for FontBook {
fn default() -> Self {
Self {
filter: Default::default(),
font_id: egui::FontId::proportional(20.0),
named_chars: Default::default(),
}
}
}
impl super::Demo for FontBook {
fn name(&self) -> &'static str {
"🔤 Font Book"
}
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
egui::Window::new(self.name()).open(open).show(ctx, |ui| {
use super::View as _;
self.ui(ui);
});
}
}
impl super::View for FontBook {
fn ui(&mut self, ui: &mut egui::Ui) {
ui.label(format!(
"The selected font supports {} characters.",
self.named_chars
.get(&self.font_id.family)
.map(|map| map.len())
.unwrap_or_default()
));
ui.horizontal_wrapped(|ui| {
ui.spacing_mut().item_spacing.x = 0.0;
ui.label("You can add more characters by installing additional fonts with ");
ui.add(egui::Hyperlink::from_label_and_url(
egui::RichText::new("Context::set_fonts").text_style(egui::TextStyle::Monospace),
"https://docs.rs/egui/latest/egui/struct.Context.html#method.set_fonts",
));
ui.label(".");
});
ui.separator();
egui::introspection::font_id_ui(ui, &mut self.font_id);
ui.horizontal(|ui| {
ui.label("Filter:");
ui.add(egui::TextEdit::singleline(&mut self.filter).desired_width(120.0));
self.filter = self.filter.to_lowercase();
if ui.button("").clicked() {
self.filter.clear();
}
});
let filter = &self.filter;
let named_chars = self
.named_chars
.entry(self.font_id.family.clone())
.or_insert_with(|| available_characters(ui, self.font_id.family.clone()));
ui.separator();
egui::ScrollArea::vertical().show(ui, |ui| {
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() {
let button = egui::Button::new(
egui::RichText::new(chr.to_string()).font(self.font_id.clone()),
)
.frame(false);
let tooltip_ui = |ui: &mut egui::Ui| {
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));
};
if ui.add(button).on_hover_ui(tooltip_ui).clicked() {
ui.output().copied_text = chr.to_string();
}
}
}
});
});
}
}
fn available_characters(ui: &egui::Ui, family: egui::FontFamily) -> BTreeMap<char, String> {
ui.fonts()
.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)))
.collect()
}
fn char_name(chr: char) -> String {
special_char_name(chr)
.map(|s| s.to_owned())
.or_else(|| unicode_names2::name(chr).map(|name| name.to_string().to_lowercase()))
.unwrap_or_else(|| "unknown".to_owned())
}
fn special_char_name(chr: char) -> Option<&'static str> {
#[allow(clippy::match_same_arms)] // many "flag"
match chr {
// Special private-use-area extensions found in `emoji-icon-font.ttf`:
// Private use area extensions:
'\u{FE4E5}' => Some("flag japan"),
'\u{FE4E6}' => Some("flag usa"),
'\u{FE4E7}' => Some("flag"),
'\u{FE4E8}' => Some("flag"),
'\u{FE4E9}' => Some("flag"),
'\u{FE4EA}' => Some("flag great britain"),
'\u{FE4EB}' => Some("flag"),
'\u{FE4EC}' => Some("flag"),
'\u{FE4ED}' => Some("flag"),
'\u{FE4EE}' => Some("flag south korea"),
'\u{FE82C}' => Some("number sign in square"),
'\u{FE82E}' => Some("digit one in square"),
'\u{FE82F}' => Some("digit two in square"),
'\u{FE830}' => Some("digit three in square"),
'\u{FE831}' => Some("digit four in square"),
'\u{FE832}' => Some("digit five in square"),
'\u{FE833}' => Some("digit six in square"),
'\u{FE834}' => Some("digit seven in square"),
'\u{FE835}' => Some("digit eight in square"),
'\u{FE836}' => Some("digit nine in square"),
'\u{FE837}' => Some("digit zero in square"),
// Special private-use-area extensions found in `emoji-icon-font.ttf`:
// Web services / operating systems / browsers
'\u{E600}' => Some("web-dribbble"),
'\u{E601}' => Some("web-stackoverflow"),
'\u{E602}' => Some("web-vimeo"),
'\u{E603}' => Some("web-twitter"),
'\u{E604}' => Some("web-facebook"),
'\u{E605}' => Some("web-googleplus"),
'\u{E606}' => Some("web-pinterest"),
'\u{E607}' => Some("web-tumblr"),
'\u{E608}' => Some("web-linkedin"),
'\u{E60A}' => Some("web-stumbleupon"),
'\u{E60B}' => Some("web-lastfm"),
'\u{E60C}' => Some("web-rdio"),
'\u{E60D}' => Some("web-spotify"),
'\u{E60E}' => Some("web-qq"),
'\u{E60F}' => Some("web-instagram"),
'\u{E610}' => Some("web-dropbox"),
'\u{E611}' => Some("web-evernote"),
'\u{E612}' => Some("web-flattr"),
'\u{E613}' => Some("web-skype"),
'\u{E614}' => Some("web-renren"),
'\u{E615}' => Some("web-sina-weibo"),
'\u{E616}' => Some("web-paypal"),
'\u{E617}' => Some("web-picasa"),
'\u{E618}' => Some("os-android"),
'\u{E619}' => Some("web-mixi"),
'\u{E61A}' => Some("web-behance"),
'\u{E61B}' => Some("web-circles"),
'\u{E61C}' => Some("web-vk"),
'\u{E61D}' => Some("web-smashing"),
'\u{E61E}' => Some("web-forrst"),
'\u{E61F}' => Some("os-windows"),
'\u{E620}' => Some("web-flickr"),
'\u{E621}' => Some("web-picassa"),
'\u{E622}' => Some("web-deviantart"),
'\u{E623}' => Some("web-steam"),
'\u{E624}' => Some("web-github"),
'\u{E625}' => Some("web-git"),
'\u{E626}' => Some("web-blogger"),
'\u{E627}' => Some("web-soundcloud"),
'\u{E628}' => Some("web-reddit"),
'\u{E629}' => Some("web-delicious"),
'\u{E62A}' => Some("browser-chrome"),
'\u{E62B}' => Some("browser-firefox"),
'\u{E62C}' => Some("browser-ie"),
'\u{E62D}' => Some("browser-opera"),
'\u{E62E}' => Some("browser-safari"),
'\u{E62F}' => Some("web-google-drive"),
'\u{E630}' => Some("web-wordpress"),
'\u{E631}' => Some("web-joomla"),
'\u{E632}' => Some("lastfm"),
'\u{E633}' => Some("web-foursquare"),
'\u{E634}' => Some("web-yelp"),
'\u{E635}' => Some("web-drupal"),
'\u{E636}' => Some("youtube"),
'\u{F189}' => Some("vk"),
'\u{F1A6}' => Some("digg"),
'\u{F1CA}' => Some("web-vine"),
'\u{F8FF}' => Some("os-apple"),
// Special private-use-area extensions found in `Ubuntu-Light.ttf`
'\u{F000}' => Some("uniF000"),
'\u{F001}' => Some("fi"),
'\u{F002}' => Some("fl"),
'\u{F506}' => Some("one seventh"),
'\u{F507}' => Some("two sevenths"),
'\u{F508}' => Some("three sevenths"),
'\u{F509}' => Some("four sevenths"),
'\u{F50A}' => Some("five sevenths"),
'\u{F50B}' => Some("six sevenths"),
'\u{F50C}' => Some("one ninth"),
'\u{F50D}' => Some("two ninths"),
'\u{F50E}' => Some("four ninths"),
'\u{F50F}' => Some("five ninths"),
'\u{F510}' => Some("seven ninths"),
'\u{F511}' => Some("eight ninths"),
'\u{F800}' => Some("zero.alt"),
'\u{F801}' => Some("one.alt"),
'\u{F802}' => Some("two.alt"),
'\u{F803}' => Some("three.alt"),
'\u{F804}' => Some("four.alt"),
'\u{F805}' => Some("five.alt"),
'\u{F806}' => Some("six.alt"),
'\u{F807}' => Some("seven.alt"),
'\u{F808}' => Some("eight.alt"),
'\u{F809}' => Some("nine.alt"),
'\u{F80A}' => Some("zero.sups"),
'\u{F80B}' => Some("one.sups"),
'\u{F80C}' => Some("two.sups"),
'\u{F80D}' => Some("three.sups"),
'\u{F80E}' => Some("four.sups"),
'\u{F80F}' => Some("five.sups"),
'\u{F810}' => Some("six.sups"),
'\u{F811}' => Some("seven.sups"),
'\u{F812}' => Some("eight.sups"),
'\u{F813}' => Some("nine.sups"),
'\u{F814}' => Some("zero.sinf"),
'\u{F815}' => Some("one.sinf"),
'\u{F816}' => Some("two.sinf"),
'\u{F817}' => Some("three.sinf"),
'\u{F818}' => Some("four.sinf"),
'\u{F819}' => Some("five.sinf"),
'\u{F81A}' => Some("six.sinf"),
'\u{F81B}' => Some("seven.sinf"),
'\u{F81C}' => Some("eight.sinf"),
'\u{F81D}' => Some("nine.sinf"),
_ => None,
}
}