1

Qt 的字体渲染问题

 2 years ago
source link: https://blog.lilydjwg.me/2022/3/8/qt-font-issues.216133.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

GUI 程序我现在依然倾向于 GTK,因为虽然 Qt 拥有良好的跨平台性,但可能是太注重跨平台性了,在 Linux 平台上反而有一些水土不服的问题。

字体太多,支持太少

你可能觉得,系统上字体太少,所以经常会遇到不常见的字符无法显示的情况。然而对于 Qt 来说,字体越多,反而越容易遇到个别字符不能显示的情况。

这是我的 /etc/fonts/conf.d/66-qt.conf 中的一段。因为顺序的原因,我只能放到 /etc 下。除了针对 sans-serif 配置外,我也有同样的配置应用于 serif 和 monospace。

66-qt.conf
<fontconfig>
<!-- Adjust font order for Qt applications -->
<alias>
<family>sans-serif</family>
<prefer>
<!-- 格拉哥里字母:Ⰽⱁⱀⱄⱅⰰⱀⱅⰹⱀ Ⰹⱍⰹⰳⱁⰲ -->
<family>Noto Sans Glagolitic</family>
<!-- 爪哇文:꧁   ꧂ -->
<family>Noto Sans Javanese</family>
<!-- 西夏文:𗷲𗒅 -->
<family>Noto Serif Tangut</family>
<!-- 埃及象形文字:𓁹 -->
<family>Noto Sans Egyptian Hieroglyphs</family>
<!-- 苏美尔楔形文字:𒆠𒂗𒂠 -->
<family>Noto Sans Cuneiform</family>
<!-- 中日韩统一表意文字扩展 C:𫚥 -->
<family>HanaMinB</family>
<!-- 拉让文:ꥃ -->
<family>Noto Sans Rejang</family>
<!-- 越南傣文:ꪀꪑ -->
<family>Noto Sans Tai Viet</family>
<!-- 切罗基文:ꮳꮧꮢ ᨣ -->
<family>Noto Sans Cherokee</family>
<!-- 老傣仂文:ᨣ -->
<family>Noto Sans Tai Tham</family>
<!-- 安纳托利亚象形文字:𔘓 -->
<family>Noto Sans Anatolian Hieroglyphs</family>
<!-- 马姆穆文补充:𖤍  -->
<family>Noto Sans Bamum</family>
<!-- 图标字体(PUA): -->
<family>OperatorMonoSSmLig Nerd Font</family>
<!-- 巴塔克文:ᯤ -->
<family>Noto Sans Batak</family>
<!-- 古北欧文:ᛋᛖᚱᚣᚨᛚᚳᚨᚾᛞᛚᛖ -->
<family>Noto Sans Runic</family>
</prefer>
</alias>
</fontconfig>

这个配置的意思是,把这些字体的优先级提高一些。当使用 fontconfig 的程序要显示字符的时候,它会指定一个模式,匹配到一个字体列表。渲染文字的时候,就可以遍历这个列表,直到找到可以显示这个字符的字体,所以一般来说,只要系统上装了对应字符的字体,它就能显示出来。

但是 Qt 额外地需要这个配置,因为 Qt 只会检查列表中的前255项。而世界上的不同文字那么多,所以想要能够显示它们,就得有一堆字体。比如 noto-fonts 这个包里就有614个字体文件,远超 Qt 支持的数量。总有些奇奇怪怪的文字被网友用来当颜文字,或者挂在名字上彰显个性。不这么调整一下,Qt 遇到了就只能「吃豆腐」了。

当一个字符显示不出来的时候,那么怎么显示好呢?一般会显示成某种方框。Pango火狐会将该字符的 Unicode 码点以十六进制的形式显示在方框里边,这样虽然不知道这个字符长什么样子,但至少知道它是哪个字符,也知道多块豆腐是不是同一字符,在不能复制字符本身的时候很有用。比如当它出现在求助者的截图里的时候,比如当它出现在不能复制的地方的时候。

然而 Qt 不这样做。管你什么字符,Qt 统一显示为空心方框。从视觉上完全无法知晓它到底是什么字符,要是复制不到的话,就别想弄明白你缺什么字体了。

PS: Matrix 客户端 fluffychat 的 Web 版,使用的是 Fluffy 图形界面库,即使在 Web 版,文字渲染依然完全是自己做的。不管浏览器的设置不管系统的设置,豆腐块是带叉号的方框,还不能选中,十分讨厌。

非 BMP 字符

所有使用 UTF-16 的平台(Java、JavaScript、Windows、Qt),外加 MySQL 容易遇到的一个问题:非 BMP 字符(也就是那些 U+FFFF 之后的字符)会被当作是两个字符处理。随着 emoji 的流行,大家应该都修了不少。然而,Qt 在展示非 BMP 字符的时候,你可以选中半个字符。如果不小心漏掉半个的话,复制出来的半个字符就会变成问号(还好不是 GBK 时代那样弄乱后续所有字符)。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK