#shaping #true-type #opentype #text

no-std rustybuzz

完整的 harfbuzz 形状算法移植到 Rust

22 个版本 (破坏性)

0.18.0 2024 年 8 月 10 日
0.17.0 2024 年 7 月 2 日
0.16.0 2024 年 7 月 2 日
0.13.0 2024 年 2 月 17 日
0.2.0 2020 年 7 月 25 日

#22 in 文本处理

Download history 34033/week @ 2024-05-02 31622/week @ 2024-05-09 29721/week @ 2024-05-16 27280/week @ 2024-05-23 27989/week @ 2024-05-30 35783/week @ 2024-06-06 48736/week @ 2024-06-13 45573/week @ 2024-06-20 52290/week @ 2024-06-27 48605/week @ 2024-07-04 65681/week @ 2024-07-11 61654/week @ 2024-07-18 52512/week @ 2024-07-25 48545/week @ 2024-08-01 56476/week @ 2024-08-08 52069/week @ 2024-08-15

220,148 下载/月
263 个 Crates 中使用 (24 直接)

MIT 许可证

1.5MB
25K SLoC

rustybuzz

Build Status Crates.io Documentation

rustybuzz 是将 harfbuzz 的形状算法完全移植到 Rust 的库。

匹配 harfbuzz v9.0.0

为什么?

因为您可以将 rustybuzz = "*" 添加到您的项目中,它就会正常工作。不需要 C++ 编译器。不需要配置任何东西。不需要链接到系统库。

兼容性

rustybuzz 通过了几乎所有的 harfbuzz 形状测试(准确来说是 2221 个中的 2252 个)。所以它们基本上是相同的,但仍有一些尚未实现或无法实现的微小边缘情况。

主要更改

  • 子集已移除。
  • TrueType 解析完全由 ttf-parser 处理。虽然解析算法非常不同,但并没有更好或更差,只是不同。
  • 损坏的字体将导致错误。在这种情况下,HarfBuzz 使用后备/虚拟形状器。
  • 没有字体大小属性。形状始终使用 UnitsPerEm。您应该手动缩放结果。
  • 大多数 TrueType 和 Unicode 处理代码已移入单独的 Crates。
  • rustybuzz 不与任何系统库交互,必须在所有 OS 和目标上产生完全相同的结果。
  • mort 表不支持,因为它已被 Apple 弃用。
  • 没有阿拉伯后备形状器,因为它需要子集。
  • 没有 graphite 库支持。
  • avar2 以及 boring-expansion-spec 的其他部分尚不支持。

性能

目前,性能并不出色。我们比 harfbuzz 慢 1.5-2 倍。

有关详细信息,请参阅 benches/README.md

关于移植的说明

rustybuzz 不是一个忠实移植。

harfbuzz 可以大致分为6个部分:成形、子集、TrueType解析、Unicode工具函数、自定义容器和实用工具(harfbuzz不使用C++ std)以及系统/第三方库的粘合剂。与此同时,rustybuzz 只包含成形。所有的 TrueType 解析都迁移到了 ttf-parser。子集功能已被移除。Unicode 代码主要迁移到外部crate。由于 Rust 的 std 已经足够好,所以我们不需要自定义容器。而且我们不使用任何非 Rust 库,因此也没有粘合代码。

最终,我们仍有大约23千行代码。而 harfbuzz 约有80千行。

代码行数

如上所述,rustybuzz 大约有23千行代码。但这并不完全准确,因为有许多自动生成的数据表。

您可以使用以下方法找到“实际”的代码大小:

tokei --exclude hb/unicode_norm.rs --exclude hb/ot_shaper_vowel_constraints.rs \
      --exclude '*_machine.rs' --exclude '*_table.rs' src

这给我们大约17千行代码,仍然相当多。

未来工作

端口完成之后,除了与新的 harfbuzz 版本同步之外,没有太多的事情要做。然而,仍有许多潜在的改进领域。

  • 更广泛的测试覆盖范围:目前,我们只测试成形输出中定位的字符的结果。我们应该添加测试,以便我们可以测试 API 的其他部分,例如字符范围和字符标志。
  • 针对 harfbuzz 的模糊测试:虽然 rustybuzz 通过了整个 harfbuzz 测试套件,但这并不意味着输出将始终与 harfbuzz 完全相同。鉴于代码库的复杂性,肯定存在尚未发现的其他错误。解决此问题的潜在方法之一可能是创建一个模糊测试器,该测试器使用随机字体,并使用随机Unicode代码点和输入设置进行成形。如果发现差异,则可以调查此测试用例。一旦识别出错误,就可以将其添加到我们的自定义测试套件中。一方面,我们可以使用 Google Fonts 字体集合,以便将字体添加到存储库中,但也可以仅使用 MacOS/Windows 系统字体,并在 CI 中进行测试,类似于当前对 harfbuzz 中的 AAT 所做的测试。
  • 性能harfbuzz 包含大量的优化结构(加速器和缓存),这些结构尚未包含在 rustybuzz 中。因此,在许多情况下性能较差,如上所述(尽管在整体上 rustybuzz 仍然非常高效),但排除所有这些优化的好处是代码库更加简单直接。这使得回滚新更改(这已经是一项非常困难的任务)变得更加容易。现在我们已经与 harfbuzz 同步,我们可以考虑尝试移植一些主要的优化改进,但我们应该谨慎进行,以避免使代码库同步变得更加困难。
  • 代码一致性rustybuzz 尽力使代码库看起来像是一个1:1的C++到Rust的翻译,大多数代码部分都是这样,但也有一些变化(最显著的是在 AAT 中),这是由于许多C++概念不便于移植。尽管如此,考虑到有人花时间研究,可能还有代码部分可以使其更加相似。

这些都是大量工作,因此欢迎贡献。

安全性

库是完全安全的。

我们确实有一个在两个POD结构之间进行转换的不安全操作,但这完全安全。但除了这个之外,这个库及其大多数依赖(不包括bytemuck)中都没有不安全操作。

替代方案

  • harfbuzz_rs - 对实际harfbuzz库的绑定。截至v2版本,没有暴露子集化和字形轮廓,这是harfbuzz所支持的。
  • allsorts - 字形生成器和子集化器。截至v0.6版本,不支持可变字体和苹果高级排版。依赖于一些不安全的代码。
  • swash - 支持可变字体、文本布局和渲染。没有子集化。依赖于一些不安全的代码。截至v0.1.4版本,没有测试。

许可协议

rustybuzzMIT协议许可。

harfbuzz旧MIT协议许可。

依赖项

~2-3MB
~64K SLoC