1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 22:53:14 -04:00

Simplify advance_width

This commit is contained in:
Emil Ernerfeldt
2026-03-28 17:42:51 +01:00
parent 1e259d7344
commit 83c03655d4
2 changed files with 25 additions and 50 deletions

View File

@@ -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<skrifa::GlyphId>,
pub(crate) id: Option<GlyphId>,
/// In [`skrifa`]s "unscaled" coordinate system.
pub advance_width_unscaled: OrderedFloat<f32>,
@@ -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<GlyphAllocation> {
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,

View File

@@ -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,