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"); // ChineseCluster 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.