Skip to content

Commit

Permalink
Make v-align and scale of user fonts tweakable (#1241)
Browse files Browse the repository at this point in the history
* Add ability to "tweak" the scale and y-offsets of individual fonts
* Change default font tweak

This help vertically center large text.
  • Loading branch information
emilk authored Feb 12, 2022
1 parent 3f8ba3a commit 6962629
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 27 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)).
Expand Down
1 change: 1 addition & 0 deletions epaint/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)).
Expand Down
14 changes: 8 additions & 6 deletions epaint/src/text/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
92 changes: 71 additions & 21 deletions epaint/src/text/fonts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,24 +120,70 @@ 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 {
pub fn from_static(font: &'static [u8]) -> Self {
Self {
font: std::borrow::Cow::Borrowed(font),
index: 0,
tweak: Default::default(),
}
}

pub fn from_owned(font: Vec<u8>) -> Self {
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) => {
Expand Down Expand Up @@ -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. <http://jslegers.github.io/emoji-icon-font/>:
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(
Expand Down Expand Up @@ -603,7 +656,7 @@ impl GalleyCache {
struct FontImplCache {
atlas: Arc<Mutex<TextureAtlas>>,
pixels_per_point: f32,
ab_glyph_fonts: BTreeMap<String, ab_glyph::FontArc>,
ab_glyph_fonts: BTreeMap<String, (FontTweak, ab_glyph::FontArc)>,

/// Map font pixel sizes and names to the cached `FontImpl`.
cache: ahash::AHashMap<(u32, String), Arc<FontImpl>>,
Expand All @@ -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 {
Expand All @@ -638,35 +695,28 @@ impl FontImplCache {
}

pub fn font_impl(&mut self, scale_in_pixels: u32, font_name: &str) -> Arc<FontImpl> {
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()
Expand Down

0 comments on commit 6962629

Please sign in to comment.