• Stars
    star
    609
  • Rank 73,614 (Top 2 %)
  • Language
    Rust
  • License
    Apache License 2.0
  • Created over 5 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

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

ttf-parser

Build Status Crates.io Documentation Rust 1.42+

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

Supports TrueType, OpenType and AAT fonts.

Can be used as Rust and as C library.

Features

  • A high-level API for most common properties, hiding all parsing and data resolving logic.
  • A low-level, but safe API to access TrueType tables data.
  • Highly configurable. You can disable most of the features, reducing binary size. You can also parse TrueType tables separately, without loading the whole font/face.
  • Zero heap allocations.
  • Zero unsafe.
  • Zero dependencies.
  • no_std/WASM compatible.
  • A basic C API.
  • Fast.
  • Stateless. All parsing methods are immutable.
  • Simple and maintainable code (no magic numbers).

Safety

  • The library must not panic. Any panic considered as a critical bug and should be reported.
  • The library forbids unsafe code.
  • No heap allocations, so crash due to OOM is not possible.
  • All recursive methods have a depth limit.
  • Technically, should use less than 64KiB of stack in the worst case scenario.
  • Most of arithmetic operations are checked.
  • Most of numeric casts are checked.

Alternatives

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

  • A table with a list of properties (like head, OS/2, etc.).
    If a library tries to parse it at all then we mark it as supported.
  • A table that contains a single type of data (glyf, CFF (kinda), hmtx, etc.).
    Can only be supported or not.
  • A table that contains multiple subtables (cmap, kern, GPOS, etc.).
    Can be partially supported and we note which subtables are actually supported.
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)
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:

  • βœ“ - supported
  • ~ - partial
  • nothing - not supported

Notes:

  1. While ttf-parser doesn't support rendering by itself, there are multiple rendering libraries on top of it: rusttype, ab-glyph and fontdue.
  2. Matching points are not supported.

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 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)

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.

More Repositories

1

resvg

An SVG rendering library.
Rust
2,684
star
2

cargo-bloat

Find out what takes most of the space in your executable.
Rust
2,295
star
3

svgcleaner

svgcleaner could help you to clean up your SVG files from the unnecessary data.
Rust
1,621
star
4

tiny-skia

A tiny Skia subset ported to Rust
Rust
1,089
star
5

pico-args

An ultra simple CLI arguments parser.
Rust
560
star
6

rustybuzz

A complete harfbuzz's shaping algorithm port to Rust
Rust
533
star
7

roxmltree

Represent an XML document as a read-only tree.
Rust
428
star
8

svgcleaner-gui

GUI for svgcleaner.
C++
306
star
9

fontdb

A simple, in-memory font database with CSS-like queries.
Rust
136
star
10

xmlparser

A low-level, pull-based, zero-allocation XML 1.0 parser.
Rust
130
star
11

color-thief-rs

Grabs the dominant color or a representative color palette from an image.
Rust
75
star
12

svgtypes

A collection of parsers for SVG types.
Rust
67
star
13

rctree

A "DOM-like" tree implemented using reference counting
Rust
37
star
14

simplecss

A simple CSS 2.1 parser and selector
Rust
35
star
15

svgdom

Library to represent an SVG as a DOM.
Rust
31
star
16

ttf-explorer

A simple tool to explore a TrueType font content as a tree
C++
30
star
17

xmlwriter

A simple, streaming XML writer.
Rust
24
star
18

resvg-test-suite

resvg test suite
C++
23
star
19

svgparser

(DEPRECATED) Featureful, pull-based, zero-allocation SVG parser.
Rust
22
star
20

notes-on-svg-parsing

Notes on SVG parsing
21
star
21

barh

A simple horizontal bar chart generator.
Rust
9
star
22

strict-num

A collection of bounded numeric types.
Rust
8
star
23

unicode-vo

Unicode vertical orientation detection
Rust
6
star
24

unicode-ccc

Unicode Canonical Combining Class detection
Rust
4
star
25

unicode-bidi-mirroring

Unicode Bidi Mirroring property detection
Rust
3
star
26

RazrFalcon

2
star
27

stb_truetype_meson

C
1
star