harfbuzzjs
Version:
Minimal version of HarfBuzz for JavaScript use
112 lines (78 loc) • 4.41 kB
Markdown
# harfbuzzjs
<div align="center">
<p><img src="logo.png" alt="harfbuzzjs Logo" width="256" align="center"/></p>
[](https://github.com/harfbuzz/harfbuzzjs/actions/workflows/build.yml)
[](https://www.npmjs.com/package/harfbuzzjs)
</div>
Providing [HarfBuzz](https://github.com/harfbuzz/harfbuzz) shaping
library for client/server side JavaScript projects.
See the demo [here](https://harfbuzz.github.io/harfbuzzjs/demo/).
## Building
1. Install emscripten
2. `make`
## Testing
1. `make test`
## Download
Download from the [releases tab](https://github.com/harfbuzz/harfbuzzjs/releases).
## Migrating from v0.x
The v1 release introduced several API-breaking changes. See [MIGRATING](MIGRATING.md) for migrating from v0.x.
## Usage
### TL;DR
```javascript
import * as hb from "harfbuzzjs";
const fontdata = await fetch('myfont.ttf').then(r => r.arrayBuffer());
const blob = new hb.Blob(fontdata); // Load the font data into Harfbuzz blob
const face = new hb.Face(blob, 0); // Select the first font in the file
const font = new hb.Font(face); // Create a Harfbuzz font object from the face
const buffer = new hb.Buffer(); // 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
const output = buffer.getGlyphInfosAndPositions();
// Enumerate the glyphs
var xCursor = 0;
var yCursor = 0;
for (var glyph of output) {
var glyphId = glyph.codepoint;
var xAdvance = glyph.xAdvance;
var yAdvance = glyph.yAdvance;
var xDisplacement = glyph.xOffset;
var yDisplacement = glyph.yOffset;
var svgPath = font.glyphToPath(glyphId);
// You need to supply this bit
drawAGlyph(svgPath, xCursor + xDisplacement, yCursor + yDisplacement);
xCursor += xAdvance;
yCursor += yAdvance;
}
```
More examples:
### Browser
1. `npx pad.js`
2. Open `http://127.0.0.1/examples/harfbuzz.example.html`
### Node.js
1. `node examples/harfbuzz.example.node.js`
## [npm](https://www.npmjs.com/package/harfbuzzjs)
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/harfbuzz-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 `harfbuzz.symbols`; in this case `_hb_ot_get_glyph_name`.
3. Now the function will be exported through the WASM object, but you need to add TypeScript to bridge to it - in this case, handling the memory allocation of the `char *` parameter `name` and marshalling it to a JavaScript string. The best way to do this is to look at the source files in `src/` 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](https://github.com/emscripten-core/emscripten/blob/master/tools/ports/harfbuzz.py)
and [emscripten-ports/HarfBuzz](https://github.com/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 harfbuzz.wasm -o harfbuzz.wasm
```
`binaryen` also provides `wasm-dis` which can be used for,
```
wasm-dis harfbuzz.wasm | grep export
wasm-dis harfbuzz.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.