Skip to content

Support .otf fonts by switching to ttf-parser & ab_glyph_rasterizer

Alex Butler requested to merge (removed):otf into master
  • Major rework to use crates ttf-parser & ab_glyph_rasterizer to respectively read and render OpenType .oft format fonts.
  • Remove dependencies approx, stb_truetype & ordered-float along with in-crate rasterization code.
  • Strip back some non-vital API functionality.
    • Remove support for .standalone() variants which are sparsely used.
    • Remove some functions that didn't immediately translate to ttf-parser. Please raise issues to re-add any you relied on via the new stack.

Supporting .otf fonts will be a major upgrade to rusttype, special thanks to @RazrFalcon for their work on ttf-parser!

Performance

Of course, changing the guts of rusttype affects performance. We have some losses and some big wins.

group                      0.8.3                     rework
-----                      -----                     ------
draw_big_biohazard         1.89    668.9±3.14µs      1.00    354.5±1.23µs
draw_iota                  3.94     20.2±0.06µs      1.00      5.1±0.03µs
draw_oft_tailed_e                                    1.00     92.4±0.47µs
draw_w                     5.06      4.9±0.02µs      1.00    965.4±8.08ns


layout_a_sentence          1.00     20.3±0.16µs      1.36     27.6±0.32µs
layout_a_sentence (vec)                              1.00     27.5±0.13µs

high_position_tolerance    1.00    832.8±5.54µs      1.19   987.7±16.62µs
moving_text                1.00    970.5±4.60µs      1.15  1113.6±11.14µs
moving_text_thrashing      1.08      5.0±0.08ms      1.00      4.6±0.05ms
multi_font_population      1.88  1328.0±81.76µs      1.00   705.6±15.37µs
mutli_font                 1.00   952.1±20.63µs      1.14   1084.6±3.41µs
resizing                   1.06      3.1±0.04ms      1.00      2.9±0.02ms
single_font                1.00    936.1±4.00µs      1.15   1078.0±7.36µs

Wins: Rasterization performance of ttf fonts is between 1.89 & 5.06 times faster using ab_glyph_rasterizer. Very nice, we can mostly thank Raph Levien's font-rs line+quad rasterization logic there which I adapted into ab_glyph_rasterizer.

Losses: Layout is down around 36% slower, also affecting general gpu-cache performance by ~15%. This may be down to differences in performance between stb_truetype-rs & ttf-parser. I also suspect this is, at least in part, due to how rusttype copies Font references very eagerly with every Glyph instance. ttf_parser::Font is heavier that stb_truetype-rs's version. Currently Rusttype uses Arc<ttf_parser::Font> to help with performance because of this.

I aim to investigate different APIs, maybe alternate crates, that avoid font reference copying all together. For now though the added ability to use .otf fonts + the greatly improved draw speed makes this a net positive for rusttype in my book.

Other drawbacks

ttf-parser does not support using owned font data. I consider this a critical ability of rusttype and so I introduced a self-borrowing wrapper for ttf-parser. This involves unsafe code as self-referencing is not currently possible in safe rust. Improvements are welcome.

Compile performance

The shift around in dependencies means clean compile times are a tiny bit faster.

Before

$ hyperfine --runs 3 'cargo clean; cargo build'
Benchmark #1: cargo clean; cargo build
  Time (mean ± σ):      1.997 s ±  0.024 s    [User: 3.638 s, System: 0.350 s]
  Range (min … max):    1.980 s …  2.025 s    3 runs

After

$ hyperfine --runs 3 'cargo clean; cargo build'
Benchmark #1: cargo clean; cargo build
  Time (mean ± σ):      1.830 s ±  0.140 s    [User: 3.157 s, System: 0.249 s]
  Range (min … max):    1.748 s …  1.993 s    3 runs

Resolves #137 (closed)

Edited by Alex Butler

Merge request reports