前言
字体渲染是浏览器自带的基本能力,不管是基于HTML还是Canvas渲染技术;针对大型Excel表格,onlyoffice内部使用Canvas技术来渲染表格内容;现代浏览器实现Canvas内字体设置和渲染的方案有成熟的API直接使用,代码简写如下:
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.font = '微软雅黑';
ctx.fillText('中', 0, 0)
这种方案能满足大部分场景需求,不过不同浏览器在字体解析和渲染实现存在差异,这会出现一致性问题:同样的字符,在不同操作系统、不同浏览器展示效果可能不一致,知乎上也有类似问题提到一致性现象;所以如果编辑器产品方案要考虑浏览器兼容性和渲染一致性问题时,那么编辑器内部就要接管字体的解析和渲染工作。本文介绍onlyoffice解决这个问题的一种思路,希望能抛砖引玉。限于本文水平有限,有不准确的地方欢迎指正或者讨论。
实现细节
onlyoffice整体方案类似浏览器底层文本渲染引擎的实现思路,浏览器内部展示文本的整体流程包括三个步骤:
- 查找字体:根据CSS font-face语法指定一系列字体列表,查找时按照顺序遍历列表,找到第一个符合条件(比如本地是否有该字体的TTF文件)的字体
- 加载字体:加载符合条件的本地字体文件
- 渲染字体:这个步骤浏览器调用OS提供的文本排版引擎,然后调用浏览器的渲染引擎(一般是CG图形接口)直接绘制,不同OS实现了不同文本排版引擎,比如IOS提供CoreText,Window7后提供DirectWrite引擎,每种排版引擎都是各自自研的。
读到这里了解到字符展示的全流程,但是网页包括很多字符,这些是通过HTML标签和CSS来组织结构,最终通过浏览器布局引擎决定文本位置,而布局引擎内部涉及到文本排版相关也是调用了OS提供的文本排版API实现。
Onlyoffice内部基本上模拟了这个流程,不过每个步骤的实现方案和浏览器原生实现不一样,整体流程如下: