IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Qt 的字体渲染问题

    依云发表于 2022-03-08 16:45:01
    love 0

    本文来自依云's Blog,转载请注明。

    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 的评论。)



沪ICP备19023445号-2号
友情链接