Skip to content
Sample of Generative Type Letterforms

toxi_openframeworks · GenerativeTypeLetterforms

Generative Type Letterforms

Letterforms assembled from a 9×9 stroke grid alphabet (A–Z subset), then modulated by a parametric function (bar widths and stroke positions follow `a * sin(b*x + c)` style curves) and optionally recursively subdivided into smaller marks. The skeleton is the parametric-typography idea behind Karsten Schmidt's `thi.ng/font` (which defines glyphs from grids of vertical / horizontal / diagonal / dot primitives via a JSON grammar) and the oF / Processing generative-typography canon (Rune Madsen's *Printing Code*) where letters are shape systems rather than polygon outlines.

Original: https://github.com/thi-ng/font

▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.

Family
toxi_openframeworks
Source
toxi · openFrameworks
Evolution
geometric
Render
rasterized_glyph
Complexity
low
Agents
0
Year
2018
Author
Karsten Schmidt (thi.ng/font) / Rune Madsen (Printing Code)

Math essence

Each character lives on a fixed 9×9 grid. For each 'on' cell at (i, j), compute mod = amp * sin(freq*π*i/(n-1) + phase) + amp/2 * sin(...). In `modulate` mode the cell size is locally scaled by `(1 + 0.35*mod)`. In `shift` mode the cell is translated by `(cell * mod, cell * mod)`. With probability `subdiv_prob`, a randomly-colored sub-cell (the 'glow' color) is painted at the cell location. The output is rasterized to a HxWx3 image with the chosen ink/glow/bg colors.

Parameters

Name Type Default Range Description
dim int 360 200–1000 Square canvas side length in pixels.
text str TOXI — Text to render (uppercased, A-Z glyph subset).
cell_size int 28 8–64 Base pixel size of one stroke cell.
param_freq float 1.6 0.5–8 Spatial frequency of the modulating sinusoid.
param_amp float 0.55 0–1 Amplitude of the modulating sinusoid.
subdiv_prob float 0.35 0–1 Per-cell probability of a sub-mark being added.
subdiv_levels int 1 0–4 Recursion depth for sub-marks.
mode str modulate — How the parametric function affects each cell.
bg_color tuple 245,240,230 — Background colour.
ink_color tuple 38,38,52 — Main glyph stroke colour.
glow_color tuple 220,90,70 — Sub-mark / subdivision colour.
seed int null 0–999999 RNG seed.

Reference

First 60 lines of reference.py. Full source: library_external/toxi_openframeworks/GenerativeTypeLetterforms/reference.py

from __future__ import annotations

from typing import ClassVar

import numpy as np


_GLYPHS: dict[str, str] = {
    "A": (
        "#########"
        "##.....##"
        "##.....##"
        "##.....##"
        "#########"
        "##.....##"
        "##.....##"
        "##.....##"
        "##.....##"
    ),
    "B": (
        "########."
        "##....##."
        "##....##."
        "##....##."
        "########."
        "##....##."
        "##....##."
        "##....##."
        "########."
    ),
    "C": (
        ".########"
        "##......."
        "##......."
        "##......."
        "##......."
        "##......."
        "##......."
        "##......."
        ".########"
    ),
    "D": (
        "########."
        "##....##."
        "##.....##"
        "##.....##"
        "##.....##"
        "##.....##"
        "##.....##"
        "##....##."
        "########."
    ),
    "E": (
        "#########"
        "##......."
        "##......."
        "##......."
        "########."
        "##......."
        "##......."

Try running it locally

The reference implementation is self-contained Python with numpy. Install the package and run:

python library_external/toxi_openframeworks/GenerativeTypeLetterforms/reference.py

Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.

More from toxi · openFrameworks

Sample of Gray-Scott Reaction-Diffusion

Gray-Scott Reaction-Diffusion

toxi_openframeworks · ReactionDiffusionGS

The canonical two-species Gray-Scott reaction-diffusion model on a periodic square grid: dU/dt = Du*lap(U) - U*V^2 + F*(1-U), dV/dt = Dv*lap(V) + U*V^2 - (F+k)*V.

View →
Sample of Median-Cut Color Quantizer

Median-Cut Color Quantizer

toxi_openframeworks · ColorQuantizer

Heckbert's 1982 median-cut color quantization applied to an evolving procedural gradient + low-resolution noise wash.

View →
Sample of Pixel Sort (Glitch Art)

Pixel Sort (Glitch Art)

toxi_openframeworks · PixelSort

Per-row pixel sorting à la Kim Asendorf's `ASDFPixelSort` and Karsten Schmidt's own glitch-art Processing sketches.

View →
Sample of Sound-Reactive Particle Field (Synthetic Audio)

Sound-Reactive Particle Field (Synthetic Audio)

toxi_openframeworks · SoundReactiveField

Particles advected by a force field whose horizontal component is driven by a synthetic audio signal: a chain of N sinusoids at different frequencies/amplitudes (the 'audio'), with the audio's instantaneous value plus its time derivative ('beat onset') driving the field.

View →
Sample of Verlet Particle-Spring Network

Verlet Particle-Spring Network

toxi_openframeworks · ParticleSpring2D

A Verlet-integrated particle network connected to its k-nearest neighbours by Hooke's-law springs.

View →
Sample of Voronoi Tessellation with Lloyd Relaxation

Voronoi Tessellation with Lloyd Relaxation

toxi_openframeworks · VoronoiRelaxation

Lloyd's algorithm applied to a jittered point cloud: each seed is replaced with the centroid of its Voronoi cell, repeatedly, producing ever-more-uniform polygonal cells.

View →

See all toxi_openframeworks artworks →