googlefonts / oxidize

Notes on moving tools and libraries to Rust.
Apache License 2.0
173 stars 7 forks source link

oxidize

Wherein we contemplate moving shaping, rasterization, font compilation, and general font inspection and manipulation from Python & C++ to Rust.

Table of Contents

Why

We currently rely C++ for anything high performance, e.g. shaping or subsetting, and Python for general purpose manipulation. The results are exactly what you'd expect:

Some logic ends up implemented in both languages. For example, when it became apparent the Python subsetter was too slow for both runtime serving and future projects like progressive font enrichment the hb-subset project was born.

Rust appears to offer us the ability to implement fast, safer code with development velocity in between Python and C++. This is a very appealing offer.

Goals

Our priorities, higher priority items first, are:

What Why
Minimal or no unsafe, fast, memory-efficient If it's not fast enough or it hogs memory nobody will ship it. We would accept unsafe - that we can convince ourselves to be safe - if it got us substantial perf. We're not specifically aiming for #![forbid(unsafe_code)], though it would be nice.
Ergonomic, hackable Ergonomic: friendly to consumers, idiomatic wherever possible. Hackable: friendly to developers modifying the code

Taken from discussion here.

Support both our primary usage patterns

  1. Performance-critical read-only users (shaping, rasterization)
    • HarfBuzz and FreeType have years of performance optimizations. A replacement that is significantly slower will not land.
  2. Read/write use (compilers, utilities)
    • Performance is less critical here. We don't want to be slow, but we don't need the level of performance obsession shaping needs either.

For read-only users we may need to support readonly mmap access. Crates like zerocopy and the like suggest this is possible. Establishing a clean pattern here should be tackled early. https://github.com/googlefonts/oxidize/pull/3 proposes a path forward.

Offer memory safety for text rendering

Chrome and Microsoft both observe that:

  1. 70% of high severity security bugs are memory safety issues (Chrome, Microsoft)
  2. Rust may help
    • If it can play nice with C++
    • For Fonts we can, if necessary, limit ourselves to stable C ABI

A safe text stack is desirable for Chrome, Android, and more. At time of writing we observe a semi-steady stream of fuzzer issues. It seems plausible a Rust rewrite can stop the bleeding. This is promising enough it's well worth giving it a try!

HarfBuzz is the primary target. Some parts of FreeType used in Chrome and Android may also need to be replaced. If we do both the stream of fuzzer issues should stop.

A productive codebase

We seek to provide a developer friendly codebase. For example, exploration of new structs for something COLRv1 should be readily achievable by forking and hacking around. That means the code needs to be simpler than today's C++ and as close as possible to Python level development velocity. To achieve this we will seek to establish an efficient pattern to support our two primary usage patterns. This will require that we:

Prefer incremental delivery, early production use

We will prefer to:

Getting started

Updated 8/16/2024. Our first phase projects are:

  1. Skrifa, meant to replace FreeType in Chrome
  2. fontc, meant to replace fontmake

The next phase is:

  1. klippa, meant to be a memory safe replacement for hb-subset and fonttools subset
    • Google Fonts depends haveily on subsetting
  2. harfruzz, meant to replace HarfBuzz shaping

Both phases build on core read/write fonts work in https://github.com/googlefonts/fontations.

Definitions

zerocopy

The direct reading/writing of scalars and, wherever possible, aggregates (structs and slices) through reinterpretation of pointers to raw bytes in memory.

Where's the code?

The graph below depicts, and links to (warning copy the links rather than clicking on them until https://github.com/community/community/discussions/17545 resolves), active projects and their relationships (arrows indicate dependency):

flowchart TD
    subgraph Font Compiler
        fontc
    end
    fontc --> read-fonts
    fontc --> write-fonts

    subgraph Typesetting Application
         Chrome
    end
    Chrome --> skrifa

    subgraph Load outlines and metadata
        skrifa
    end
    subgraph read
        read-fonts    
    end
    subgraph write
        write-fonts    
    end

    skrifa --> read-fonts
    write-fonts --> read-fonts    
    subgraph common
        font-types
    end

    read-fonts --> common

    click fontmake-rs "https://github.com/googlefonts/fontmake-rs"
    click otexplorer "https://github.com/googlefonts/fontations/tree/main/otexplorer"
    click read-fonts "https://github.com/googlefonts/fontations/tree/main/read-fonts"
    click write-fonts "https://github.com/googlefonts/fontations/tree/main/write-fonts"
    click font-types "https://github.com/googlefonts/fontations/tree/main/font-types"

References

Internal

References within this repository.

External