gpui_wgpu: Reuse glyph image after measuring bounds (#63209)

Release Notes:

- Improved rasterization performance on Linux by caching glyphs after
measuring bounds.
This commit is contained in:
Jakub Konka authored and GitHub committed 2026-08-25 17:56:09 +00:00
1 parent f3c23ec56b
commit a90d3772f8
1 file changed
+14 -4
+14 -4
View File
@@ -6,7 +6,7 @@ use cosmic_text::{
};
use gpui::{
Bounds, DevicePixels, Font, FontFallbacks, FontFeatures, FontId, FontMetrics, FontRun, GlyphId,
LineLayout, Pixels, PlatformTextSystem, RenderGlyphParams, SUBPIXEL_VARIANTS_X,
IsZero as _, LineLayout, Pixels, PlatformTextSystem, RenderGlyphParams, SUBPIXEL_VARIANTS_X,
SUBPIXEL_VARIANTS_Y, ShapedGlyph, ShapedRun, SharedString, Size, TextRenderingMode, point,
size,
};
@@ -44,6 +44,7 @@ struct CosmicTextSystemState {
font_system: FontSystem,
scratch: ShapeBuffer,
swash_scale_context: ScaleContext,
pending_glyph_images: HashMap<RenderGlyphParams, swash::scale::image::Image>,
/// Contains all already loaded fonts, including all faces. Indexed by `FontId`.
loaded_fonts: Vec<LoadedFont>,
/// Caches the `FontId`s associated with a specific family to avoid iterating the font database
@@ -90,6 +91,7 @@ impl CosmicTextSystem {
font_system,
scratch: ShapeBuffer::default(),
swash_scale_context: ScaleContext::new(),
pending_glyph_images: HashMap::default(),
loaded_fonts: Vec::new(),
font_ids_by_family_cache: HashMap::default(),
system_font_fallback: system_font_fallback.to_string(),
@@ -106,6 +108,7 @@ impl CosmicTextSystem {
font_system,
scratch: ShapeBuffer::default(),
swash_scale_context: ScaleContext::new(),
pending_glyph_images: HashMap::default(),
loaded_fonts: Vec::new(),
font_ids_by_family_cache: HashMap::default(),
system_font_fallback: system_font_fallback.to_string(),
@@ -385,10 +388,14 @@ impl CosmicTextSystemState {
fn raster_bounds(&mut self, params: &RenderGlyphParams) -> Result<Bounds<DevicePixels>> {
let image = self.render_glyph_image(params)?;
Ok(Bounds {
let bounds = Bounds {
origin: point(image.placement.left.into(), (-image.placement.top).into()),
size: size(image.placement.width.into(), image.placement.height.into()),
})
};
if !bounds.is_zero() {
self.pending_glyph_images.insert(params.clone(), image);
}
Ok(bounds)
}
#[profiling::function]
@@ -401,7 +408,10 @@ impl CosmicTextSystemState {
anyhow::bail!("glyph bounds are empty");
}
let mut image = self.render_glyph_image(params)?;
let mut image = match self.pending_glyph_images.remove(params) {
Some(image) => image,
None => self.render_glyph_image(params)?,
};
let bitmap_size = glyph_bounds.size;
match image.content {
swash::scale::image::Content::Color | swash::scale::image::Content::SubpixelMask => {