Files
ascii-pwa/bitmap.js
T
2026-10-10 12:51:33 +02:00

96 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Original 5×7 bitmap glyphs. All rendering is local; no fonts or API are fetched.
const patterns = {
A: '01110/10001/10001/11111/10001/10001/10001',
B: '11110/10001/10001/11110/10001/10001/11110',
C: '01111/10000/10000/10000/10000/10000/01111',
D: '11110/10001/10001/10001/10001/10001/11110',
E: '11111/10000/10000/11110/10000/10000/11111',
F: '11111/10000/10000/11110/10000/10000/10000',
G: '01111/10000/10000/10111/10001/10001/01111',
H: '10001/10001/10001/11111/10001/10001/10001',
I: '11111/00100/00100/00100/00100/00100/11111',
J: '00111/00010/00010/00010/10010/10010/01100',
K: '10001/10010/10100/11000/10100/10010/10001',
L: '10000/10000/10000/10000/10000/10000/11111',
M: '10001/11011/10101/10101/10001/10001/10001',
N: '10001/11001/10101/10011/10001/10001/10001',
O: '01110/10001/10001/10001/10001/10001/01110',
P: '11110/10001/10001/11110/10000/10000/10000',
Q: '01110/10001/10001/10001/10101/10010/01101',
R: '11110/10001/10001/11110/10100/10010/10001',
S: '01111/10000/10000/01110/00001/00001/11110',
T: '11111/00100/00100/00100/00100/00100/00100',
U: '10001/10001/10001/10001/10001/10001/01110',
V: '10001/10001/10001/10001/10001/01010/00100',
W: '10001/10001/10001/10101/10101/10101/01010',
X: '10001/10001/01010/00100/01010/10001/10001',
Y: '10001/10001/01010/00100/00100/00100/00100',
Z: '11111/00001/00010/00100/01000/10000/11111',
0: '01110/10001/10011/10101/11001/10001/01110',
1: '00100/01100/00100/00100/00100/00100/01110',
2: '01110/10001/00001/00010/00100/01000/11111',
3: '11110/00001/00001/01110/00001/00001/11110',
4: '00010/00110/01010/10010/11111/00010/00010',
5: '11111/10000/10000/11110/00001/00001/11110',
6: '01110/10000/10000/11110/10001/10001/01110',
7: '11111/00001/00010/00100/01000/01000/01000',
8: '01110/10001/10001/01110/10001/10001/01110',
9: '01110/10001/10001/01111/00001/00001/01110',
' ': '000/000/000/000/000/000/000',
'!': '1/1/1/1/1/0/1',
'?': '01110/10001/00001/00010/00100/00000/00100',
'.': '0/0/0/0/0/0/1',
',': '00/00/00/00/00/01/10',
':': '0/1/0/0/1/0/0',
';': '00/01/00/00/01/01/10',
'-': '000/000/000/111/000/000/000',
'_': '00000/00000/00000/00000/00000/00000/11111',
'+': '00000/00100/00100/11111/00100/00100/00000',
'=': '00000/00000/11111/00000/11111/00000/00000',
'/': '00001/00001/00010/00100/01000/10000/10000',
'\\': '10000/10000/01000/00100/00010/00001/00001',
'(': '001/010/100/100/100/010/001',
')': '100/010/001/001/001/010/100',
'[': '111/100/100/100/100/100/111',
']': '111/001/001/001/001/001/111',
'{': '001/010/010/100/010/010/001',
'}': '100/010/010/001/010/010/100',
'<': '0001/0010/0100/1000/0100/0010/0001',
'>': '1000/0100/0010/0001/0010/0100/1000',
"'": '1/1/0/0/0/0/0',
'"': '101/101/000/000/000/000/000',
'`': '10/01/00/00/00/00/00',
'#': '01010/11111/01010/01010/11111/01010/00000',
'$': '00100/01111/10100/01110/00101/11110/00100',
'%': '11001/11010/00010/00100/01000/01011/10011',
'&': '01100/10010/10100/01000/10101/10010/01101',
'*': '00000/10101/01110/11111/01110/10101/00000',
'@': '01110/10001/10111/10101/10111/10000/01111',
'^': '00100/01010/10001/00000/00000/00000/00000',
'|': '1/1/1/1/1/1/1',
'~': '00000/00000/01001/10110/00000/00000/00000',
};
export const styles = ['block', 'banner', 'slant', 'compact'];
export function normalizeText(text) {
return text.replace(/ı/g, 'i').normalize('NFD').replace(/[\u0300-\u036f]/g, '').toUpperCase();
}
export function render(text, style = 'block') {
if (!styles.includes(style)) throw new Error('Unknown lettering style');
if (text.length > 500) throw new Error('Text is too long');
return normalizeText(text).replace(/\r\n?/g, '\n').split('\n').map(line => {
const characters = [...line.replace(/\t/g, ' ')];
const glyphs = characters.map(char => (patterns[char] || patterns['?']).split('/'));
return Array.from({length: 7}, (_, row) => {
const pixels = glyphs.map((glyph, i) => [...glyph[row]].map(pixel => {
if (style === 'banner') return pixel === '1' ? characters[i] : ' ';
if (style === 'compact') return pixel === '1' ? '#' : ' ';
return pixel === '1' ? '##' : ' ';
}).join('')).join(style === 'compact' || style === 'banner' ? ' ' : ' ');
return (style === 'slant' ? ' '.repeat(6 - row) : '') + pixels.trimEnd();
}).join('\n');
}).join('\n\n');
}