diff --git a/crates/epaint/src/text/font.rs b/crates/epaint/src/text/font.rs index 4e342560f..535b111b6 100644 --- a/crates/epaint/src/text/font.rs +++ b/crates/epaint/src/text/font.rs @@ -2,7 +2,7 @@ use emath::{GuiRounding as _, OrderedFloat, Vec2, vec2}; use self_cell::self_cell; -use skrifa::MetadataProvider as _; +use skrifa::{GlyphId, MetadataProvider as _}; use std::collections::BTreeMap; use vello_cpu::{color, kurbo}; @@ -44,7 +44,7 @@ pub struct GlyphInfo { /// Doesn't need to be unique. /// /// Is `None` for a special "invisible" glyph. - pub(crate) id: Option, + pub(crate) id: Option, /// In [`skrifa`]s "unscaled" coordinate system. pub advance_width_unscaled: OrderedFloat, @@ -119,11 +119,8 @@ impl SubpixelBin { } } -#[derive(Clone, Copy, Debug, PartialEq, Default)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub struct GlyphAllocation { - /// Unit: screen pixels. - pub advance_width_px: f32, - /// UV rectangle for drawing. pub uv_rect: UvRect, } @@ -134,7 +131,7 @@ struct GlyphCacheKey(u64); impl nohash_hasher::IsEnabled for GlyphCacheKey {} impl GlyphCacheKey { - fn new(glyph_id: skrifa::GlyphId, metrics: &StyledMetrics, bin: SubpixelBin) -> Self { + fn new(glyph_id: GlyphId, metrics: &StyledMetrics, bin: SubpixelBin) -> Self { let StyledMetrics { pixels_per_point, px_scale_factor, @@ -187,12 +184,10 @@ impl FontCell { &mut self, atlas: &mut TextureAtlas, metrics: &StyledMetrics, - glyph_info: &GlyphInfo, + glyph_id: GlyphId, bin: SubpixelBin, location: skrifa::instance::LocationRef<'_>, ) -> Option { - let glyph_id = glyph_info.id?; - debug_assert!( glyph_id != skrifa::GlyphId::NOTDEF, "Can't allocate glyph for id 0" @@ -277,10 +272,7 @@ impl FontCell { } }; - Some(GlyphAllocation { - advance_width_px: glyph_info.advance_width_unscaled.0 * metrics.px_scale_factor, - uv_rect, - }) + Some(GlyphAllocation { uv_rect }) } } @@ -478,7 +470,7 @@ impl FontFace { let glyph_id = font_data .charmap .map(c) - .filter(|id| *id != skrifa::GlyphId::NOTDEF)?; + .filter(|id| *id != GlyphId::NOTDEF)?; let glyph_info = GlyphInfo { id: Some(glyph_id), @@ -554,12 +546,11 @@ impl FontFace { ) -> (GlyphAllocation, i32) { let ShapedGlyph { glyph_id, - advance_width_px, h_pos, is_cjk, } = *shaped; - if glyph_id == skrifa::GlyphId::NOTDEF { + if glyph_id == GlyphId::NOTDEF { return (GlyphAllocation::default(), h_pos.round() as i32); } @@ -570,41 +561,28 @@ impl FontFace { }; let cache_key = GlyphCacheKey::new(glyph_id, metrics, bin); - if let Some(cached) = self.glyph_alloc_cache.get(&cache_key) { - let mut alloc = *cached; - alloc.advance_width_px = advance_width_px; - (alloc, h_pos_round) - } else { - let glyph_info = GlyphInfo { - id: Some(glyph_id), - advance_width_unscaled: OrderedFloat(advance_width_px / metrics.px_scale_factor), - }; + let alloc = if let Some(cached) = self.glyph_alloc_cache.get(&cache_key) { + *cached + } else { let alloc = self .font - .allocate_glyph_uncached( - atlas, - metrics, - &glyph_info, - bin, - (&metrics.location).into(), - ) + .allocate_glyph_uncached(atlas, metrics, glyph_id, bin, (&metrics.location).into()) .unwrap_or_default(); self.glyph_alloc_cache.insert(cache_key, alloc); - (alloc, h_pos_round) - } + alloc + }; + + (alloc, h_pos_round) } } /// Positioning info for a single glyph, ready for atlas allocation. #[derive(Clone, Copy, Debug)] pub(crate) struct ShapedGlyph { - pub glyph_id: skrifa::GlyphId, - - /// How far the cursor advances after this glyph, in physical pixels. - pub advance_width_px: f32, + pub glyph_id: GlyphId, /// Horizontal position of the glyph origin, in physical pixels. pub h_pos: f32, diff --git a/crates/epaint/src/text/text_layout.rs b/crates/epaint/src/text/text_layout.rs index 4791abb63..d0cdeba2e 100644 --- a/crates/epaint/src/text/text_layout.rs +++ b/crates/epaint/src/text/text_layout.rs @@ -259,6 +259,8 @@ fn layout_shaped_run( ff.styled_metrics(ctx.pixels_per_point, ctx.font_size, &Default::default()) }) .unwrap_or_default(); + let advance_width_px = + glyph_info.advance_width_unscaled.0 * fallback_metrics.px_scale_factor; let (glyph_alloc, physical_x) = if let Some(ff) = font.fonts_by_id.get_mut(&fallback_key) { ff.allocate_glyph( @@ -266,8 +268,6 @@ fn layout_shaped_run( &fallback_metrics, &ShapedGlyph { glyph_id: glyph_info.id.unwrap_or(skrifa::GlyphId::NOTDEF), - advance_width_px: glyph_info.advance_width_unscaled.0 - * fallback_metrics.px_scale_factor, h_pos: paragraph.cursor_x_px, is_cjk: is_cjk(chr), }, @@ -279,7 +279,7 @@ fn layout_shaped_run( paragraph.glyphs.push(Glyph { chr, pos: pos2(physical_x as f32 / ctx.pixels_per_point, f32::NAN), - advance_width: glyph_alloc.advance_width_px / ctx.pixels_per_point, + advance_width: advance_width_px / ctx.pixels_per_point, line_height: ctx.line_height, font_face_height: fallback_metrics.row_height, font_face_ascent: fallback_metrics.ascent, @@ -289,7 +289,7 @@ fn layout_shaped_run( section_index: ctx.section_index, first_vertex: 0, }); - paragraph.cursor_x_px += glyph_alloc.advance_width_px; + paragraph.cursor_x_px += advance_width_px; } else { let (mut glyph_alloc, physical_x) = if let Some(ff) = font.fonts_by_id.get_mut(&run.font_key) { @@ -298,7 +298,6 @@ fn layout_shaped_run( face_metrics, &ShapedGlyph { glyph_id, - advance_width_px, h_pos: paragraph.cursor_x_px + x_offset_px, is_cjk: is_cjk(chr), }, @@ -695,9 +694,9 @@ fn replace_last_glyph_with_overflow_character( 0.0 // TODO(emilk): heed paragraph leading_space 😬 }; - let replacement_glyph_width = glyph_info.advance_width_unscaled.0 - * font_face_metrics.px_scale_factor - / pixels_per_point; + let advance_width_px = + glyph_info.advance_width_unscaled.0 * font_face_metrics.px_scale_factor; + let replacement_glyph_width = advance_width_px / pixels_per_point; // Check if we're within width budget: if overflow_glyph_x + replacement_glyph_width <= job.effective_wrap_width() @@ -713,8 +712,6 @@ fn replace_last_glyph_with_overflow_character( &font_face_metrics, &ShapedGlyph { glyph_id: glyph_info.id.unwrap_or(skrifa::GlyphId::NOTDEF), - advance_width_px: glyph_info.advance_width_unscaled.0 - * font_face_metrics.px_scale_factor, h_pos: overflow_glyph_x * pixels_per_point, is_cjk: is_cjk(overflow_character), }, @@ -732,7 +729,7 @@ fn replace_last_glyph_with_overflow_character( row.glyphs.push(Glyph { chr: overflow_character, pos: pos2(physical_x as f32 / pixels_per_point, f32::NAN), - advance_width: replacement_glyph_alloc.advance_width_px / pixels_per_point, + advance_width: advance_width_px / pixels_per_point, line_height, font_face_height: font_face_metrics.row_height, font_face_ascent: font_face_metrics.ascent,