o
odinpkg.dev
packages / app / Runa

Runa

v1.2.1app

A pure-Odin modern text engine — parsing, shaping, layout, COLRv1 emoji, bidi, OpenType features.

Zlib · updated 1 month ago

runa

A pure-Odin modern text engine — parsing, itemization, shaping, line-breaking, rasterization. Built first to replace fontstash + stb_truetype in Skald, designed to be useful for any Odin project that needs production-quality text.

Status: v1.2.1 — bounded shape cache (LRU) on top of v1.1's Latin autohinter and v1.0's complex-script punch list. UAX #9 bidi at 100 %, UAX #29 graphemes at 100 %, CFF2 variable instances, COLRv1 emoji with the full 28 W3C composite blend modes + linear / radial / sweep gradients, GPOS mark-to-ligature, frozen API (API.md), per-script shaping for Devanagari, Bengali, Gujarati, Kannada, Odia, Tamil, Telugu, Malayalam, Gurmukhi, Thai, Lao, Khmer, Myanmar verified against HarfBuzz byte-for-byte, and a Thai word-break dictionary so Thai paragraphs reflow at word boundaries rather than as one giant unbreakable word. Full scoreboard in CHANGELOG.md.

runa rendering Latin, Cyrillic, Greek, Arabic (joined RTL), Hebrew (RTL), CJK, colour emoji, and ligatures

Latin · Cyrillic · Greek · Arabic (joined + RTL) · Hebrew (RTL) · Chinese · Japanese · colour emoji · OpenType ligatures.

What this is

The current Odin text-rendering story is vendor:fontstash plus stb_truetype — a glyph atlas and basic kerning. That covers Latin text at small scales but cannot:

  • Shape complex scripts (Arabic joining, Devanagari conjuncts, Thai clusters, bidi).
  • Break lines per Unicode UAX #14.
  • Render colour emoji (COLRv0 / COLRv1 / CBDT / sbix tables).
  • Apply OpenType features (ligatures, GPOS kerning, contextual alternates, stylistic sets).
  • Subpixel-position glyphs.

runa is the long-term fix — a modern text engine in idiomatic Odin with zero C dependencies at v1.0.

v1.0 punch list status

All four items closed:

  • Thai word-break dictionary — embedded PyThaiNLP corpus, longest-match trie, ~62 k entries. ✓
  • Complex Khmer multi-consonant clusters — pre-base reorder fixed to move to syllable start, not just before base. ✓
  • Full Myanmar shaping — joined the Indic pipeline; medial YA / medial RA / IPC=Top_And_Bottom_And_Left all reorder correctly. ✓
  • Two remaining bidi BidiCharacterTest mismatches — ISR formation now tunnels through all-BN higher-level intervening runs. 100.00 % conformance. ✓

Per-feature deliverables, conformance numbers, and tracked patch-level work in CHANGELOG.md.

Building

The library is a set of plain Odin packages — no build script needed.

odin check . -no-entry-point          # type-check the library
odin test  tests/parse                # parser tests
odin test  tests/raster               # rasterizer smoke tests
odin test  tests/runa                 # facade integration tests

The runnable demos:

# PGM-output, no GUI dependency — shapes Latin + emoji, writes a PPM
# image you can open in any viewer.
odin run examples/hello_world -- \
    tests/fonts/Roboto-Regular.ttf \
    tests/fonts/Twemoji-Mozilla.ttf \
    /tmp/hello.ppm

# Live raylib window — shows OpenType shaping, kerning, ligatures,
# and tinted text running through raylib's stock DrawTexturePro.
# ~50 lines of glue between runa and the renderer; demonstrates that
# runa is renderer-agnostic — works in any Odin project that can
# sample a texture and draw a quad (sokol_gfx, custom Vulkan / Metal,
# even a pure CPU pixel buffer).
odin run examples/raylib

Test fonts are not committed — fetch them into tests/fonts/ per tests/fonts/README.md, or let CI fetch them. Tests that need a missing font skip with an INFO log so the synthetic suite still runs on a fresh clone.

License

runa is licensed under the zlib license — see LICENSE. Permissive, GPL-compatible, the same licence Odin's own standard library uses.

Embedded Unicode UCD data files (Scripts.txt, LineBreak.txt, DerivedBidiClass.txt) ship under the Unicode-DFS-2016 licence. Test fonts are not committed — see tests/fonts/README.md for per-font sources and licences.

Contributing

API is frozen (API.md) — bidi at 100 %, line break at 99.91 %, graphemes at 100 %, UAX #29 word boundaries at 100 %, UAX #15 normalization (NFC / NFD / NFKC / NFKD) at 100 %, all 28 COLR composite blend modes, CFF2 variations, and the full complex-script set (9 Brahmic — Devanagari, Bengali, Tamil, Telugu, Kannada, Malayalam, Gurmukhi, Gujarati, Odia — plus 4 SEA — Thai, Lao, Myanmar, Khmer) all real. See CONTRIBUTING.md for build / test instructions and the open-work pointer list (long-tail Khmer cluster polish, performance hardening, COLRv1 sweep gradients).