我正在通过Google字体API / CSS加载OpenType webfont Open Sans
。
在Chrome 43(Linux + Windows)和Internet Explorer 11(Windows)中,浏览器完全按照字体中的指定呈现文本。但是,在Firefox 38.0.5中,对于某些字符,文本宽度和/或间距的呈现方式不同。所有字体变体都是默认值("普通")。
例如,我们可以使用字符1
,a
,b
和i
。打开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
输出每个1
,a
,b
的30个字符的宽度,和i
。
Chrome文本长度与预期值完全匹配:
Firefox Linux文本长度与a
以外的任何字符都不匹配,即使考虑到Firefox不提供子像素精度这一事实:
我已经确认画布报告的宽度确实是Chrome和Firefox输出的宽度 - 下图显示红色背景,Chrome的文字为黑色,Firefox的文字为白色 - 宽度与上面的输出相匹配,根据Gimp"测量"工具。 Firefox的b
和i
太宽,1
太窄了:
作为旁注,Firefox Windows文本长度与Firefox Linux不一致 - a
和b
宽度现在符合预期,但是1
和{{1仍然不正确:
这是一个干净的Firefox配置文件,默认设置并没有安装扩展程序。
有人可以解释发生了什么,以及如何根据字体规范强制Firefox渲染字体?
更新:在Windows上,将首选项i
设置为gfx.font_rendering.directwrite.enabled
可解决问题(我认为当硬件加速可用时,我认为这是Firefox的默认设置,此设置只是强制它即使硬件加速不可用,例如在我的测试VMWare系统上)。 DirectWrite是Windows since version 37上Chrome中的默认设置。 Linux的行为仍然无法解释。 This blog post详细介绍了Windows上的Firefox中的DirectWrite渲染。
答案 0 :(得分:2)
(这个答案总结了问题评论中提出的要点,以及在问题发布后进行的一系列额外研究。)
对于various和complex原因,并非所有浏览器/操作系统/字体大小组合都以相同方式呈现为屏幕,也不总是遵循字体规范。因此,一般来说,应该以避免需要对文本进行像素完美定位的方式创建应用程序。
有关配置特定浏览器/操作系统组合以支持子像素文本呈现的一些注释:
gfx.font_rendering.directwrite.enabled
设置为true
来启用它。Disable DirectWrite
来禁用。 Configure您的显示器通过设置用于子像素渲染的fontconfig(通常通过Gnome或KDE显示管理器设置,但可以通过fontconfig配置文件手动完成)进行抗锯齿和子像素文本渲染,安装freetype -freeworld(具有非自由子像素渲染支持的freetype),并为没有fontconfig支持的应用程序添加Xft.lcdfilter: lcddefault
到~/.Xresources
。根据{{3}}设置正确的子像素渲染类型。
此平台尚无信息。
如果尽管有困难,一个人正在构建一个需要像素完美的文本定位和检查的应用程序,那么通常有两种方法可以实现:
1)Canvas或基于DOM的文本宽度/高度测量:请参阅LCD display type。另请参阅Mike Kamermans(Pomax)的Calculate text width with JavaScript。
2)使用Font.js从源字体确定文本维度,这比上面的方法更快,但在所有情况下都不起作用。