宇宙纪元

hinder110 的思考、读书与代码札记。

0%

Linux 字体配置完全指南——从 fontconfig 到桌面美化

字体的四层结构

Linux 桌面没有「设置 → 字体」一键搞定。字体的配置分布在四个独立的层面,各管各的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──────────────────────────────────────┐
│ 应用硬指定字体 │
│ 如 WezTerm 写死 JetBrainsMono NF │
│ 最优先,fontconfig 管不了 │
└──────────────────────────────────────┘
↓ 如果应用没说具体字体名
┌──────────────────────────────────────┐
│ 桌面框架字体 (GTK / Qt) │
│ GTK: ~/.config/gtk-3.0/settings.ini │
│ Qt: ~/.config/qt5ct/qt5ct.conf │
└──────────────────────────────────────┘
↓ 请求传到 fontconfig
┌──────────────────────────────────────┐
│ fontconfig — 字体匹配引擎 │
│ ~/.config/fontconfig/fonts.conf │
│ 别名 / 语言映射 / 字体替换 / 渲染设置 │
└──────────────────────────────────────┘
↓ fontconfig 找到字体文件
┌──────────────────────────────────────┐
│ 字体文件本身 │
│ /usr/share/fonts/ │
│ ~/.local/share/fonts/ │
└──────────────────────────────────────┘

理解这四层,就不会问「为什么改了 fontconfig 我的终端字体没变」——因为终端在第 1 层就写死了。


fontconfig 能做什么

fontconfig 是 Linux 字体系统的核心引擎。它不是应用,是一个库——所有 GTK/Qt/浏览器在需要渲染文字时都调用它。

配置文件放在 ~/.config/fontconfig/fonts.conf,XML 格式。主要能干四件事:

1. 设定别名(Fallback 链)

当程序说「我要 sans-serif」时,fontconfig 告诉你应该给哪个字体:

1
2
3
4
5
6
7
<alias>
<family>sans-serif</family>
<prefer>
<family>MiSans</family>
<family>Noto Sans CJK SC</family>
</prefer>
</alias>

2. 按语言分派字形

Linux 装了多个 CJK 字体时,经常把中文的「门」「复」「直」显示成日文的字形。按语言精确分配:

1
2
3
4
5
6
<match target="pattern">
<test name="lang" compare="contains"><string>zh-tw</string></test>
<edit name="family" mode="prepend" binding="strong">
<string>LXGW WenKai Screen</string>
</edit>
</match>

3. 劫持商业字体(最实用的功能)

浏览网页或打开 Windows 文档时,把网页请求的 微软雅黑ArialSimSun 全部拦截,换成自己系统里的高清字体:

1
2
3
4
5
6
<match target="pattern">
<test name="family" qual="any"><string>Microsoft YaHei</string></test>
<edit name="family" mode="assign" binding="strong">
<string>MiSans</string>
</edit>
</match>

这样打开任何中文网站,眼不见为净——再也没有中易宋体的锯齿和微软雅黑的过时骨骼。

4. 渲染设置

1
2
3
4
5
6
7
8
<match target="font">
<edit name="antialias" mode="assign"><bool>true</bool></edit>
<edit name="hinting" mode="assign"><bool>true</bool></edit>
<edit name="hintstyle" mode="assign"><const>hintslight</const></edit>
<edit name="rgba" mode="assign"><const>rgb</const></edit>
<edit name="lcdfilter" mode="assign"><const>lcddefault</const></edit>
<edit name="embeddedbitmap" mode="assign"><bool>false</bool></edit>
</match>
  • hintslight — 轻度微调,适合高分屏
  • rgba=rgb — 标准 LCD 次像素排布
  • embeddedbitmap=false — 禁用点阵字,消灭旧宋体的锯齿毛边

实战:确认配置生效

改完配置后必须刷新缓存:

1
fc-cache -fv

然后用 fc-match 验证每一项:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 默认字体族
fc-match sans-serif # 应该返回你设的首选
fc-match serif
fc-match monospace

# 语言映射
fc-match sans-serif:lang=zh-tw
fc-match sans-serif:lang=ja

# 字体劫持
fc-match "Microsoft YaHei" # 应该被换成你的字体
fc-match "SimSun"
fc-match "Arial"

命令行验证通过,重启应用就能看到效果。


推荐的字体组合

经过多轮对比和实战,这里给出一套适合中文用户的字体组合:

用途 字体 特点
无衬线 UI MiSans 小米开源,字形现代化,屏幕阅读舒适
衬线阅读 LXGW WenKai / 霞鹜文楷 霞鹜基于 Klee One 制作,温润有书写感
等宽 / 终端 Maple Mono NF CN 圆角等宽,带 Nerd Font 图标,中文支持好

安装

1
paru -S otf-misans ttf-lxgw-wenkai-screen maple-mono-nf-cn

配置

完整配置文件我放在了 GitHub: emoeem/fontconfig,核心思路和上面一致——别名 → 语言映射 → 商业字体劫持 → 渲染设置。


常见坑

改了配置不生效

先用 fc-cache -fv 刷新缓存,再 fc-match 验证,最后重启应用。有些应用(如浏览器)会缓存字体信息,彻底关掉再开才行。

Noto CJK 怎么总是抢优先权

Noto 系列字体自带完整的语言元数据,fontconfig 匹配时会给高分。单靠 mode="prepend" 不够——加 binding="strong" 才能压住。

终端字体为什么没变

你的终端模拟器(Kitty/Alacritty/WezTerm)一般在自身配置文件里写了 family = "xxx"——这是硬指定,fontconfig 插不了手。想改终端字体就去改终端的 config。

桌面环境(DMS/KDE/GNOME)的界面字体怎么改

  • GNOME: gsettings set org.gnome.desktop.interface font-name 'xxx 10'
  • GTK 应用: 改 ~/.config/gtk-3.0/settings.ini
  • Qt/Quickshell/DMS: 改其自身的 settings.json

它们都在 fontconfig 之上,先于 fontconfig 决定了请求什么字体族。


写在最后

Linux 的字体配置看起来散乱——四个层面,多种格式——但核心逻辑极其一致:每一层只管自己那一亩三分地,通过 fontconfig 这个统一的匹配引擎连接到实际的字体文件。

理解了这个,就不会迷茫。你知道改了 fontconfig 影响哪里,知道 DMS 的字体设置为什么独立,也知道 WezTerm 为什么不听话。

Linux 不是替你选择,是给你选择。字体是第一个你能完全按自己审美把控的东西。