diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index ec899461a..562a15ba1 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -4,9 +4,15 @@ use std::{borrow::Cow, cell::RefCell, panic::Location, sync::Arc, time::Duration use containers::area::AreaState; use epaint::{ - emath, emath::TSTransform, mutex::RwLock, pos2, stats::PaintStats, tessellator, text::Fonts, - util::OrderedFloat, vec2, ClippedPrimitive, ClippedShape, Color32, ImageData, ImageDelta, Pos2, - Rect, TessellationOptions, TextureAtlas, TextureId, Vec2, + emath::{self, TSTransform}, + mutex::RwLock, + pos2, + stats::PaintStats, + tessellator, + text::Fonts, + util::OrderedFloat, + vec2, ClippedPrimitive, ClippedShape, Color32, ImageData, ImageDelta, Pos2, Rect, + TessellationOptions, TextureAtlas, TextureId, Vec2, }; use crate::{ @@ -2817,6 +2823,10 @@ impl Context { let prev_options = self.options(|o| o.clone()); let mut options = prev_options.clone(); + ui.collapsing("🔠 Font tweak", |ui| { + self.fonts_tweak_ui(ui); + }); + options.ui(ui); if options != prev_options { @@ -2824,6 +2834,23 @@ impl Context { } } + fn fonts_tweak_ui(&self, ui: &mut Ui) { + let mut font_definitions = self.write(|ctx| ctx.font_definitions.clone()); + let mut changed = false; + + for (name, data) in &mut font_definitions.font_data { + ui.collapsing(name, |ui| { + if data.tweak.ui(ui).changed() { + changed = true; + } + }); + } + + if changed { + self.set_fonts(font_definitions); + } + } + /// Show the state of egui, including its input and output. pub fn inspection_ui(&self, ui: &mut Ui) { use crate::containers::CollapsingHeader; diff --git a/crates/egui/src/style.rs b/crates/egui/src/style.rs index dbbb989b9..be4021501 100644 --- a/crates/egui/src/style.rs +++ b/crates/egui/src/style.rs @@ -4,7 +4,7 @@ use std::{collections::BTreeMap, ops::RangeInclusive, sync::Arc}; -use epaint::{Rounding, Shadow, Stroke}; +use epaint::{text::FontTweak, Rounding, Shadow, Stroke}; use crate::{ ecolor::Color32, @@ -2498,3 +2498,48 @@ impl Widget for &mut crate::Frame { .response } } + +impl Widget for &mut FontTweak { + fn ui(self, ui: &mut Ui) -> Response { + let original: FontTweak = *self; + + let mut response = Grid::new("font_tweak") + .num_columns(2) + .show(ui, |ui| { + let FontTweak { + scale, + y_offset_factor, + y_offset, + baseline_offset_factor, + } = self; + + ui.label("Scale"); + let speed = *scale * 0.01; + ui.add(DragValue::new(scale).range(0.01..=10.0).speed(speed)); + ui.end_row(); + + ui.label("y_offset_factor"); + ui.add(DragValue::new(y_offset_factor).speed(-0.0025)); + ui.end_row(); + + ui.label("y_offset"); + ui.add(DragValue::new(y_offset).speed(-0.02)); + ui.end_row(); + + ui.label("baseline_offset_factor"); + ui.add(DragValue::new(baseline_offset_factor).speed(-0.0025)); + ui.end_row(); + + if ui.button("Reset").clicked() { + *self = Default::default(); + } + }) + .response; + + if *self != original { + response.mark_changed(); + } + + response + } +} diff --git a/crates/egui/src/ui.rs b/crates/egui/src/ui.rs index 9638d7a69..3a75afb21 100644 --- a/crates/egui/src/ui.rs +++ b/crates/egui/src/ui.rs @@ -1404,7 +1404,7 @@ impl Ui { /// /// If this is called multiple times per frame for the same [`crate::ScrollArea`], the deltas will be summed. /// - /// /// See also: [`Response::scroll_to_me`], [`Ui::scroll_to_rect`], [`Ui::scroll_to_cursor`] + /// See also: [`Response::scroll_to_me`], [`Ui::scroll_to_rect`], [`Ui::scroll_to_cursor`] /// /// ``` /// # use egui::{Align, Vec2}; diff --git a/crates/egui_demo_lib/src/demo/font_book.rs b/crates/egui_demo_lib/src/demo/font_book.rs index a5e8eb138..e2310f8a1 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 5a119cdc1..8fc6e9efc 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 }) diff --git a/crates/epaint/src/text/fonts.rs b/crates/epaint/src/text/fonts.rs index 0f8f87c87..dcfbbd7fe 100644 --- a/crates/epaint/src/text/fonts.rs +++ b/crates/epaint/src/text/fonts.rs @@ -159,6 +159,8 @@ pub struct FontTweak { /// Shift font's glyphs downwards by this fraction of the font size (in points). /// this is only a visual effect and does not affect the text layout. /// + /// Affects larger font sizes more. + /// /// A positive value shifts the text downwards. /// A negative value shifts it upwards. /// @@ -168,6 +170,8 @@ pub struct FontTweak { /// Shift font's glyphs downwards by this amount of logical points. /// this is only a visual effect and does not affect the text layout. /// + /// Affects all font sizes equally. + /// /// Example value: `2.0`. pub y_offset: f32, diff --git a/crates/epaint/src/text/text_layout.rs b/crates/epaint/src/text/text_layout.rs index 4fa3ba494..96dd06758 100644 --- a/crates/epaint/src/text/text_layout.rs +++ b/crates/epaint/src/text/text_layout.rs @@ -482,7 +482,7 @@ fn replace_last_glyph_with_overflow_character( /// Horizontally aligned the text on a row. /// -/// /// Ignores the Y coordinate. +/// Ignores the Y coordinate. fn halign_and_justify_row( point_scale: PointScale, row: &mut Row,