pcbjam/tests/tools/screenshots/font8x8.ts

123 lines
6.5 KiB
TypeScript
Raw Normal View History

/**
* Minimal 8x8 bitmap font for baking captions onto screenshot composites.
*
* Glyphs are the public-domain `font8x8_basic` set (Daniel Hepper's font8x8,
* https://github.com/dhepper/font8x8 — public domain / "do whatever you want"),
* printable ASCII 0x20–0x7E, plus a custom middle-dot (·, 0xB7) used as the label
* separator. Public domain, so fine to embed under our GPLv3.
*
* Each glyph is 8 row-bytes (top→bottom). Within a row byte, bit `c` (LSB = 0) is
* column `c`, left→right: pixel (c,row) is set iff `(byte >> c) & 1`.
*/
// prettier-ignore
const GLYPHS: Record<string, number[]> = {
' ': [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
'!': [0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00],
'"': [0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
'#': [0x36, 0x36, 0x7f, 0x36, 0x7f, 0x36, 0x36, 0x00],
'$': [0x0c, 0x3e, 0x03, 0x1e, 0x30, 0x1f, 0x0c, 0x00],
'%': [0x00, 0x63, 0x33, 0x18, 0x0c, 0x66, 0x63, 0x00],
'&': [0x1c, 0x36, 0x1c, 0x6e, 0x3b, 0x33, 0x6e, 0x00],
"'": [0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00],
'(': [0x18, 0x0c, 0x06, 0x06, 0x06, 0x0c, 0x18, 0x00],
')': [0x06, 0x0c, 0x18, 0x18, 0x18, 0x0c, 0x06, 0x00],
'*': [0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00],
'+': [0x00, 0x0c, 0x0c, 0x3f, 0x0c, 0x0c, 0x00, 0x00],
',': [0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x06],
'-': [0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00],
'.': [0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00],
'/': [0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00],
'0': [0x3e, 0x63, 0x73, 0x7b, 0x6f, 0x67, 0x3e, 0x00],
'1': [0x0c, 0x0e, 0x0c, 0x0c, 0x0c, 0x0c, 0x3f, 0x00],
'2': [0x1e, 0x33, 0x30, 0x1c, 0x06, 0x33, 0x3f, 0x00],
'3': [0x1e, 0x33, 0x30, 0x1c, 0x30, 0x33, 0x1e, 0x00],
'4': [0x38, 0x3c, 0x36, 0x33, 0x7f, 0x30, 0x78, 0x00],
'5': [0x3f, 0x03, 0x1f, 0x30, 0x30, 0x33, 0x1e, 0x00],
'6': [0x1c, 0x06, 0x03, 0x1f, 0x33, 0x33, 0x1e, 0x00],
'7': [0x3f, 0x33, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x00],
'8': [0x1e, 0x33, 0x33, 0x1e, 0x33, 0x33, 0x1e, 0x00],
'9': [0x1e, 0x33, 0x33, 0x3e, 0x30, 0x18, 0x0e, 0x00],
':': [0x00, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x0c, 0x00],
';': [0x00, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x0c, 0x06],
'<': [0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x00],
'=': [0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00],
'>': [0x06, 0x0c, 0x18, 0x30, 0x18, 0x0c, 0x06, 0x00],
'?': [0x1e, 0x33, 0x30, 0x18, 0x0c, 0x00, 0x0c, 0x00],
'@': [0x3e, 0x63, 0x7b, 0x7b, 0x7b, 0x03, 0x1e, 0x00],
'A': [0x0c, 0x1e, 0x33, 0x33, 0x3f, 0x33, 0x33, 0x00],
'B': [0x3f, 0x66, 0x66, 0x3e, 0x66, 0x66, 0x3f, 0x00],
'C': [0x3c, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3c, 0x00],
'D': [0x1f, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1f, 0x00],
'E': [0x7f, 0x46, 0x16, 0x1e, 0x16, 0x46, 0x7f, 0x00],
'F': [0x7f, 0x46, 0x16, 0x1e, 0x16, 0x06, 0x0f, 0x00],
'G': [0x3c, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7c, 0x00],
'H': [0x33, 0x33, 0x33, 0x3f, 0x33, 0x33, 0x33, 0x00],
'I': [0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x00],
'J': [0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1e, 0x00],
'K': [0x67, 0x66, 0x36, 0x1e, 0x36, 0x66, 0x67, 0x00],
'L': [0x0f, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7f, 0x00],
'M': [0x63, 0x77, 0x7f, 0x7f, 0x6b, 0x63, 0x63, 0x00],
'N': [0x63, 0x67, 0x6f, 0x7b, 0x73, 0x63, 0x63, 0x00],
'O': [0x1c, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1c, 0x00],
'P': [0x3f, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x0f, 0x00],
'Q': [0x1e, 0x33, 0x33, 0x33, 0x3b, 0x1e, 0x38, 0x00],
'R': [0x3f, 0x66, 0x66, 0x3e, 0x36, 0x66, 0x67, 0x00],
'S': [0x1e, 0x33, 0x07, 0x0e, 0x38, 0x33, 0x1e, 0x00],
'T': [0x3f, 0x2d, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x00],
'U': [0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3f, 0x00],
'V': [0x33, 0x33, 0x33, 0x33, 0x33, 0x1e, 0x0c, 0x00],
'W': [0x63, 0x63, 0x63, 0x6b, 0x7f, 0x77, 0x63, 0x00],
'X': [0x63, 0x63, 0x36, 0x1c, 0x1c, 0x36, 0x63, 0x00],
'Y': [0x33, 0x33, 0x33, 0x1e, 0x0c, 0x0c, 0x1e, 0x00],
'Z': [0x7f, 0x63, 0x31, 0x18, 0x4c, 0x66, 0x7f, 0x00],
'[': [0x1e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1e, 0x00],
'\\': [0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x40, 0x00],
']': [0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1e, 0x00],
'^': [0x08, 0x1c, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00],
'_': [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff],
'`': [0x0c, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00],
'a': [0x00, 0x00, 0x1e, 0x30, 0x3e, 0x33, 0x6e, 0x00],
'b': [0x07, 0x06, 0x06, 0x3e, 0x66, 0x66, 0x3b, 0x00],
'c': [0x00, 0x00, 0x1e, 0x33, 0x03, 0x33, 0x1e, 0x00],
'd': [0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6e, 0x00],
'e': [0x00, 0x00, 0x1e, 0x33, 0x3f, 0x03, 0x1e, 0x00],
'f': [0x1c, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0f, 0x00],
'g': [0x00, 0x00, 0x6e, 0x33, 0x33, 0x3e, 0x30, 0x1f],
'h': [0x07, 0x06, 0x36, 0x6e, 0x66, 0x66, 0x67, 0x00],
'i': [0x0c, 0x00, 0x0e, 0x0c, 0x0c, 0x0c, 0x1e, 0x00],
'j': [0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1e],
'k': [0x07, 0x06, 0x66, 0x36, 0x1e, 0x36, 0x67, 0x00],
'l': [0x0e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x00],
'm': [0x00, 0x00, 0x33, 0x7f, 0x7f, 0x6b, 0x63, 0x00],
'n': [0x00, 0x00, 0x1f, 0x33, 0x33, 0x33, 0x33, 0x00],
'o': [0x00, 0x00, 0x1e, 0x33, 0x33, 0x33, 0x1e, 0x00],
'p': [0x00, 0x00, 0x3b, 0x66, 0x66, 0x3e, 0x06, 0x0f],
'q': [0x00, 0x00, 0x6e, 0x33, 0x33, 0x3e, 0x30, 0x78],
'r': [0x00, 0x00, 0x3b, 0x6e, 0x66, 0x06, 0x0f, 0x00],
's': [0x00, 0x00, 0x3e, 0x03, 0x1e, 0x30, 0x1f, 0x00],
't': [0x08, 0x0c, 0x3e, 0x0c, 0x0c, 0x2c, 0x18, 0x00],
'u': [0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6e, 0x00],
'v': [0x00, 0x00, 0x33, 0x33, 0x33, 0x1e, 0x0c, 0x00],
'w': [0x00, 0x00, 0x63, 0x6b, 0x7f, 0x7f, 0x36, 0x00],
'x': [0x00, 0x00, 0x63, 0x36, 0x1c, 0x36, 0x63, 0x00],
'y': [0x00, 0x00, 0x33, 0x33, 0x33, 0x3e, 0x30, 0x1f],
'z': [0x00, 0x00, 0x3f, 0x19, 0x0c, 0x26, 0x3f, 0x00],
'{': [0x38, 0x0c, 0x0c, 0x07, 0x0c, 0x0c, 0x38, 0x00],
'|': [0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00],
'}': [0x07, 0x0c, 0x0c, 0x38, 0x0c, 0x0c, 0x07, 0x00],
'~': [0x6e, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
'·': [0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00], // custom middle-dot separator
};
const BLANK = GLYPHS[' '];
/** 8 row-bytes for a character; falls back to a blank cell for anything unmapped. */
export function glyphFor(ch: string): number[] {
return GLYPHS[ch] ?? BLANK;
}
/** Whether a character has a real glyph (used for width estimation / fitting). */
export function hasGlyph(ch: string): boolean {
return ch in GLYPHS;
}