在 Windows 看习惯 MacType 渲染之后的字体之后再看 Linux 下的字体总感觉细得发虚,很不习惯。字体的 Semibold 样式看着粗细正好,就想把它设为默认的粗细。搜了搜在 openSUSE 论坛 看到了一个同样需求的人,可是他也没找到解决办法,下面还有人回复说:“Linux 的默认字体都是为 4k 显示器准备的。拥有 4k 显示器你才配使用它……

  这真是个悲伤的故事……

  edit 2026-02-02: 通过 fontconfig 修改默认字重的方法很麻烦,而且很多程序不吃这个配置,还是修改字体文件最省事。今天问了下 Gemini,他直接抛了个 Python 脚本给我,不得不说有了 AI 之后真是方便好多。修改后的字体最好放在 /usr/share/fonts/ 下,KDE 的字体安装器会装到 /usr/local/share/fonts/ 里,Steam 不认。

from fontTools.ttLib import TTFont

def make_semibold_appear_regular(input_path, output_path):
# 1. 加载字体
font = TTFont(input_path)
print(f"正在处理: {input_path}")

# -------------------------------------------------
# 修改 OS/2 表 (Windows/通用 字重和选择位)
# -------------------------------------------------
if 'OS/2' in font:
os2 = font['OS/2']

# 将字重等级改为 400 (Standard Regular)
# 原本 SemiBold 通常是 600
print(f" - 修改 usWeightClass: {os2.usWeightClass} -> 400")
os2.usWeightClass = 400

# 修改 fsSelection (字体选择标志)
# 我们需要清除 Bold (bit 5),并勾选 Regular (bit 6)
# 0b01000000 = 64 (Regular)
print(" - 修改 fsSelection 标志为 Regular")
os2.fsSelection = 0b1000000

# -------------------------------------------------
# 修改 head 表 (Mac 样式标记)
# -------------------------------------------------
if 'head' in font:
# 清除 Bold (bit 0) 和 Italic (bit 1) 标记,设为 0 表示 Regular
print(" - 清除 head.macStyle (设为 0)")
font['head'].macStyle = 0

# -------------------------------------------------
# 修改 name 表 (字体的显示名称)
# -------------------------------------------------
# 我们需要遍历名称记录,把 "SemiBold" 改为 "Regular"
# 或者把 "MyFont SemiBold" 改为 "MyFont"
if 'name' in font:
print(" - 更新 name 表 (ID 1, 2, 4, 6, 16, 17)...")

# 常见 Name ID 说明:
# 1: Font Family Name (e.g. "Arial")
# 2: Font Subfamily Name (e.g. "Bold" -> 改为 "Regular")
# 4: Full Font Name (e.g. "Arial Bold" -> 改为 "Arial Regular")
# 6: PostScript Name (e.g. "Arial-Bold" -> 改为 "Arial-Regular")
# 16: Typographic Family Name (首选家族名)
# 17: Typographic Subfamily Name (首选子家族名)

for record in font['name'].names:
try:
# 获取解码后的字符串
name_str = record.toUnicode()
new_str = name_str

# 逻辑 A: 修改子家族名 (ID 2 & 17)
if record.nameID in [2, 17]:
if "SemiBold" in name_str or "Semibold" in name_str:
new_str = "Regular"
elif name_str == "Bold": # 防止它是Bold
new_str = "Regular"

# 逻辑 B: 修改完整名称和PS名称 (ID 4 & 6)
# 简单粗暴的替换,你可以根据需要调整
if "SemiBold" in name_str:
new_str = name_str.replace("SemiBold", "Regular")
elif "Semibold" in name_str:
new_str = name_str.replace("Semibold", "Regular")

# 如果名称发生了变化,则更新
if new_str != name_str:
record.string = new_str.encode(record.getEncoding())
print(f" [ID {record.nameID}] {name_str} -> {new_str}")

except UnicodeDecodeError:
pass # 忽略无法解码的旧记录

# 3. 保存新字体
font.save(output_path)
print(f"完成!已保存为: {output_path}")

# --- 运行示例 ---
# 请将 'SourceSans-SemiBold.ttf' 替换为你实际的文件名
if __name__ == "__main__":
input_font = "SarasaUiSC-SemiBold.ttf" # <--- 在这里修改你的输入文件名
output_font = "SarasaUiSC-Regular.ttf"

try:
make_semibold_appear_regular(input_font, output_font)
except Exception as e:
print(f"发生错误: {e}")
print("请确保文件名正确,且文件在当前目录下。")

这个是斜体的:

from fontTools.ttLib import TTFont

def convert_semibold_italic_to_italic(input_path, output_path):
print(f"正在加载字体: {input_path}")
font = TTFont(input_path)

