/** * Simple 5x7 Matrix Pixel Font * Each character is a 5x7 bitmask */ const FONT_DATA = { 'A': [0x0E, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11], 'B': [0x1E, 0x11, 0x11, 0x1E, 0x11, 0x11, 0x1E], 'C': [0x0E, 0x11, 0x11, 0x10, 0x11, 0x11, 0x0E], 'D': [0x1E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1E], 'E': [0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x1F], 'F': [0x1F, 0x10, 0x10, 0x1E, 0x10, 0x10, 0x10], 'G': [0x0F, 0x10, 0x10, 0x17, 0x11, 0x11, 0x0F], 'H': [0x11, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11], 'I': [0x0E, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0E], 'J': [0x07, 0x02, 0x02, 0x02, 0x02, 0x12, 0x0C], 'K': [0x11, 0x12, 0x14, 0x18, 0x14, 0x12, 0x11], 'L': [0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F], 'M': [0x11, 0x1B, 0x15, 0x15, 0x11, 0x11, 0x11], 'N': [0x11, 0x11, 0x19, 0x15, 0x13, 0x11, 0x11], 'O': [0x0E, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E], 'P': [0x1E, 0x11, 0x11, 0x1E, 0x10, 0x10, 0x10], 'Q': [0x0E, 0x11, 0x11, 0x11, 0x15, 0x12, 0x0D], 'R': [0x1E, 0x11, 0x11, 0x1E, 0x14, 0x12, 0x11], 'S': [0x0E, 0x11, 0x10, 0x0E, 0x01, 0x11, 0x0E], 'T': [0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04], 'U': [0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E], 'V': [0x11, 0x11, 0x11, 0x11, 0x11, 0x0A, 0x04], 'W': [0x11, 0x11, 0x11, 0x15, 0x15, 0x1B, 0x11], 'X': [0x11, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x11], 'Y': [0x11, 0x11, 0x0A, 0x04, 0x04, 0x04, 0x04], 'Z': [0x1F, 0x01, 0x02, 0x04, 0x08, 0x10, 0x1F], '0': [0x0E, 0x11, 0x13, 0x15, 0x19, 0x11, 0x0E], '1': [0x04, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x0E], '2': [0x0E, 0x11, 0x01, 0x02, 0x04, 0x08, 0x1F], '3': [0x1F, 0x02, 0x04, 0x02, 0x01, 0x11, 0x0E], '4': [0x02, 0x06, 0x0A, 0x12, 0x1F, 0x02, 0x02], '5': [0x1F, 0x10, 0x1E, 0x01, 0x01, 0x11, 0x0E], '6': [0x06, 0x08, 0x10, 0x1E, 0x11, 0x11, 0x0E], '7': [0x1F, 0x01, 0x02, 0x04, 0x08, 0x08, 0x08], '8': [0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x0E], '9': [0x0E, 0x11, 0x11, 0x0F, 0x01, 0x02, 0x0C], ':': [0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00], '.': [0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00], ',': [0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08], '!': [0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04], '?': [0x0E, 0x11, 0x01, 0x02, 0x04, 0x00, 0x04], '+': [0x00, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x00], '-': [0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00], '/': [0x01, 0x02, 0x04, 0x08, 0x10, 0x10, 0x10], '(': [0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02], ')': [0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08], ' ': [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], '|': [0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04] }; export const PixelFont = { drawText(ctx, text, x, y, color = '#ffffff', scale = 1) { ctx.save(); ctx.fillStyle = color; let cursorX = x; const chars = text.toUpperCase().split(''); chars.forEach(char => { const glyph = FONT_DATA[char] || FONT_DATA['?']; for (let row = 0; row < 7; row++) { for (let col = 0; col < 5; col++) { if ((glyph[row] >> (4 - col)) & 1) { ctx.fillRect(cursorX + col * scale, y + row * scale, scale, scale); } } } cursorX += 6 * scale; // 5 width + 1 spacing }); ctx.restore(); }, getTextWidth(text, scale = 1) { return text.length * 6 * scale; } };