Have ideas to improve npm?Join in the discussion! »


    0.1.5 • Public • Published


    Providing HarfBuzz shaping library for client/server side JavaScript projects.

    See the demo here.


    1. Install clang, lld and git
    2. ./build.sh

    Note that if building on Mac OS X, clang 11.0 needs to be installed from Homebrew (brew install clang). Also note that Homebrew clang is not in the path by default, so you need to add /usr/local/opt/llvm/bin to your path or you will get weird compiled errors.


    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


    hb = require("hbjs.js")
    WebAssembly.instantiateStreaming(fetch("hb.wasm")).then(function (result) {
      // WebAssembly needs its own heap - allocate 400 16k pages to do our work in.
      fetch('myfont.ttf').then(function (data) {
        return data.arrayBuffer();
      }).then(function (fontdata) {
        var blob = hb.createBlob(fontdata); // Load the font data into something Harfbuzz can use
        var face = hb.createFace(blob, 0);  // Select the first font in the file (there's normally only one!)
        var font = hb.createFont(face);     // Create a Harfbuzz font object from the face
        var buffer = hb.createBuffer();     // Make a buffer to hold some text
        buffer.addText('abc');              // Fill it with some stuff
        buffer.guessSegmentProperties();    // Set script, language and direction
        hb.shape(font, buffer);             // Shape the text, determining glyph IDs and positions
        var output = shape.json();
        // Enumerate the glyphs
        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);
            // You need to supply this bit
            drawAGlyph(svgPath, xCursor + xDisplacement, yDisplacement);
            xCursor += xAdvance;
        // Release memory

    More examples:


    1. npx pad.js
    2. Open or


    1. (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:

    1. First, undefine the macro in question, by adding e.g. #undef HB_NO_OT_GLYPH_NAMES to config-override.h.
    2. Next, export any function that you need by adding a line to build.sh; in this case -Wl,--export=hb_ot_get_glyph_name.
    3. 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.


    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.


    npm i harfbuzzjs

    DownloadsWeekly Downloads






    Unpacked Size

    1 MB

    Total Files


    Last publish


    • avatar