Javascript OpenType字体的Firefox呈现与字体规范不匹配

Javascript OpenType字体的Firefox呈现与字体规范不匹配,javascript,firefox,webfonts,opentype,html5-apps,Javascript,Firefox,Webfonts,Opentype,Html5 Apps,我正在通过Google字体API/CSS加载OpenType webfont 在Chrome43(Linux+Windows)和InternetExplorer11(Windows)中,浏览器完全按照字体中的指定呈现文本。但是,在Firefox 38.0.5中,某些字符的文本宽度和/或间距呈现不同。所有字体变体均为默认值(“正常”) 例如,我们可以使用字符1、a、b和i。开放式SAN“unitsPerEm”是2048。因此,在字体大小为18.0px时,基于1/u*p*c*w,上述每个字符的30个

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

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

例如,我们可以使用字符
1
a
b
i
。开放式SAN“unitsPerEm”是2048。因此,在字体大小为18.0px时,基于1/u*p*c*w,上述每个字符的30个字符的宽度应如下所示,其中u=2048,p=18.0,c=30,w是每个字符的前进宽度()

+----------------------------------------+-----------+ |字符|字体(px)|数字字符|前进|宽度(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| +----------------------------------------+-----------+ 此()使用画布方法
measureText
输出
1
a
b
i
中每个字符的宽度(以像素为单位)

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

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

我已经确认canvas报告的宽度确实是Chrome和Firefox输出的宽度——下图显示了红色背景,Chrome文本为黑色,Firefox文本为白色——根据Gimp“测量”工具,宽度与上述输出匹配。Firefox的
b
i
太宽,而
1
太窄:

另外,Firefox Windows的文本长度甚至与Firefox Linux不一致--
a
b
宽度现在与预期一致,但
1
i
仍然不正确:

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

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

UPDATE:在Windows上,将首选项
gfx.font\u rendering.directwrite.enabled
设置为
true
可以解决此问题(我认为这是Firefox在硬件加速可用时的默认设置,即使硬件加速不可用,此设置也会强制启用,例如在我的测试VMWare系统上)。DirectWrite是Windows上Chrome的默认设置。Linux的行为仍然无法解释。解释有关Windows上Firefox中DirectWrite呈现的更多信息。

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

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

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

窗户
  • 支持和启用DirectWrite(与旧的GDI方法相反)的浏览器确实倾向于支持线性、非暗示、亚像素文本定位,因此能够(并且通常确实)遵循字体推进宽度规范。这包括和。
    • 当硬件加速不可用时,Firefox默认禁用DirectWrite,但可以通过将config属性
      gfx.font\u rendering.DirectWrite.enabled
      设置为
      true
      来启用它
    • Chrome 37+DirectWrite在默认情况下处于启用状态,但可以通过设置标志
      禁用DirectWrite
      来禁用
    • Internet Explorer(9+?)DirectWrite在默认情况下处于启用状态,但可以通过设置兼容模式禁用
Linux 通过设置子像素渲染的fontconfig(通常通过Gnome或KDE显示管理器设置,但可以通过fontconfig配置文件手动完成),安装freetype freeworld(具有非免费子像素渲染支持的freetype),可以显示抗锯齿和亚像素文本渲染,对于不支持fontconfig的应用程序,将
Xft.lcdfilter:lcddefault
添加到
~/.Xresources
中。根据您的需要设置正确的子像素渲染类型

  • 即使基础显示支持并配置为子像素渲染,浏览器行为也似乎不一致。
    • 最新版本的Chrome(44测试版)似乎支持线性、非暗示、亚像素文本定位,因此通常遵循字体规范。在KDE 4.14上测试,启用RGB亚像素文本渲染
    • Firefox(38.0.5测试版)似乎做了非线性暗示定位,因此不符合字体规范,即使显示器配置为亚像素渲染。我还没有找到强迫Firefox使用亚像素文本呈现的方法
Mac OS/X 还没有关于这个平台的信息

像素完美定位 尽管困难重重,如果要构建需要像素完美文本定位和检查的应用程序,通常有两种方法:

1) 基于画布或DOM的文本宽度/高度测量:请参阅。另见Mike Kamermans(Pomax)

2) 使用从源字体确定文本尺寸,比方法a更快 +----------------------------------------+-----------+ | 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 | +----------------------------------------+-----------+