Skip to content

textmode.js / loadables / TextmodeFont

Class: TextmodeFont

Manages the font used for rendering characters via TextmodeLayer.loadFont.

This class coordinates font loading, character extraction, texture atlas creation, and provides character information.

Each TextmodeLayer has its own instance of this class to allow for layer-specific font configurations.

Example

javascript
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight, fontSize: 8 });
const accentLayer = t.layers.add({ fontSize: 8, offset: [0, 6] });

let customFont;

function label(text, y, color = [220, 220, 220]) {
	t.push();
	t.translate(-Math.floor(text.length / 2), y);
	t.charColor(color[0], color[1], color[2]);
	for (let i = 0; i < text.length; i++) {
		t.push();
		t.translate(i, 0);
		t.char(text[i]);
		t.point();
		t.pop();
	}
	t.pop();
}

t.setup(async () => {
	customFont = await t.loadFont('../../primitives/FROGBLOCK-V2.1.ttf', false);
	await accentLayer.loadFont(customFont);
});

t.draw(() => {
	t.background(8, 10, 22);
	label('TextmodeFont creation', -6, [255, 210, 90]);
	label(`glyphs: ${customFont ? customFont.characters.length : 'loading'}`, -2);
	label('base layer keeps its original font', 2, [150, 160, 190]);
});

accentLayer.draw(() => {
	t.clear();
	label('custom font on another layer', 0, [120, 220, 255]);
});

t.windowResized(() => {
	t.resizeCanvas(window.innerWidth, window.innerHeight);
});
codex avatar
@codex{ai-generated}Replace it with your own sketch, claim the credit, and climb the leaderboard.View sketch on GitHub

Extends

  • Disposable

Properties

_isInitialized

ts
_isInitialized: boolean = false;

Accessors

characterMap

Get Signature

ts
get characterMap(): Map<string, TextmodeCharacter>;

Returns the character map for O(1) lookups.

Returns

Map<string, TextmodeCharacter>

Example
javascript
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight, fontSize: 8 });

function label(text, y, color = [220, 220, 220]) {
	t.push();
	t.translate(-Math.floor(text.length / 2), y);
	t.charColor(color[0], color[1], color[2]);
	for (let i = 0; i < text.length; i++) {
		t.push();
		t.translate(i, 0);
		t.char(text[i]);
		t.point();
		t.pop();
	}
	t.pop();
}

t.draw(() => {
	const glyph = t.font.characterMap.get('A');
	const color = glyph ? glyph.color.map((value) => Math.round(value * 255)) : [220, 220, 220];

	t.background(8, 10, 22);
	t.char('A');
	t.charColor(color[0], color[1], color[2]);
	t.rect(10, 10);
	label('characterMap', -6, [255, 210, 90]);
	label(`map.has('A'): ${t.font.characterMap.has('A')}`, -2);
	label('fast lookup for glyph metadata', 5, [150, 160, 190]);
});

t.windowResized(() => {
	t.resizeCanvas(window.innerWidth, window.innerHeight);
});
codex avatar
@codex{ai-generated}Replace it with your own sketch, claim the credit, and climb the leaderboard.View sketch on GitHub

characters

Get Signature

ts
get characters(): TextmodeCharacter[];

Returns the array of TextmodeCharacter objects in the font.

Returns

TextmodeCharacter[]

Example
javascript
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight, fontSize: 8 });

t.draw(() => {
	const chars = t.font.characters.slice(0, 96);
	const cols = 16;
	const rows = Math.ceil(chars.length / cols);
	const startX = -Math.floor(cols / 2);
	const startY = -Math.floor(rows / 2);

	t.background(8, 10, 22);

	for (let i = 0; i < chars.length; i++) {
		const glyph = chars[i];
		t.push();
		t.translate(startX + (i % cols), startY + Math.floor(i / cols));
		t.char(glyph.character);
		t.charColor(120 + (i % cols) * 6, 140 + (i % rows) * 10, 255 - (i % cols) * 5);
		t.point();
		t.pop();
	}
});

