diff --git a/CHANGELOG.md b/CHANGELOG.md index eeb02be9..8a3f29fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w * Easily change text styles with `Style::text_styles`. * Added `Ui::text_style_height`. * Added `TextStyle::resolve`. +* Made v-align and scale of user fonts tweakable ([#1241](https://github.com/emilk/egui/pull/1027)). * `Context::load_texture` to convert an image into a texture which can be displayed using e.g. `ui.image(texture, size)` ([#1110](https://github.com/emilk/egui/pull/1110)). * Added `Ui::add_visible` and `Ui::add_visible_ui`. * Opt-in dependency on `tracing` crate for logging warnings ([#1192](https://github.com/emilk/egui/pull/1192)). diff --git a/epaint/CHANGELOG.md b/epaint/CHANGELOG.md index 4395c203..0039d9e5 100644 --- a/epaint/CHANGELOG.md +++ b/epaint/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to the epaint crate will be documented in this file. * Much improved font selection ([#1154](https://github.com/emilk/egui/pull/1154)): * Replaced `TextStyle` with `FontId` which lets you pick any font size and font family. * Replaced `Fonts::font_image` with `font_image_delta` for partial font atlas updates. +* Made v-align and scale of user fonts tweakable ([#1241](https://github.com/emilk/egui/pull/1027)). * Added `ImageData` and `TextureManager` for loading images into textures ([#1110](https://github.com/emilk/egui/pull/1110)). * Added `Shape::dashed_line_many` ([#1027](https://github.com/emilk/egui/pull/1027)). * Replaced `corner_radius: f32` with `rounding: Rounding`, allowing per-corner rounding settings ([#1206](https://github.com/emilk/egui/pull/1206)). diff --git a/epaint/src/text/font.rs b/epaint/src/text/font.rs index 1dca6030..1f779ddf 100644 --- a/epaint/src/text/font.rs +++ b/epaint/src/text/font.rs @@ -73,20 +73,22 @@ impl FontImpl { pixels_per_point: f32, ab_glyph_font: ab_glyph::FontArc, scale_in_pixels: u32, - y_offset: f32, + y_offset_points: f32, ) -> FontImpl { assert!(scale_in_pixels > 0); assert!(pixels_per_point > 0.0); let height_in_points = scale_in_pixels as f32 / pixels_per_point; - // TODO: use v_metrics for line spacing ? - // let v = rusttype_font.v_metrics(Scale::uniform(scale_in_pixels)); - // let height_in_pixels = v.ascent - v.descent + v.line_gap; - // let height_in_points = height_in_pixels / pixels_per_point; + // TODO: use these font metrics? + // use ab_glyph::ScaleFont as _; + // let scaled = ab_glyph_font.as_scaled(scale_in_pixels as f32); + // dbg!(scaled.ascent()); + // dbg!(scaled.descent()); + // dbg!(scaled.line_gap()); // Round to closest pixel: - let y_offset = (y_offset * pixels_per_point).round() / pixels_per_point; + let y_offset = (y_offset_points * pixels_per_point).round() / pixels_per_point; Self { ab_glyph_font, diff --git a/epaint/src/text/fonts.rs b/epaint/src/text/fonts.rs index bd6a9e2b..790db06b 100644 --- a/epaint/src/text/fonts.rs +++ b/epaint/src/text/fonts.rs @@ -120,6 +120,9 @@ pub struct FontData { /// Which font face in the file to use. /// When in doubt, use `0`. pub index: u32, + + /// Extra scale and vertical tweak to apply to all text of this font. + pub tweak: FontTweak, } impl FontData { @@ -127,6 +130,7 @@ impl FontData { Self { font: std::borrow::Cow::Borrowed(font), index: 0, + tweak: Default::default(), } } @@ -134,10 +138,52 @@ impl FontData { Self { font: std::borrow::Cow::Owned(font), index: 0, + tweak: Default::default(), + } + } + + pub fn tweak(self, tweak: FontTweak) -> Self { + Self { tweak, ..self } + } +} + +// ---------------------------------------------------------------------------- + +/// Extra scale and vertical tweak to apply to all text of a certain font. +#[derive(Copy, Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +pub struct FontTweak { + /// Scale the font by this much. + /// + /// Default: `1.0` (no scaling). + pub scale: f32, + + /// Shift font downwards by this fraction of the font size (in points). + /// + /// A positive value shifts the text upwards. + /// A negative value shifts it downwards. + /// + /// Example value: `-0.2`. + pub y_offset_factor: f32, + + /// Shift font downwards by this amount of logical points. + /// + /// Example value: `-1.0`. + pub y_offset: f32, +} + +impl Default for FontTweak { + fn default() -> Self { + Self { + scale: 1.0, + y_offset_factor: -0.2, // makes the default fonts look more centered in buttons and such + y_offset: 0.0, } } } +// ---------------------------------------------------------------------------- + fn ab_glyph_font_from_font_data(name: &str, data: &FontData) -> ab_glyph::FontArc { match &data.font { std::borrow::Cow::Borrowed(bytes) => { @@ -220,10 +266,17 @@ impl Default for FontDefinitions { "NotoEmoji-Regular".to_owned(), FontData::from_static(include_bytes!("../../fonts/NotoEmoji-Regular.ttf")), ); + // Bigger emojis, and more. : font_data.insert( "emoji-icon-font".to_owned(), - FontData::from_static(include_bytes!("../../fonts/emoji-icon-font.ttf")), + FontData::from_static(include_bytes!("../../fonts/emoji-icon-font.ttf")).tweak( + FontTweak { + scale: 0.8, // make it smaller + y_offset_factor: 0.07, // move it down slightly + y_offset: 0.0, + }, + ), ); families.insert( @@ -603,7 +656,7 @@ impl GalleyCache { struct FontImplCache { atlas: Arc>, pixels_per_point: f32, - ab_glyph_fonts: BTreeMap, + ab_glyph_fonts: BTreeMap, /// Map font pixel sizes and names to the cached `FontImpl`. cache: ahash::AHashMap<(u32, String), Arc>, @@ -617,7 +670,11 @@ impl FontImplCache { ) -> Self { let ab_glyph_fonts = font_data .iter() - .map(|(name, font_data)| (name.clone(), ab_glyph_font_from_font_data(name, font_data))) + .map(|(name, font_data)| { + let tweak = font_data.tweak; + let ab_glyph = ab_glyph_font_from_font_data(name, font_data); + (name.clone(), (tweak, ab_glyph)) + }) .collect(); Self { @@ -638,35 +695,28 @@ impl FontImplCache { } pub fn font_impl(&mut self, scale_in_pixels: u32, font_name: &str) -> Arc { - let scale_in_pixels = if font_name == "emoji-icon-font" { - (scale_in_pixels as f32 * 0.8).round() as u32 // TODO: remove font scale HACK! - } else { - scale_in_pixels - }; + let (tweak, ab_glyph_font) = self + .ab_glyph_fonts + .get(font_name) + .unwrap_or_else(|| panic!("No font data found for {:?}", font_name)) + .clone(); - let y_offset = if font_name == "emoji-icon-font" { + let scale_in_pixels = (scale_in_pixels as f32 * tweak.scale).round() as u32; + + let y_offset_points = { let scale_in_points = scale_in_pixels as f32 / self.pixels_per_point; - scale_in_points * 0.29375 // TODO: remove font alignment hack - } else { - 0.0 - }; - let y_offset = y_offset - 3.0; // Tweaked to make text look centered in buttons and text edit fields + scale_in_points * tweak.y_offset_factor + } + tweak.y_offset; self.cache .entry((scale_in_pixels, font_name.to_owned())) .or_insert_with(|| { - let ab_glyph_font = self - .ab_glyph_fonts - .get(font_name) - .unwrap_or_else(|| panic!("No font data found for {:?}", font_name)) - .clone(); - Arc::new(FontImpl::new( self.atlas.clone(), self.pixels_per_point, ab_glyph_font, scale_in_pixels, - y_offset, + y_offset_points, )) }) .clone()