A high-level, safe, zero-allocation TrueType font parser.
APACHE-2.0 License
A high-level, safe, zero-allocation font parser for TrueType, OpenType, and AAT.
Can be used as a Rust or C library.
no_std
/WASM compatible.It's very hard to compare different libraries, so we are using table-based comparison. There are roughly three types of TrueType tables:
head
, OS/2
, etc.).glyf
, CFF
(kinda), hmtx
, etc.).cmap
, kern
, GPOS
, etc.).Feature/Library | ttf-parser | FreeType | stb_truetype |
---|---|---|---|
Memory safe | ✓ | ||
Thread safe | ✓ | ~ (mostly reentrant) | |
Zero allocation | ✓ | ||
Variable fonts | ✓ | ✓ | |
Rendering | -1 | ✓ | ~ (very primitive) |
ankr table |
✓ | ||
avar table |
✓ | ✓ | |
bdat table |
~ (no 4) | ✓ | |
bloc table |
✓ | ✓ | |
CBDT table |
~ (no 8, 9) | ✓ | |
CBLC table |
✓ | ✓ | |
COLR table |
✓ | ✓ | |
CPAL table |
✓ | ✓ | |
CFF table |
✓ | ✓ | ~ (no seac support) |
CFF2 table |
✓ | ✓ | |
cmap table |
~ (no 8) | ✓ | ~ (no 2,8,10,14; Unicode-only) |
EBDT table |
~ (no 8, 9) | ✓ | |
EBLC table |
✓ | ✓ | |
feat table |
✓ | ||
fvar table |
✓ | ✓ | |
gasp table |
✓ | ||
GDEF table |
~ | ||
glyf table |
~2 | ✓ | ~2 |
GPOS table |
✓ | ~ (only 2) | |
GSUB table |
✓ | ||
gvar table |
✓ | ✓ | |
head table |
✓ | ✓ | ✓ |
hhea table |
✓ | ✓ | ✓ |
hmtx table |
✓ | ✓ | ✓ |
HVAR table |
✓ | ✓ | |
kern table |
✓ | ~ (only 0) | ~ (only 0) |
kerx table |
✓ | ||
MATH table |
✓ | ||
maxp table |
✓ | ✓ | ✓ |
morx table |
✓ | ||
MVAR table |
✓ | ✓ | |
name table |
✓ | ✓ | |
OS/2 table |
✓ | ✓ | |
post table |
✓ | ✓ | |
sbix table |
~ (PNG only) | ~ (PNG only) | |
STAT table |
✓ | ||
SVG table |
✓ | ✓ | ✓ |
trak table |
✓ | ||
vhea table |
✓ | ✓ | |
vmtx table |
✓ | ✓ | |
VORG table |
✓ | ✓ | |
VVAR table |
✓ | ✓ | |
Language | Rust + C API | C | C |
Tested version | 0.17.0 | 2.12.0 | 1.24 |
License | MIT / Apache-2.0 | FTL / GPLv2 | public domain |
Legend:
Notes:
ttf-parser
doesn't support rendering by itself,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 a font.
x86 (AMD 3700X)
Table/Library | ttf-parser | FreeType | stb_truetype |
---|---|---|---|
glyf |
0.901 ms |
1.171 ms |
0.675 ms |
gvar |
2.972 ms |
4.132 ms |
- |
CFF |
1.197 ms |
5.647 ms |
2.813 ms |
CFF2 |
1.968 ms |
6.392 ms |
- |
ARM (Apple M1)
Table/Library | ttf-parser | FreeType | stb_truetype |
---|---|---|---|
glyf |
0.550 ms |
0.854 ms |
0.703 ms |
gvar |
2.270 ms |
4.594 ms |
- |
CFF |
1.054 ms |
5.223 ms |
3.262 ms |
CFF2 |
1.765 ms |
5.995 ms |
- |
Note: FreeType is surprisingly slow, so I'm worried that I've messed something up.
And here are some methods benchmarks:
test outline_glyph_276_from_cff2 ... bench: 867 ns/iter (+/- 15)
test from_data_otf_cff ... bench: 968 ns/iter (+/- 13)
test from_data_otf_cff2 ... bench: 887 ns/iter (+/- 25)
test outline_glyph_276_from_cff ... bench: 678 ns/iter (+/- 41)
test outline_glyph_276_from_glyf ... bench: 649 ns/iter (+/- 11)
test outline_glyph_8_from_cff2 ... bench: 534 ns/iter (+/- 14)
test from_data_ttf ... bench: 467 ns/iter (+/- 11)
test glyph_name_post_276 ... bench: 223 ns/iter (+/- 5)
test outline_glyph_8_from_cff ... bench: 315 ns/iter (+/- 13)
test outline_glyph_8_from_glyf ... bench: 291 ns/iter (+/- 5)
test family_name ... bench: 183 ns/iter (+/- 102)
test glyph_name_cff_276 ... bench: 62 ns/iter (+/- 1)
test glyph_index_u41 ... bench: 16 ns/iter (+/- 0)
test glyph_name_cff_8 ... bench: 5 ns/iter (+/- 0)
test glyph_name_post_8 ... bench: 2 ns/iter (+/- 0)
test subscript_metrics ... bench: 2 ns/iter (+/- 0)
test glyph_hor_advance ... bench: 2 ns/iter (+/- 0)
test glyph_hor_side_bearing ... bench: 2 ns/iter (+/- 0)
test glyph_name_8 ... bench: 1 ns/iter (+/- 0)
test ascender ... bench: 1 ns/iter (+/- 0)
test underline_metrics ... bench: 1 ns/iter (+/- 0)
test strikeout_metrics ... bench: 1 ns/iter (+/- 0)
test x_height ... bench: 1 ns/iter (+/- 0)
test units_per_em ... bench: 0.5 ns/iter (+/- 0)
test width ... bench: 0.2 ns/iter (+/- 0)
Licensed under either of
at your option.
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.