我们希望未来的设计工具是这样的:任何人在任何地方都可以轻松使用它并获得它产生的内容。因此,我们创建了Figma,这是一种基于浏览器的云服务,可实现协作设计。当我们开始研究Figma时,我们知道这是一个挑战。为完成这一挑战,我们需要提供接近原始版本的编辑体验,以便设计师能够接受该工具并在任何地方使用它。真的很难做到这一点。我们最终基本上在浏览器中构建了一个新的浏览器。这很难,因为Web并非设计为通用计算平台。它主要是为处理文档而生,开发应用的一整套东西都绑在上面。这些东西通常针对特定的场景使用特定的API,但不提供一个通用的接口,可以用来实现各种东西。比如:css有很多花哨的文字排版算法,但是它不能自定义排版算法,不能分析排版过程,所以其他算法不能使用排版算法。所有的浏览器都提供了高性能的gpu合成器,但是在web平台上,渲染算法是没有办法接入的,所以你不能改变合成器的工作方式来增加性能分析,或者自定义混合模式的功能.浏览器嵌入了一个高度优化的图像解析器,它可以在UI线程之外工作,并使用最新的硬件特性。但是没有API可以将参数传递给这些解析器来实现诸如“处理EXIF方向”或“在使用drawImage和getImageData方法时避免触摸显示色彩空间”等功能。Web平台缺乏通用底层接口的情况现在开始发生变化,因为WebGL和asm.js等技术允许开发人员绕过浏览器直接与硬件对话。技术进步最终使基于Web平台的高性能图形应用成为可能。开发人员无需等待网络平台添加他们需要的额外功能,他们可以自己构建!Emscripten我们的编辑器是用C++编写的,然后使用跨平台编译器emscripten编译成JavaScript。emscripten编译了一个名为asm.js的javascript子集,它为JavascriptJIT提供了一种生成可预测的压缩机器代码的方法,并且得到了所有现代浏览器的广泛支持。它有以下优点:我们自己可以完全控制内存布局,可以使用小的32位浮点数,有时甚至是字节,而不是js的64位双精度浮点数。这对于像我们这样使用大量数据的应用程序至关重要。构建的代码可以完全控制内存分配,这避免了GC引起的卡顿,并使应用程序更容易达到每秒60帧。所有C++对象都在预先分配的保留范围内,因此Js的GC永远不会参与。生成的代码由LLVM的高级优化器预先优化。这与专门的C++模板相结合,生成了比本机性能高出2倍或更多的高效代码。所有asm.js代码都不需要再次优化,因此JIT可以预编译它并提供可预测的性能。常规的Js代码依赖于JIT进行优化,因此同一段代码在未来的性能可能会相差很大。这并不是说emscripten是完美的。与任何新技术一样,前面的道路将是崎岖不平的。对我们来说一个大问题是某些浏览器设置无法为emscriptions分配大的连续内存地址。最糟糕的例子是Windows上的32位Chrome,有时我们甚至无法分配256MTypedArray,因为ASLR会碎片化内存地址。此问题现已解决。另一个有用的技巧是对大型资源(例如图片或缓冲区片段)使用堆外引用。我们有一个名为IndirectBuffer的内部API来表示外部TypedArray并使其在C++中可用。将大内存分配移出主堆可减少长会话中的内存碎片,并允许我们在有限的32位浏览器中使用更多内存,并允许我们突破64位浏览器的31位TypedAray大小限制。对asm.js的支持现在很好,但还有一些更令人兴奋的变化即将到来。WebAssembly是对asm.js二进制形式实现的努力,它可以大大减少asm.js代码的解析时间,所有浏览器都准备实现它。目前使用多线程的唯一方法是使用webworker并通过post消息传递消息,但即将到来的可共享TypedArray标准将使多线程之间的共享内存成为现实。呈现我们实施了自己的呈现引擎,以确保跨多个平台快速一致地呈现内容。浏览器有惊人的图形实现,我们并没有打算自己构建渲染引擎。如果没有可以获取浏览器RenderTree的底层API,则只能选择HTML、SVG或2DCanvas。但是它们都不能满足我们的需求,原因如下:HTML和SVG有很多包袱,并且由于获取DOM的原因通常比2dCanvas慢得多。这通常针对滚动而不是缩放进行了优化,并且每次缩放更改时通常都会重新绘制几何图形。Gpu加速没有保证,很多东西还是在CPU上渲染,在某些场景下很慢。在HTML和SVG上,对屏蔽、模糊和混合模式的支持在浏览器之间差异很大,并且通常没有消除锯齿或在高DPI显示器上分辨率太低。2D画布API是立即模式API而不是保留模式API,因此所有集合形状每帧都会重新上传到显卡。这是不必要的浪费,也是潜在的性能瓶颈。跨浏览器的文本布局不一致,甚至可能在不同平台的同一浏览器中。我们想添加任何渲染API都不支持的功能,例如“角度渐变”。我们没有尝试让其中之一可用,而是使用WebGl从头开始??实现所有内容。我们的渲染器是一个高度优化的基于Tile的架构引擎,支持遮罩、模糊、抖动角度、混合模式、嵌套层透明度等。所有渲染都在GPU上完成,并且完全抗锯齿。深入研究代码,尤其是像浏览器中的浏览器一样。我们有自己的DOM、我们自己的合成器、我们自己的文本布局引擎,我们正在考虑添加一个渲染树,就像浏览器用来渲染HTML的树一样。浏览器web平台的能力仍在赶上原生平台,不幸的是还有一些差距。虽然我们没有资源来填补这些巨大的空白,但我在仍然有意义的时候尽我所能。在我去Figma工作之前,高DPI定制鼠标在网上完全坏了。我必须一一修复Chrome、Firefox和WebKit,因为它们的损坏方式不同。目前还没有一个统一的方法来解决这个问题,但至少现在是可以的。我还修复了几个糟糕的性能和可用性错误,以使我们的产品变得更好。Web平台有时会令人沮丧,但浏览器不是黑盒子,解决Web上一些恼人问题的代价通常是一个下午调试浏览器代码,一天专注于补丁,或者几个月的等待对于新版本。在Web平台上还有一些事情可以做,让Figma变得更好:我们最大的痛点是我们无法访问字形轮廓和“字距调整表”,到目前为止也没有办法解决。我们主要担心的问题之一是指纹,这是一场对于战士来说已经失败的战斗。我们希望能够获得字体数据,当用户同意一个类似于我们的协议,类似于隐私政策的API。Chrome目前正在提议解决此问题,但尚不清楚其他浏览器何时会这样做。我们想添加常见的剪贴板格式,比如.ai、.pdf等,但是web平台根本做不到。唯一的剪辑格式是文本/纯文本或文本/html。我们的Figma切口采用文本/html格式,带有二进制数据注释。我们面临的另一个问题是缺乏对触控板手势的支持。Chrome添加了一个鲜为人知的技巧,触控板可以通过按下ctrl键发送滚轮事件并调用preventDefault以允许页面处理它。这让Figma的缩放感觉很自然。我尝试在FireFox上添加它,但卡住了。Safari上的触摸缩放行为可能会让用户感到困惑,但没有办法阻止它。
