如何在 fontconfig 中设置每个 Unicode 范围/代码点的字体?
Posted
技术标签:
【中文标题】如何在 fontconfig 中设置每个 Unicode 范围/代码点的字体?【英文标题】:How to set font per Unicode range / codepoint in fontconfig? 【发布时间】:2018-05-10 03:06:44 【问题描述】:我最近想出了如何在 Linux 上使用fontconfig
为 serif、sans-serif 和等宽字体设置系统默认字体;基本上,您将 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 字符,并且有一些有问题的字形。
假设我不喜欢〇 U+3007 IDEOGRAPHIC NUMBER ZERO
在Sun-ExtA
中的出现,而宁愿使用HanaMinA
,我怎么能用fontconfig
做到这一点?显然,我不能将HanaMinA
的条目优先于Sun-ExtA
,因为这会影响所有两种字体中包含的字形。
我的预感是应该有一个涉及元素 <charset>
的解决方案(根据
fontconfig user documentation,“该元素至少包含一个或多个 Unicode 代码点的元素”)和/或<range>
(“该元素包含范围表示的两个元素”——可能表示一系列 Unicode 代码点)。不过,我找不到一个如何使用这些元素的示例。
是否可以将 fontconfig 配置为对单个 Unicode 代码点或一系列代码点使用特定字体?
【问题讨论】:
【参考方案1】:在扫描模式中,在 <edit>
标记中包含 <minus>
元素可让您从字符集中减去。
这主要是为从字体中删除“坏”或有问题的字符而设计的,但更进一步,您可以编写一个 <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
s。
据我所知,这在以前没有真正记录在案,我发现了它from a redhat bug
【讨论】:
首先,这个答案包含一个错误:fontconfig 抱怨“范围”周围缺少“字符集”。而且,不幸的是,它似乎不适用于 fontconfig 2.13 或干扰其他东西。所有应用程序(包括浏览器和终端仿真器)仍然呈现“已删除”的字符,其中应将其删除:( 这个 sn-p 对我有用,但我能得到的最好的结果是删除字符的矩形。有没有人真的能够让 fontconfig 回退到另一种字体? 对我来说,类似的情况不适用于 fontconfig 2.13.1,除非在<range>
部分周围添加<charset>
标签,即<charset><range><int>0x0021</int><int>0x00FF</int></range></charset>
,(也可以使用多个范围。)
我不得不使用target="font"
而不是"scan"
来完成这项工作。【参考方案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>
需要谨慎使用 fontconfig 优先级,以便在您不想要的字体之前和常见的拉丁/希腊/西里尔字体之后提升字体(因为 CJK 拉丁字形往往很糟糕)。
当然,这假设您的软件环境能够在您在需要此覆盖的语言环境中读/写时发出 fontconfig 信号。
【讨论】:
以上是关于如何在 fontconfig 中设置每个 Unicode 范围/代码点的字体?的主要内容,如果未能解决你的问题,请参考以下文章
Flexbox布局:如何在多行中设置每个项目相同的宽度? [复制]
python - 如何在python中的旭日形图的所有层中设置每个类别的颜色?
如何在 Flutter 中设置 Firebase Analytics 自定义事件,而不在每个屏幕中传递“分析/观察者”对象