2

我正在Open Sans通过 Google Fonts API / CSS 加载 OpenType 网络字体。

在 Chrome 43 (Linux+Windows) 和 Internet Explorer 11 (Windows) 中,浏览器完全按照字体中指定的方式呈现文本。但是,在 Firefox 38.0.5 中,某些字符的文本宽度和/或间距呈现不同。所有字体变体均采用默认值(“正常”)。

例如,我们可以使用字符1abi。Open Sans "unitsPerEm" 为 2048。因此,在字体大小为 18.0px 时,上述每个字符的 30 个字符的宽度应如下基于 1/u * p * c * w 其中 u = 2048, p = 18.0,c = 30,w 是每个字符的前进宽度(Wolfram Alpha 方程)。

+----------------------------------------+-------- ---+
| 字符 | 字体(px) | 数字字符 | 提前| 宽度(像素) |
+--------+----------+----------+-----------+-------- ---+
| 1 | 18.0 | 30 | 第1171章 308.76 |   
| 一个 | 18.0 | 30 | 第1139章 300.322 |
| 乙 | 18.0 | 30 | 第1255章 330.908 |
| 我 | 18.0 | 30 | 518 | 136.582 |
+----------------------------------------+-------- ---+

这个 ( JSFiddle ) 使用 canvas 方法输出、、和measureText30 个字符的宽度(以像素为单位)。1abi

Chrome 文本长度与预期值完全匹配:

镀铬宽度

Firefox Linux 文本长度与除 之外的任何字符都不匹配a,即使考虑到 Firefox 不提供亚像素精度这一事实:

Firefox Linux 宽度

我已经确认画布报告的宽度确实是 Chrome 和 Firefox 的输出——下图显示红色背景,Chrome 的文本为黑色,Firefox 的文本为白色——宽度与上面的输出相匹配Gimp“测量”工具。Firefox 的bandi太宽,又1太窄:

Chrome/Firefox 比较

附带说明一下,Firefox Windows 文本长度甚至与 Firefox Linux 不一致——ab宽度现在符合预期,但1仍然i不正确:

Firefox Windows 宽度

这是一个干净的 Firefox 配置文件,具有默认设置且未安装任何扩展。

有人可以解释发生了什么,以及如何强制 Firefox 根据字体规范呈现字体吗?

更新:在 Windows 上,设置首选项gfx.font_rendering.directwrite.enabledtrue解决问题(我相信这是硬件加速可用时的 Firefox 默认设置,即使硬件加速不可用,此设置也会强制启用它,例如在我的测试 VMWare 系统上)。自版本 37 以来,DirectWrite 一直是 Windows 上 Chrome 的默认设置。Linux 行为仍然无法解释。这篇博文详细介绍了 Windows 上 Firefox 中的 DirectWrite 渲染。

4

1 回答 1

2

(这个答案总结了问题评论中提出的要点,以及问题发布后进行的一系列额外研究。)

由于各种复杂的原因,并非所有浏览器/操作系统/字体大小组合都以相同的方式呈现到屏幕上,它们也不总是遵循字体的规范。因此,一般而言,应用程序的创建方式应避免需要对文本进行像素完美定位。

亚像素文本渲染配置

关于配置特定浏览器/操作系统组合以支持亚像素文本渲染的一些评论:

视窗

  • 支持和启用 DirectWrite(与旧的 GDI 方法相反)的浏览器确实倾向于支持线性、无提示、亚像素文本定位,因此能够(并且通常会)遵循字体前进宽度规范。这包括Chrome 37+Firefox 4+
    • 当硬件加速不可用时,Firefox 默认禁用 DirectWrite,但可以通过将 config 属性设置gfx.font_rendering.directwrite.enabledtrue.
    • Chrome 37+ DirectWrite 默认开启,但可以通过设置 flag 来禁用Disable DirectWrite
    • Internet Explorer (9+?) DirectWrite 默认开启,但可以通过设置兼容模式禁用。

Linux

通过设置fontconfig 进行子像素渲染(通常通过 Gnome 或 KDE 显示管理器设置,但可以通过 fontconfig 配置文件手动完成)、安装 freetype-freeworld(freetype 与非免费的亚像素渲染支持),并添加Xft.lcdfilter: lcddefault~/.Xresources不支持 fontconfig 的应用程序中。根据您的LCD 显示类型设置正确的子像素渲染类型

  • 即使底层显示支持并配置为子像素渲染,浏览器行为似乎也不一致。
    • 最近版本的 Chrome(44 测试)似乎支持线性、无提示、亚像素文本定位,因此通常遵循字体规范。在启用了 RGB 亚像素文本渲染的 KDE 4.14 上进行了测试。
    • Firefox(38.0.5 测试)似乎进行非线性提示定位,因此不遵循字体规范,即使显示器配置为亚像素渲染。我还没有找到强制 Firefox 使用亚像素文本渲染的方法。

Mac OS/X

暂无此平台的信息。

像素完美定位

如果尽管有困难,但要构建一个需要像素完美的文本定位和检查的应用程序,那么通常有两种方法可以解决:

1) 画布或基于 DOM 的文本宽度/高度测量:请参阅使用 JavaScript 计算文本宽度。另请参阅Mike Kamermans (Pomax) 的 Font.js。

2)使用OpenType.js从源字体中确定文本尺寸,在工作时比上面的方法快,但并非在所有情况下都有效。

于 2015-06-21T04:54:22.547 回答