vs重构插件原理_FontCut - Chrome 字体裁剪插件

00fc012f22a4561aecc7e5cf5e813430.png

本文介绍了前端使用字体的一些问题,并介绍了一个基于 opentype.js 实现的Chrome字体裁剪插件,能够实时预览字体,裁剪并导出otf和woff格式的字体子集。

为什么要截取字体?

相对于英文字体,中文字体文字多轮廓复杂,一个文件动辄10多MB。而一些活动页等场景必须要实现富文本。所以我们会将用到的字体裁剪出一个子集。

目前font-carrier,fontkit,fontmin等等字体裁剪方案只能借助服务端能力,着实不便。其实这些项目大多也是基于opentype.js的。opentype.js能够在浏览器将 ttf otf woff 三种文件格式解析为一个 font 类,其实字体裁剪在浏览器就能完成。

e1d19473311cd2c159ef826facf36f42.png

字体那些事

字体格式

ttf 与 otf

OpenType字体的Outline描述方法主要有TrueType和Postscript,前者的字库文件后缀名一般为ttf,后者的后缀名一般为otf。 OTF通过提供许多TTF无法提供的功能来扩展TTF。例如,OTF的格式允许最多存储65,000个字符。OTF和TTF之间的主要区别是高级排版功能。OTF具有诸如连字和替代字符(也称为字形)之类的装饰。

bca8469b92c1bc41b035441de7087015.png

WOFF

摘录维基百科中的介绍:

Web开放字体格式(Web Open Font Format,简称WOFF)是一种网页所采用的字体格式标准。此字体格式发展于2009年,由万维网联盟的Web字体工作小组标准化,现在已经是推荐标准。此字体格式不但能够有效利用压缩来减少文件大小,并且不包含加密也不受DRM(数字著作权管理)限制。

WOFF 1.0使用zlib压缩,文件大小一般比TTF小40%。而WOFF 2.0使用Brotli压缩,文件大小比上一版小30%。

WOFF 与 ttf 这种格式还是类似的,主要是压缩了而已。

字体文件是如何存储的

字体文件本身是一个二进制文件,内部是由若干个表组成的。以 TrueType 为例其中最关键的是 glyf表,存储了字体的轮廓信息,包含了二次贝塞尔曲线的控制点;字体裁剪插件也是收集这些信息再次生成新的文件。

你可以在这里 photopea.github.io 看一下字体的解析

89dc19085567611467f2b248b592be9c.png

打开控制台可以看到 opentype 解析出的结果。

fc384e8589aa2e8c145e85586b5d2b1c.png

CSS @font-face

字体格式可以选择以下几种:"woff", "woff2", "truetype", "opentype", "embedded-opentype" 和 "svg"。通常 woff + ttf 就能满足大部分浏览器的兼容(IOS 不支持 woff2)。

@font-face {
  font-family:'Awesome Font';
  font-style: normal;
  font-weight: 400;
  src: local('Awesome Font'),
       url('/fonts/awesome.woff2') format('woff2'),
       url('/fonts/awesome.woff') format('woff'),
       url('/fonts/awesome.ttf') format('truetype'),
       url('/fonts/awesome.eot') format('embedded-opentype');
}

加载顺序

字体指定顺序很重要,浏览器将选取其支持的第一种格式。所以如果需要兼容的浏览器使用 WOFF2,则应将 WOFF2 声明置于 WOFF 之上,依此类推。

字体的加载

字体延迟加载可能会有延迟文本渲染的问题:浏览器必须构建渲染树(它依赖 DOM 和 CSSOM 树),然后才能知道需要使用哪些字体资源来渲染文本。 因此,字体请求的处理将远远滞后于其他关键资源请求的处理,并且在提取资源之前,可能会阻止浏览器渲染文本。

15875a84955ff6b170234814332c3856.png

如果我们知道页面用了那些文字,我们还可以利用新特性:<link rel="preload">,在关键渲染路径中提早触发对网络字体的请求,而不必等待创建 CSSOM。

<head>
  <!-- Other tags... -->
  <link rel="preload" href="/fonts/awesome-l.woff2" as="font">
</head>

字体的展示时机

字体下载需要时间,那如果这段时间比较长页面已经渲染好了,使用这些字体的文字是如何展示的?

其实浏览器在加载字体是可以分为如下三个阶段:

  • 阻塞期:如果未加载字体,则任何尝试使用它的元素都必须呈现不可见的备用字体。如果在此期间成功加载了字体,则可以正常使用。
  • 交换期:如果未加载字体,则任何尝试使用它的元素都必须展示备用字体。如果在此期间成功加载了字体,则可以正常使用。
  • 失效期;如果未加载字体,则视为加载失败,字体回退。

CSS 中的font-display属性可以让我们控制这几个阶段的策略,该属性接受五个值 auto|block|swap|fallback|optional(默认为 auto,行为与和 block 类似)。区别如下表:

0ebd96d00b0edab50cf1c22b1989b102.png

裁剪原理

先将字体文件转换为 arrayBuffer,传递给 opentype.js 的 parse 函数得到字体文件的解析结果。 使用 stringToGlyphs(string) 方法获取需要裁剪的字形信息列表。结合字体名等信息 new 一个新的 Font 就能得到字体子集。最后会下载 ttf和woff两种格式的子集文件。

字体预览是通过 getPath 方法获得文字的路径,然后调用path下的draw方法,就能在canvas上绘制出文字。

项目地址

https://github.com/zhangchen915/FontSubset/releases

FontSubset 下载 crx 文件安装即可。 欢迎试用,来点个⭐呀 ~

参考文献:

  1. 微软 OTF 规范:http://www.microsoft.com/typography/otspec/otff.htm
  2. 苹果 Truetype 规范文档https://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html
  3. OTF vs TTFhttps://www.makeuseof.com/tag/otf-vs-ttf-fonts-one-better/
  4. sfnt2WOFFhttps://github.com/odemiral/woff2sfnt-sfnt2woff/
  5. optimize-webfonts https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization#%E4%BC%98%E5%8C%96%E5%8A%A0%E8%BD%BD%E5%92%8C%E6%B8%B2%E6%9F%93
  6. 字体是如何存储的?https://zhuanlan.zhihu.com/p/53036815

福利部分

文章在 “大转转FE” 公众号也会发送,并且公众号有抽奖活动,本文奖品是转转纪念T恤一件或转转随机手办一个,可任选其一,欢迎大家关注 ✿✿ヽ(°▽°)ノ✿

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值