Table of Contents
Development
Layout
cl-harfbuzz.asd three systems: cl-harfbuzz, cl-harfbuzz/ft2, cl-harfbuzz/test
src/
package.lisp cl-harfbuzz/ffi and cl-harfbuzz packages
ffi-library.lisp locating and loading libharfbuzz (bundled DLL on Windows)
ffi-types.lisp scalar types, enums, bitfields
ffi-structs.lisp hand-written struct layouts
ffi-functions.lisp defcfun for every bound C function
conditions.lisp harfbuzz-error
common.lisp tags, languages, scripts, directions, colors, version
face.lisp font.lisp buffer.lisp shape.lisp
draw.lisp glyph-outline (draw callbacks)
paint.lisp glyph-paint (paint callbacks)
ot.lisp names, metrics, layout tags, variations, color tables
ft2/ the cl-harfbuzz/ft2 bridge
native/
build-windows.sh reproducible cross-build of harfbuzz.dll
windows-x64/ harfbuzz.dll and HarfBuzz's license
tests/ parachute tests and test fonts
The two layers follow cl-ft2 and cl-net: a raw */ffi package that transcribes C, and an idiomatic package on top. Struct layouts use cl-ffi's C-sized types, written by hand, so nothing is compiled.
Dependencies
Pinned in the stiftfile with stift: cl-ffi and cl-ft2, each at a commit of its main branch, and Parachute, with the four libraries it needs, for the tests.
After a change to cl-ffi or cl-ft2 is pushed, move the pin with stift work sync at the workspace's root, or stift update https://fakehacker.cc/dxtr/cl-ft2.git here, and commit the stiftfile.
Running the tests
stift test
asdf:test-system signals an error if any test fails, so the command exits unsuccessfully.
The suite (cl-harfbuzz/test, parachute) covers faces, fonts, shaping, outlines, paint, OpenType data, argument checking, the exported types, loading the library and the cl-ft2 bridge: 51 tests, 402 checks. shapes-without-cl-ft2 loads cl-harfbuzz alone in a fresh SBCL, which it gives the suite's own source registry and output translations, so the child loads the fasls stift built for this build list and never ones another run built against other versions of the dependencies.
The tests need:
| What | Debian / Ubuntu | Windows |
|---|---|---|
| HarfBuzz | libharfbuzz0b |
bundled |
| FreeType (for the bridge tests) | libfreetype6 |
bundled with cl-ft2 |
| DejaVu Sans | fonts-dejavu-core |
install DejaVu Sans |
The exact expectations are DejaVu Sans's. To use it from another location, set CL_HARFBUZZ_TEST_FONT to its path.
Test fonts
tests/fonts/cl-harfbuzz-test-color.ttfis built bytests/fonts/make-test-color-font.py(needs fontTools). Its docstring specifies the font: 1000 units per EM; glyphsboxandbar;Awith COLRv0 layers,Bwith a COLRv1 linear gradient,Cplain; two CPAL palettes. The color tests are written against that description.- The variable-font tests use cl-ft2's
tests/fonts/cl-ft2-test-variable.ttf(axeswghtandwdth, instances Thin, Regular, Black), found through ASDF.
The Windows DLL
native/windows-x64/harfbuzz.dll is HarfBuzz 14.6.0, cross-compiled on Linux with MinGW-w64 by native/build-windows.sh:
apt install g++-mingw-w64-x86-64 curl xz-utils
native/build-windows.sh # rebuild windows-x64/harfbuzz.dll
native/build-windows.sh --check # rebuild and fail unless identical to the committed DLL
- Sources (HarfBuzz and FreeType's headers) are downloaded and checked against pinned SHA-256 sums.
- It is HarfBuzz's single-file build (
harfbuzz.cc), with hb-ft and without glib, ICU, Graphite or the Windows shapers. Only HarfBuzz's public API is exported. - FreeType is delay-loaded: the script generates a delay-load import library for exactly the
FT_functions hb-ft calls, soharfbuzz.dllloads withoutfreetype.dll. KeepFREETYPE_VERSIONequal to the version cl-ft2 builds. - The build is reproducible (no paths or timestamps in the binary), which is what
--checkrelies on.
To update HarfBuzz: change HARFBUZZ_VERSION and HARFBUZZ_SHA256, run the script, run the tests on Windows, and commit the DLL and HARFBUZZ-COPYING.
CI
Forgejo Actions, .forgejo/workflows/ci.yml, on pushes to main and pull requests, in a debian:forky container:
- test:
fakehacker/actions/stift-ci@v1, the action's major tag, which follows its compatible releases, on SBCL 2.6.9, installinglibharfbuzz0b libfreetype6 fonts-dejavu-core, then runningstift test, which fails unless the suite passes. No C toolchain or headers are needed. - windows-dll: installs MinGW-w64 and runs
native/build-windows.sh --check. A MinGW-w64 update can change the bytes; then rebuild the DLL and commit it.
Conventions
- Every failure is a
harfbuzz-errorwhose message says what went wrong in terms of the Lisp call and whose hint says what to do; argument type problems aretype-errors. See Errors. - Every exported function declaims its
ftypedirectly above itsdefunand checks its arguments withcheck-type; a list of allowed keywords is adeftypeof(member …). Every definition, internal ones included, has a docstring. - Structs and classes document their fields in their own docstring, not per accessor.
- New C bindings go in
ffi-functions.lispand thecl-harfbuzz/ffiexport list, named after the C function.