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