| Crates.io | beamterm-atlas |
| lib.rs | beamterm-atlas |
| version | 0.7.0 |
| created_at | 2025-06-06 15:28:20.66391+00 |
| updated_at | 2025-09-07 16:20:29.853975+00 |
| description | Font atlas generator for beamterm WebGL terminal renderer, creating GPU-optimized texture arrays from TTF/OTF fonts |
| homepage | https://github.com/junkdog/beamterm |
| repository | https://github.com/junkdog/beamterm |
| max_upload_size | |
| id | 1703191 |
| size | 121,090 |
A font atlas generator for WebGL terminal renderers, optimized for GPU texture memory and rendering efficiency.
beamterm-atlas generates tightly-packed 2D texture array atlases from TTF/OTF font files, producing a
binary format optimized for GPU upload. The system supports multiple font styles, full Unicode
including emoji, and automatic grapheme clustering.
The crate consists of:
The system uses a 16-bit glyph ID that encodes both the base character and its style variations:
| Bit Range | Purpose | Description |
|---|---|---|
| 0-9 | Base Glyph ID | 1024 possible base glyphs (0x000-0x3FF) |
| 10 | Bold Flag | Selects bold variant (0x0400) |
| 11 | Italic Flag | Selects italic variant (0x0800) |
| 12 | Emoji Flag | Indicates emoji glyph (0x1000) |
| 13 | Underline | Underline effect (0x2000) |
| 14 | Strikethrough | Strikethrough effect (0x4000) |
| 15 | Reserved | Reserved for future use |
The atlas only encodes glyphs with the first 13 bits. Bits 13 and 14 are applied at runtime for text decoration effects, while bit 15 is reserved for future extensions.
Each base glyph automatically generates four style variants by combining the bold and italic flags:
| Style | Bit Pattern | ID Offset | Example ('A' = 0x41) |
|---|---|---|---|
| Normal | 0x0000 |
+0 | 0x0041 |
| Bold | 0x0200 |
+512 | 0x0241 |
| Italic | 0x0400 |
+1024 | 0x0441 |
| Bold+Italic | 0x0600 |
+1536 | 0x0641 |
This encoding allows the shader to compute texture coordinates directly from the glyph ID without lookup tables.
The generator assigns IDs based on three character categories:
1. ASCII Characters (0x00-0x7F)
2. Unicode Characters
3. Emoji Characters
With the ID assignment scheme:
For a typical atlas with ~500 base glyphs + 100 emoji:
Each texture layer contains a 32×1 grid of glyphs:
Position in layer = ID & 0x1F (modulo 32)
Grid X = Position (0-31)
Grid Y = 0 (always single row)
Layer = ID ÷ 32
The 2D texture array uses RGBA format with dimensions:
The RGBA format is required for emoji support - while monochrome glyphs could use a single channel, emoji glyphs need full color information.
This layout ensures:
The system determines cell size by measuring the full block character █ to ensure all glyphs
fit within the cell boundaries. Additional padding of 1px on all sides prevents texture bleeding.
Each glyph is rendered four times, one for each of the styles (normal, bold, italic, bold+italic).
Emoji glyphs require special processing:
The presence of emoji is the primary reason the atlas uses RGBA format instead of a single-channel texture. While monochrome glyphs only need an alpha channel, emoji require full color information to render correctly.
The atlas uses a versioned binary format with header validation:
Header (5 bytes)
├─ Magic: [0xBA, 0xB1, 0xF0, 0xA7]
└─ Version: 0x01
Metadata Section
├─ Font name (u8 length + UTF-8 string)
├─ Font size (f32)
├─ Texture width (i32)
├─ Texture height (i32)
├─ Texture layers (i32)
├─ Cell width (i32)
├─ Cell height (i32)
├─ Underline position (f32)
├─ Underline thickness (f32)
├─ Strikethrough position (f32)
├─ Strikethrough thickness (f32)
└─ Glyph count (u16)
Glyph Definitions
└─ Per glyph:
├─ ID (u16 - includes style bits)
├─ Style (u8) - ordinal: 0=Normal, 1=Bold, 2=Italic, 3=BoldItalic
├─ Is emoji (u8) - 0=false, 1=true
├─ Pixel X (i32)
├─ Pixel Y (i32)
└─ Symbol (u8 length + UTF-8 string)
Compressed Texture Data
├─ Data length (u32)
└─ zlib-compressed RGBA data
cargo install beamterm-atlas
beamterm-atlas [OPTIONS] <FONT>
<FONT> - Font selection by name (partial match) or 1-based index-s, --font-size <SIZE> - Font size in points (default: 15.0)-l, --line-height <MULTIPLIER> - Line height multiplier (default: 1.0)-o, --output <PATH> - Output file path (default: "./bitmap_font.atlas")--underline-position <FRACTION> - Underline position from 0.0 (top) to 1.0 (bottom) of cell (default: 0.85)--underline-thickness <PERCENT> - Underline thickness as percentage of cell height (default: 5.0)--strikethrough-position <FRACTION> - Strikethrough position from 0.0 (top) to 1.0 (bottom) of cell (default: 0.5)--strikethrough-thickness <PERCENT> - Strikethrough thickness as percentage of cell height (default: 5.0)-L, --list-fonts - List available fonts and exitList all available monospace fonts with complete style variants:
beamterm-atlas --list-fonts
Generate an atlas using JetBrains Mono at 16pt:
beamterm-atlas "JetBrains Mono" -s 16 -o jetbrains-16.atlas
Generate with custom text decoration settings:
beamterm-atlas "Fira Code" \
--underline-position 0.9 \
--underline-thickness 7.5 \
--strikethrough-position 0.45
Select font by index (useful for scripting):
# First, list fonts to see indices
beamterm-atlas -L
# Then select by number
beamterm-atlas 5 -s 14
The tool generates an atlas from a predefined character set including:
The verify-atlas binary visualizes the texture layout, showing:
verify-atlas
The generator requires monospace fonts with all four style variants:
Fonts missing any variant will not appear in the font list. The system automatically discovers all installed system fonts that meet these requirements.