Font outlines in. Pixels out. Pure Ruby.

Read TrueType, OpenType, and TTC files, extract their outlines, and render antialiased grayscale, LCD, or color glyph bitmaps— without native extensions.

gem install alhena
Rendered coverage Noto Sans · S · 48 px
The letter S rendered as a 23 by 36 pixel grayscale coverage bitmap by Alhena
Width
23 px
Height
36 px
Channels
R8

One path from font table to bitmap.

  1. 1Parse tables
  2. 2Resolve glyph
  3. 3Build outline
  4. 4Rasterize coverage

The rendering layer Ruby was missing.

Alhena keeps the path from raw font bytes to immutable bitmap coverage inside one dependency-free Ruby library.

Analytic rasterization

Grayscale and RGB/BGR LCD coverage with gamma, darkening, and subpixel positioning.

Variable fonts

Inspect axes and render persistent instances across fvar, gvar, avar, HVAR, and VVAR data.

Color glyphs

Render COLR/CPAL layers and embedded sbix or CBDT/CBLC bitmap strikes.

Bounded by design

Lazy table parsing, checked reads, immutable output, and entry- or byte-bounded LRU caching.

A glyph bitmap in six lines.

The API exposes the useful result without hiding outlines, metrics, or raw table data.

require "alhena"

font = Alhena::Font.open("NotoSans-Regular.ttf")
glyph = font.glyph_id("A")
bitmap = font.rasterize(glyph, size: 24)

puts bitmap.to_ascii

Broad font support, explicit limits.

Supported paths are documented precisely. Unsupported structures fail with typed errors.

Containers
TrueType, OpenType CFF1/CFF2, TTC
Unicode maps
cmap 0, 4, 6, 12, 13, 14
Variation
fvar, gvar, avar v1, HVAR, VVAR
Color
COLR/CPAL v0, sbix PNG, CBDT/CBLC

Shaping, hinting, kerning, and system font discovery stay outside Alhena’s scope. Pair it with the specialist tool your application needs.

Measured, not promised.

Median local measurements on Ruby 4.0 with YJIT on arm64-darwin24.

Open Noto Sans
64.73 µs
Rasterize A at 14 px
40.11 µs
Cached glyph hit
0.48 µs
Prewarm 95 ASCII glyphs
4.79 ms

Render your first glyph.

gem install alhena
Start with the README