Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 57 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,81 +1,88 @@
# harfbuzzjs

<div align="center">
<p><img src="logo.png" alt="harfbuzzjs Logo" width="256" align="center"/></p>

[![Build](https://github.com/harfbuzz/harfbuzzjs/actions/workflows/build.yml/badge.svg)](https://github.com/harfbuzz/harfbuzzjs/actions/workflows/build.yml)
[![NPM Version](https://img.shields.io/npm/v/harfbuzzjs)](https://www.npmjs.com/package/harfbuzzjs)
<p><img src="logo.png" alt="harfbuzzjs Logo" width="256" align="center"/></p>

[![Build](https://github.com/harfbuzz/harfbuzzjs/actions/workflows/build.yml/badge.svg)](https://github.com/harfbuzz/harfbuzzjs/actions/workflows/build.yml)
[![NPM Version](https://img.shields.io/npm/v/harfbuzzjs)](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`
## Download

## Testing
1. `make test`
From the repo's [releases](https://github.com/harfbuzz/harfbuzzjs/releases), or npm:

## Download
Download from the [releases tab](https://github.com/harfbuzz/harfbuzzjs/releases).
```
npm install harfbuzzjs
```

## Migrating from v0.x
The v1 release introduced several API-breaking changes. See [MIGRATING](MIGRATING.md) for migrating from v0.x.

## Usage
The v1 release introduced several API-breaking changes. See [MIGRATING](MIGRATING.md) for migrating from v0.x.

### TL;DR
## Usage examples

```javascript
```js
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;
// Load data from a font file:
const response = await fetch("font.ttf");
const arrayBuffer = await response.arrayBuffer();

// Create a HarfBuzz font object from the data:
const blob = new hb.Blob(arrayBuffer);
const face = new hb.Face(blob);
const font = new hb.Font(face);

// Shape text in a HarfBuzz buffer with the font:
const buffer = new hb.Buffer();
buffer.addText("abc");
buffer.guessSegmentProperties();
hb.shape(font, buffer);

// Enumerate the resulted glyphs in the buffer:
const infos = buffer.getGlyphInfos();
const positions = buffer.getGlyphPositions();
for (const [index, glyph] of infos.entries()) {
const gid = glyph.codepoint; // Glyph ID despite the property name
console.log(
font.glyphToPath(gid), // SVG path
positions[index], // xAdvance, yAdvance, xOffset, yOffset
);
}
```

More examples:
### Alternative browser example

See [examples/harfbuzz.example.html](examples/harfbuzz.example.html). To quickly run it in a browser:

```
npx http-server -o /examples/harfbuzz.example.html
```

### Node.js example

### Browser
See [examples/harfbuzz.example.node.js](examples/harfbuzz.example.node.js).

1. `npx pad.js`
2. Open `http://127.0.0.1/examples/harfbuzz.example.html`
## Development

### Node.js
### Building

1. `node examples/harfbuzz.example.node.js`
First install [emscripten](https://emscripten.org), then:

## [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.
```
make
```

### Testing

```
make test
```

## Need more of the library?

Expand Down
45 changes: 23 additions & 22 deletions examples/harfbuzz.example.node.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { Blob, Face, Font, Buffer, shape } from "../dist/index.mjs";
import * as hb from "harfbuzzjs";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
// Load data from a font file:
const nodeBuffer = fs.readFileSync(
path.join(import.meta.dirname, "../test/fonts/noto/NotoSans-Regular.ttf"),
);

function example(fontPath, text) {
var blob = new Blob(fs.readFileSync(fontPath));
var face = new Face(blob, 0);
var font = new Font(face);
// Create a HarfBuzz font object from the data:
const blob = new hb.Blob(nodeBuffer);
const face = new hb.Face(blob);
const font = new hb.Font(face);

var buffer = new Buffer();
buffer.addText(text || "abc");
buffer.guessSegmentProperties();
shape(font, buffer);
// Shape text in a HarfBuzz buffer with the font:
const buffer = new hb.Buffer();
buffer.addText("abc");
buffer.guessSegmentProperties();
hb.shape(font, buffer);

return buffer.getGlyphInfosAndPositions();
// Enumerate the resulted glyphs in the buffer:
const infos = buffer.getGlyphInfos();
const positions = buffer.getGlyphPositions();
for (const [index, glyph] of infos.entries()) {
const gid = glyph.codepoint; // Glyph ID despite the property name
console.log(
font.glyphToPath(gid), // SVG path
positions[index], // xAdvance, yAdvance, xOffset, yOffset
);
}

console.log(
example(path.resolve(__dirname, "../test/fonts/noto/NotoSans-Regular.ttf")),
);
console.log(
example(
path.resolve(__dirname, "../test/fonts/noto/NotoSansArabic-Variable.ttf"),
"أبجد",
),
);