Skip to content

fix: pick a usable default font family on Linux CJK locales - #332

Merged
HMBSbige merged 2 commits into
HMBSbige:masterfrom
abc1763613206:fix/linux-default-font-family
Oct 8, 2026
Merged

HMBSbige merged 2 commits into
HMBSbige:masterfrom
abc1763613206:fix/linux-default-font-family

Conversation

@abc1763613206

Copy link
Copy Markdown
Contributor

写字母显示成小型大写,例如 stun.miwifi.com → STUN.MIWIFI.COM、Unknown → UNKNOWN。中文字符不受影响,因为它们走的是按字符回退的路径。en_US/C locale 下正常。
compare-zh_CN

原因

  1. Avalonia 的 FontManagerImpl.GetDefaultFontFamilyName() 直接返回 SKTypeface.Default.FamilyName(FontManagerImpl.cs#L18-L22)。
  2. Skia(SkiaSharp 3.119.4 对应的 m119)的 fontconfig 后端在按名字匹配后,会再检查匹配结果的 family 是否出现在请求 pattern 的 family 列表里,但只看前 16 个(AnyMatching 的 maxId = 16,用于 onMatchFamilyStyle)。
  3. 中文 locale 下,fontconfig 会按语言优先选中 Noto Sans CJK SC,fc-match sans-serif 的结果也是它。但 sans-serif 展开后有一百多个别名,Noto Sans CJK SC 排在一百多位,于是 Skia 判定匹配失败,SKTypeface.Default 变成空名字的空字体。
  4. 默认字体名为空时,Avalonia 退回到 SystemFonts[0],也就是按字母序排第一的已安装字体(FontManager.cs#L470-L473),所以结果完全取决于用户装了哪些字体。

修改

仅当 SKTypeface.Default.FamilyName 为空时,用 SKFontManager.Default.MatchCharacter('A') 取一个覆盖拉丁字符的字体,并通过 FontManagerOptions.DefaultFamilyName 交给 Avalonia。按字符匹配的路径不做上述 family 检查,并且同样遵循 locale,结果与 fc-match sans-serif 一致:

locale fc-match sans-serif MatchCharacter('A')
zh_CN Noto Sans CJK SC Noto Sans CJK SC
zh_TW Noto Sans CJK TC Noto Sans CJK TC
ja_JP Noto Sans CJK JP Noto Sans CJK JP
en_US Noto Sans Noto Sans

默认字体本来就正常的环境(Windows、macOS、Linux 的 en_US 等)不受影响,此时返回 null,Avalonia 照常走原来的逻辑。

abc1763613206 and others added 2 commits October 5, 2026 17:16
Skia's fontconfig backend only accepts a match among the first 16 family
aliases of the request. Under CJK locales (zh_CN, zh_TW, ja_JP, ...)
fontconfig prefers Noto Sans CJK by language, but that family sits far
behind the first 16 sans-serif aliases, so Skia rejects the match and
SKTypeface.Default comes back with an empty family name. Avalonia then
falls back to SystemFonts[0], the alphabetically first installed family
(e.g. the decorative "Abydos"), and renders all Latin text with it.

When SKTypeface.Default is empty, ask the font manager for a font that
covers Latin text instead. That follows the locale the same way
`fc-match sans-serif` does, and changes nothing where the default
typeface already resolves.
@HMBSbige
HMBSbige merged commit 7a202f6 into HMBSbige:master Oct 8, 2026
@abc1763613206
abc1763613206 deleted the fix/linux-default-font-family branch October 8, 2026 07:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants