gpui: Fix macOS font render clipped bug again (#47001)

Continue #45957 #46906 to fix font render issue again.

Release Notes:

- Fixed macOS font render clipped bug when use `.SystemUIFont`.

| .SystemUIFont | .ZedMono |
| --- | --- |
| <img width="1034" height="978" alt="image"
src="https://github.com/user-attachments/assets/96b815a1-9484-4a38-8391-a4af3db51a36"
/> | <img width="1034" height="978" alt="image"
src="https://github.com/user-attachments/assets/1aaece42-9acd-47b0-a0a0-3cb425f40301"
/> |

```bash
cargo run -p gpui --example text
```

Test in Zed with `.ZedMono` font:

<img width="815" height="844" alt="image"
src="https://github.com/user-attachments/assets/1e44d186-cee5-4f54-910a-4c4602ca010e"
/>

With `.ZedSans`:

<img width="815" height="844" alt="image"
src="https://github.com/user-attachments/assets/1e502f3e-794c-4082-9faf-5a920adc1214"
/>

`Monaco`:

<img width="815" height="844" alt="image"
src="https://github.com/user-attachments/assets/906a3fd2-715a-4f53-b6fe-4614f4c6edab"
/>

`Menlo`:

<img width="815" height="844" alt="image"
src="https://github.com/user-attachments/assets/a8f8c302-2083-477c-ae72-f6e5c7f91d00"
/>
This commit is contained in:
Jason Lee authored and GitHub committed 2026-03-19 09:56:35 +00:00
1 parent 68174396d6
commit ed1397b166
3 files changed
+74 -5

No files matched your search

+1 -1
View File
@@ -144,7 +144,7 @@ windows = { version = "0.61", features = ["Win32_Foundation"] }
backtrace.workspace = true
collections = { workspace = true, features = ["test-support"] }
env_logger.workspace = true
gpui_platform.workspace = true
gpui_platform = { workspace = true, features = ["font-kit"] }
lyon = { version = "1.0", features = ["extra"] }
rand.workspace = true
scheduler = { workspace = true, features = ["test-support"] }
+62 -2
View File
@@ -1,6 +1,7 @@
#![cfg_attr(target_family = "wasm", no_main)]
use std::{
borrow::Cow,
ops::{Deref, DerefMut},
sync::Arc,
};
@@ -204,7 +205,7 @@ impl RenderOnce for CharacterGrid {
"❮", "<=", "!=", "==", "--", "++", "=>", "->", "🏀", "🎊", "😍", "❤️", "👍", "👎",
];
let columns = 11;
let columns = 20;
let rows = characters.len().div_ceil(columns);
let grid_rows = (0..rows).map(|row_idx| {
@@ -238,6 +239,7 @@ impl RenderOnce for CharacterGrid {
struct TextExample {
next_id: usize,
font_family: SharedString,
}
impl TextExample {
@@ -245,8 +247,33 @@ impl TextExample {
self.next_id += 1;
self.next_id
}
fn button(
text: &str,
cx: &mut Context<Self>,
on_click: impl Fn(&mut Self, &mut Context<Self>) + 'static,
) -> impl IntoElement {
div()
.id(text.to_string())
.flex_none()
.child(text.to_string())
.bg(gpui::black())
.text_color(gpui::white())
.active(|this| this.opacity(0.8))
.px_3()
.py_1()
.on_click(cx.listener(move |this, _, _, cx| on_click(this, cx)))
}
}
const FONT_FAMILIES: [&str; 5] = [
".ZedMono",
".SystemUIFont",
"Menlo",
"Monaco",
"Courier New",
];
impl Render for TextExample {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let tcx = cx.text_context();
@@ -265,7 +292,26 @@ impl Render for TextExample {
let step_up_6 = step_up_5 * type_scale;
div()
.font_family(self.font_family.clone())
.size_full()
.child(
div()
.bg(gpui::white())
.border_b_1()
.border_color(gpui::black())
.p_3()
.flex()
.child(Self::button(&self.font_family, cx, |this, cx| {
let new_family = FONT_FAMILIES
.iter()
.position(|f| *f == this.font_family.as_str())
.map(|idx| FONT_FAMILIES[(idx + 1) % FONT_FAMILIES.len()])
.unwrap_or(FONT_FAMILIES[0]);
this.font_family = SharedString::new(new_family);
cx.notify();
})),
)
.child(
div()
.id("text-example")
@@ -307,6 +353,15 @@ fn run_example() {
items: vec![],
}]);
let fonts = [include_bytes!(
"../../../assets/fonts/lilex/Lilex-Regular.ttf"
)]
.iter()
.map(|b| Cow::Borrowed(&b[..]))
.collect();
_ = cx.text_system().add_fonts(fonts);
cx.init_colors();
cx.set_global(GlobalTextContext(Arc::new(TextContext::default())));
@@ -323,7 +378,12 @@ fn run_example() {
))),
..Default::default()
},
|_window, cx| cx.new(|_cx| TextExample { next_id: 0 }),
|_window, cx| {
cx.new(|_cx| TextExample {
next_id: 0,
font_family: ".ZedMono".into(),
})
},
)
.unwrap();
+11 -2
View File
@@ -361,13 +361,22 @@ impl MacTextSystemState {
fn raster_bounds(&self, params: &RenderGlyphParams) -> Result<Bounds<DevicePixels>> {
let font = &self.fonts[params.font_id.0];
let scale = Transform2F::from_scale(params.scale_factor);
Ok(bounds_from_rect_i(font.raster_bounds(
let mut bounds: Bounds<DevicePixels> = bounds_from_rect_i(font.raster_bounds(
params.glyph_id.0,
params.font_size.into(),
scale,
HintingOptions::None,
font_kit::canvas::RasterizationOptions::GrayscaleAa,
)?))
)?);
// Add 3% of font size as padding, clamped between 1 and 5 pixels
// to avoid clipping of anti-aliased edges.
let pad =
((params.font_size.as_f32() * 0.03 * params.scale_factor).ceil() as i32).clamp(1, 5);
bounds.origin.x -= DevicePixels(pad);
bounds.size.width += DevicePixels(pad);
Ok(bounds)
}
fn rasterize_glyph(