OpenType字体的Firefox渲染与字体规范

时间:2015-06-18 18:03:28

标签: javascript firefox webfonts opentype html5-apps

我正在通过Google字体API / CSS加载OpenType webfont Open Sans

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

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

+----------------------------------------+-----------+
| char | font(px) | numChars |  advance  | width(px) |
+------+----------+----------+-----------+-----------+
|  1   |   18.0   |    30    |   1171    |  308.76   |   
|  a   |   18.0   |    30    |   1139    |  300.322  |
|  b   |   18.0   |    30    |   1255    |  330.908  |
|  i   |   18.0   |    30    |   518     |  136.582  |
+----------------------------------------+-----------+

这个(JSFiddle)使用画布方法measureText输出每个1ab的30个字符的宽度,和i

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

Chrome widths

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

Firefox Linux widths

我已经确认画布报告的宽度确实是Chrome和Firefox输出的宽度 - 下图显示红色背景,Chrome的文字为黑色,Firefox的文字为白色 - 宽度与上面的输出相匹配,根据Gimp"测量"工具。 Firefox的bi太宽,1太窄了:

Chrome/Firefox Comparison

作为旁注,Firefox Windows文本长度与Firefox Linux不一致 - ab宽度现在符合预期,但是1和{{1仍然不正确:

Firefox Windows widths

这是一个干净的Firefox配置文件,默认设置并没有安装扩展程序。

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

更新:在Windows上,将首选项i设置为gfx.font_rendering.directwrite.enabled可解决问题(我认为当硬件加速可用时,我认为这是Firefox的默认设置,此设置只是强制它即使硬件加速不可用,例如在我的测试VMWare系统上)。 DirectWrite是Windows since version 37上Chrome中的默认设置。 Linux的行为仍然无法解释。 This blog post详细介绍了Windows上的Firefox中的DirectWrite渲染。

1 个答案:

答案 0 :(得分:2)

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

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

亚像素文本渲染配置

有关配置特定浏览器/操作系统组合以支持子像素文本呈现的一些注释:

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

的Linux

Configure您的显示器通过设置用于子像素渲染的fontconfig(通常通过Gnome或KDE显示管理器设置,但可以通过fontconfig配置文件手动完成)进行抗锯齿和子像素文本渲染,安装freetype -freeworld(具有非自由子像素渲染支持的freetype),并为没有fontconfig支持的应用程序添加Xft.lcdfilter: lcddefault~/.Xresources。根据{{​​3}}设置正确的子像素渲染类型。

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

Mac OS / X

此平台尚无信息。

像素完美定位

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

1)Canvas或基于DOM的文本宽度/高度测量:请参阅LCD display type。另请参阅Mike Kamermans(Pomax)的Calculate text width with JavaScript

2)使用Font.js从源字体确定文本维度,这比上面的方法更快,但在所有情况下都不起作用。