Skia 是 Google 一个开源的跨平台图形库,用于 Android, Chromium, Flutter 等项目。目前项目内有在开发的一个 Skia + WebAssembly 版的 CanvasKit, 可以使用 JS 调用预先编译好的 c++ -> wasm 模块,为一些跨平台的图形项目(例如 lottie 的 Skia 版 skottie )移植到 web 端提供了一种新的可能性。

编译

Skia 代码准备

下载和编译源码部分参看官方文档 How to build Skia, 准备好梯子。

canvaskit 相关源码都在 modules/canvaskit 目录下。

拉取完代码后进行到同步依赖这一步就行。因为我们的构建脚本在 modules/canvaskit 里已经有了,可以不用从头编译所有 skia 样例代码和可执行程序,当然了你也可以跟着教程构建完整项目,加深对各功能模块的理解。

python2 tools/git-sync-deps

选择 emscripten 工具链

使用 emsdk 安装 emscripten 相关工具链。

emsdk 的各个发行 tag 里有几套命名,例如 1.38.451.38.45-upstream, 区别在于前者使用 fastcomp 后端,后者使用 llvm 后端。虽然 emscripten 官方推荐使用较新的 llvm 后端,但是在对 canvaskit 里实际使用的时候我发现 wasm-ld 步骤会报错,无法编译成功。 因此选择 fastcomp 版。

emsdk install 1.38.45

canvaskit/compile.sh

这个编译脚本组织了调用 gn 和 em++ 的参数。有以下可选参数,不细看的话可以直接跳到下一步编译步骤

  • no_font / no_embedded_font 字体管理相关,不指定的话会包括 skia fontmgr 相关内容,且内嵌一个默认字体 NotoMono-Regular.ttf
  • debug / profiling 不指定的话默认按照 release 标准,开启最高代码优化模式。
  • cpu 不指定的话默认会加上 webgl 支持。
  • no_canvas 指定的话会排除掉 htmlcanvas/*.js 文件

编译步骤

source ~/dev/emsdk/emsdk_env.sh
emsdk activate 1.38.45

cd /path/to/skia
./modules/pathkit/compile.sh

喝杯茶伸伸懒腰,大概四五分钟后,等到最后一步 log 'Generating final wasm' 完成,便可以在 skia/out/canvaskit_wasm 里找到结果文件。

canvaskit.js  canvaskit.wasm ...

TIPS

  • 不知道别的 emsdk 编译的之前结果有没有影响,所以如果更换了 emsdk 的版本,推荐开始前 emcc --clear-cache

查看效果

使用刚才编译出来的 js/wasm 文件查看效果。

cd /path/to/skia/modules/canvaskit
mkdir -p node_modules/canvaskit
ln -s /path/to/skia/out/canvaskit_wasm node_modules/canvaskit/bin

使用一个简单的 http 静态服务器程序 (如 http-server ) :

http-server .

然后可以在 http://127.0.0.1:8080/canvaskit/example.htmlhttp://127.0.0.1:8080/canvaskit/extra.html 页面里看示意效果。