6 Home
dxtr edited this page 2026-10-18 15:21:04 +02:00

cl-harfbuzz

Common Lisp bindings for HarfBuzz, the text shaping engine. It turns a run of text and a font into positioned glyphs (ligatures, kerning, Arabic joining, Indic reordering, mark placement), and reads glyph outlines, color glyphs and OpenType font data.

(asdf:load-system :cl-harfbuzz)

(defpackage #:example
  (:use #:cl)
  (:local-nicknames (#:hb #:cl-harfbuzz)))
(in-package #:example)

(hb:with-face (face "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf")
  (hb:with-font (font face)
    (map 'list #'hb:shaped-glyph-index (hb:shape-text font "office"))))
;; => (82 5044 70 72)    ; o, the "ffi" ligature, c, e

Two layers, and a bridge

System / package What it is
cl-harfbuzz The Lisp-idiomatic API. OpenType tags, scripts and languages are strings ("kern", "Arab", "ar"), directions and flags are keywords, colors are lists (r g b a), and every failure signals a harfbuzz-error.
cl-harfbuzz/ffi The raw layer underneath, on cl-ffi, named after the C API (hb_buffer_add_codepoints → hb-buffer-add-codepoints). No error checking or lifetime tracking.
cl-harfbuzz/ft2 (optional system) HarfBuzz fonts built on cl-ft2 faces, so shaping and rendering use the same FreeType data, in pixels. Plain cl-harfbuzz does not load cl-ft2.

The packages have no global nicknames: the examples in this wiki give cl-harfbuzz the local nickname hb, as above, and cl-ft2 the nickname ft2. Most programs only need cl-harfbuzz. The FFI layer is there for HarfBuzz features that cl-harfbuzz does not wrap; face-handle, font-handle and buffer-handle connect the two.

Contents

Start here

  • Installation: requirements, loading, Windows
  • Getting started: a guided tour from opening a font to drawing shaped text
  • Core concepts: faces, fonts and buffers; units; clusters; visual order; lifetimes; threads

Reference

  • Faces: make-face, face-count, face properties, raw tables
  • Fonts and metrics: make-font, scale, ppem, point size, glyph lookup, advances, extents, font-metric
  • Shaping: buffers and their properties, shape, shape-text, features, cluster levels, flags, shaped-glyph
  • Outlines: glyph-outline
  • Color glyphs: glyph-paint, palettes, COLR layers, SVG and PNG glyphs
  • Font variations: axes, named instances, design and normalized coordinates
  • OpenType data: names, layout script and feature tags
  • FreeType bridge: cl-harfbuzz/ft2, make-ft2-font, pixels, lifetimes
  • Errors: harfbuzz-error and type-error
  • FFI layer: the raw cl-harfbuzz/ffi package
  • API index: every exported symbol, alphabetically

Guides

  • Cookbook: measuring and drawing a line, bidi runs, features, hit testing with clusters, re-shaping, emoji, variable fonts
  • Scope and limitations: what is left to ICU, cl-ft2 and your code
  • Development: tests, test fonts, the Windows DLL, CI

At a glance

  • Runtime requirement: the libharfbuzz shared library, 7.0 or newer. Struct layouts are written by hand, so building needs no C compiler, headers or groveller. On Windows cl-harfbuzz carries its own harfbuzz.dll.
  • Dependencies: cl-ffi, uiop. cl-harfbuzz/ft2 adds cl-ft2; the tests add parachute.
  • Lisp: SBCL. The code has no implementation-specific parts: those are cl-ffi's.
  • License: MIT.
  • Source: https://fakehacker.cc/dxtr/cl-harfbuzz

cl-harfbuzz is the shaping layer of a text stack:

  • cl-ft2 rasterizes glyphs. cl-harfbuzz/ft2 builds HarfBuzz fonts on its faces.
  • cl-icu handles bidi, script runs, line breaking and normalization: the steps that come before shaping.
  • cl-textrender lays text out on cl-icu and cl-harfbuzz (without FreeType), and has an optional raster backend on cl-ft2.