1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-03 07:10:04 -04:00

Refactor GlyphInfo

This commit is contained in:
Emil Ernerfeldt
2025-09-05 10:07:18 +02:00
committed by valadaptive
parent 686f0709db
commit 6f53261f4a
3 changed files with 29 additions and 33 deletions

View File

@@ -41,25 +41,20 @@ pub struct GlyphInfo {
/// Used for pair-kerning. /// Used for pair-kerning.
/// ///
/// Doesn't need to be unique. /// Doesn't need to be unique.
/// Use `ab_glyph::GlyphId(0)` if you just want to have an id, and don't care. ///
pub(crate) id: ab_glyph::GlyphId, /// Is `None` for a special "invisible" glyph.
pub(crate) id: Option<ab_glyph::GlyphId>,
/// In [`ab_glyph`]s "unscaled" coordinate system. /// In [`ab_glyph`]s "unscaled" coordinate system.
pub advance_width_unscaled: OrderedFloat<f32>, pub advance_width_unscaled: OrderedFloat<f32>,
/// Whether this glyph has any outlines.
pub visible: bool,
} }
impl Default for GlyphInfo { impl GlyphInfo {
/// Basically a zero-width space. /// A valid, but invisible, glyph of zero-width.
fn default() -> Self { pub const INVISIBLE: Self = Self {
Self { id: None,
id: ab_glyph::GlyphId(0), advance_width_unscaled: OrderedFloat(0.0),
advance_width_unscaled: 0.0.into(), };
visible: false,
}
}
} }
#[derive(Clone, Copy, Debug, PartialEq, Default)] #[derive(Clone, Copy, Debug, PartialEq, Default)]
@@ -197,7 +192,7 @@ impl FontImpl {
} }
if invisible_char(c) { if invisible_char(c) {
let glyph_info = GlyphInfo::default(); let glyph_info = GlyphInfo::INVISIBLE;
self.glyph_info_cache.insert(c, glyph_info); self.glyph_info_cache.insert(c, glyph_info);
return Some(glyph_info); return Some(glyph_info);
} }
@@ -209,9 +204,8 @@ impl FontImpl {
None // unsupported character None // unsupported character
} else { } else {
let glyph_info = GlyphInfo { let glyph_info = GlyphInfo {
id: glyph_id, id: Some(glyph_id),
advance_width_unscaled: self.ab_glyph_font.h_advance_unscaled(glyph_id).into(), advance_width_unscaled: self.ab_glyph_font.h_advance_unscaled(glyph_id).into(),
visible: true,
}; };
self.glyph_info_cache.insert(c, glyph_info); self.glyph_info_cache.insert(c, glyph_info);
Some(glyph_info) Some(glyph_info)
@@ -259,9 +253,11 @@ impl FontImpl {
font_size: f32, font_size: f32,
pixels_per_point: f32, pixels_per_point: f32,
) -> GlyphAllocation { ) -> GlyphAllocation {
if !glyph_info.visible { let Some(glyph_id) = glyph_info.id else {
// Invisible.
return GlyphAllocation::default(); return GlyphAllocation::default();
} };
// Round to an even number of physical pixels to get even kerning. // Round to an even number of physical pixels to get even kerning.
// See https://github.com/emilk/egui/issues/382 // See https://github.com/emilk/egui/issues/382
let scale = self let scale = self
@@ -275,11 +271,9 @@ impl FontImpl {
std::collections::hash_map::Entry::Vacant(entry) => entry, std::collections::hash_map::Entry::Vacant(entry) => entry,
}; };
assert!(glyph_info.id.0 != 0, "Can't allocate glyph for id 0"); debug_assert!(glyph_id.0 != 0, "Can't allocate glyph for id 0");
let glyph = glyph_info let glyph = glyph_id.with_scale_and_position(scale, ab_glyph::Point { x: 0.0, y: 0.0 });
.id
.with_scale_and_position(scale, ab_glyph::Point { x: 0.0, y: 0.0 });
// Tweak the scale as the user desired // Tweak the scale as the user desired
let y_offset_in_points = { let y_offset_in_points = {
@@ -334,7 +328,7 @@ impl FontImpl {
let uv_rect = uv_rect.unwrap_or_default(); let uv_rect = uv_rect.unwrap_or_default();
let allocation = GlyphAllocation { let allocation = GlyphAllocation {
id: glyph_info.id, id: glyph_id,
advance_width: (glyph_info.advance_width_unscaled.0 * scale advance_width: (glyph_info.advance_width_unscaled.0 * scale
/ self.ab_glyph_font.height_unscaled()) / self.ab_glyph_font.height_unscaled())
/ pixels_per_point, / pixels_per_point,

View File

@@ -444,7 +444,7 @@ impl CachedFamily {
return Self { return Self {
fonts, fonts,
characters: None, characters: None,
replacement_glyph: (FontFaceKey::INVALID, Default::default()), replacement_glyph: (FontFaceKey::INVALID, GlyphInfo::INVISIBLE),
glyph_info_cache: Default::default(), glyph_info_cache: Default::default(),
}; };
} }
@@ -452,7 +452,7 @@ impl CachedFamily {
let mut slf = Self { let mut slf = Self {
fonts, fonts,
characters: None, characters: None,
replacement_glyph: (FontFaceKey::INVALID, Default::default()), replacement_glyph: (FontFaceKey::INVALID, GlyphInfo::INVISIBLE),
glyph_info_cache: Default::default(), glyph_info_cache: Default::default(),
}; };
@@ -467,7 +467,7 @@ impl CachedFamily {
log::warn!( log::warn!(
"Failed to find replacement characters {PRIMARY_REPLACEMENT_CHAR:?} or {FALLBACK_REPLACEMENT_CHAR:?}. Will use empty glyph." "Failed to find replacement characters {PRIMARY_REPLACEMENT_CHAR:?} or {FALLBACK_REPLACEMENT_CHAR:?}. Will use empty glyph."
); );
(FontFaceKey::INVALID, GlyphInfo::default()) (FontFaceKey::INVALID, GlyphInfo::INVISIBLE)
}); });
slf.replacement_glyph = replacement_glyph; slf.replacement_glyph = replacement_glyph;

View File

@@ -453,12 +453,14 @@ fn replace_last_glyph_with_overflow_character(
// Kerning: // Kerning:
x += section.format.extra_letter_spacing; x += section.format.extra_letter_spacing;
if let Some(font_impl) = font_impl { if let Some(font_impl) = font_impl {
x += font_impl.pair_kerning( if let Some(last_glyph_id) = last_glyph_info.id {
last_glyph_info.id, x += font_impl.pair_kerning(
replacement_glyph_alloc.id, last_glyph_id,
section.format.font_id.size, replacement_glyph_alloc.id,
pixels_per_point, section.format.font_id.size,
); pixels_per_point,
);
}
} }
row.glyphs.push(Glyph { row.glyphs.push(Glyph {