npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pixi-slug

v0.1.1

Published

Render fonts in pixi.js using bezier curves with the slug algorithm.

Readme

Toreda

GitHub package.json version (branch) GitHub Release Date GitHub issues

license

pixi-slug

Fast GPU-accelerated vector text for PixiJS. Crisp at any size, rotation, or 3D transform.

  • No atlases or SDFs. Just Béziers on the GPU.
  • Perspective-correct antialiasing via dynamic dilation.
  • Supports TrueType (.ttf), OpenType (.otf), and WOFF/WOFF2 fonts — including cubic-outline (CFF) fonts.
  • Word wrap, newlines, underline, and strikethrough.
  • Works on PixiJS v8, v7, and v6.

 

FAQ

A: It renders text using shaders.

A: No, it doesn't affect PIXI.Text. pixi-slug is a standalone plugin that uses its own SlugText.

A: Unfortunately no, it's not a drop-in replacement where you can just replace new Text(...) with new SlugText(...). It's close but not identical.

A:

  • Text always appears crisp & clear.
  • Font size changes don't affect rendering clarity.
  • The same SlugText can be used on multiple resolutions.
  • SlugText content changes have only a minimal impact on performance. Replacing text content several times per second (or more) doesn't create intense GC pressure the way PIXI.Text does.

Do these advantages matter for you? It depends on your use case. This package probably won't benefit you if:

  • Your PIXI scenes have a small number of Text objects.
  • Text rarely (or never) changes size or content.
  • Your scene can afford to render text at a large base size & scale the text down to the target font size to guarantee clear rendering.

A: Yes, but it requires using a font with emoji characters. Find one online, make one, or try one of these Google fonts:

A: Yes — cubic outlines are approximated as two quadratics per cubic segment, since the Slug algorithm operates on quadratic Béziers. Quality is indistinguishable at typical sizes; extreme zooms on cubic-heavy fonts may reveal the approximation.

A: Yes they can be used together. pixi-slug doesn't replace or change PIXI.Text. You can use both together or just one. It's up to you.

A: pixi-slug is a plugin for the PIXI.js game engine which draws text using the slug algorithm. Read more about Slug at sluglibrary.com.

Features

