chore: Improve Font Rendering on Linux (#100)

* add zed plex sans

* .
This commit is contained in:
reya
2025-07-25 07:20:47 +07:00
committed by GitHub
parent 12168c6084
commit 91cca37d69
20 changed files with 321 additions and 64 deletions

11
crates/assets/Cargo.toml Normal file
View File

@@ -0,0 +1,11 @@
[package]
name = "assets"
version.workspace = true
edition.workspace = true
publish.workspace = true
[dependencies]
gpui.workspace = true
anyhow.workspace = true
log.workspace = true
rust-embed.workspace = true

59
crates/assets/src/lib.rs Normal file
View File

@@ -0,0 +1,59 @@
use anyhow::Context;
use gpui::{App, AssetSource, Result, SharedString};
use rust_embed::RustEmbed;
#[derive(RustEmbed)]
#[folder = "../../assets"]
#[include = "fonts/**/*"]
#[include = "brand/*"]
#[include = "icons/**/*"]
#[exclude = "*.DS_Store"]
pub struct Assets;
impl AssetSource for Assets {
fn load(&self, path: &str) -> Result<Option<std::borrow::Cow<'static, [u8]>>> {
Self::get(path)
.map(|f| Some(f.data))
.with_context(|| format!("loading asset at path {path:?}"))
}
fn list(&self, path: &str) -> Result<Vec<SharedString>> {
Ok(Self::iter()
.filter_map(|p| {
if p.starts_with(path) {
Some(p.into())
} else {
None
}
})
.collect())
}
}
impl Assets {
/// Populate the [`TextSystem`] of the given [`AppContext`] with all `.ttf` fonts in the `fonts` directory.
pub fn load_fonts(&self, cx: &App) -> anyhow::Result<()> {
let font_paths = self.list("fonts")?;
let mut embedded_fonts = Vec::new();
for font_path in font_paths {
if font_path.ends_with(".ttf") {
let font_bytes = cx
.asset_source()
.load(&font_path)?
.expect("Assets should never return None");
embedded_fonts.push(font_bytes);
}
}
cx.text_system().add_fonts(embedded_fonts)
}
pub fn load_test_fonts(&self, cx: &App) {
cx.text_system()
.add_fonts(vec![self
.load("fonts/plex-mono/ZedPlexMono-Regular.ttf")
.unwrap()
.unwrap()])
.unwrap()
}
}

View File

@@ -9,6 +9,7 @@ name = "coop"
path = "src/main.rs"
[dependencies]
assets = { path = "../assets" }
ui = { path = "../ui" }
identity = { path = "../identity" }
theme = { path = "../theme" }
@@ -34,7 +35,6 @@ serde.workspace = true
serde_json.workspace = true
itertools.workspace = true
dirs.workspace = true
rust-embed.workspace = true
log.workspace = true
smallvec.workspace = true
smol.workspace = true

View File

@@ -1,27 +0,0 @@
use anyhow::anyhow;
use gpui::{AssetSource, Result, SharedString};
use rust_embed::RustEmbed;
#[derive(RustEmbed)]
#[folder = "../../assets"]
pub struct Assets;
impl AssetSource for Assets {
fn load(&self, path: &str) -> Result<Option<std::borrow::Cow<'static, [u8]>>> {
Self::get(path)
.map(|f| Some(f.data))
.ok_or_else(|| anyhow!("could not find asset at path \"{}\"", path))
}
fn list(&self, path: &str) -> Result<Vec<SharedString>> {
Ok(Self::iter()
.filter_map(|p| {
if p.starts_with(path) {
Some(p.into())
} else {
None
}
})
.collect())
}
}

View File

@@ -1,9 +1,9 @@
use std::collections::BTreeSet;
use std::sync::Arc;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use anyhow::{anyhow, Error};
use asset::Assets;
use assets::Assets;
use auto_update::AutoUpdater;
#[cfg(not(target_os = "linux"))]
use global::constants::APP_NAME;
@@ -27,7 +27,6 @@ use smol::channel::{self, Sender};
use theme::Theme;
use ui::Root;
pub(crate) mod asset;
pub(crate) mod chatspace;
pub(crate) mod views;
@@ -183,6 +182,9 @@ fn main() {
// Run application
app.run(move |cx| {
// Load embedded fonts in assets/fonts
load_embedded_fonts(cx);
// Register the `quit` function
cx.on_action(quit);
@@ -318,6 +320,30 @@ fn main() {
});
}
fn load_embedded_fonts(cx: &App) {
let asset_source = cx.asset_source();
let font_paths = asset_source.list("fonts").unwrap();
let embedded_fonts = Mutex::new(Vec::new());
let executor = cx.background_executor();
executor.block(executor.scoped(|scope| {
for font_path in &font_paths {
if !font_path.ends_with(".ttf") {
continue;
}
scope.spawn(async {
let font_bytes = asset_source.load(font_path).unwrap().unwrap();
embedded_fonts.lock().unwrap().push(font_bytes);
});
}
}));
cx.text_system()
.add_fonts(embedded_fonts.into_inner().unwrap())
.unwrap();
}
fn quit(_: &Quit, cx: &mut App) {
log::info!("Gracefully quitting the application . . .");
cx.quit();

View File

@@ -390,13 +390,7 @@ impl From<ThemeColor> for Theme {
Theme {
font_size: px(15.),
font_family: if cfg!(target_os = "macos") {
".SystemUIFont".into()
} else if cfg!(target_os = "windows") {
"Segoe UI".into()
} else {
"FreeMono".into()
},
font_family: ".SystemUIFont".into(),
radius: px(5.),
mode,
colors,

View File

@@ -256,6 +256,7 @@ impl Root {
impl Render for Root {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let base_font_size = cx.theme().font_size;
let font_family = cx.theme().font_family.clone();
window.set_rem_size(base_font_size);
window_border().child(
@@ -263,7 +264,7 @@ impl Render for Root {
.id("root")
.relative()
.size_full()
.font_family(".SystemUIFont")
.font_family(font_family)
.bg(cx.theme().background)
.text_color(cx.theme().text)
.child(self.view.clone()),