Table of Contents
Getting Started
Requirements
cl-textrender calls three C libraries. Only the first two are needed for layout:
| Library | Version | Used by | Debian/Ubuntu package |
|---|---|---|---|
HarfBuzz (libharfbuzz) |
7.0 or newer | cl-textrender, through cl-harfbuzz |
libharfbuzz0b |
ICU (libicuuc) |
52 or newer | cl-textrender, through cl-icu |
libicu-dev, or a versioned runtime such as libicu74 |
FreeType (libfreetype) |
2.13.1 or newer | cl-textrender/raster and cl-textrender/atlas, through cl-ft2 |
libfreetype6 |
You also need fonts: any TrueType (.ttf), OpenType (.otf) or collection
(.ttc, .otc) file. WOFF and WOFF2 web fonts must be converted first.
The examples in this wiki use DejaVu Sans (fonts-dejavu-core).
cl-textrender runs on SBCL. See Platforms and Testing for the details.
Getting the code
cl-textrender and the libraries under it are not in Quicklisp. Fetch them
from their git repositories. With stift,
require cl-textrender in your project's stiftfile:
stift get https://fakehacker.cc/dxtr/cl-textrender.git
cl-textrender's own stiftfile requires the libraries under it, those of
the optional systems included, so they come along as indirect entries.
Start Lisp with stift exec sbcl.
Without stift, clone each repository where ASDF finds it, such as
~/common-lisp/: cl-textrender, cl-harfbuzz, cl-icu and cl-ffi, and for
cl-textrender/raster, /atlas and /sdf, cl-ft2, cl-atlas and cl-sdf, all
under https://fakehacker.cc/dxtr/.
Loading
(asdf:load-system :cl-textrender) ; layout, hit testing, outlines
(asdf:load-system :cl-textrender/raster) ; optional: CPU rasterizer
(asdf:load-system :cl-textrender/atlas) ; optional: glyph texture atlas
(asdf:load-system :cl-textrender/sdf) ; optional: distance field atlas
ql:quickload works the same, if Quicklisp is loaded.
The packages have no global nicknames. The examples in this wiki run in a
package of their own that gives cl-textrender the local nickname tr:
(defpackage #:example
(:use #:cl)
(:local-nicknames (#:tr #:cl-textrender)))
(in-package #:example)
A local nickname needs its package to exist, so define the package after loading the systems it names.
A first program
Make a font, lay out a string, and walk its glyphs:
(tr:with-font (font "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
:size 16)
(let ((layout (tr:layout-text "Hi there" font)))
(tr:do-glyphs (g layout)
(format t "glyph ~3D for ~S at ~6,2F ~6,2F~%"
(tr:glyph-id g)
(char (tr:layout-string layout) (tr:glyph-text-index g))
(tr:glyph-x g)
(tr:glyph-y g)))))
glyph 43 for #\H at 0.00 14.85
glyph 76 for #\i at 12.03 14.85
glyph 3 for #\ at 16.48 14.85
glyph 87 for #\t at 21.56 14.85
glyph 75 for #\h at 27.84 14.85
glyph 72 for #\e at 37.98 14.85
glyph 85 for #\r at 47.82 14.85
glyph 72 for #\e at 54.05 14.85
What happened:
with-fontopened DejaVu Sans at 16 layout units per em, and destroys it when the body is left. Layout units are whatever you want them to be: pixels for UI text, world units for text in a scene.layout-textshaped the string into glyphs. Without:widththe text stays on one line.- Each glyph has the ID of the glyph to draw, the index of the character it
came from (
glyph-text-index), and the position of its origin on the baseline. The first line's top is at y 0 and y grows downwards, so the baseline is at the font's ascent, 14.85.
A renderer draws each glyph from its font, ID and position. Which way depends on the renderer:
| You want to... | Read |
|---|---|
| draw from a texture of rasterized glyphs | Glyph Atlas |
| draw from distance fields, with outlines, glows and shadows | Distance Field Atlas |
| draw from outlines (Slug, SVG, PDF, meshes) | Glyph Outlines |
| make an image on the CPU | Raster Backend |
Next
- Concepts explains what a layout is made of.
- Laying Out Text covers every option of
layout-text. - Carets and Selection covers editing.
- Recipes has complete examples.