ttf-parser

Build Status Crates.io Documentation Rust 1.35+

A high-level, safe, zero-allocation TrueType font parser.

Can be used as Rust and as C library.

Features

Safety

Alternatives

It's very hard to compare different libraries, so we are using table-based comparison. There are roughly three types of TrueType tables:

| Feature/Library | ttf-parser | FreeType | stb_truetype | | ----------------- | :--------------------: | :-----------------: | :----------------------------: | | Memory safe | ✓ | | | | Thread safe | ✓ | | ~ (mostly reentrant) | | Zero allocation | ✓ | | | | Variable fonts | ✓ | ✓ | | | Rendering | | ✓ | ~ (very primitive) | | avar table | ✓ | ✓ | | | bdat table | | ✓ | | | bloc table | | ✓ | | | CBDT table | ✓ | ✓ | | | CBLC table | ✓ | ✓ | | | CFF table | ✓ | ✓ | ~ (no seac support) | | CFF2 table | ✓ | ✓ | | | cmap table | ~ (no 8; Unicode-only) | ✓ | ~ (no 2,8,10,14; Unicode-only) | | EBDT table | | ✓ | | | EBLC table | | ✓ | | | fvar table | ✓ | ✓ | | | gasp table | | ✓ | | | GDEF table | ~ | | | | glyf table | ~1 | ✓ | ~1 | | GPOS table | | | ~ (only 2) | | GSUB table | | | | | gvar table | ✓ | ✓ | | | head table | ✓ | ✓ | ✓ | | hhea table | ✓ | ✓ | ✓ | | hmtx table | ✓ | ✓ | ✓ | | HVAR table | ✓ | ✓ | | | kern table | ✓ | ~ (only 0) | ~ (only 0) | | maxp table | ✓ | ✓ | ✓ | | MVAR table | ✓ | ✓ | | | name table | ✓ | ✓ | | | OS/2 table | ✓ | ✓ | | | post table | ✓ | ✓ | | | sbix table | ~ (PNG only) | ~ (PNG only) | | | SVG table | ✓ | | ✓ | | vhea table | ✓ | ✓ | | | vmtx table | ✓ | ✓ | | | VORG table | ✓ | ✓ | | | VVAR table | ✓ | ✓ | | | Language | Rust + C API | C | C | | Dynamic lib size | <300KiB2 | ~760KiB3 | ? (header-only) | | Tested version | 0.8.0 | 2.9.1 | 1.24 | | License | MIT / Apache-2.0 | FTL / GPLv2 | public domain |

Legend:

Notes:

  1. Matching points are not supported.
  2. When using from Rust, the library binary overhead depends on used methods and can vary from 10KiB up to 100KiB.
    When using from C, we have to include the Rust's std too, which blows up the size.
  3. Depends on build flags.

Performance

TrueType fonts designed for fast querying, so most of the methods are very fast. The main exception is glyph outlining. Glyphs can be stored using two different methods: using Glyph Data format and Compact Font Format (pdf). The first one is fairly simple which makes it faster to process. The second one is basically a tiny language with a stack-based VM, which makes it way harder to process.

The benchmark tests how long it takes to outline all glyphs in the font.

| Table/Library | ttf-parser | FreeType | stb_truetype | | ------------- | -------------: | ---------: | -------------: | | glyf | 0.835 ms | 1.194 ms | 0.695 ms | | gvar | 3.158 ms | 3.594 ms | - | | CFF | 1.114 ms | 5.946 ms | 2.862 ms | | CFF2 | 1.763 ms | 7.001 ms | - |

Note: FreeType is surprisingly slow, so I'm worried that I've messed something up.

And here are some methods benchmarks:

```text test outlineglyph276fromcff2 ... bench: 778 ns/iter (+/- 15) test fromdataotfcff ... bench: 760 ns/iter (+/- 13) test fromdataotfcff2 ... bench: 709 ns/iter (+/- 25) test outlineglyph276fromcff ... bench: 678 ns/iter (+/- 41) test outlineglyph276fromglyf ... bench: 649 ns/iter (+/- 11) test outlineglyph8fromcff2 ... bench: 476 ns/iter (+/- 14) test fromdatattf ... bench: 352 ns/iter (+/- 11) test glyphnamepost276 ... bench: 223 ns/iter (+/- 5) test outlineglyph8fromcff ... bench: 261 ns/iter (+/- 13) test outlineglyph8fromglyf ... bench: 281 ns/iter (+/- 5) test familyname ... bench: 183 ns/iter (+/- 102) test glyphnamecff276 ... bench: 109 ns/iter (+/- 1) test glyphindexu41 ... bench: 16 ns/iter (+/- 0) test glyphnamecff8 ... bench: 7 ns/iter (+/- 0) test glyphnamepost_8 ... bench: 2 ns/iter (+/- 0)

test subscriptmetrics ... bench: 2 ns/iter (+/- 0) test glyphhoradvance ... bench: 2 ns/iter (+/- 0) test glyphhorsidebearing ... bench: 2 ns/iter (+/- 0) test glyphname8 ... bench: 1 ns/iter (+/- 0) test ascender ... bench: 1 ns/iter (+/- 0) test underlinemetrics ... bench: 1 ns/iter (+/- 0) test strikeoutmetrics ... bench: 1 ns/iter (+/- 0) test xheight ... bench: 1 ns/iter (+/- 0) test unitsper_em ... bench: 0.5 ns/iter (+/- 0) test width ... bench: 0.2 ns/iter (+/- 0) ```

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.