go-opentype

Pure-Go, zero-dependency TrueType/OpenType text stack.

pure Go ยท CGO=0 stdlib only 100% statement coverage runs in js/wasm runs on native BSD-3-Clause
opentype repo docs org
pkg.go.dev Go License

go-opentype is a family of pure-Go, standard-library-only packages that together read a font file, lay out Unicode text โ€” including mixed-direction and Arabic script โ€” and rasterise the result, with zero third-party dependencies anywhere in the stack.

import (
    "github.com/go-opentype/opentype"
    "github.com/go-opentype/shape"
)

f, _ := opentype.Parse(ttf)   // ttf is a []byte TrueType/OpenType blob
face := f.NewFace(32)         // 32px per em

for _, g := range shape.Shape(face, "ุจูŠุช", shape.Options{}) {
    // g.GID              glyph to draw
    // g.XAdvance, g.YAdvance   advance to move the pen by (px)
    // g.XOffset, g.YOffset     placement relative to the pen (px)
}

bounds, mask, maskp, advance, ok := face.GlyphMask('H', penX, baselineY)
// mask is an *image.Alpha coverage mask, ready to composite

opentype ready

The engine: a pure-Go, stdlib-only sfnt parser and anti-aliased rasteriser. TrueType glyf + CFF + CFF2 outlines; all cmap formats (0/2/4/6/8/10/12/13/14 + variation selectors); every GSUB and GPOS lookup type with GDEF + lookup flags (mark filtering); variable fonts (fvar/avar/gvar + IUP, plus HVAR/VVAR/MVAR metric variation); the full TrueType instruction hinter and a CFF/Type 2 stem grid-fitter (blue zones, counter control, stem darkening); vertical metrics; the OpenType MATH table; and font subsetting + instancing (SubsetTrueType/SubsetCFF, Instance) plus OS/2 font-descriptor accessors for PDF/CSS embedding. Feature parity with FreeType on the outline + hinting paths.

bidi ready

A pure-Go, stdlib-only implementation of the Unicode Bidirectional Algorithm (UAX #9) for mixed left-to-right / right-to-left text. Bidi_Class and paired-bracket properties are compiled into generated lookup tables โ€” no golang.org/x/text dependency. ResolveLevels, Reorder and a VisualOrder convenience wrapper.

shape ready

A HarfBuzz-lite complex-text shaper composing the two siblings above: bidi reordering from bidi and the font’s substitution/positioning tables from opentype. Dedicated shapers for Arabic (cursive joining), the Indic scripts (Devanagari, Bengali, Tamil, โ€ฆ โ€” two-pass reordering, reph modes, split matras, dotted-circle), the Universal Shaping Engine (Thai/Lao, Khmer, Myanmar, Tibetan and ~100 more โ€” sakot, split vowels, feature-driven reorder), Egyptian hieroglyph quadrats, Hangul jamo composition, vertical writing mode, and Latin/default (ligatures, marks, kerning) โ€” all to positioned glyphs in visual order. Validated on real Noto fonts.

fonts ready

46 legible, permissively-licensed families โ€” Atkinson Hyperlegible, Inter, Lora, JetBrains Mono, the Go pair, dozens of Noto faces, and non-Latin scripts (Arabic, Hebrew, Devanagari, Thai, Egyptian Hieroglyphs, plus CJK via Noto Sans SC, JP and KR) โ€” each its own subpackage embedded via go:embed, so a binary links only the faces it imports. fonts.MostLegible() returns Atkinson Hyperlegible, designed by the Braille Institute to maximise character distinction for low-vision readers.

What it replaces: the narrow slice of golang.org/x/image/font + font/opentype a glyph-blitting UI needs, and golang.org/x/text/unicode/bidi โ€” both dropped in favour of a smaller, purpose-built, dependency-free stack โ€” reaching functional parity with the HarfBuzz + FreeType pair for anti-aliased rendering and OpenType shaping: TrueType + CFF + CFF2 outlines, all cmap formats, every GSUB/GPOS lookup with GDEF + lookup flags, variable fonts with metric variation, full TrueType + CFF hinting, the OpenType MATH table, UAX #9 bidi, and complex-script shaping for Arabic, the Indic scripts, the Universal Shaping Engine (Thai/Khmer/Myanmar/โ€ฆ), Egyptian hieroglyphs, Hangul and vertical text.

Every package in the stack ships with a 100 % statement coverage gate, tested against synthesised in-memory fonts so no package depends on an external .ttf to run its suite. The whole stack is pure Go with cgo disabled โ€” no C toolchain, no runtime fetch, no vendored assets โ€” and cross-compiles trivially, including to GOOS=js GOARCH=wasm. Everything is BSD-3-Clause.