diff --git a/crates/epaint/src/text/font.rs b/crates/epaint/src/text/font.rs index 910379cfc..3d647f668 100644 --- a/crates/epaint/src/text/font.rs +++ b/crates/epaint/src/text/font.rs @@ -41,25 +41,20 @@ pub struct GlyphInfo { /// Used for pair-kerning. /// /// 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, /// In [`ab_glyph`]s "unscaled" coordinate system. pub advance_width_unscaled: OrderedFloat, - - /// Whether this glyph has any outlines. - pub visible: bool, } -impl Default for GlyphInfo { - /// Basically a zero-width space. - fn default() -> Self { - Self { - id: ab_glyph::GlyphId(0), - advance_width_unscaled: 0.0.into(), - visible: false, - } - } +impl GlyphInfo { + /// A valid, but invisible, glyph of zero-width. + pub const INVISIBLE: Self = Self { + id: None, + advance_width_unscaled: OrderedFloat(0.0), + }; } #[derive(Clone, Copy, Debug, PartialEq, Default)] @@ -197,7 +192,7 @@ impl FontImpl { } if invisible_char(c) { - let glyph_info = GlyphInfo::default(); + let glyph_info = GlyphInfo::INVISIBLE; self.glyph_info_cache.insert(c, glyph_info); return Some(glyph_info); } @@ -209,9 +204,8 @@ impl FontImpl { None // unsupported character } else { let glyph_info = GlyphInfo { - id: glyph_id, + id: Some(glyph_id), advance_width_unscaled: self.ab_glyph_font.h_advance_unscaled(glyph_id).into(), - visible: true, }; self.glyph_info_cache.insert(c, glyph_info); Some(glyph_info) @@ -259,9 +253,11 @@ impl FontImpl { font_size: f32, pixels_per_point: f32, ) -> GlyphAllocation { - if !glyph_info.visible { + let Some(glyph_id) = glyph_info.id else { + // Invisible. return GlyphAllocation::default(); - } + }; + // Round to an even number of physical pixels to get even kerning. // See https://github.com/emilk/egui/issues/382 let scale = self @@ -275,11 +271,9 @@ impl FontImpl { 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 - .id - .with_scale_and_position(scale, ab_glyph::Point { x: 0.0, y: 0.0 }); + let glyph = glyph_id.with_scale_and_position(scale, ab_glyph::Point { x: 0.0, y: 0.0 }); // Tweak the scale as the user desired let y_offset_in_points = { @@ -334,7 +328,7 @@ impl FontImpl { let uv_rect = uv_rect.unwrap_or_default(); let allocation = GlyphAllocation { - id: glyph_info.id, + id: glyph_id, advance_width: (glyph_info.advance_width_unscaled.0 * scale / self.ab_glyph_font.height_unscaled()) / pixels_per_point, diff --git a/crates/epaint/src/text/fonts.rs b/crates/epaint/src/text/fonts.rs index ef99b2a9f..844fd019d 100644 --- a/crates/epaint/src/text/fonts.rs +++ b/crates/epaint/src/text/fonts.rs @@ -444,7 +444,7 @@ impl CachedFamily { return Self { fonts, characters: None, - replacement_glyph: (FontFaceKey::INVALID, Default::default()), + replacement_glyph: (FontFaceKey::INVALID, GlyphInfo::INVISIBLE), glyph_info_cache: Default::default(), }; } @@ -452,7 +452,7 @@ impl CachedFamily { let mut slf = Self { fonts, characters: None, - replacement_glyph: (FontFaceKey::INVALID, Default::default()), + replacement_glyph: (FontFaceKey::INVALID, GlyphInfo::INVISIBLE), glyph_info_cache: Default::default(), }; @@ -467,7 +467,7 @@ impl CachedFamily { log::warn!( "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; diff --git a/crates/epaint/src/text/text_layout.rs b/crates/epaint/src/text/text_layout.rs index 8f60b8da7..240336458 100644 --- a/crates/epaint/src/text/text_layout.rs +++ b/crates/epaint/src/text/text_layout.rs @@ -453,12 +453,14 @@ fn replace_last_glyph_with_overflow_character( // Kerning: x += section.format.extra_letter_spacing; if let Some(font_impl) = font_impl { - x += font_impl.pair_kerning( - last_glyph_info.id, - replacement_glyph_alloc.id, - section.format.font_id.size, - pixels_per_point, - ); + if let Some(last_glyph_id) = last_glyph_info.id { + x += font_impl.pair_kerning( + last_glyph_id, + replacement_glyph_alloc.id, + section.format.font_id.size, + pixels_per_point, + ); + } } row.glyphs.push(Glyph {