t.windowResized(() => {
	t.resizeCanvas(window.innerWidth, window.innerHeight);
});
codex avatar
@codex{ai-generated}Replace it with your own sketch, claim the credit, and climb the leaderboard.View sketch on GitHub

fontFramebuffer

Get Signature

ts
get fontFramebuffer(): TextmodeFramebuffer;

Returns the WebGL framebuffer containing the font texture atlas.

Returns

TextmodeFramebuffer

Example
javascript
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight, fontSize: 8 });

function label(text, y, color = [220, 220, 220]) {
	t.push();
	t.translate(-Math.floor(text.length / 2), y);
	t.charColor(color[0], color[1], color[2]);
	for (let i = 0; i < text.length; i++) {
		t.push();
		t.translate(i, 0);
		t.char(text[i]);
		t.point();
		t.pop();
	}
	t.pop();
}

t.draw(() => {
	const atlas = t.font.fontFramebuffer;
	t.background(8, 10, 22);
	label('fontFramebuffer', -5, [255, 210, 90]);
	label(`atlas size: ${atlas.width} x ${atlas.height}px`, -1);
	label(`grid: ${t.font.textureColumns} cols x ${t.font.textureRows} rows`, 3, [150, 160, 190]);
});

t.windowResized(() => {
	t.resizeCanvas(window.innerWidth, window.innerHeight);
});
codex avatar
@codex{ai-generated}Replace it with your own sketch, claim the credit, and climb the leaderboard.View sketch on GitHub

fontSize

Get Signature

ts
get fontSize(): number;

Returns the font size used for the texture atlas.

Returns

number

Example
javascript
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight, fontSize: 8 });
const miniLayer = t.layers.add({ fontSize: 16, offset: [0, 6] });

function label(text, y, color = [220, 220, 220]) {
	t.push();
	t.translate(-Math.floor(text.length / 2), y);
	t.charColor(color[0], color[1], color[2]);
	for (let i = 0; i < text.length; i++) {
		t.push();
		t.translate(i, 0);
		t.char(text[i]);
		t.point();
		t.pop();
	}
	t.pop();
}

t.draw(() => {
	t.background(8, 10, 22);
	label('fontSize', -6, [255, 210, 90]);
	label(`base font size: ${t.layers.base.font.fontSize}`, -2);
	label(`upper layer font size: ${miniLayer.font.fontSize}`, 2, [150, 160, 190]);
});

miniLayer.draw(() => {
	t.clear();
	label('larger layer font', 0, [120, 220, 255]);
});

t.windowResized(() => {
	t.resizeCanvas(window.innerWidth, window.innerHeight);
});
codex avatar
@codex{ai-generated}Replace it with your own sketch, claim the credit, and climb the leaderboard.View sketch on GitHub

maxGlyphDimensions

Get Signature

ts
get maxGlyphDimensions(): object;

Returns the maximum dimensions of a glyph in the font in pixels.

Returns

object

NameType
heightnumber
widthnumber
Example
javascript
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight, fontSize: 8 });

function label(text, y, color = [220, 220, 220]) {
	t.push();
	t.translate(-Math.floor(text.length / 2), y);
	t.charColor(color[0], color[1], color[2]);
	for (let i = 0; i < text.length; i++) {
		t.push();
		t.translate(i, 0);
		t.char(text[i]);
		t.point();
		t.pop();
	}
	t.pop();
}

t.draw(() => {
	const dims = t.font.maxGlyphDimensions;
	const w = Math.max(2, Math.round(dims.width / 4));
	const h = Math.max(2, Math.round(dims.height / 4));

	t.background(8, 10, 22);
	t.char('#');
	t.charColor(120, 220, 255);
	t.rect(w, h);
	label('maxGlyphDimensions', -6, [255, 210, 90]);
	label(`${dims.width}px x ${dims.height}px`, -2);
	label('scaled box shows the max glyph bounds', 5, [150, 160, 190]);
});

t.windowResized(() => {
	t.resizeCanvas(window.innerWidth, window.innerHeight);
});
codex avatar
@codex{ai-generated}Replace it with your own sketch, claim the credit, and climb the leaderboard.View sketch on GitHub

