1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-31 22:00:03 -04:00

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
This commit is contained in:
Emil Ernerfeldt
2022-01-24 14:32:36 +01:00
committed by GitHub
parent bb407e9b00
commit fa43d16c41
67 changed files with 1231 additions and 640 deletions

View File

@@ -71,7 +71,7 @@ impl super::View for CodeEditor {
ui.collapsing("Theme", |ui| {
ui.group(|ui| {
theme.ui(ui);
theme.store_in_memory(ui.ctx());
theme.clone().store_in_memory(ui.ctx());
});
});
@@ -85,7 +85,7 @@ impl super::View for CodeEditor {
egui::ScrollArea::vertical().show(ui, |ui| {
ui.add(
egui::TextEdit::multiline(code)
.text_style(egui::TextStyle::Monospace) // for cursor height
.font(egui::TextStyle::Monospace) // for cursor height
.code_editor()
.desired_rows(10)
.lock_focus(true)

View File

@@ -98,7 +98,8 @@ impl CodeExample {
);
ui.horizontal(|ui| {
let indentation = 8.0 * ui.fonts()[egui::TextStyle::Monospace].glyph_width(' ');
let font_id = egui::TextStyle::Monospace.resolve(ui.style());
let indentation = 8.0 * ui.fonts().glyph_width(&font_id, ' ');
let item_spacing = ui.spacing_mut().item_spacing;
ui.add_space(indentation - item_spacing.x);

View File

@@ -2,15 +2,15 @@ use std::collections::BTreeMap;
pub struct FontBook {
filter: String,
text_style: egui::TextStyle,
named_chars: BTreeMap<egui::TextStyle, BTreeMap<char, String>>,
font_id: egui::FontId,
named_chars: BTreeMap<egui::FontFamily, BTreeMap<char, String>>,
}
impl Default for FontBook {
fn default() -> Self {
Self {
filter: Default::default(),
text_style: egui::TextStyle::Button,
font_id: egui::FontId::proportional(20.0),
named_chars: Default::default(),
}
}
@@ -34,7 +34,7 @@ impl super::View for FontBook {
ui.label(format!(
"The selected font supports {} characters.",
self.named_chars
.get(&self.text_style)
.get(&self.font_id.family)
.map(|map| map.len())
.unwrap_or_default()
));
@@ -51,13 +51,7 @@ impl super::View for FontBook {
ui.separator();
egui::ComboBox::from_label("Text style")
.selected_text(format!("{:?}", self.text_style))
.show_ui(ui, |ui| {
for style in egui::TextStyle::all() {
ui.selectable_value(&mut self.text_style, style, format!("{:?}", style));
}
});
egui::introspection::font_id_ui(ui, &mut self.font_id);
ui.horizontal(|ui| {
ui.label("Filter:");
@@ -68,16 +62,11 @@ impl super::View for FontBook {
}
});
let text_style = self.text_style;
let filter = &self.filter;
let named_chars = self.named_chars.entry(text_style).or_insert_with(|| {
ui.fonts()[text_style]
.characters()
.iter()
.filter(|chr| !chr.is_whitespace() && !chr.is_ascii_control())
.map(|&chr| (chr, char_name(chr)))
.collect()
});
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();
@@ -88,12 +77,14 @@ impl super::View for FontBook {
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()).text_style(text_style),
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()).text_style(text_style));
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));
};
@@ -107,6 +98,18 @@ impl super::View for FontBook {
}
}
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())

View File

@@ -140,7 +140,7 @@ impl Widgets {
ui.horizontal_wrapped(|ui| {
// Trick so we don't have to add spaces in the text below:
let width = ui.fonts()[TextStyle::Body].glyph_width(' ');
let width = ui.fonts().glyph_width(&TextStyle::Body.resolve(ui.style()), ' ');
ui.spacing_mut().item_spacing.x = width;
ui.label(RichText::new("Text can have").color(Color32::from_rgb(110, 255, 110)));
@@ -418,7 +418,6 @@ fn text_layout_ui(ui: &mut egui::Ui) {
"This is a demonstration of ",
first_row_indentation,
TextFormat {
style: TextStyle::Body,
color: default_color,
..Default::default()
},
@@ -427,7 +426,6 @@ fn text_layout_ui(ui: &mut egui::Ui) {
"the egui text layout engine. ",
0.0,
TextFormat {
style: TextStyle::Body,
color: strong_color,
..Default::default()
},
@@ -436,7 +434,6 @@ fn text_layout_ui(ui: &mut egui::Ui) {
"It supports ",
0.0,
TextFormat {
style: TextStyle::Body,
color: default_color,
..Default::default()
},
@@ -445,7 +442,6 @@ fn text_layout_ui(ui: &mut egui::Ui) {
"different ",
0.0,
TextFormat {
style: TextStyle::Body,
color: Color32::from_rgb(110, 255, 110),
..Default::default()
},
@@ -454,7 +450,6 @@ fn text_layout_ui(ui: &mut egui::Ui) {
"colors, ",
0.0,
TextFormat {
style: TextStyle::Body,
color: Color32::from_rgb(128, 140, 255),
..Default::default()
},
@@ -463,7 +458,6 @@ fn text_layout_ui(ui: &mut egui::Ui) {
"backgrounds, ",
0.0,
TextFormat {
style: TextStyle::Body,
color: default_color,
background: Color32::from_rgb(128, 32, 32),
..Default::default()
@@ -473,7 +467,7 @@ fn text_layout_ui(ui: &mut egui::Ui) {
"mixing ",
0.0,
TextFormat {
style: TextStyle::Heading,
font_id: FontId::proportional(20.0),
color: default_color,
..Default::default()
},
@@ -482,7 +476,7 @@ fn text_layout_ui(ui: &mut egui::Ui) {
"fonts, ",
0.0,
TextFormat {
style: TextStyle::Monospace,
font_id: FontId::monospace(14.0),
color: default_color,
..Default::default()
},
@@ -491,7 +485,7 @@ fn text_layout_ui(ui: &mut egui::Ui) {
"raised text, ",
0.0,
TextFormat {
style: TextStyle::Small,
font_id: FontId::proportional(8.0),
color: default_color,
valign: Align::TOP,
..Default::default()
@@ -501,7 +495,6 @@ fn text_layout_ui(ui: &mut egui::Ui) {
"with ",
0.0,
TextFormat {
style: TextStyle::Body,
color: default_color,
..Default::default()
},
@@ -510,7 +503,6 @@ fn text_layout_ui(ui: &mut egui::Ui) {
"underlining",
0.0,
TextFormat {
style: TextStyle::Body,
color: default_color,
underline: Stroke::new(1.0, Color32::LIGHT_BLUE),
..Default::default()
@@ -520,7 +512,6 @@ fn text_layout_ui(ui: &mut egui::Ui) {
" and ",
0.0,
TextFormat {
style: TextStyle::Body,
color: default_color,
..Default::default()
},
@@ -529,7 +520,6 @@ fn text_layout_ui(ui: &mut egui::Ui) {
"strikethrough",
0.0,
TextFormat {
style: TextStyle::Body,
color: default_color,
strikethrough: Stroke::new(2.0, Color32::RED.linear_multiply(0.5)),
..Default::default()
@@ -539,7 +529,6 @@ fn text_layout_ui(ui: &mut egui::Ui) {
". Of course, ",
0.0,
TextFormat {
style: TextStyle::Body,
color: default_color,
..Default::default()
},
@@ -548,7 +537,6 @@ fn text_layout_ui(ui: &mut egui::Ui) {
"you can",
0.0,
TextFormat {
style: TextStyle::Body,
color: default_color,
strikethrough: Stroke::new(1.0, strong_color),
..Default::default()
@@ -558,7 +546,7 @@ fn text_layout_ui(ui: &mut egui::Ui) {
" mix these!",
0.0,
TextFormat {
style: TextStyle::Small,
font_id: FontId::proportional(8.0),
color: Color32::LIGHT_BLUE,
background: Color32::from_rgb(128, 0, 0),
underline: Stroke::new(1.0, strong_color),

View File

@@ -261,9 +261,10 @@ impl Widget for &mut LegendDemo {
egui::Grid::new("settings").show(ui, |ui| {
ui.label("Text style:");
ui.horizontal(|ui| {
TextStyle::all().for_each(|style| {
ui.selectable_value(&mut config.text_style, style, format!("{:?}", style));
});
let all_text_styles = ui.style().text_styles();
for style in all_text_styles {
ui.selectable_value(&mut config.text_style, style.clone(), style.to_string());
}
});
ui.end_row();
@@ -284,7 +285,9 @@ impl Widget for &mut LegendDemo {
ui.end_row();
});
let legend_plot = Plot::new("legend_demo").legend(*config).data_aspect(1.0);
let legend_plot = Plot::new("legend_demo")
.legend(config.clone())
.data_aspect(1.0);
legend_plot
.show(ui, |plot_ui| {
plot_ui.line(LegendDemo::line_with_slope(0.5).name("lines"));

View File

@@ -81,7 +81,7 @@ fn huge_content_lines(ui: &mut egui::Ui) {
ui.add_space(4.0);
let text_style = TextStyle::Body;
let row_height = ui.fonts()[text_style].row_height();
let row_height = ui.text_style_height(&text_style);
let num_rows = 10_000;
ScrollArea::vertical().auto_shrink([false; 2]).show_rows(
ui,
@@ -101,8 +101,8 @@ fn huge_content_painter(ui: &mut egui::Ui) {
ui.label("A lot of rows, but only the visible ones are painted, so performance is still good:");
ui.add_space(4.0);
let text_style = TextStyle::Body;
let row_height = ui.fonts()[text_style].row_height() + ui.spacing().item_spacing.y;
let font_id = TextStyle::Body.resolve(ui.style());
let row_height = ui.fonts().row_height(&font_id) + ui.spacing().item_spacing.y;
let num_rows = 10_000;
ScrollArea::vertical()
@@ -130,7 +130,7 @@ fn huge_content_painter(ui: &mut egui::Ui) {
pos2(x, y),
Align2::LEFT_TOP,
text,
text_style,
font_id.clone(),
ui.visuals().text_color(),
);
used_rect = used_rect.union(text_rect);
@@ -265,7 +265,7 @@ impl super::View for ScrollStickTo {
ui.add_space(4.0);
let text_style = TextStyle::Body;
let row_height = ui.fonts()[text_style].row_height();
let row_height = ui.text_style_height(&text_style);
ScrollArea::vertical().stick_to_bottom().show_rows(
ui,
row_height,

View File

@@ -216,7 +216,7 @@ fn selectable_text(ui: &mut egui::Ui, mut text: &str) {
ui.add(
egui::TextEdit::multiline(&mut text)
.desired_width(f32::INFINITY)
.text_style(egui::TextStyle::Monospace),
.font(egui::TextStyle::Monospace),
);
}
@@ -257,7 +257,7 @@ impl ColoredText {
let mut text = self.0.text.as_str();
ui.add(
egui::TextEdit::multiline(&mut text)
.text_style(egui::TextStyle::Monospace)
.font(egui::TextStyle::Monospace)
.desired_width(f32::INFINITY)
.layouter(&mut layouter),
);