Skip to content

Basic Usage ​

UnicodeBuffer Configuration ​

The UnicodeBuffer class holds input text and configuration for shaping. It supports various options for different text layouts and scripts.

Adding Text ​

typescript
import { UnicodeBuffer } from "text-shaper";

const buffer = new UnicodeBuffer();

// Add string
buffer.addStr("Hello");

// Add codepoints array
buffer.addCodepoints([0x48, 0x65, 0x6C, 0x6C, 0x6F]);

// Chain calls
const buffer2 = new UnicodeBuffer()
	.addStr("Hello ")
	.addStr("World");

Text Direction ​

Set the text direction for proper layout:

typescript
import { Direction } from "text-shaper";

// Left-to-right (default)
buffer.setDirection(Direction.LTR);

// Right-to-left (Arabic, Hebrew)
buffer.setDirection(Direction.RTL);

// Top-to-bottom
buffer.setDirection(Direction.TTB);

// Bottom-to-top
buffer.setDirection(Direction.BTT);

Script and Language ​

Specify the script and language for correct shaping:

typescript
// Set script (ISO 15924 code)
buffer.setScript("Arab");  // Arabic
buffer.setScript("Latn");  // Latin
buffer.setScript("Deva");  // Devanagari
buffer.setScript("Hans");  // Simplified Chinese

// Set language (BCP 47 code)
buffer.setLanguage("ar");   // Arabic
buffer.setLanguage("en");   // English
buffer.setLanguage("hi");   // Hindi
buffer.setLanguage("zh");   // Chinese

Cluster Level ​

Control how character clusters are formed:

typescript
import { ClusterLevel } from "text-shaper";

// Monotone graphemes (default)
buffer.setClusterLevel(ClusterLevel.MonotoneGraphemes);

// Monotone characters
buffer.setClusterLevel(ClusterLevel.MonotoneCharacters);

// Characters
buffer.setClusterLevel(ClusterLevel.Characters);

Shaping Context ​

Provide surrounding text context for better shaping at boundaries:

typescript
// Set text before the buffer
buffer.setPreContext("previous ");

// Set text after the buffer
buffer.setPostContext(" next");

Complete Example ​

English Text ​

typescript
import { Font, shape, UnicodeBuffer, Direction } from "text-shaper";

const font = await Font.fromFile("font.ttf");

const buffer = new UnicodeBuffer()
	.addStr("Hello, World!")
	.setDirection(Direction.LTR)
	.setScript("Latn")
	.setLanguage("en");

const result = shape(font, buffer);

Arabic Text ​

typescript
const buffer = new UnicodeBuffer()
	.addStr("مرحبا بك")
	.setDirection(Direction.RTL)
	.setScript("Arab")
	.setLanguage("ar");

const result = shape(font, buffer);

Devanagari Text ​

typescript
const buffer = new UnicodeBuffer()
	.addStr("नमस्ते")
	.setDirection(Direction.LTR)
	.setScript("Deva")
	.setLanguage("hi");

const result = shape(font, buffer);

Working with Results ​

Iterating Glyphs ​

typescript
const result = shape(font, buffer);

for (let i = 0; i < result.length; i++) {
	const info = result.infos[i];
	const pos = result.positions[i];

	console.log(`Glyph ${i}:`);
	console.log(`  ID: ${info.glyphId}`);
	console.log(`  Cluster: ${info.cluster}`);
	console.log(`  X Advance: ${pos.xAdvance}`);
	console.log(`  Y Advance: ${pos.yAdvance}`);
}

Calculating Text Width ​

typescript
const result = shape(font, buffer);

let totalWidth = 0;
for (let i = 0; i < result.length; i++) {
	totalWidth += result.positions[i].xAdvance;
}

// Convert to pixels
const pixelSize = 16;
const widthPixels = (totalWidth * pixelSize) / font.unitsPerEm;

Mapping Glyphs to Characters ​

Use the cluster index to map glyphs back to character positions:

typescript
const result = shape(font, buffer);
const text = "Hello";

for (let i = 0; i < result.length; i++) {
	const cluster = result.infos[i].cluster;
	const char = text[cluster];
	console.log(`Glyph ${i} corresponds to character '${char}' at position ${cluster}`);
}

Reusing Buffers ​

For better performance, reuse buffers instead of creating new ones:

typescript
const buffer = new UnicodeBuffer();

// Shape first text
buffer.addStr("Hello");
const result1 = shape(font, buffer);

// Clear and reuse
buffer.clear();
buffer.addStr("World");
const result2 = shape(font, buffer);

Font Information ​

Access font metadata:

typescript
const font = await Font.fromFile("font.ttf");

console.log(`Units per em: ${font.unitsPerEm}`);
console.log(`Ascent: ${font.ascent}`);
console.log(`Descent: ${font.descent}`);
console.log(`Line gap: ${font.lineGap}`);

// Check available tables
console.log(`Has GSUB: ${font.hasTable("GSUB")}`);
console.log(`Has GPOS: ${font.hasTable("GPOS")}`);

Error Handling ​

typescript
try {
	const font = await Font.fromFile("font.ttf");
	const buffer = new UnicodeBuffer().addStr("Hello");
	const result = shape(font, buffer);
} catch (error) {
	console.error("Shaping failed:", error);
}

Fluent API ​

For rendering individual glyphs with transforms and effects, TextShaper provides a fluent API:

typescript
import { glyph, char } from "text-shaper";

// Render a glyph with transforms
const rgba = glyph(font, glyphId)
  ?.scale(2)
  .rotateDeg(15)
  .rasterizeAuto({ padding: 2 })
  .toRGBA();

// Render from character
const svg = char(font, "A")
  ?.scale(2)
  .italic(12)
  .toSVG();

// With effects
const blurred = glyph(font, glyphId)
  ?.scale(2)
  .rasterizeAuto({ padding: 10 })
  .blur(5)
  .toRGBA();

The fluent API supports:

  • Transforms: scale(), rotate(), translate(), shear(), italic(), perspective()
  • Path effects: embolden(), condense(), oblique(), stroke()
  • Rasterization: rasterize(), rasterizeAuto(), toSdf(), toMsdf()
  • Bitmap effects: blur(), fastBlur(), embolden(), composite()
  • Output: toRGBA(), toGray(), toSVG(), toCanvas()

See the Fluent API Reference for complete documentation.