Web浏览器如何实现字体回退?

时间:2015-03-24 19:59:20

标签: fonts fallback opentype true-type-fonts

我有兴趣了解字体回退在字体整形/渲染堆栈中的位置。换句话说,在什么时候缺少检测到的字形以及它们如何被替换?

我在this文档中看到,FontConfig工具可以透明地基于字形覆盖进行字体回退。"

所以问题是:

  1. 此算法究竟有用吗?
  2. 这是大多数浏览器使用的标准算法 - webkit,gecko(可能不是IE)?
  3. 基于字体内缺少字形的字体回退如何与CSS字体回退相关(当字体完全丢失时,它指定依次使用哪些字体?)
  4. 编辑:我找到了this文件,其中解释了"什么" FontConfig,但不是"如何。"问题1是关于"如何。"

    总结一下 - 这篇文章只与一件事有关 - 当字体中缺少字形时,字体回退是如何工作的。

2 个答案:

答案 0 :(得分:9)

浏览器中的字体后备(与操作系统相反)基于两件事:

  1. CSS规范,它提供了用于回退的字体和
  2. 文本引擎,用于文本整形。
  3. CSS规范在这方面相当简单,只是使用系统名称给出字体列表,但是几种可能的“catch all”字体在计算机之间不能保证是相同的(没有)例如,假设serif映射到TimesTimes New Roman的原因。

    文本引擎使用的回退算法完全取决于引擎,但通常在字形查找步骤中启动:文本引擎看到一串代码点,并尝试使用字体来整形该字符串。对于序列中的每个点,它检查字体是否具有匹配的字形(通过查询CMAP表和子表),或者一个规则告诉引擎可能只有在跟随更多代码点时才使用字形,通过GSUB机制(例如,单个字母etc没有字形的字体,但带有&的字形和说明序列的GSUB规则e + t + c应该使用单个字形&替换文字内容,并且当它完成累积此类“点数单位”时,它会形成将文本交给任何要求它塑造文本的文本。

    如果在字形查找过程中,事实证明字体不包含任何让引擎形成特定代码点的内容(即通过CMAP数据运行以及GSUB规则仍然显示“没有字形”)然后文本引擎可以做两件事:

    1. 放弃。没有字形,而是使用定义为字形id 0的.notdef轮廓,并且通常为您提供带有可爱空盒子的文本(由字体伙伴亲切地称为“豆腐”)或问号。
    2. 尝试字体回退,它将尝试使用其他字体查找不受支持的代码点的字形。
    3. 当使用回退时,引擎可以向下移动替代字体列表,直到:(a)找到字形,或(b)列表耗尽,此时引擎 放弃,并将使用.notdef字形。引擎是从原始字体还是从列表中的最后一个字体抓取.notdef字形,完全取决于引擎(尽管通常它会使用第一种字体,但易读性)

      在任何地方都没有“标准”算法; font fallback基本上是文本引擎作者提供的一种便利机制,就像浏览器带有书签管理器一样(方便,而不是任何规范的一部分)。就OpenType而言,没有要求引擎在找不到字形时是否应该只提供.notdef,或者它是否应该提供它可以形成的部分,然后在其他地方找到缺少的字形,并以这种方式呈现文本。 CSS意味着你的文本引擎应至少具有某种形式的字体回退,但它没有指定它应该如何工作,或者何时应该启动。

答案 1 :(得分:1)

在Windows上:

Firefox字体回退

Firefox对于CJK字形和非CJK字形具有不同的算法:

非中日韩语

非CJK算法非常简单:尝试使用给定html语言配置的所有字体。其中包括配置font.name.{generic}.{language}和配置font.name-list.{generic}.{language}的列表。

CJK

由于字形的剪切数,编码和语言变化,CJK本质上很复杂。 Firefox使用动态搜索算法来解析字形。

  1. 使用给定的html语言配置的字体。
  2. 使用配置的日语ja)字体。
  3. 使用配置的韩语ko)字体。
  4. 使用配置的简体中文zh-CN)字体。
  5. 使用配置的繁体中文(香港)zh-HK)字体。
  6. 使用配置的繁体中文(台湾)zh-TW)字体。

该算法当前在GetLangPrefs()中实现。在CJK和非CJK情况下,要搜索的字体数量都有限制(32)。脚本搜索顺序是硬编码的,因此目前无法由用户配置。

Firefox的后备算法的优势在于,由于其动态特性,可以搜索更多字体,从而最大程度地减少了用户遇到缺少字形的机会。此外,通过了解搜索顺序,用户可以操纵配置以为缺少的字形选择所需的字体。

缺点是不一致:由于搜索列表是硬编码的,因此所有网页的优先级都来自特定语言的字体。例如,日语优化字体可能会在缺少标签的韩国网页中使用。另外,由于尝试了更多的字体,因此性能可能会降低。

铬字体回退

与Firefox不同,Chromium选择了一种更加静态的搜索字体方法。 Chromium不必为CJK大小写划分大小和字体列表,而是为每个脚本硬编码几种“核心”字体。 Chromium假定这些字体应始终可用,因此仅搜索这些字体。脚本到字体的映射可以在InitializeScriptFontMap()中找到。此映射目前无法由用户配置。

该算法的优点是简单,一致和高性能,但以灵活性和可配置性为代价。

将来实现可能会更改。在https://gist.github.com/CrendKing/c162f5a16507d2163d58ee0cf542e695中有更多详细信息。