Skip to content

fix(shell): 修复 #367 - 使用 msyh.ttc 时部分菜单项显示 "□"#371

Open
mc-yzy15 wants to merge 1 commit into
std-microblock:masterfrom
mc-yzy15:fix/font-fallback-with-msyh
Open

fix(shell): 修复 #367 - 使用 msyh.ttc 时部分菜单项显示 "□"#371
mc-yzy15 wants to merge 1 commit into
std-microblock:masterfrom
mc-yzy15:fix/font-fallback-with-msyh

Conversation

@mc-yzy15

Copy link
Copy Markdown

复现

font_path_main 改为微软雅黑 msyh.ttc 后,回收站和图片文件的
右键菜单里部分选项会渲染成 (fontstash 的 .notdef 字形)。
默认配置(segoeui.ttf)正常。

根因

config::apply_fonts_to_nvg 一直直接委托给
ui::register_default_windows_font_suite,其内部回退链写死成:
main → fallback → system

这套设计基于一个隐含假设:用户配置的 main 是 Segoe UI(Latin),
fallback 是 msyh(中文)。换句话说——靠系统已经默认帮你把 Latin
和 CJK 拼好了。

但用户改了 font_path_main = msyh.ttc 之后,假设就破了:

  • main = msyh.ttc
  • fallback = msyh.ttc(用户没改这条,默认还是 msyh.ttc)
  • system = Segoe UI

main 和 fallback 两个节点都是同一个 msyh.ttc,没有任何拉丁/符号
字体兜底
。Shell 扩展菜单项的字符串里会夹带一些普通 CJK
之外的特殊 Unicode 字符(部分扩展程序用到的私有区符号、
半角连字、键盘上标之类的),这些字符在 msyh.ttc 里压根没有。
原来的设计里指望 Segoe UI 兜底,但现在 fallback 链里的
「system」压根不会被走到——因为「fallback」先于「system」,
且 fallback 自己就找不到、循环到下一个还是找不到就直接 break。

结果就是 .notdef → 一坨方框。

顺带还有个小问题:msyh.ttc 是个集合字体,index 0 是「Microsoft YaHei」
普通版,index 1 是「Microsoft YaHei UI」。之前的实现始终用 index 0,
但 UI 场景下用 YaHei UI 的字面度量和字形间距其实更合适。把它一起修了。

修复

不再委托给 register_default_windows_font_suite,直接在
apply_fonts_to_nvg 里手工注册四个字体族,固定把系统 Segoe UI
作为最终兜底:

字体族 来源 fallback_families
segoeui 系统 Segoe UI(硬加载,不依赖用户配置)
fallback 用户配置(msyh.ttc 时 collection_index=1) {"segoeui"}
main 用户配置 {"segoeui", "fallback"}
monospace 用户配置 {"main", "segoeui", "fallback"}

不管用户怎么折腾 main 和 fallback,Segoe UI 始终在「main」的
fallback 链上一步,特殊符号字符总能找到字形。fallback 系列也
新增了 segoeui 兜底。

变更

  • src/shell/config.cc 重写 apply_fonts_to_nvg
    • 新增 segoeui 字体族
    • 调整 fallback / main / monospacefallback_families
    • msyh.ttc 自动选 collection_index=1(YaHei UI)
    • 字重变体通过 add_with_system_variants lambda 复用
  • src/shell/config.cc 新增 <cctype> 头(文件名做大小写不敏感匹配)

close #367

原 apply_fonts_to_nvg 委托给 ui::register_default_windows_font_suite,
其回退链设计假设 main=Segoe UI(Latin) + fallback=msyh(CJK)。
当用户把 main 改成 msyh.ttc 时,main 和 fallback 两条线都指向 msyh.ttc,
没有任何拉丁/符号字体兜底。Shell 扩展菜单项中混入了少量特殊
Unicode 字符(不在 msyh.ttc 中),原本指望 Segoe UI 兜底,现在
兜底没了,直接渲染成 .notdef → "□"。

另外 msyh.ttc 集合里 index=1 是「Microsoft YaHei UI」,
字面度量和字形都更贴 UI 场景;之前的实现始终用 index=0
「Microsoft YaHei」普通版,菜单里看着略偏大、有些字间距也对不齐。

变更:
- src/shell/config.cc: 重写 apply_fonts_to_nvg
  - 新增独立的 "segoeui" 字体族,从系统字体目录直接加载 segoeui.ttf
    及其字重变体(semilight / light / semibold / bold)
  - "fallback" 的 fallback_families 设为 {"segoeui"},确保兜底
  - "main" 的 fallback_families 设为 {"segoeui", "fallback"},
    改 CJK 字体也不会再丢掉拉丁/符号覆盖
  - "monospace" 的 fallback_families 设为 {"main", "segoeui", "fallback"}
  - 检测到 fallback 路径是 msyh.ttc 时 collection_index=1
    (选 YaHei UI 而非普通 YaHei)
- src/shell/config.cc: 新增 <cctype> 头(用 std::tolower 做大小写不敏感匹配)

close std-microblock#367
@mc-yzy15

Copy link
Copy Markdown
Author

我承认此PR是由AI进行编写,但PR中的内容代码均为我个人进行编写。

@mc-yzy15

Copy link
Copy Markdown
Author

在进行排查的时候,我使用了辅助的AI模型GPT5.5。

@mc-yzy15

Copy link
Copy Markdown
Author

代码编写使用Cursor完成,使用的模型是Claude Sonnet。

@mc-yzy15

Copy link
Copy Markdown
Author

Cursor 仅作为辅助,为我提供了一个排查整个代码仓库的简便工具。

随后在代码编写方面,先由我完成部分修复代码的编写,最后再由 Claude Sonnet 读取我修复的部分代码并向我提出建议,由我们共同协作完成这部分代码修复。

@mc-yzy15

Copy link
Copy Markdown
Author

但由于一些原因,在提交的时候并没有加上协作者。

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.

使用微软雅黑作为主字体时,部分右键菜单选项会出现“□”

1 participant