Vertically center glyphs in Line::paint based on ascender/descender for line

Nathan Sobo created

Change summary

gpui/examples/text.rs          |  2 +-
gpui/src/font_cache.rs         |  4 ++--
gpui/src/platform/mac/fonts.rs |  7 ++++---
gpui/src/text_layout.rs        | 15 ++++++++++-----
zed/src/editor/buffer_view.rs  |  4 +---
5 files changed, 18 insertions(+), 14 deletions(-)

Detailed changes

gpui/examples/text.rs 🔗

@@ -2,7 +2,7 @@ use gpui::{
     color::ColorU,
     fonts::{Properties, Weight},
     platform::{current as platform, Runner},
-    Border, Element as _, Quad,
+    Element as _, Quad,
 };
 use log::LevelFilter;
 use simplelog::SimpleLogger;

gpui/src/font_cache.rs 🔗

@@ -132,8 +132,8 @@ impl FontCache {
     }
 
     pub fn line_height(&self, font_id: FontId, font_size: f32) -> f32 {
-        let bounding_box = self.metric(font_id, |m| m.bounding_box);
-        self.scale_metric(bounding_box.height(), font_id, font_size)
+        let height = self.metric(font_id, |m| m.bounding_box.height());
+        self.scale_metric(height, font_id, font_size)
     }
 
     pub fn cap_height(&self, font_id: FontId, font_size: f32) -> f32 {

gpui/src/platform/mac/fonts.rs 🔗

@@ -228,8 +228,6 @@ impl FontSystemState {
 
         let line = CTLine::new_with_attributed_string(string.as_concrete_TypeRef());
 
-        let width = line.get_typographic_bounds().width as f32;
-
         let mut utf16_chars = text.encode_utf16();
         let mut char_ix = 0;
         let mut prev_utf16_ix = 0;
@@ -268,8 +266,11 @@ impl FontSystemState {
             runs.push(Run { font_id, glyphs })
         }
 
+        let typographic_bounds = line.get_typographic_bounds();
         Line {
-            width,
+            width: typographic_bounds.width as f32,
+            ascent: typographic_bounds.ascent as f32,
+            descent: typographic_bounds.descent as f32,
             runs,
             font_size,
             len: char_ix + 1,

gpui/src/text_layout.rs 🔗

@@ -136,6 +136,8 @@ impl<'a> CacheKey for CacheKeyRef<'a> {
 #[derive(Default, Debug)]
 pub struct Line {
     pub width: f32,
+    pub ascent: f32,
+    pub descent: f32,
     pub runs: Vec<Run>,
     pub len: usize,
     pub font_size: f32,
@@ -191,12 +193,15 @@ impl Line {
         let mut colors = colors.iter().peekable();
         let mut color = ColorU::black();
 
+        let padding_top = (bounds.height() - self.ascent - self.descent) / 2.;
+        let baseline_origin = vec2f(0., padding_top + self.ascent);
+
         for run in &self.runs {
-            let bounding_box = ctx.font_cache.bounding_box(run.font_id, self.font_size);
-            let descent = ctx.font_cache.descent(run.font_id, self.font_size);
-            let max_glyph_width = bounding_box.x();
+            let max_glyph_width = ctx.font_cache.bounding_box(run.font_id, self.font_size).x();
+
             for glyph in &run.glyphs {
-                let glyph_origin = glyph.position - vec2f(0.0, descent);
+                let glyph_origin = baseline_origin + glyph.position;
+
                 if glyph_origin.x() + max_glyph_width < bounds.origin().x() {
                     continue;
                 }
@@ -217,7 +222,7 @@ impl Line {
                     font_id: run.font_id,
                     font_size: self.font_size,
                     id: glyph.id,
-                    origin: origin + glyph_origin + vec2f(0., bounding_box.y() / 2.),
+                    origin: origin + glyph_origin,
                     color,
                 });
             }

zed/src/editor/buffer_view.rs 🔗

@@ -893,9 +893,7 @@ impl BufferView {
     pub fn line_height(&self, font_cache: &FontCache) -> f32 {
         let settings = smol::block_on(self.settings.read());
         let font_id = font_cache.default_font(settings.buffer_font_family);
-        font_cache
-            .bounding_box(font_id, settings.buffer_font_size)
-            .y()
+        font_cache.line_height(font_id, settings.buffer_font_size)
     }
 
     pub fn em_width(&self, font_cache: &FontCache) -> f32 {