DirectWrite (CreateTextFormat) 如何选择后备字体?

Fiz*_*izz 5 fonts directwrite

CreateTextFormat的文档没有说明字体回退选择,但如果选择了默认(NULL = 系统)集合,那么 DirectWrite 清楚地实现了字体回退。例如,如果我将 Gabriola 字体中未找到的两个字形添加到 DirectWrite SDK 演示应用程序使用的测试字符串中,则 DirectWrite 会从 Segoe UI Symbol 字体中选择丢失的字形。这发生在基本DrawText调用和自定义渲染器(对字体回退不做任何自定义)时,如下所示(唯一的修改是测试字符串):

在此处输入图片说明

复选标记和白星来自 Segoe UI Symbol,而不是来自 Gabriola,即使在演示应用程序中只指定了 Gabriola。那么,有谁知道 DirectWrite (CreateTextFormat) 是如何选择后备字体的?

更新。我看到有一个GetSystemFontFallback可以列出后备字体,但它只在 Windows 8.1 中可用(因为它在 IDWriteFactory2 中)。我猜他们已经注意到 API 在枚举后备字体方面的差距。所以我猜在 Windows 8.1 之前没有办法做到这一点,但如果有人知道黑客/解决方法......

更新2。引用MSFT 员工的话

DirectWrite 具有无法从注册表读取或以任何方式配置的回退数据。但是,在 Windows 8.1 中,引入了允许应用指定其自己的回退的 API。(它类似于用于创建复合字体定义的 WPF API。)

这仍然不能准确解释硬编码算法/替换方案实际上是什么。

Dwa*_*son 3

IDWriteTextLayoutIDWriteFontFallback::MapCharacters将每个 Unicode 字符映射到字体系列的有序列表的调用,将尝试这些字体系列,直到满足该字符为止。想象一个循环逐一读取每个字符,将代码点值和语言标记映射到 Unicode 范围,并在 cmap 表中支持该字符的第一个字体处停止。伪代码:

for each ch in text
    if ch is a combining mark or other similar extending character
        if the previously selected font supports the combining mark too
            use the previously selected font
            continue
        endif
    endif
    find first mapping for ch within the Unicode range, which matches
        the current language and base font family too (if pertinent)
    if mapping found
        for each font in mapping (starting with first listed)
            if ch in font cmap
                use current font
            endif
        endfor
    else
        use base font and undefined (.notdef) glyph
    endif
endfor
Run Code Online (Sandbox Code Playgroud)

还有确定后备区域设置的逻辑(例如 for zh-Hans/Hant或一般ja匹配更具体的ja-jp)。它有点类似于(但比 )CSS 为浏览器指定的字体后备算法 [http://www.w3.org/TR/css3-fonts/#font-matching-algorithm] 并且类似于使用的后备通过 WPF/XAML/Silverlight。

请参阅IDWriteFontFallbackBuilder::AddMappingAPI (Win 8.1+),用于构建自定义回退列表的 API (Win 8.1+),了解所使用的输入的想法。

请参阅 C:\Windows\Fonts\GlobalUserInterface.CompositeFont 以获取示例数据(请注意,此文件实际上用于 WPF,与 DWrite 使用的定义不完全相同)。

<FontFamilyMap
    Unicode  = "3000-30FF, 31F0-31FF"
    Language = "ja"
    Target   = "Meiryo UI, Meiryo, Microsoft YaHei UI, Microsoft YaHei, MS Gothic, MingLiu, Arial Unicode MS"
    Scale    = "1.0" />
Run Code Online (Sandbox Code Playgroud)