# ===============================
# 1. 修改 OS/2 表 (Windows 属性)
# ===============================
if 'OS/2' in font:
os2 = font['OS/2']

# [关键] 将字重改为 400 (Regular)
print(f" - 修改 usWeightClass: {os2.usWeightClass} -> 400")
os2.usWeightClass = 400

# [关键] 修改 fsSelection
# 我们需要:保留 Italic (bit 0),清除 Bold (bit 5)
# 操作:(原值 & ~32) | 1
# 32 是 Bold 的位掩码,1 是 Italic 的位掩码
original_sel = os2.fsSelection
os2.fsSelection = (os2.fsSelection & ~0b100000) | 0b1
print(f" - 修改 fsSelection: {original_sel} -> {os2.fsSelection} (清除Bold, 确保Italic)")

# ===============================
# 2. 修改 head 表 (Mac 属性)
# ===============================
if 'head' in font:
head = font['head']
# macStyle: Bit 0 是 Bold, Bit 1 是 Italic
# 我们要清除 Bit 0 (Bold),确保 Bit 1 (Italic) 为 1
# 操作:(原值 & ~1) | 2
original_style = head.macStyle
head.macStyle = (head.macStyle & ~1) | 2
print(f" - 修改 head.macStyle: {original_style} -> {head.macStyle} (清除Bold, 确保Italic)")

# ===============================
# 3. 修改 name 表 (核心名称替换)
# ===============================
if 'name' in font:
print(" - 正在处理名称表 (Name Table)...")
# 常见 Name ID:
# 1: Family Name (Sarasa UI SC)
# 2: Subfamily Name (SemiBold Italic -> Italic)
# 4: Full Name (Sarasa UI SC SemiBold Italic -> Sarasa UI SC Italic)
# 6: PostScript Name (Sarasa-UI-SC-SemiBold-Italic -> Sarasa-UI-SC-Italic)

for record in font['name'].names:
try:
name_str = record.toUnicode()
original_str = name_str
new_str = name_str

# --- 替换逻辑 ---

# 情况 A: PostScript 名称 (ID 6) - 通常不允许有空格,用横杠连接
if record.nameID == 6:
new_str = new_str.replace("SemiBold-Italic", "Italic")
new_str = new_str.replace("SemiBold", "") # 防御性替换

# 情况 B: 子家族名 (ID 2, 17) - 这是我们在字体菜单里看到的“样式”
elif record.nameID in [2, 17]:
if "SemiBold Italic" in new_str:
new_str = "Italic"
elif "SemiBold" in new_str:
# 如果只写了 SemiBold (少见但可能),强行改为 Italic
new_str = "Italic"

# 情况 C: 完整名称和其他描述 (ID 1, 3, 4, etc.)
else:
# 替换带有空格的名称
if "SemiBold Italic" in new_str:
new_str = new_str.replace("SemiBold Italic", "Italic")
# 单独替换 SemiBold (注意处理空格,避免出现双空格)
if "SemiBold" in new_str:
new_str = new_str.replace(" SemiBold", "") # 尝试移除前面的空格
new_str = new_str.replace("SemiBold", "") # 兜底

# 最后的清理:如果替换导致多余空格,清理一下
new_str = " ".join(new_str.split())

# 如果是 PS Name,不能有空格,要严谨处理
if record.nameID == 6:
new_str = new_str.replace(" ", "")

# 写入更改
if new_str != original_str:
record.string = new_str.encode(record.getEncoding())
# 仅打印 ID 4 (全名) 和 ID 6 (PS名) 以减少刷屏,方便检查
if record.nameID in [4, 6]:
print(f" [ID {record.nameID}] {original_str} -> {new_str}")

except UnicodeDecodeError:
pass

# ===============================
# 4. 保存
# ===============================
font.save(output_path)
print("-" * 30)
print(f"成功!文件已保存至: {output_path}")
print("提示:安装前请先卸载旧的 'Sarasa UI SC Italic' (如果存在),并重启相关软件。")

# --- 执行 ---
if __name__ == "__main__":
# 请确保文件名与你目录下的文件完全一致
input_file = "SarasaUiSC-SemiBoldItalic.ttf"
output_file = "SarasaUiSC-Italic.ttf"

try:
convert_semibold_italic_to_italic(input_file, output_file)
except Exception as e:
print(f"发生错误: {e}")

** 以下是旧内容,现在不需要了。 **

  后来自己慢慢摸索到一个勉强能用的办法,就是在 fontconfig scan 的时候,把 Semibold 的字体的 fullname style weight 都换成 Regular 的,再把 Regular 的换成 Light 的,Light 的 的再换成 EXLight 的或者直接删掉。这样一般的程序默认的字重就是 Semibold 了。

