@@ -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"] }
@@ -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();
@@ -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(