harfbuzzjs
Providing HarfBuzz shaping
library for client/server side JavaScript projects.
See the demo here.
Building
- Install emscripten
./build.sh
Download
Download the pack from releases tab
of the project, or just download the demo page (the
demo source is in gh-pages branch).
Usage and testing
TL;DR
hb = require("hbjs.js")
WebAssembly.instantiateStreaming(fetch("hb.wasm")).then(function (result) {
fetch('myfont.ttf').then(function (data) {
return data.arrayBuffer();
}).then(function (fontdata) {
var blob = hb.createBlob(fontdata);
var face = hb.createFace(blob, 0);
var font = hb.createFont(face);
var buffer = hb.createBuffer();
buffer.addText('abc');
buffer.guessSegmentProperties();
hb.shape(font, buffer);
var output = buffer.json();
var xCursor = 0;
var yCursor = 0;
for (glyph of output) {
var glyphId = glyph.g;
var xAdvance = glyph.ax;
var xDisplacement = glyph.dx;
var yDisplacement = glyph.dy;
var svgPath = font.glyphToPath(glyphId);
drawAGlyph(svgPath, xCursor + xDisplacement, yDisplacement);
xCursor += xAdvance;
}
buffer.destroy();
font.destroy();
face.destroy();
blob.destroy();
})
})
More examples:
Browser
npx pad.js
- Open
http://127.0.0.1/examples/hbjs.example.html
or http://127.0.0.1/examples/nohbjs.html
Node.js
(cd examples && node hbjs.example.node.js)
We provide a tiny wrapper (hbjs.js
) around the main functionality of harfbuzz, but it's also easy to use other parts. (See example/nohbjs.js
as an example. However, you may need a custom build to expose additional functionality.)
Can be added with npm i harfbuzzjs
or yarn add harfbuzzjs
, see the examples for
how to use it.
Need more of the library?
harfbuzzjs uses a stripped-down version of Harfbuzz generated by compiling Harfbuzz with -DHB_TINY
. This may mean that some functions you need are not available. Look at src/hb-config.hh
in the Harfbuzz source directory to see what has been removed. For example, HB_TINY
defines HB_LEAN
which (amongst other things) defines HB_NO_OT_GLYPH_NAMES
. If, for example, you really need to get at the glyph names:
- First, undefine the macro in question, by adding e.g.
#undef HB_NO_OT_GLYPH_NAMES
to config-override.h
. - Next, export any function that you need by adding a line to
hbjs.symbols
; in this case _hb_ot_get_glyph_name
. - Now the function will be exported through the WASM object, but you need to add Javascript to bridge to it - in this case, handling the memory allocation of the
char *
parameter name
and marshalling it to a JavaScript string with heapu8.subarray
. The best way to do this is to look at hbjs.js
for functions which use similar signatures.
If you have extended harfbuzzjs in ways that you think others will also benefit from, please raise a pull request. If there are parts of Harfbuzz that you need but the instructions above don't work, describe what you are trying to do in an issue.
Using the library in a bigger emscripten project?
See harfbuzz port inside emscripten
and emscripten-ports/HarfBuzz, basically all you need is to use
-s USE_HARFBUZZ=1
in your build.
binaryen
Optionally you can install binaryen
and use wasm-opt
like:
wasm-opt -Oz hb.wasm -o hb.wasm
binaryen
also provides wasm-dis
which can be used for,
wasm-dis hb.wasm | grep export
wasm-dis hb.wasm | grep import
with that you can check if the built wasm file only exports things you need and
doesn't need to import anything, as usual with wasm files built here.