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
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);
});
Extends
Disposable
Properties
_isInitialized
_isInitialized: boolean = false;Accessors
characterMap
Get Signature
get characterMap(): Map<string, TextmodeCharacter>;Returns the character map for O(1) lookups.
Returns
Map<string, TextmodeCharacter>
Example
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);
});
characters
Get Signature
get characters(): TextmodeCharacter[];Returns the array of TextmodeCharacter objects in the font.
Returns
Example
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);
});
fontFramebuffer
Get Signature
get fontFramebuffer(): TextmodeFramebuffer;Returns the WebGL framebuffer containing the font texture atlas.
Returns
Example
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);
});
fontSize
Get Signature
get fontSize(): number;Returns the font size used for the texture atlas.
Returns
number
Example
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);
});
maxGlyphDimensions
Get Signature
get maxGlyphDimensions(): object;Returns the maximum dimensions of a glyph in the font in pixels.
Returns
object
| Name | Type |
|---|---|
height | number |
width | number |
Example
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);
});
textureColumns
Get Signature
get textureColumns(): number;Returns the number of columns in the texture atlas.
Returns
number
Example
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);
});
textureRows
Get Signature
get textureRows(): number;Returns the number of rows in the texture atlas.
Returns
number
Example
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);
});
Methods
dispose()
dispose(): void;Dispose of all resources used by this font manager.
Returns
void
Example
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);
});
Overrides
Disposable.dispose