如何在fontconfig中按Unicode范围/代码点设置字体?

14

我最近学会了如何在Linux上使用fontconfig来设置系统默认的衬线字体、无衬线字体和等宽字体;基本上,你需要将以下内容保存为XML配置文件到~/.config/fontconfig/fonts.conf中:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>

<match>
  <test qual="any" name="family"><string>serif</string></test>
  <edit name="family" binding="strong" mode="prepend_first">
    <string>Gentium</string>
    <string>Sun-ExtA</string>
    <string>HanaMinA</string>
    <string>HanaMinB</string>
    </edit>
  </match>

</fontconfig>
binding="strong" mode="prepend_first"属性确保匹配规则优先于其他设置,并且字体名称的顺序确保在一个字体不包含给定代码点/字符时,将尝试列表中的下一个字体(此列表从上到下应用;在我看来,它应该是后绑定更强的逻辑,但无论如何)。
这种配置之所以好用,是因为它可以在文本编辑器和终端仿真器中使用。
然而,仍有一个问题:许多情况下,一个给定的字体确实包含了一个给定的字形,但另一种字体对于该代码点更合适;例如,Sun-ExtA是CJK字符的默认字体,但它也涵盖了很多非CJK字符,并且有一些问题字形。
如果我不喜欢Sun-ExtA〇 U+3007 IDEOGRAPHIC NUMBER ZERO的外观,并希望改用HanaMinA,那么我应该如何使用fontconfig来实现呢?显然,我不能仅仅将HanaMinA的条目置于Sun-ExtA之前,因为那会影响到两个字体都包含的所有字形。
我的直觉是,应该存在一种解决方案,涉及元素<charset>(根据fontconfig用户文档,"此元素至少包含一个Unicode代码点或多个元素")和/或<range>("此元素包含范围表示的两个元素"——可能用于表示一系列Unicode代码点)。不过,我找不到任何使用这些元素的示例。 是否可以配置fontconfig以在单个Unicode代码点或代码点范围内使用特定字体?
2个回答

5
在扫描模式中,将<minus>元素包含在<edit>标记中,可以从字符集中减去相应的字符。这种设计大多用于从字体中删除“有问题”的字符,但更进一步,您还可以编写一个测试<test>,匹配除您想使用的字体之外的所有字体。
<match target="scan">
  <test name="family" compare="not_eq">
    <string>VL Gothic</string>
  </test>
  <edit name="charset" mode="assign">
    <minus>
      <name>charset</name>
      <range>
        <int>0x0021</int>
        <int>0x00FF</int>
      </range>
    </minus>
  </edit>
</match>

类似的配置也可以用于从字体中删除整个lang

据我所知,这在现在之前实际上没有被任何地方记录下来,我是从一个红帽子公司的 bug 上发现的


3
首先,这个答案含有一个错误:fontconfig 抱怨在“range”周围缺少“charset”。不幸的是,在 fontconfig 2.13 上它似乎要么无法工作,要么会与其他某些东西产生干扰。所有应用程序(包括浏览器和终端仿真器)仍然使用字体渲染了应该被删除的字符 :( - Vadim A. Misbakh-Soloviov
1
这段代码对我来说是有效的,但是我能得到的最好结果只是一个矩形,用于表示已删除的字符。有人真的能让fontconfig回退到另一种字体吗? - VPhantom
3
对于我来说,在fontconfig 2.13.1中类似的情况是不能工作的,除非在<range>部分周围添加<charset>标签,即<charset><range><int>0x0021</int><int>0x00FF</int></range></charset>,(也可以使用多个范围)。 - gnucchi
我不得不使用 target="font" 而不是 "scan" 来使其工作。 - nialv7

2
您可以使用fontconfig为特定语言环境推广字体,方法如下:
   <match>
    <test name="lang">
      <string>[RFC-3066 language code]</string>
    </test>
    <test name="family">
      <string>[genericname]</string>
    </test>
    <edit name="family" mode="prepend">
      <string>[fontname]</string>
    </edit>
  </match>
   <alias>
    <family>[fontname]</family>
     <default>
      <family>[genericname]</family>
     </default>
   </alias>

需要仔细使用字体配置优先级,以便在不需要的字体之前和常见的拉丁/希腊/西里尔文字体之后提升字体(因为CJK拉丁字形往往很糟糕)。
当然,这假设您的软件环境能够在需要此覆盖时向字体配置发出信号。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接