| Feature | v8 | v7 | v6 | | ------------------------------------ | :--: | :--: | :--: | | TTF (.ttf) fonts | ✅ | ✅ | ✅ | | OTF (.otf) (CFF) fonts | ✅ | ✅ | ✅ | | WOFF (.woff) fonts | ✅ | ✅ | ✅ | | WOFF2 (.woff2) fonts | ✅ | ✅ | ✅ | | URL string font loading (cached) | ✅ | ✅ | ✅ | | Raw bytes (ArrayBuffer/Uint8Array) | ✅ | ✅ | ✅ | | FontFace input (PIXI asset loader) | ✅ | ✅ | ✅ | | Fallback font on load failure | ✅ | ✅ | ✅ | | Hex color input (#rrggbb[aa]) | ✅ | ✅ | ✅ | | Word wrap + newlines | ✅ | ✅ | ✅ | | Font ref counting + autoDestroy | ✅ | ✅ | ✅ | | PIXI Ticker auto-hook | ✅ | ✅ | ✅ | | Application plugin | ✅ | ✅ | ✅ | | Text decoration: underline | ✅ | ❌ | ❌ | | Text decoration: strikethrough | ✅ | ❌ | ❌ | | Text decoration: overline | ❌ | ❌ | ❌ | | superscript | ❌ | ❌ | ❌ | | subscript | ❌ | ❌ | ❌ | | RTL glyph support | ❌ | ❌ | ❌ |

 

Examples

Every version has the same SlugText / SlugFonts API. Only the import path and the surrounding PIXI scaffolding change between v6, v7, and v8.

Creating a SlugText

font accepts a URL string, a registered name, a pre-built SlugFont, raw ArrayBuffer / Uint8Array bytes, or a FontFace returned by PIXI's asset loader. Strings that look like URLs are fetched and cached automatically.

Pixi v8

const {Application} = require('pixi.js');
const {SlugText} = require('pixi-slug');

const app = new Application();
await app.init({width: 800, height: 600});

const text = new SlugText({
    text: 'Hello Slug',
    font: 'https://cdn.example.com/roboto.ttf',
    options: {
        fontSize: 48,
        fill: [1, 1, 1, 1]
    }
});

app.stage.addChild(text);

Pixi v7

const {Application} = require('pixi.js');
const {SlugText} = require('pixi-slug/v7');

const app = new Application({width: 800, height: 600});

const text = new SlugText({
    text: 'Hello Slug',
    font: 'https://cdn.example.com/roboto.ttf',
    options: {
        fontSize: 48,
        fill: [1, 1, 1, 1]
    }
});

app.stage.addChild(text);

Pixi v6

const {Application} = require('pixi.js');
const {SlugText} = require('pixi-slug/v6');

const app = new Application({width: 800, height: 600});

const text = new SlugText({
    text: 'Hello Slug',
    font: 'https://cdn.example.com/roboto.ttf',
    options: {
        fontSize: 48,
        fill: [1, 1, 1, 1]
    }
});

app.stage.addChild(text);

Updating a SlugText

Mutate properties directly — SlugText rebuilds its geometry on change. This pattern is identical across v6, v7, and v8.

text.text = 'Updated!';
text.fontSize = 72;
text.color = [1, 0.2, 0.2, 1];
text.wordWrap = true;
text.wordWrapWidth = 300;
text.font = await SlugFonts.from('https://cdn.example.com/inter.ttf');

Colors

Every SlugText color field — fill, stroke color, drop shadow color, and the setter equivalents (text.color, text.strokeColor) — accepts the same flexible input set: hex strings, hex numbers, or numeric arrays.

text.color = '#FF0000';           // 6-digit hex, preserves existing alpha
text.color = '0xFF0000AA';        // 8-digit hex string, alpha 0xAA
text.color = '#F00';              // 3-digit shorthand, preserves alpha
text.color = '#F00F';             // 4-digit shorthand with alpha
text.color = '#80';               // 2-digit grayscale, preserves alpha
text.color = 0xFF0000;            // hex number ≤ 0xFFFFFF, preserves alpha
text.color = 0xFF0000CC;          // hex number > 0xFFFFFF, alpha from input
text.color = [1, 0, 0];           // 3-elem 0..1, preserves alpha
text.color = [1, 0, 0, 0.5];      // 4-elem 0..1
text.color = [255, 0, 0];         // 3-elem 0..255 (any element > 1 triggers 0..255 scale)
text.color = [255, 0, 0, 128];    // 4-elem 0..255

Alpha-preservation rules:

  • Forms without an alpha component (2/3/6-digit hex, hex numbers ≤ 0xFFFFFF, 3-element arrays) preserve the existing alpha.
  • Forms with an alpha component (4/8-digit hex, hex numbers > 0xFFFFFF, 4-element arrays) set alpha from the input.

Array scale detection: arrays are scanned before parsing. If every element is ≤ 1 the array is treated as already normalized (0..1). If any element is > 1 the whole array is treated as 0..255. You cannot mix scales within a single array.

Invalid input: malformed hex strings, numbers out of range, or arrays with bad shapes log console.error and leave the existing color unchanged — SlugText never throws on a color parse failure.

Full specification: _features/color_input.md.

Aliases

Bind a short name to a font URL inline at the SlugText construction site — no separate preload step. The first SlugText that references a given URL fetches and caches the font; subsequent references (by alias or URL) share the cached entry.

// Tuple: [alias, url]
const title = new SlugText({
    text: 'Title',
    font: ['roboto', 'https://cdn.example.com/roboto.ttf'],
    options: {fontSize: 64}
});

// Equivalent object form
const body = new SlugText({
    text: 'Body text',
    font: {alias: 'roboto', url: 'https://cdn.example.com/roboto.ttf'}
});

// Once the alias is registered, later sites can reference it by name alone
const caption = new SlugText({
    text: 'Caption',
    font: 'roboto'  // alias lookup (string without URL characters)
});

Alias resolution rules:

  • font: 'roboto' (bare string, no URL characters) → alias lookup. Miss is a console.error and the SlugText renders with the bundled fallback font.
  • font: 'roboto.ttf' or font: 'https://…' → URL-sniffed and fetched. .ttf/.otf/.woff/.woff2 extensions, /, ./, ../, //, data:, and :// all trigger URL mode.
  • font: {alias} / font: [alias] → pure alias lookup, same as the bare string form.
  • font: {url} / font: [url] (URL-sniffed) → URL fetch; the URL itself doubles as the alias.
  • font: {alias, url} / font: [alias, url] → fetch url, bind alias to the loaded font.

Alias collision: if alias is already registered to a different URL, the new binding is ignored — console.error is logged and the SlugText falls back. Call SlugFonts.unregister('roboto') before rebinding to a different URL.

Preload pattern — register once, reference everywhere by alias

For apps that want fonts ready before any SlugText renders — e.g. a splash/loading screen or predictable typography across every view — call SlugFonts directly at startup. Every later SlugText can use the bare alias and resolves synchronously, with no fallback flash while a URL fetches.

const {SlugFonts, SlugText} = require('pixi-slug'); // or '/v7' / '/v6'

// Preload at app startup — typically inside an async bootstrap function.
async function preloadFonts() {
    const roboto = await SlugFonts.fromUrl('https://cdn.example.com/roboto.ttf');
    const inter  = await SlugFonts.fromUrl('https://cdn.example.com/inter.ttf');

    SlugFonts.register('roboto', roboto);
    SlugFonts.register('inter',  inter);
}

await preloadFonts();

// Every SlugText created afterwards hits the registry synchronously.
// No URL fetch, no fallback font flash.
const title    = new SlugText({text: 'Dashboard', font: 'roboto', options: {fontSize: 64}});
const subtitle = new SlugText({text: 'Welcome back',           font: 'inter'});
const footer   = new SlugText({text: '© 2026 Acme Corp',       font: 'roboto'});

Why this pattern? The inline tuple/object forms (['roboto', 'https://…']) work fine, but the first SlugText that references a new URL fetches asynchronously — it renders with the fallback font until the real font loads, then swaps. Preloading sidesteps the flash entirely and keeps construction sites terse (font: 'roboto').

If an alias is referenced before it's registered, the SlugText falls back to the bundled font and a console.error surfaces — so this pattern also acts as a startup sanity check.

Loading fonts through PIXI's asset loader

PIXI.Assets.load() (v7/v8) returns a browser FontFace, which SlugText accepts directly. For more efficient loading — skip the intermediate FontFace and receive raw bytes — call the version-specific installer once at app startup:

// v8
const {Assets} = require('pixi.js');
const {SlugText, slugFontsInstallLoaderV8} = require('pixi-slug');

slugFontsInstallLoaderV8();
const bytes = await Assets.load('roboto.ttf'); // now returns ArrayBuffer
const text = new SlugText({text: 'Hi', font: bytes});
// v7
const {Assets} = require('pixi.js');
const {SlugText, slugFontsInstallLoaderV7} = require('pixi-slug/v7');

slugFontsInstallLoaderV7();
const bytes = await Assets.load('roboto.ttf');
const text = new SlugText({text: 'Hi', font: bytes});
// v6 — PIXI.Loader can't be extended to return raw bytes; use the
// helper instead of `loader.add(url)` when the font is destined for SlugText.
const {SlugText, slugFontsFetchV6} = require('pixi-slug/v6');

const bytes = await slugFontsFetchV6('roboto.ttf');
const text = new SlugText({text: 'Hi', font: bytes});

Integrating with PIXI.Application

The SlugFonts registry needs a ticker to run its auto-destroy sweep. Two ways to wire it up — pick whichever fits your app.

Quick path — shared ticker

One call. Uses Ticker.shared in the background. Works even if you don't use PIXI.Application at all.

const {slugFontsAttachTickerV8} = require('pixi-slug');
slugFontsAttachTickerV8();

Per-version exports: slugFontsAttachTickerV6, slugFontsAttachTickerV7, slugFontsAttachTickerV8.

Plugin path — app lifecycle

Register a plugin so the registry follows one specific Application's ticker and tears down cleanly on app.destroy().

// v8
const {Application, extensions} = require('pixi.js');
const {SlugApplicationPluginV8} = require('pixi-slug');

extensions.add(SlugApplicationPluginV8);
const app = new Application();
await app.init({width: 800, height: 600});
// ... later
app.destroy(); // ticker detaches, unused fonts freed immediately

v7 is identical with imports from @pixi/core and pixi-slug/v7:

const {extensions} = require('@pixi/core');
const {SlugApplicationPluginV7} = require('pixi-slug/v7');
extensions.add(SlugApplicationPluginV7);

v6 uses the older registration surface:

const {Application} = require('@pixi/app');
const {SlugApplicationPluginV6} = require('pixi-slug/v6');
Application.registerPlugin(SlugApplicationPluginV6);

Conflict behavior: both paths call SlugFonts.attachTicker under the hood. If one is already active and another tries to attach, SlugFonts.reattachPolicy decides what happens — 'throw' by default, or 'error' / 'warn' / 'silent'. Change it with SlugFonts.setReattachPolicy('warn') (validated — invalid modes are rejected and logged). Pass {force: true} as the second arg to attachTicker to replace silently. Full details in _features/application_plugin.md.

Slug Reference Code

Eric Lengyel created and patented the Slug algorithm. He published reference code on Github.

Legal

Eric Lengyel created the patented slug algorithm in 2016. He graciously released it into the public domain for free in 2026. pixi-slug is a TypeScript port of his work to add gpu-based font rendering to pixi.js.

pixi-slug is not affiliated with, or endorsed by Eric Lengyel.

License

MIT © Toreda, Inc.

Bundled third-party components (currently the Roboto fallback font, Apache-2.0) are attributed in NOTICES.

Website

Toreda's website can be found at toreda.com

Toreda Open Source Packages

Explore other open source packages by toreda.com designed to support generics and no runtime dependencies:

| Package | npm | Description | | ---------------------------------------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | | @toreda/build-tools | @toreda/build-tools | Reusable helpers to simplify webpack and esbuild build pipelines. | | @toreda/cache | @toreda/cache | Generic TTL-based object caching. | | @toreda/fate | @toreda/fate | Typed result wrapper with built-in success, failure, and status context | | @toreda/lifecycle | @toreda/lifecycle | Phased async hooks for multi-step object flows | | @toreda/log | @toreda/log | Zero-dependency logger for browser, Node, and Web Workers with pluggable transports and granular filtering. | | @toreda/strong-types | @toreda/strong-types | Self-validating types that eliminate boilerplate validation code | | @toreda/time | @toreda/time | Type-safe time units with built-in conversion, math operations, and input validation. | | @toreda/types | @toreda/types | Expressive aliases & helpers that clarify code intent. | | @toreda/verify | @toreda/verify | Runtime schema and type validation with recursive definitions, custom types, and detailed validation output. |