苹果的Swift:迁移TrueType提示解释器
TrueType是一种被广泛使用的矢量字体标准,用于在网页、PDF、操作系统和应用程序中呈现文本。像Helvetica、Garamond和Monaco这样的常用字体都是基于TrueType轮廓构建的。该格式指定了一个提示解释器,旨在帮助轮廓在低分辨率显示器上忠实地栅格化。现代高分辨率显示器仅靠轮廓就能实现美丽的排版,但仍然使用需要提示以清晰呈现的TrueType字体,我们继续对其提供支持。字体解析器处理来自不受信任来源的数据,使TrueType提示解释器成为一个安全关键的攻击面。为了使该格式在苹果平台上更具弹性,我们将其提示解释器从C语言重写为安全内存的Swift,以便在2025年秋季发布。除了内存安全外,我们还提高了性能:平均而言,我们的Swift解释器比其替代的C解释器快13%。为了配合这篇文章,我们还发布了Swift TrueType提示解释器的源代码。我们希望分享我们的经验能帮助其他人在Swift中做类似的工作。TrueType和苹果开发的提示引擎在1980年代后期,苹果开发了TrueType,并在1991年推出System 7时发布。TrueType在当时是一个重大突破:它给予字体开发者对字形显示方式的巨大控制,采用了先进的网格适配算法和围绕特殊用途字节码解释器构建的复杂提示引擎。TrueType在当时的计算机上完成了这一切,而这些计算机的性能远不及今天,所以它必须针对性能进行极其精细的调整。然后互联网革命性地改变了字体的使用方式。TrueType在1994年可以嵌入PDF文件中,在2008年可以嵌入网页中,并且至今仍然保持相关性。然而,这些新用例带来了额外的风险:TrueType现在可能接触到来自互联网任何地方的不受信任的字体。TrueType字体可能包含提示引擎通过字节码解释器运行的程序。该解释器涉及输入驱动的控制流、复杂的数据结构和小心的内存管理——正是这些代码难以做到完美,而且内存错误更容易被利用。这种高内在复杂性也使得正确性尤为重要。重写需要一种内存安全的语言,能够与现有代码库集成,并提供与被替换实现等效的性能水平。Swift显然是这个任务的最佳选择。二进制兼容性对该项目的成功至关重要:现有程序必须继续以与以前相同的方式运行,实际上并不知道新的实现已经到位。这意味着不仅需要接口兼容性,还需要相对于C实现的像素相同的字形渲染。提示可以极大地改变字形在屏幕上的显示效果,因此解释器行为的微小变化可能导致显著的用户可见变化。对于这个项目,我们将正确性定义为与C实现输出的精确兼容。为了确保正确性,我们开发了两个测试套件。第一个是一个可以针对两个实现的单元测试套件,为两者提供全面的(99.7%)代码覆盖率。这个套件包含在Swift解释器的开源发布中。然后,为了代表现实世界工作负载,我们使用模糊测试器将1000万PDF文件中的一个语料库最小化到4200个文件,而没有任何代码覆盖率的损失。最小化语料库中的文档嵌入了25572种字体,总共2700万个字形,我们使用四种不同的转换渲染这些字形,并将生成的位图与参考解释器进行比较。这让我们对新解释器的兼容性充满信心。在项目结束时,我们编写的测试代码行数几乎是我们为Swift解释器本身编写的四倍。一旦我们的新实现通过了所有测试,我们就将注意力转向性能。我们通过PDF渲染时间在高层次上评估性能,然后基于基准测试指导的改进进行迭代,这些基准测试渲染了三种不同字体的所有字形。这些改进分为四个主要类别。Swift使用自动引用计数来管理共享引用类型的生命周期,并使用运行时独占性检查来防止对数据结构的重叠访问。这些开销源通常因别名化而加剧,解释器的规范设计中存在一定不可降低的别名化。这些开销源可以通过放弃可拷贝的便利性来消除,在整个体系结构中采用 ~Copyable 值类型(另请参见:使用结构体而不是类),为高级抽象保留引用类型。Span,在Swift 6.2中引入,并提供向后兼容支持到macOS 10.14.4和iOS 12.2,使我们能够有效地操作这些类型的序列。有时我们希望改变...
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