From 75067c94adb6e78f5b57d9012560bd8eb482add2 Mon Sep 17 00:00:00 2001 From: Bennet Bo Fenner Date: Thu, 9 Oct 2025 18:43:37 +0200 Subject: [PATCH] gpui: Fix ascent/descent calculation on macOS (#39886) As you can see in the image, we were previously returning different `ascent`s/`descent`s when a line would/would not contain an Emoji. image --- CoreTexts `CTLineGetTypographicBounds` seems to return a different ascent/descent depending on if an Emoji is there or not AFAIK it is not documented if this is intended behaviour or not. For us it is undesirable, as typing an Emoji causes the line to be shifted to the bottom, see here: https://github.com/user-attachments/assets/2ad1c82e-6297-48ac-a522-fb382ea56eea --- Instead of using `CTLineGetTypographicBounds` to resolve the ascent/descent, we look at every run and choose the maximum ascent/descent. This matches how it [works on Linux](https://github.com/zed-industries/zed/blob/f1d17fcfbef41690fdeb523f0fbddc7c406c5ad6/crates/gpui/src/platform/linux/text_system.rs#L452) Release Notes: - Fixed an issue on macOS where typing an emoji on a line would cause the line to shift downwards by a few pixels --- crates/gpui/src/platform/mac/text_system.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/gpui/src/platform/mac/text_system.rs b/crates/gpui/src/platform/mac/text_system.rs index 505c665dedd0eabd9327928b700b80ee273bd118..aa9c5850d5375cad41166161ba595c3fab85d457 100644 --- a/crates/gpui/src/platform/mac/text_system.rs +++ b/crates/gpui/src/platform/mac/text_system.rs @@ -430,6 +430,8 @@ impl MacTextSystemState { fn layout_line(&mut self, text: &str, font_size: Pixels, font_runs: &[FontRun]) -> LineLayout { // Construct the attributed string, converting UTF8 ranges to UTF16 ranges. let mut string = CFMutableAttributedString::new(); + let mut max_ascent = 0.0f32; + let mut max_descent = 0.0f32; { string.replace_str(&CFString::new(text), CFRange::init(0, 0)); let utf16_line_len = string.char_len() as usize; @@ -451,6 +453,11 @@ impl MacTextSystemState { let font: &FontKitFont = &self.fonts[run.font_id.0]; + let font_metrics = font.metrics(); + let font_scale = font_size.0 / font_metrics.units_per_em as f32; + max_ascent = max_ascent.max(font_metrics.ascent * font_scale); + max_descent = max_descent.max(-font_metrics.descent * font_scale); + unsafe { string.set_attribute( cf_range, @@ -508,8 +515,8 @@ impl MacTextSystemState { runs, font_size, width: typographic_bounds.width.into(), - ascent: typographic_bounds.ascent.into(), - descent: typographic_bounds.descent.into(), + ascent: max_ascent.into(), + descent: max_descent.into(), len: text.len(), } }