Procedural Grapheme Generator

Cellular automata → bitmap → vector → TTF. The font running in the banner at the top of this page came out of this.

Where it came from

Procedural Grapheme Generator

I've been into roguelites for a long time — Rogue, Caves of Qud, Dungeons of Dredmor. Part of what draws me to that genre is how much emerges from small, composable systems. I started reading RogueBasin in undergrad and kept coming back to a certain type of article: the ones about tiny algorithms with outsized results. Boids is the obvious example. Cellular automata cave generation is another. A handful of rules, applied repeatedly, and you get something that looks organic and complex.

The grapheme generator came from that same impulse. I was interested in procedural generation generally and stumbled onto the idea that if you treat a character glyph as a bitmap grid, you can run cellular automata on it and get symbol shapes that look like they belong to a real writing system — alien, consistent enough to feel like a language, but completely invented. The other thing I find interesting is the pipeline itself: I didn't write a bitmap library, a vectorizer, or a font compiler. Those tools all exist. The idea was just to chain them together in a way nobody had specifically done before. There's something satisfying about that kind of work — leveraging what's already there and finding where the seams fit.

The font used in the scrolling banner at the top of this site is one that came out of this generator.

The pipeline

Each run generates 100 symbols. The process per symbol is:

  1. Initialize a 2D boolean grid with random fill at a given probability
  2. Apply cellular automata evolution rules for N iterations — each cell lives or dies based on neighbor counts, controlled by two thresholds (r1_cutoff, r2_cutoff)
  3. Write the result to a BMP via EasyBMP
  4. Convert the BMP to SVG with Potrace (bitmap → vector)
  5. Feed all 100 SVGs into FontForge via a Python script to compile a TTF
Directory Structure
ProceduralGraphemeGenerator/
├── src/
│   ├── proceduralGraphemeGenerator.cpp
│   ├── generator.cpp / generator.h    # Cellular automata engine
│   ├── grapheme.cpp / grapheme.h      # Bitmap matrix
│   └── base.cpp / base.h
├── lib/
│   └── EasyBMP.cpp
├── output/                            # BMPs, SVGs, and final TTF land here
├── fontScript.py                      # FontForge compilation script
└── makefile

The cellular automata step is where most of the interesting variation comes from. The two cutoff parameters control the birth and survival rules — small changes produce very different character aesthetics, from sparse geometric shapes to dense blob-like forms. Iteration count handles how "settled" the pattern looks; more iterations smooth things out, fewer leave the shapes rougher.

Parameter Range Description
size_x, size_y 8–128 Bitmap grid dimensions
fill_prob 0–100 Initial fill probability (%)
r1_cutoff 1–10 First evolution rule threshold
r2_cutoff 1–10 Second evolution rule threshold
iterations 1–10 Number of evolution steps

Dependencies you'll need beyond the included EasyBMP:

  • apt-get install potrace — bitmap to vector
  • apt-get install fontforge — TTF compilation

Usage

Bash
# Build
make all

# Run — 32x32 grid, 50% fill, evolution rules 3/5, 5 iterations
./pgg 32 32 50 3 5 5

Output lands in output/: 100 BMP files, 100 SVG files, and one foobar.ttf with all 100 glyphs mapped to ASCII characters.

Web interface

There's a browser-based version where you can tweak parameters and preview the generated symbols without building anything locally.