GUI 程序我现在依然倾向于 GTK,因为虽然 Qt 拥有良好的跨平台性,但可能是太注重跨平台性了,在 Linux 平台上反而有一些水土不服的问题。
字体太多,支持太少
你可能觉得,系统上字体太少,所以经常会遇到不常见的字符无法显示的情况。然而对于 Qt 来说,字体越多,反而越容易遇到个别字符不能显示的情况。
这是我的 /etc/fonts/conf.d/66-qt.conf
中的一段。因为顺序的原因,我只能放到 /etc 下。除了针对 sans-serif 配置外,我也有同样的配置应用于 serif 和 monospace。
<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 时代那样弄乱后续所有字符)。
font features
一些字体可以通过 fontconfig 设置 fontfeatures 属性来启用(或者禁用)一些特性,比如连字,带斜杠的 0,小型大写字母,居中的中文标点,等等。Pango 很早就支持了,火狐最近也支持了,但 Qt 那边依旧没啥动静。(感谢 Coelacanthus 的评论。)