Fonts

#默认字体

每个应用都从主题自带的一套 UI 字体和等宽字体开始:

用途字体字号
UI 文本.SystemUIFont16px
代码/等宽macOS:Menlo,Windows:Consolas,Linux:DejaVu Sans Mono13px

编辑器使用 mono_font_familymono_font_size 绘制代码,详见 Editor

#系统字体

桌面应用可以直接按名称使用操作系统已安装的任意字体,无需打包、无需配置。GPUI 会实时向系统字库解析(macOS 用 CoreText,Windows 用 DirectWrite,Linux 用 fontconfig)。

div().font_family("Segoe UI")

Editor::new(&editor).font_family("JetBrains Mono")

各平台常见字体举例:

  • macOS:SF ProHelveticaArialTimes New RomanMenloMonaco
  • Windows:Segoe UIArialConsolasCourier New
  • Linux:Noto SansDejaVu SansLiberation SansDejaVu Sans Mono

如果名称与已安装字体不匹配,GPUI 会静默回退——请在每个目标平台上确认准确的 family 名称。

#通过 Theme 修改字体

Theme 全局量上设置应用级字体,然后同步到底层:

Theme::global_mut(cx).font_family = "Inter".into();
Theme::global_mut(cx).mono_font_family = "JetBrains Mono".into();
Theme::global_mut(cx).font_size = px(18.);
Theme::sync_base(cx);
window.refresh();

font_size 同时是应用缩放控制——Root 会调用 window.set_rem_size(cx.theme().font_size),因此基于 rem 的间距会跟随缩放。详见编码指南

#元素级覆盖

任何元素都可以在不改动主题的情况下覆盖字体:

div()
    .font_family("JetBrains Mono")
    .text_size(px(15.))
    .font_weight(FontWeight::BOLD)

这些就是普通的 Styled 方法,与样式链的其余部分组合使用。

#打包自定义字体

用户系统中没有的字体必须打包,并在首帧之前注册到文本系统:

cx.text_system()
    .add_fonts(vec![Cow::Borrowed(
        include_bytes!("../fonts/MyFont-Regular.ttf").as_slice(),
    )])
    .expect("Failed to load fonts");

之后照常用 family 名称引用:

Theme::global_mut(cx).font_family = "MyFont".into();
Theme::sync_base(cx);

Web 版画廊就是这样打包 InterJetBrains MonoNotoSansSCNotoEmoji 的,参见 crates/story-web/src/lib.rs

#主题 JSON 配置

字体与字号也可以来自主题文件:

{
    "font.family": "Inter",
    "font.size": 16,
    "mono_font.family": "JetBrains Mono",
    "mono_font.size": 13
}

ThemeRegistry 加载:

ThemeRegistry::watch_dir(PathBuf::from("./themes"), cx, move |cx| {
    if let Some(theme) = ThemeRegistry::global(cx).themes().get(&theme_name).cloned() {
        Theme::global_mut(cx).apply_config(&theme);
    }
});

完整配置说明参见 Theme

#WebAssembly 说明

浏览器不会向 WASM 应用暴露系统字体。在 gpui-kit.com/gallery/ 运行的 story-web 画廊必须打包它用到的每一种字体,并在 Theme::change 之后重新 声明,否则文本系统会 panic。桌面应用完全不需要这一步。