Mixed scripts detected. HarfBuzz shapes one script per run; results may be wrong.
Welcome
harfbuzz-world.cc is a single-file build of
HarfBuzz that drops into your own C or C++ project
without any build-system glue, plus a live playground
for it right here in your browser.
- shape — the shaped glyph stream as a table, alongside an SVG preview.
- subset — produce a font subset for the current text and download it.
- raster — pixel-perfect BGRA rendering at any size, blitted to a canvas.
- vector — the same shaped text rendered to SVG and downloadable PDF.
- gpu — slug-based GPU rendering via WebGL2.
Each tab has additional resources at the bottom.
Embedding
Add HarfBuzz to your project as a submodule (or vendor
a checkout next to your code). Then point your build
at one file inside it —
src/harfbuzz-world.cc, the amalgamation
that #includes every .cc in
the library so the whole thing compiles as a single
translation unit:
c++ -std=c++11 -O2 \
-I third_party/harfbuzz/src \
-c third_party/harfbuzz/src/harfbuzz-world.cc \
-o harfbuzz-world.o
Link harfbuzz-world.o with the rest of
your program and call the public C API as usual:
#include <hb.h>
#include <hb-ot.h>
hb_blob_t *blob = hb_blob_create_from_file ("MyFont.ttf");
hb_face_t *face = hb_face_create (blob, 0);
hb_font_t *font = hb_font_create (face);
hb_buffer_t *buf = hb_buffer_create ();
hb_buffer_add_utf8 (buf, "Hello", -1, 0, -1);
hb_buffer_guess_segment_properties (buf); /* toy: real apps set script/lang/dir explicitly */
hb_shape (font, buf, NULL, 0);
unsigned len;
hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buf, &len);
hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buf, NULL);
/* …draw the glyphs… */
Customizing the build
HarfBuzz reads a handful of compile-time
#defines when the amalgamation is
compiled. Pass them on the command line
(-DHB_TINY) or via a small wrapper
header that #defines them and then
#includes
harfbuzz-world.cc.
HB_TINY— turn on every size-saving knob: drop deprecated APIs, variable fonts, AAT, legacy fallbacks, hinting, glyph names, math, name table, metrics, and a long etc., and switch the compiler to size optimization. All script shapers stay in. Combine with theHB_HAS_*flags below to add back the subsystems you need.HB_HAS_SUBSET— pull in the font-subsetting subsystem (hb-subset).HB_HAS_RASTER— pull inhb-rasterfor software pixel rendering.HB_HAS_VECTOR— pull inhb-vectorfor SVG / PDF output.HB_HAS_GPU— pull inhb-gpufor slug-based GPU shaders.HB_HAS_FREETYPE,HB_HAS_GLIB,HB_HAS_ICU,HB_HAS_GRAPHITE,HB_HAS_CAIRO, etc. — opt into the matching system integration.
Under HB_TINY, a few subsystems are
stripped out that you may want back. Undefine the
corresponding HB_NO_* flag in your
override header to opt them back in. Notable one:
HB_NO_AAT — gates shaping for Apple
Advanced Typography tables (morx,
kerx, trak, …). If your
input includes Mac system fonts, undefine it.
Building for the web (Emscripten)
The same amalgamation compiles to wasm via
em++; this site's wasm bundle is built
exactly this way, with shape, subset, raster,
vector, and AAT all enabled. The GPU tab embeds the
separate hb-gpu demo.
em++ -std=c++11 -Oz -flto \
-I third_party/harfbuzz/src \
-DHB_TINY -DHB_HAS_SUBSET -DHB_HAS_RASTER \
-DHB_HAS_VECTOR -DHB_HAS_GPU \
bindings.cc third_party/harfbuzz/src/harfbuzz-world.cc \
-sMODULARIZE=1 -sALLOW_MEMORY_GROWTH=1 \
-sEXPORTED_FUNCTIONS='["_my_shape_export","_malloc","_free"]' \
-o myhb.js
See this site's
scripts/build.sh
and
src/bindings.cc
for a complete working example.
Resources
- github.com/harfbuzz/harfbuzz — source, issues, releases.
- harfbuzz.github.io — user manual and API reference.
- BUILD.md — Meson / packaging guidance for systems that have a build system already.
- CONFIG.md
— overview of compile-time configuration. The full
knob list lives in
src/hb-config.hh
(
HB_NO_*feature gates and theHB_TINY/HB_LEAN/HB_MINIpresets) and src/hb-features.h.in (theHB_HAS_*subsystem flags). - github.com/harfbuzz/harfbuzz-world.cc — source for this site.
Other languages
If C/C++ isn't where you live, there are first-class HarfBuzz bindings for several other ecosystems:
- uharfbuzz — Pythonic bindings, used by FontTools and friends.
- harfbuzzjs — JS / wasm wrapper for web pages and Node.
- harfrust — pure-Rust port, no C dependency.
What HarfBuzz is primarily known for: turn text into a positioned glyph stream. HarfBuzz picks glyph ids from the font's character map, then applies the font's layout rules to substitute and position them. The SVG preview shows the laid-out result; the table below is the raw stream.
Glyphs are shown in visual order (left to right) regardless of text direction.
Code snippet
Learn more
Text shaping is what HarfBuzz is primarily known for: turn a Unicode string + font into a positioned glyph stream. HarfBuzz handles complex scripts (Arabic, Indic, Khmer, …), OpenType features, variable fonts including cutting-edge technology like avar2, as well as Apple Advanced Typography (AAT).
Slim the font down to the glyphs needed for the text above; hb-subset closes over the layout rules so any glyph that could participate in shaping survives. The preview renders with the produced subset font in your browser, so what you see is what it can shape — try selecting the text to confirm it's live.
Per-table breakdown
Code snippet
Learn more
The subsetter produces a minimal font covering just the glyphs needed for your text. It closes over OpenType layout rules so shaping still works on the subset. Common workflows: webfont serving (cut to page text), custom subsets for embedding, instancing (pin axes to produce a static font), limiting or reshaping the variation space, and changing default axis values.
Pixel-perfect software rendering at the chosen size via
hb-raster — BGRA32 buffer blitted straight into a
<canvas>. No hinting (HarfBuzz doesn't
do that); pair with FreeType via
hb-ft
if you need hinted output at small sizes.
Code snippet
Learn more
Software rasterizer with full COLRv1 support — gradients, compositing, transforms, and embedded PNG images all render correctly. Mono outlines produce A8 coverage masks; color glyphs produce BGRA32 premultiplied pixels. Unhinted — designed for high-DPI and embedding use cases rather than screen-optimized small sizes.
Resolution-independent output via hb-vector: the same shaped text emitted as SVG and PDF, both downloadable; the SVG is also rendered inline below as a preview. Both embed the outlines directly so the receiver needs no font.
Code snippet
Learn more
Converts shaped text to resolution-independent vector output with full COLRv1 support. SVG output is useful for quick previews, web embedding, and debugging. PDF output is designed for production: embed COLRv1 color glyphs as scalable vector artwork in PDF documents (e.g. via Type 3 fonts), giving tools like LibreOffice infinitely-scalable emoji rendering.
Slug-based GPU rendering via hb-gpu, running on WebGL2. Glyph outlines are encoded into compact blobs the GPU decodes and rasterizes in the fragment shader — no atlas, no CPU rasterization. Click animates, drag pans, scroll zooms, right-drag rotates in 3D. Standalone demo has more controls and a WebGPU build.
Code snippet
Learn more
GPU text rendering with full COLRv1 support, designed for games, UI frameworks, and any real-time context where CPU rasterization is too slow. Glyph outlines and color paint trees are encoded into compact blobs that a fragment shader decodes and rasterizes — the client manages a blob atlas, but there is no bitmap atlas and glyphs scale to any size. Shader sources are provided in GLSL, WGSL, MSL, and HLSL.