Library / SDK
dfrg/swash avatar
dfrg/swash

swash: font introspection, text shaping and glyph rendering in Rust

Font introspection, complex text shaping and glyph rendering.

878 stars62 forksRustApache-2.0

At a glance

What is it?
swash is a pure Rust crate that reads fonts, shapes complex scripts and renders glyphs without imposing a layout or rendering policy, which leaves the last two layers of the stack to the application.
Who is it for?
swash suits Rust developers building a custom text stack, a game engine renderer or a script-aware editor who need shaping and glyph access without a full layout engine. It is the wrong dependency if you want line breaking and paragraph layout handled for you, since the project lists text layout as an explicit non goal and points to a sibling crate still in development.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 98 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A crate that deliberately stops before layout

Swash describes itself as a pure Rust, cross-platform crate for font introspection, complex text shaping and glyph rendering, and the interesting part of the design is where it refuses to go. The project keeps text layout out of scope on the grounds that the requirements for features and performance differ greatly among web browsers, word processors, text editors and game engines. Composition is excluded too, since glyph caching, geometry batching and rendering are said to be hardware dependent. What remains is the layer that all of those applications share: reading font files, understanding what they contain, turning characters into positioned glyphs, and producing outlines or bitmaps. A developer who needs a shaping layer that will not dictate how pixels are pushed is the intended user. Anyone expecting a drop in text rendering engine will be disappointed by design rather than by omission.

Borrowed font data and per-thread acceleration structures

The architecture claim worth understanding is the separation of font bytes from acceleration structures. Swash presents font data as a simple borrowed representation that imposes no requirements on resource management, and it keeps acceleration structures completely separate from that data. Those structures can be retained per thread, discarded, and rebuilt whenever the application wants. The scratch buffers and caches live in contexts, and resources belonging to evicted cache entries are reused immediately rather than returned to the allocator. The project describes its introspection work as zero allocation and zero copy. None of that is measurable from the outside without running benchmarks, and no benchmark numbers are published in the README, so the claims here are design intentions stated by the author rather than verified figures. For an application that shapes the same script in several threads, the per-thread context model is the part that changes how you structure the code.

Shaping scripts that OpenType tables alone do not cover

Complex text shaping is where swash puts most of its weight. It supports the OpenType advanced typography tables GSUB and GPOS, variable fonts including positioning and feature substitutions, ligatures, marks and kerning. For Apple fonts, glyph metamorphosis through the morx table is fully supported, while extended kerning through kerx is described as covering most common cases, kerning and mark positioning, which is a partial guarantee rather than a complete one. An implementation of the Universal Shaping Engine is included for scripts such as Devanagari and Malayalam, and Arabic joining is handled with Urdu style climbing runs. Individual features can be enabled or disabled, and alternates such as swashes can be activated with argument support. Shaper output is organised by cluster and includes original source ranges, so a caller can map a shaped glyph back to the text that produced it, and per character user data plus per cluster information can be carried through for style properties, word and line boundaries, whitespace and emoji presentation modes.

Font introspection that covers the awkward fields

The introspection surface is broad, and several of the entries cover cases that are easy to get wrong in a home grown font reader. Swash can enumerate font collections in ttc and otc form, extract localized strings including names and metadata, and list variation axes with their named instances. It reports comprehensive font and per-glyph metrics, synthesising vertical metrics when the font does not provide them, and it exposes primary attributes such as stretch, weight and style with synthesis suggestions based on available variations and scaler transforms, which covers faux bold and oblique. There is support for colour palettes, embedded colour and alpha bitmap strikes, and character to nominal glyph identifier mapping with the ability to enumerate all pairs. The writing system information goes beyond a script name, providing a list of supported script and language pairs together with their associated typographic features. A separate text analysis area handles Unicode character properties, canonical and compatible composition and decomposition, script aware cluster segmentation, and a single pass iterator based analysis that determines word and line boundaries and detects whether bidi resolution is needed.

Emoji strikes and a configurable glyph source order

Glyph rendering in swash covers scalable outlines for TrueType and Postscript with full variation support, asymmetric vertical hinting, horizontal subpixel rendering and fractional positioning, plus path effects such as stroking and dashing. Transforms include synthetic emboldening and affine transformations. The colour side is the more unusual part. Full emoji support is offered for the Apple sbix format, the Google CBLC and CBDT formats and the Microsoft COLR and CPAL formats, and the choice of which source to use is not left to the caller as a binary decision. Swash applies a customizable glyph source prioritisation, best fit colour bitmap first, then exact size alpha bitmap, then the outline, and lets you change that order. That ordering is the kind of detail that normally ends up hard coded in every engine that draws emoji, so having it as a policy decision is a reasonable reason to reach for this crate.

Feature flags decide how much of the stack you compile

