1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-28 07:23:13 -04:00
This commit is contained in:
Emil Ernerfeldt
2026-03-28 17:30:27 +01:00
parent cc560acc2b
commit 1e259d7344
2 changed files with 64 additions and 57 deletions

View File

@@ -556,7 +556,6 @@ impl FontFace {
glyph_id,
advance_width_px,
h_pos,
y_offset_points,
is_cjk,
} = *shaped;
@@ -574,28 +573,28 @@ impl FontFace {
if let Some(cached) = self.glyph_alloc_cache.get(&cache_key) {
let mut alloc = *cached;
alloc.advance_width_px = advance_width_px;
alloc.uv_rect.offset.y += y_offset_points;
return (alloc, h_pos_round);
(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 = self
.font
.allocate_glyph_uncached(
atlas,
metrics,
&glyph_info,
bin,
(&metrics.location).into(),
)
.unwrap_or_default();
self.glyph_alloc_cache.insert(cache_key, alloc);
(alloc, h_pos_round)
}
let glyph_info = GlyphInfo {
id: Some(glyph_id),
advance_width_unscaled: OrderedFloat(advance_width_px / metrics.px_scale_factor),
};
let mut allocation = self
.font
.allocate_glyph_uncached(atlas, metrics, &glyph_info, bin, (&metrics.location).into())
.unwrap_or_default();
// Cache the allocation WITHOUT the shaper y_offset (which varies per call)
self.glyph_alloc_cache.insert(cache_key, allocation);
// Apply shaper y_offset after caching — the offset varies per call site
// so we cache the base allocation without it.
allocation.uv_rect.offset.y += y_offset_points;
(allocation, h_pos_round)
}
}
@@ -610,9 +609,6 @@ pub(crate) struct ShapedGlyph {
/// Horizontal position of the glyph origin, in physical pixels.
pub h_pos: f32,
/// Vertical offset from the baseline, in UI points.
pub y_offset_points: f32,
/// CJK glyphs skip subpixel positioning to save atlas space.
pub is_cjk: bool,
}

View File

@@ -214,7 +214,7 @@ fn layout_shaped_run(
{
let glyph_id = skrifa::GlyphId::new(info.glyph_id);
let cluster = info.cluster;
let mut x_advance_px = pos.x_advance as f32 * px_scale;
let mut advance_width_px = pos.x_advance as f32 * px_scale;
let x_offset_px = pos.x_offset as f32 * px_scale;
let y_offset_px = -(pos.y_offset as f32 * px_scale); // harfrust Y+ up → screen Y+ down
@@ -227,7 +227,7 @@ fn layout_shaped_run(
// Override the advance width to TAB_SIZE × space width.
if chr == '\t' {
let (_, space_info) = font.glyph_info(' ');
x_advance_px =
advance_width_px =
crate::text::TAB_SIZE as f32 * space_info.advance_width_unscaled.0 * px_scale;
}
@@ -259,17 +259,19 @@ fn layout_shaped_run(
ff.styled_metrics(ctx.pixels_per_point, ctx.font_size, &Default::default())
})
.unwrap_or_default();
let shaped = 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,
y_offset_points: 0.0,
is_cjk: is_cjk(chr),
};
let (glyph_alloc, physical_x) =
if let Some(ff) = font.fonts_by_id.get_mut(&fallback_key) {
ff.allocate_glyph(font.atlas, &fallback_metrics, &shaped)
ff.allocate_glyph(
font.atlas,
&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),
},
)
} else {
Default::default()
};
@@ -289,25 +291,30 @@ fn layout_shaped_run(
});
paragraph.cursor_x_px += glyph_alloc.advance_width_px;
} else {
let shaped = ShapedGlyph {
glyph_id,
advance_width_px: x_advance_px,
h_pos: paragraph.cursor_x_px + x_offset_px,
y_offset_points: y_offset_px / ctx.pixels_per_point,
is_cjk: is_cjk(chr),
};
let (glyph_alloc, physical_x) =
let (mut glyph_alloc, physical_x) =
if let Some(ff) = font.fonts_by_id.get_mut(&run.font_key) {
ff.allocate_glyph(font.atlas, face_metrics, &shaped)
ff.allocate_glyph(
font.atlas,
face_metrics,
&ShapedGlyph {
glyph_id,
advance_width_px,
h_pos: paragraph.cursor_x_px + x_offset_px,
is_cjk: is_cjk(chr),
},
)
} else {
Default::default()
};
// Apply shaper y_offset — this varies per glyph instance so it
// is not part of the cached ShapedGlyph / GlyphAllocation.
glyph_alloc.uv_rect.offset.y += y_offset_px / ctx.pixels_per_point;
paragraph.glyphs.push(Glyph {
chr,
pos: pos2(physical_x as f32 / ctx.pixels_per_point, f32::NAN),
advance_width: x_advance_px / ctx.pixels_per_point,
advance_width: advance_width_px / ctx.pixels_per_point,
line_height: ctx.line_height,
font_face_height: face_metrics.row_height,
font_face_ascent: face_metrics.ascent,
@@ -317,7 +324,7 @@ fn layout_shaped_run(
section_index: ctx.section_index,
first_vertex: 0,
});
paragraph.cursor_x_px += x_advance_px;
paragraph.cursor_x_px += advance_width_px;
}
}
}
@@ -698,17 +705,21 @@ fn replace_last_glyph_with_overflow_character(
{
// we are done
let shaped = 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,
y_offset_points: 0.0,
is_cjk: is_cjk(overflow_character),
};
let (replacement_glyph_alloc, physical_x) = font_face
.as_mut()
.map(|f| f.allocate_glyph(font.atlas, &font_face_metrics, &shaped))
.map(|f| {
f.allocate_glyph(
font.atlas,
&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),
},
)
})
.unwrap_or_default();
let font_metrics =