获取字体文件 fullnameweight

❯ fc-query --format="%{fullname} %{weight}\\n" /usr/local/share/fonts/s/sarasa_term_sc_nerd_regular.ttf
Sarasa Term SC Nerd Regular,终端更纱黑体-简 Nerd Regular 80

❯ fc-query --format="%{fullname} %{weight}\\n" /usr/local/share/fonts/s/sarasa_term_sc_nerd_semibold.ttf
Sarasa Term SC Nerd Semibold,终端更纱黑体-简 Nerd Semibold 180

fontconfig 配置:

<match target="scan">
<test name="fullname"><string>Sarasa Term SC Nerd Regular</string></test>
<edit name="fullname"><string>Sarasa Term SC Nerd Light</string></edit>
<edit name="style"><string>Light</string></edit>
<edit name="weight"><int>50</int></edit>
</match>

<match target="scan">
<test name="fullname"><string>Sarasa Term SC Nerd Semibold</string></test>
<edit name="fullname"><string>Sarasa Term SC Nerd Regular</string></edit>
<edit name="style"><string>Regular</string></edit>
<edit name="weight"><int>80</int></edit>
</match>

  改完 fc-cache -f 就可以了,但 Telegram 不吃系统的 fontconfig,主要就是他的字体不好看,那就只能改用 telegram-desktop-userfonts 了。

  Chromium 系及 Electron 的应用还是会默认使用 Regular ,这点在这个回答中找到了解决办法。

<match target="pattern">
<test compare="eq" name="family"><string>Sarasa Term SC Nerd</string></test>
<edit mode="prepend" name="style"><string>Semibold</string></edit>
</match>

  但是自带字体的网页或 Electron 应用就没办法了,只能继续用 fontconfig 改字重/替换字体或是直接修改 CSS。比如 Discord 就可以用 BeautifulDiscord 修改 CSS。

discord-custom.css
:root:lang(zh-CN) {
--font-primary: "Sarasa UI SC", "Noto Color Emoji", sans-serif !important;
--font-display: "Sarasa UI SC", "Noto Color Emoji", sans-serif !important;
--font-headline: "Sarasa UI SC", "Noto Color Emoji" sans-serif !important;
--font-code: "Sarasa Term SC Nerd", "Noto Color Emoji", monospace !important;
}

下面是我的配置,用的是 Sarasa UI SCSarasa Term SC Nerd

~/.config/fontconfig/conf.d/20-replace-regular.conf
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
<fontconfig>

<match target="scan">
<test name="fullname"><string>Sarasa Term SC Nerd Regular</string></test>
<edit name="fullname"><string>Sarasa Term SC Nerd Light</string></edit>
<edit name="style"><string>Light</string></edit>
<edit name="weight"><int>50</int></edit>
</match>
<match target="scan">
<test name="fullname"><string>Sarasa Term SC Nerd Semibold</string></test>
<edit name="fullname"><string>Sarasa Term SC Nerd Regular</string></edit>
<edit name="style"><string>Regular</string></edit>
<edit name="weight"><int>80</int></edit>
</match>
<match target="scan">
<test name="fullname"><string>Sarasa UI SC</string></test>
<edit name="fullname"><string>Sarasa UI SC Light</string></edit>
<edit name="style"><string>Light</string></edit>
<edit name="weight"><int>50</int></edit>
</match>
<match target="scan">
<test name="fullname"><string>Sarasa UI SC Semibold</string></test>
<edit name="fullname"><string>Sarasa UI SC</string></edit>
<edit name="style"><string>Regular</string></edit>
<edit name="weight"><int>80</int></edit>
</match>

<match target="pattern">
<test compare="eq" name="family"><string>Sarasa UI SC</string></test>
<edit mode="prepend" name="style"><string>Semibold</string></edit>
</match>
<match target="pattern">
<test compare="eq" name="family"><string>Sarasa Term SC Nerd</string></test>
<edit mode="prepend" name="style"><string>Semibold</string></edit>
</match>

</fontconfig>

  对了,还要在 fonts.conf 里面把 hinting 关掉。

~/.config/fontconfig/fonts.conf
<match target="font">
<edit mode="assign" name="hinting">
<bool>false</bool>
</edit>
</match>
<match target="font">
<edit mode="assign" name="hintstyle">
<const>hintnone</const>
</edit>
</match>


参考链接:

  1. https://forum.suse.org.cn/t/c/14990
  2. https://unix.stackexchange.com/a/685529
  3. https://www.freedesktop.org/software/fontconfig/fontconfig-user.html