textureColumns

Get Signature

ts
get textureColumns(): number;

Returns the number of columns in the texture atlas.

Returns

number

Example
javascript
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight, fontSize: 8 });

function label(text, y, color = [220, 220, 220]) {
	t.push();
	t.translate(-Math.floor(text.length / 2), y);
	t.charColor(color[0], color[1], color[2]);
	for (let i = 0; i < text.length; i++) {
		t.push();
		t.translate(i, 0);
		t.char(text[i]);
		t.point();
		t.pop();
	}
	t.pop();
}

t.draw(() => {
	const cols = t.font.textureColumns;
	t.background(8, 10, 22);
	label('textureColumns', -6, [255, 210, 90]);
	label(`atlas columns: ${cols}`, -2);

	for (let i = 0; i < cols; i++) {
		t.push();
		t.translate(-cols / 2 + i, 3);
		t.char('|');
		t.charColor(120 + (i % 12) * 10, 180, 255);
		t.line(0, -2, 0, 2);
		t.pop();
	}
});

t.windowResized(() => {
	t.resizeCanvas(window.innerWidth, window.innerHeight);
});
codex avatar
@codex{ai-generated}Replace it with your own sketch, claim the credit, and climb the leaderboard.View sketch on GitHub

textureRows

Get Signature

ts
get textureRows(): number;

Returns the number of rows in the texture atlas.

Returns

number

Example
javascript
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight, fontSize: 8 });

function label(text, y, color = [220, 220, 220]) {
	t.push();
	t.translate(-Math.floor(text.length / 2), y);
	t.charColor(color[0], color[1], color[2]);
	for (let i = 0; i < text.length; i++) {
		t.push();
		t.translate(i, 0);
		t.char(text[i]);
		t.point();
		t.pop();
	}
	t.pop();
}

t.draw(() => {
	const rows = t.font.textureRows;
	t.background(8, 10, 22);
	label('textureRows', -6, [255, 210, 90]);
	label(`atlas rows: ${rows}`, -2);

	for (let i = 0; i < rows; i++) {
		t.push();
		t.translate(0, i - rows / 2 + 4);
		t.char('-');
		t.charColor(120, 170 + (i % 10) * 8, 255);
		t.line(-6, 0, 6, 0);
		t.pop();
	}
});

t.windowResized(() => {
	t.resizeCanvas(window.innerWidth, window.innerHeight);
});
codex avatar
@codex{ai-generated}Replace it with your own sketch, claim the credit, and climb the leaderboard.View sketch on GitHub

Methods

dispose()

ts
dispose(): void;

Dispose of all resources used by this font manager.

Returns

void

Example

javascript
const t = textmode.create({ width: window.innerWidth, height: window.innerHeight, fontSize: 8 });

let tempFont;
let disposed = false;

function label(text, y, color = [220, 220, 220]) {
	t.push();
	t.translate(-Math.floor(text.length / 2), y);
	t.charColor(color[0], color[1], color[2]);
	for (let i = 0; i < text.length; i++) {
		t.push();
		t.translate(i, 0);
		t.char(text[i]);
		t.point();
		t.pop();
	}
	t.pop();
}

t.setup(async () => {
	tempFont = await t.loadFont('../../primitives/CHUNKY.ttf', false);
});

t.draw(() => {
	t.background(8, 10, 22);
	label('dispose()', -4, [255, 210, 90]);
	label(disposed ? 'temporary font disposed' : 'disposing temp font after 3 seconds', -1);
	label('active layer font keeps rendering normally', 2, [150, 160, 190]);

	if (tempFont && !disposed && t.frameCount > 180) {
		tempFont.dispose();
		disposed = true;
	}
});

t.windowResized(() => {
	t.resizeCanvas(window.innerWidth, window.innerHeight);
});
codex avatar
@codex{ai-generated}Replace it with your own sketch, claim the credit, and climb the leaderboard.View sketch on GitHub

Overrides

ts
Disposable.dispose