The manifest shows how the crate is layered. The default feature set is std, scale and render, where render depends on scale, and scale is what pulls in the scaling and evaluation dependencies. Optional dependencies are yazi, zeno, core_maths and skrifa, and each of them is tied to a feature rather than pulled in unconditionally:

toml
[features]
default = ["std", "scale", "render"]

Two of the optional crates are interesting for constrained targets. A libm feature forwards to core_maths, skrifa/libm and the optional zeno dependency, and a std feature forwards to skrifa/std, zeno and the optional yazi dependency. The dependency on skrifa is the widest constraint in the file:

toml
skrifa = { version = ">= 0.31.1, <= 0.44", default-features = false }

That range spans a wide set of releases, so a conflict with another crate in the same graph is plausible, and a project adding swash should resolve the skrifa version early rather than at the end of a build. Clippy lints are configured in the manifest for doc markdown and for semicolons after statements that return nothing. The documentation build is set to include all features, and the docs are platform neutral with the x86_64 unknown linux gnu target used as the default target for rendering.

Adding swash to a Cargo project and reading the manifest

The README does not contain a shell command for adding the crate, so there is no install snippet to reproduce here. The badges at the top of the README point to the crates.io listing for swash and to the generated documentation on docs.rs, and those are the places the project directs you to. The manifest is the honest description of what you would pull in. A dependency entry in the 2021 edition carries the crate version, its author, the dual license and the category metadata:

toml
[package]
name = "swash"
version = "0.2.10"
authors = ["Chad Brokaw <[email protected]>"]
edition = "2021"
description = "Font introspection, complex text shaping and glyph rendering."
license = "Apache-2.0 OR MIT"

A first real use therefore starts by adding swash to a Cargo project and turning features on or off deliberately, rather than accepting the default set of std, scale and render. If the goal is introspection and shaping only, dropping the render feature also drops the scale feature and the yazi and zeno dependencies, which is where the crate gets its bulk. The repository itself is small in layout terms, with .github, .clippy.toml, .typos.toml, Cargo.toml, LICENSE-APACHE, LICENSE-MIT, README.md and a src directory.

Where swash hands the work back to you

The clearest boundary is the one the project draws around itself. Because layout and composition are non goals, adopting swash means accepting responsibility for line breaking, paragraph direction, glyph caching, geometry batching and the choice of how to submit draws to the graphics API. That is a fair trade for an application with unusual typographic needs, and a poor one for a product that simply needs text on screen quickly. The project points to a sibling crate in development that provides general purpose text layout based on swash, and that is the natural next thing to watch rather than building a layout engine from scratch. Version numbers also deserve a second look. The manifest carries version 0.2.10 while the most recent tagged releases listed for the project are v0.2.2 from 2025-04-02, with v0.2.1 and v0.2.0 both dated 2025-03-25, so the tags and the manifest version are not aligned. The last push to the repository was on 2026-07-17 and the repository is not archived.

Editorial conclusion

swash suits Rust developers building a custom text stack, a game engine renderer or a script-aware editor who need shaping and glyph access without a full layout engine. It is the wrong dependency if you want line breaking and paragraph layout handled for you, since the project lists text layout as an explicit non goal and points to a sibling crate still in development. Before you adopt it, check the default feature set in Cargo.toml, because render pulls in scaling, and confirm that the skrifa version range it accepts matches the rest of your dependency graph.

Frequently asked questions

What does the swash crate do?

Swash is a pure Rust, cross-platform crate that provides font introspection, complex text shaping and glyph rendering. It deliberately leaves text layout and composition to the application.

Which license is swash released under?

The crate is offered under either the Apache License, Version 2.0 or the MIT license, at your option. The manifest records it as license = "Apache-2.0 OR MIT" and the repository root holds LICENSE-APACHE and LICENSE-MIT.

Does swash support complex scripts and emoji?

Yes. It includes an implementation of the Universal Shaping Engine for scripts such as Devanagari and Malayalam, Arabic joining with Urdu style climbing runs, and full emoji support for the Apple sbix, Google CBLC and CBDT, and Microsoft COLR and CPAL formats.

Can I use swash without the standard library?

The manifest exposes a libm feature that forwards to core_maths, skrifa/libm and the optional zeno dependency, alongside a std feature. The default feature set is std, scale and render, so a no_std build means turning those defaults off explicitly.

Does swash do text layout for me?

No. Text layout is listed as an explicit non goal, along with composition, because those areas are application specific and hardware dependent. A sibling crate in development provides general purpose text layout based on this library.

What dependency version range does swash require for skrifa?

The manifest pins skrifa to a range of ">= 0.31.1, <= 0.44" with default features disabled. A wide range like that can conflict with other crates in the same dependency graph, so it is worth resolving early.

Official sources

  1. dfrg/swash on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dfrg-swash.svg)](https://hysenlabs.com/projects/dfrg-swash)

Was this useful?