diff --git a/library/dwarf.png b/library/dwarf.png new file mode 100644 index 0000000..7dd8b98 Binary files /dev/null and b/library/dwarf.png differ diff --git a/library/dwarf.py b/library/dwarf.py new file mode 100644 index 0000000..034f7e7 --- /dev/null +++ b/library/dwarf.py @@ -0,0 +1,389 @@ +#!/usr/bin/env python3 + +import numpy as np + + +def load(image_path): + from PIL import Image + + image = np.array(Image.open(image_path).convert("RGB")) + height, width, channels = image.shape + charwidth = 0 + separator = (255, 0, 255) # magenta, a la LÖVE + previous = -1 + glyphs = [] + for x, c in enumerate(image[0]): + if np.all(c == separator): + if not charwidth and previous < 0: + previous = x + continue + if not charwidth: + charwidth = x - previous + assert charwidth == x - previous, "font must be monospace" + glyph = image[:, previous + 1 : x] + glyphs.append(glyph) + previous = x + + return np.any(glyphs, axis=-1).astype(np.uint8) + + +charset = "\ +\x00☺☻♥♦♣♠•◘○◙♂♀♪♫☼\ +►◄↕‼¶§▬↨↑↓→←∟↔▲▼\ + !\"#$%&'()*+,-./\ +0123456789:;<=>?\ +@ABCDEFGHIJKLMNO\ +PQRSTUVWXYZ[\\]^_\ +`abcdefghijklmno\ +pqrstuvwxyz{|}~⌂\ +ÇüéâäàåçêëèïîìÄÅ\ +ÉæÆôöòûùÿÖÜ¢£¥₧ƒ\ +áíóúñѪº¿⌐¬½¼¡«»\ +░▒▓│┤╡╢╖╕╣║╗╝╜╛┐\ +└┴┬├─┼╞╟╚╔╩╦╠═╬╧\ +╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀\ +αßΓπΣσµτΦΘΩδ∞φε∩\ +≡±≥≤⌠⌡÷≈°∙·√ⁿ²■�" + +assert len(charset) == 256 + +chars = b"\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x7E\xC3\x81\xA5\x81\xBD\x99\xC3\x7E\x00\x00\ +\x00\x7E\xFF\xFF\xDB\xFF\xC3\xE7\xFF\x7E\x00\x00\ +\x00\x00\x44\xEE\xFE\xFE\xFE\x7C\x38\x10\x00\x00\ +\x00\x10\x38\x7C\xFE\xFE\x7C\x38\x10\x00\x00\x00\ +\x00\x18\x3C\x3C\xFF\xE7\xE7\x18\x18\x7E\x00\x00\ +\x00\x18\x3C\x7E\xFF\xFF\x7E\x18\x18\x7E\x00\x00\ +\x00\x00\x00\x00\x3C\x7E\x7E\x3C\x00\x00\x00\x00\ +\xFF\xFF\xFF\xFF\xC3\x81\x81\xC3\xFF\xFF\xFF\xFF\ +\x00\x00\x3C\x7E\x66\x42\x42\x66\x7E\x3C\x00\x00\ +\xFF\xFF\xC3\x81\x99\xBD\xBD\x99\x81\xC3\xFF\xFF\ +\x00\x3E\x0E\x3A\x72\xF8\xCC\xCC\xCC\x78\x00\x00\ +\x00\x3C\x66\x66\x66\x3C\x18\x7E\x18\x18\x00\x00\ +\x00\x1F\x19\x19\x1F\x18\x18\x78\xF8\x70\x00\x00\ +\x00\x7F\x63\x7F\x63\x63\x63\x67\xE7\xE6\xC0\x00\ +\x00\x00\x18\xDB\x7E\xE7\xE7\x7E\xDB\x18\x00\x00\ +\x00\x80\xC0\xE0\xF8\xFE\xF8\xE0\xC0\x80\x00\x00\ +\x00\x02\x06\x0E\x3E\xFE\x3E\x0E\x06\x02\x00\x00\ +\x00\x18\x3C\x7E\x18\x18\x18\x7E\x3C\x18\x00\x00\ +\x00\x66\x66\x66\x66\x66\x00\x00\x66\x66\x00\x00\ +\x00\x7F\xDB\xDB\xDB\x7B\x1B\x1B\x1B\x1B\x00\x00\ +\x00\x7E\x63\x30\x3C\x66\x66\x3C\x0C\xC6\x7E\x00\ +\x00\x00\x00\x00\x00\x00\x00\xFE\xFE\xFE\x00\x00\ +\x00\x18\x3C\x7E\x18\x18\x18\x7E\x3C\x18\x7E\x00\ +\x00\x18\x3C\x7E\x18\x18\x18\x18\x18\x18\x00\x00\ +\x00\x18\x18\x18\x18\x18\x18\x7E\x3C\x18\x00\x00\ +\x00\x00\x00\x18\x0C\xFE\x0C\x18\x00\x00\x00\x00\ +\x00\x00\x00\x30\x60\xFE\x60\x30\x00\x00\x00\x00\ +\x00\x00\x00\x00\xC0\xC0\xC0\xFE\x00\x00\x00\x00\ +\x00\x00\x00\x24\x66\xFF\x66\x24\x00\x00\x00\x00\ +\x00\x00\x10\x10\x38\x38\x7C\x7C\xFE\xFE\x00\x00\ +\x00\x00\xFE\xFE\x7C\x7C\x38\x38\x10\x10\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x30\x78\x78\x78\x30\x30\x00\x30\x30\x00\x00\ +\x00\x66\x66\x66\x24\x00\x00\x00\x00\x00\x00\x00\ +\x00\x6C\x6C\xFE\x6C\x6C\x6C\xFE\x6C\x6C\x00\x00\ +\x30\x30\x7C\xC0\xC0\x78\x0C\x0C\xF8\x30\x30\x00\ +\x00\x00\x00\xC4\xCC\x18\x30\x60\xCC\x8C\x00\x00\ +\x00\x70\xD8\xD8\x70\xFA\xDE\xCC\xDC\x76\x00\x00\ +\x00\x30\x30\x30\x60\x00\x00\x00\x00\x00\x00\x00\ +\x00\x0C\x18\x30\x60\x60\x60\x30\x18\x0C\x00\x00\ +\x00\x60\x30\x18\x0C\x0C\x0C\x18\x30\x60\x00\x00\ +\x00\x00\x00\x66\x3C\xFF\x3C\x66\x00\x00\x00\x00\ +\x00\x00\x00\x18\x18\x7E\x18\x18\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x38\x38\x60\x00\ +\x00\x00\x00\x00\x00\xFE\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x38\x38\x00\x00\ +\x00\x00\x02\x06\x0C\x18\x30\x60\xC0\x80\x00\x00\ +\x00\x7C\xC6\xCE\xDE\xD6\xF6\xE6\xC6\x7C\x00\x00\ +\x00\x10\x30\xF0\x30\x30\x30\x30\x30\xFC\x00\x00\ +\x00\x78\xCC\xCC\x0C\x18\x30\x60\xCC\xFC\x00\x00\ +\x00\x78\xCC\x0C\x0C\x38\x0C\x0C\xCC\x78\x00\x00\ +\x00\x0C\x1C\x3C\x6C\xCC\xFE\x0C\x0C\x1E\x00\x00\ +\x00\xFC\xC0\xC0\xC0\xF8\x0C\x0C\xCC\x78\x00\x00\ +\x00\x38\x60\xC0\xC0\xF8\xCC\xCC\xCC\x78\x00\x00\ +\x00\xFE\xC6\xC6\x06\x0C\x18\x30\x30\x30\x00\x00\ +\x00\x78\xCC\xCC\xEC\x78\xDC\xCC\xCC\x78\x00\x00\ +\x00\x78\xCC\xCC\xCC\x7C\x18\x18\x30\x70\x00\x00\ +\x00\x00\x00\x38\x38\x00\x00\x38\x38\x00\x00\x00\ +\x00\x00\x00\x38\x38\x00\x00\x38\x38\x18\x30\x00\ +\x00\x0C\x18\x30\x60\xC0\x60\x30\x18\x0C\x00\x00\ +\x00\x00\x00\x00\x7E\x00\x7E\x00\x00\x00\x00\x00\ +\x00\x60\x30\x18\x0C\x06\x0C\x18\x30\x60\x00\x00\ +\x00\x78\xCC\x0C\x18\x30\x30\x00\x30\x30\x00\x00\ +\x00\x7C\xC6\xC6\xDE\xDE\xDE\xC0\xC0\x7C\x00\x00\ +\x00\x30\x78\xCC\xCC\xCC\xFC\xCC\xCC\xCC\x00\x00\ +\x00\xFC\x66\x66\x66\x7C\x66\x66\x66\xFC\x00\x00\ +\x00\x3C\x66\xC6\xC0\xC0\xC0\xC6\x66\x3C\x00\x00\ +\x00\xF8\x6C\x66\x66\x66\x66\x66\x6C\xF8\x00\x00\ +\x00\xFE\x62\x60\x64\x7C\x64\x60\x62\xFE\x00\x00\ +\x00\xFE\x66\x62\x64\x7C\x64\x60\x60\xF0\x00\x00\ +\x00\x3C\x66\xC6\xC0\xC0\xCE\xC6\x66\x3E\x00\x00\ +\x00\xCC\xCC\xCC\xCC\xFC\xCC\xCC\xCC\xCC\x00\x00\ +\x00\x78\x30\x30\x30\x30\x30\x30\x30\x78\x00\x00\ +\x00\x1E\x0C\x0C\x0C\x0C\xCC\xCC\xCC\x78\x00\x00\ +\x00\xE6\x66\x6C\x6C\x78\x6C\x6C\x66\xE6\x00\x00\ +\x00\xF0\x60\x60\x60\x60\x62\x66\x66\xFE\x00\x00\ +\x00\xC6\xEE\xFE\xFE\xD6\xC6\xC6\xC6\xC6\x00\x00\ +\x00\xC6\xC6\xE6\xF6\xFE\xDE\xCE\xC6\xC6\x00\x00\ +\x00\x38\x6C\xC6\xC6\xC6\xC6\xC6\x6C\x38\x00\x00\ +\x00\xFC\x66\x66\x66\x7C\x60\x60\x60\xF0\x00\x00\ +\x00\x38\x6C\xC6\xC6\xC6\xCE\xDE\x7C\x0C\x1E\x00\ +\x00\xFC\x66\x66\x66\x7C\x6C\x66\x66\xE6\x00\x00\ +\x00\x78\xCC\xCC\xC0\x70\x18\xCC\xCC\x78\x00\x00\ +\x00\xFC\xB4\x30\x30\x30\x30\x30\x30\x78\x00\x00\ +\x00\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x78\x00\x00\ +\x00\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x78\x30\x00\x00\ +\x00\xC6\xC6\xC6\xC6\xD6\xD6\x6C\x6C\x6C\x00\x00\ +\x00\xCC\xCC\xCC\x78\x30\x78\xCC\xCC\xCC\x00\x00\ +\x00\xCC\xCC\xCC\xCC\x78\x30\x30\x30\x78\x00\x00\ +\x00\xFE\xCE\x98\x18\x30\x60\x62\xC6\xFE\x00\x00\ +\x00\x3C\x30\x30\x30\x30\x30\x30\x30\x3C\x00\x00\ +\x00\x00\x80\xC0\x60\x30\x18\x0C\x06\x02\x00\x00\ +\x00\x3C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x3C\x00\x00\ +\x10\x38\x6C\xC6\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\x00\ +\x30\x30\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x78\x0C\x7C\xCC\xCC\x76\x00\x00\ +\x00\xE0\x60\x60\x7C\x66\x66\x66\x66\xDC\x00\x00\ +\x00\x00\x00\x00\x78\xCC\xC0\xC0\xCC\x78\x00\x00\ +\x00\x1C\x0C\x0C\x7C\xCC\xCC\xCC\xCC\x76\x00\x00\ +\x00\x00\x00\x00\x78\xCC\xFC\xC0\xCC\x78\x00\x00\ +\x00\x38\x6C\x60\x60\xF8\x60\x60\x60\xF0\x00\x00\ +\x00\x00\x00\x00\x76\xCC\xCC\xCC\x7C\x0C\xCC\x78\ +\x00\xE0\x60\x60\x6C\x76\x66\x66\x66\xE6\x00\x00\ +\x00\x18\x18\x00\x78\x18\x18\x18\x18\x7E\x00\x00\ +\x00\x0C\x0C\x00\x3C\x0C\x0C\x0C\x0C\xCC\xCC\x78\ +\x00\xE0\x60\x60\x66\x6C\x78\x6C\x66\xE6\x00\x00\ +\x00\x78\x18\x18\x18\x18\x18\x18\x18\x7E\x00\x00\ +\x00\x00\x00\x00\xFC\xD6\xD6\xD6\xD6\xC6\x00\x00\ +\x00\x00\x00\x00\xF8\xCC\xCC\xCC\xCC\xCC\x00\x00\ +\x00\x00\x00\x00\x78\xCC\xCC\xCC\xCC\x78\x00\x00\ +\x00\x00\x00\x00\xDC\x66\x66\x66\x66\x7C\x60\xF0\ +\x00\x00\x00\x00\x76\xCC\xCC\xCC\xCC\x7C\x0C\x1E\ +\x00\x00\x00\x00\xEC\x6E\x76\x60\x60\xF0\x00\x00\ +\x00\x00\x00\x00\x78\xCC\x60\x18\xCC\x78\x00\x00\ +\x00\x00\x20\x60\xFC\x60\x60\x60\x6C\x38\x00\x00\ +\x00\x00\x00\x00\xCC\xCC\xCC\xCC\xCC\x76\x00\x00\ +\x00\x00\x00\x00\xCC\xCC\xCC\xCC\x78\x30\x00\x00\ +\x00\x00\x00\x00\xC6\xC6\xD6\xD6\x6C\x6C\x00\x00\ +\x00\x00\x00\x00\xC6\x6C\x38\x38\x6C\xC6\x00\x00\ +\x00\x00\x00\x00\x66\x66\x66\x66\x3C\x0C\x18\xF0\ +\x00\x00\x00\x00\xFC\x8C\x18\x60\xC4\xFC\x00\x00\ +\x00\x1C\x30\x30\x60\xC0\x60\x30\x30\x1C\x00\x00\ +\x00\x18\x18\x18\x18\x00\x18\x18\x18\x18\x00\x00\ +\x00\xE0\x30\x30\x18\x0C\x18\x30\x30\xE0\x00\x00\ +\x00\x73\xDA\xCE\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x10\x38\x6C\xC6\xC6\xFE\x00\x00\x00\ +\x00\x78\xCC\xCC\xC0\xC0\xC0\xCC\xCC\x78\x30\xF0\ +\x00\xCC\xCC\x00\xCC\xCC\xCC\xCC\xCC\x76\x00\x00\ +\x0C\x18\x30\x00\x78\xCC\xFC\xC0\xCC\x78\x00\x00\ +\x30\x78\xCC\x00\x78\x0C\x7C\xCC\xCC\x76\x00\x00\ +\x00\xCC\xCC\x00\x78\x0C\x7C\xCC\xCC\x76\x00\x00\ +\xC0\x60\x30\x00\x78\x0C\x7C\xCC\xCC\x76\x00\x00\ +\x38\x6C\x6C\x38\xF8\x0C\x7C\xCC\xCC\x76\x00\x00\ +\x00\x00\x00\x00\x78\xCC\xC0\xC0\xCC\x78\x30\xF0\ +\x30\x78\xCC\x00\x78\xCC\xFC\xC0\xC0\x7C\x00\x00\ +\x00\xCC\xCC\x00\x78\xCC\xFC\xC0\xC0\x7C\x00\x00\ +\xC0\x60\x30\x00\x78\xCC\xFC\xC0\xC0\x7C\x00\x00\ +\x00\x6C\x6C\x00\x78\x18\x18\x18\x18\x7E\x00\x00\ +\x10\x38\x6C\x00\x78\x18\x18\x18\x18\x7E\x00\x00\ +\x60\x30\x18\x00\x78\x18\x18\x18\x18\x7E\x00\x00\ +\x00\xCC\x00\x30\x78\xCC\xCC\xFC\xCC\xCC\x00\x00\ +\x78\xCC\xCC\x78\x78\xCC\xCC\xFC\xCC\xCC\x00\x00\ +\x0C\x18\x30\xFC\xC4\xC0\xF8\xC0\xC4\xFC\x00\x00\ +\x00\x00\x00\x00\xFE\x1B\x7F\xD8\xD8\xEF\x00\x00\ +\x00\x3E\x78\xD8\xD8\xFE\xD8\xD8\xD8\xDE\x00\x00\ +\x30\x78\xCC\x00\x78\xCC\xCC\xCC\xCC\x78\x00\x00\ +\x00\xCC\xCC\x00\x78\xCC\xCC\xCC\xCC\x78\x00\x00\ +\xC0\x60\x30\x00\x78\xCC\xCC\xCC\xCC\x78\x00\x00\ +\x30\x78\xCC\x00\xCC\xCC\xCC\xCC\xCC\x76\x00\x00\ +\xC0\x60\x30\x00\xCC\xCC\xCC\xCC\xCC\x76\x00\x00\ +\x00\x66\x66\x00\x66\x66\x66\x66\x3C\x0C\x18\xF0\ +\xCC\x00\x78\xCC\xCC\xCC\xCC\xCC\xCC\x78\x00\x00\ +\xCC\x00\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x78\x00\x00\ +\x00\x30\x30\x78\xCC\xC0\xC0\xCC\x78\x30\x30\x00\ +\x3C\x66\x60\x60\x60\xFC\x60\x60\xC0\xFE\x00\x00\ +\xCC\xCC\xCC\xCC\x78\xFC\x30\xFC\x30\x30\x00\x00\ +\xF0\x88\x88\x88\xF0\x88\x9E\x8C\x8D\x86\x00\x00\ +\x0E\x1B\x18\x18\x7E\x18\x18\x18\xD8\x70\x00\x00\ +\x0C\x18\x30\x00\x78\x0C\x7C\xCC\xCC\x76\x00\x00\ +\x0C\x18\x30\x00\x78\x18\x18\x18\x18\x7E\x00\x00\ +\x0C\x18\x30\x00\x78\xCC\xCC\xCC\xCC\x78\x00\x00\ +\x0C\x18\x30\x00\xCC\xCC\xCC\xCC\xCC\x76\x00\x00\ +\x00\x76\xDC\x00\xF8\xCC\xCC\xCC\xCC\xCC\x00\x00\ +\x76\xDC\x00\xC6\xE6\xF6\xDE\xCE\xC6\xC6\x00\x00\ +\x00\x78\xCC\xCC\x7E\x00\xFE\x00\x00\x00\x00\x00\ +\x00\x78\xCC\xCC\x78\x00\xFE\x00\x00\x00\x00\x00\ +\x00\x30\x30\x00\x30\x60\xC0\xC0\xCC\x78\x00\x00\ +\x00\x00\x00\x00\x00\xFC\xC0\xC0\xC0\x00\x00\x00\ +\x00\x00\x00\x00\x00\xFC\x0C\x0C\x0C\x00\x00\x00\ +\x00\x42\xC6\xCC\xD8\x30\x6E\xC3\x86\x0C\x1F\x00\ +\x00\x63\xE6\x6C\x78\x37\x6F\xDB\xB3\x3F\x03\x00\ +\x00\x30\x30\x00\x30\x30\x78\x78\x78\x30\x00\x00\ +\x00\x00\x00\x00\x33\x66\xCC\xCC\x66\x33\x00\x00\ +\x00\x00\x00\x00\xCC\x66\x33\x33\x66\xCC\x00\x00\ +\x24\x92\x49\x24\x92\x49\x24\x92\x49\x24\x92\x49\ +\x55\xAA\x55\xAA\x55\xAA\x55\xAA\x55\xAA\x55\xAA\ +\x6D\xDB\xB6\x6D\xDB\xB6\x6D\xDB\xB6\x6D\xDB\xB6\ +\x18\x18\x18\x18\x18\x18\x18\x18\x18\x18\x18\x18\ +\x18\x18\x18\x18\x18\xF8\x18\x18\x18\x18\x18\x18\ +\x18\x18\x18\x18\xF8\x18\x18\xF8\x18\x18\x18\x18\ +\x66\x66\x66\x66\x66\xE6\x66\x66\x66\x66\x66\x66\ +\x00\x00\x00\x00\x00\xFE\x66\x66\x66\x66\x66\x66\ +\x00\x00\x00\x00\xF8\x18\x18\xF8\x18\x18\x18\x18\ +\x66\x66\x66\x66\xE6\x06\x06\xE6\x66\x66\x66\x66\ +\x66\x66\x66\x66\x66\x66\x66\x66\x66\x66\x66\x66\ +\x00\x00\x00\x00\xFE\x06\x06\xE6\x66\x66\x66\x66\ +\x66\x66\x66\x66\xE6\x06\x06\xFE\x00\x00\x00\x00\ +\x66\x66\x66\x66\x66\xFE\x00\x00\x00\x00\x00\x00\ +\x18\x18\x18\x18\xF8\x18\x18\xF8\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xF8\x18\x18\x18\x18\x18\x18\ +\x18\x18\x18\x18\x18\x1F\x00\x00\x00\x00\x00\x00\ +\x18\x18\x18\x18\x18\xFF\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\xFF\x18\x18\x18\x18\x18\x18\ +\x18\x18\x18\x18\x18\x1F\x18\x18\x18\x18\x18\x18\ +\x00\x00\x00\x00\x00\xFF\x00\x00\x00\x00\x00\x00\ +\x18\x18\x18\x18\x18\xFF\x18\x18\x18\x18\x18\x18\ +\x18\x18\x18\x18\x1F\x18\x18\x1F\x18\x18\x18\x18\ +\x66\x66\x66\x66\x66\x67\x66\x66\x66\x66\x66\x66\ +\x66\x66\x66\x66\x67\x60\x60\x7F\x00\x00\x00\x00\ +\x00\x00\x00\x00\x7F\x60\x60\x67\x66\x66\x66\x66\ +\x66\x66\x66\x66\xE7\x00\x00\xFF\x00\x00\x00\x00\ +\x00\x00\x00\x00\xFF\x00\x00\xE7\x66\x66\x66\x66\ +\x66\x66\x66\x66\x67\x60\x60\x67\x66\x66\x66\x66\ +\x00\x00\x00\x00\xFF\x00\x00\xFF\x00\x00\x00\x00\ +\x66\x66\x66\x66\xE7\x00\x00\xE7\x66\x66\x66\x66\ +\x18\x18\x18\x18\xFF\x00\x00\xFF\x00\x00\x00\x00\ +\x66\x66\x66\x66\x66\xFF\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\xFF\x00\x00\xFF\x18\x18\x18\x18\ +\x00\x00\x00\x00\x00\xFF\x66\x66\x66\x66\x66\x66\ +\x66\x66\x66\x66\x66\x7F\x00\x00\x00\x00\x00\x00\ +\x18\x18\x18\x18\x1F\x18\x18\x1F\x00\x00\x00\x00\ +\x00\x00\x00\x00\x1F\x18\x18\x1F\x18\x18\x18\x18\ +\x00\x00\x00\x00\x00\x7F\x66\x66\x66\x66\x66\x66\ +\x66\x66\x66\x66\x66\xE7\x66\x66\x66\x66\x66\x66\ +\x18\x18\x18\x18\xFF\x00\x00\xFF\x18\x18\x18\x18\ +\x18\x18\x18\x18\x18\xF8\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x1F\x18\x18\x18\x18\x18\x18\ +\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\ +\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\ +\xF0\xF0\xF0\xF0\xF0\xF0\xF0\xF0\xF0\xF0\xF0\xF0\ +\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\ +\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x76\xDE\xCC\xCC\xDE\x76\x00\x00\ +\x00\x78\xCC\xCC\xD8\xCC\xCC\xCC\xF8\xC0\x60\x00\ +\x00\xFC\xCC\xCC\xC0\xC0\xC0\xC0\xC0\xC0\x00\x00\ +\x00\xFE\x6C\x6C\x6C\x6C\x6C\x6C\x6C\x66\x00\x00\ +\x00\xFC\xC4\x64\x60\x30\x60\x64\xC4\xFC\x00\x00\ +\x00\x00\x00\x00\x7E\xC8\xCC\xCC\xCC\x78\x00\x00\ +\x00\x00\x00\x00\x66\x66\x66\x66\x66\x7B\x60\xC0\ +\x00\x00\x00\x76\xDC\x18\x18\x18\x18\x0E\x00\x00\ +\x00\xFC\x30\x78\xCC\xCC\xCC\x78\x30\xFC\x00\x00\ +\x00\x78\xCC\xCC\xCC\xFC\xCC\xCC\xCC\x78\x00\x00\ +\x00\x7C\xC6\xC6\xC6\xC6\x6C\x6C\x6C\xEE\x00\x00\ +\x00\x3C\x60\x30\x78\xCC\xCC\xCC\xCC\x78\x00\x00\ +\x00\x00\x00\x76\xDB\xDB\xDB\x6E\x00\x00\x00\x00\ +\x00\x00\x06\x7C\xDE\xD6\xF6\x7C\xC0\x00\x00\x00\ +\x00\x3C\x60\xC0\xC0\xFC\xC0\xC0\x60\x3C\x00\x00\ +\x00\x00\x78\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x00\x00\ +\x00\x00\xFC\x00\x00\xFC\x00\x00\xFC\x00\x00\x00\ +\x00\x00\x30\x30\xFC\x30\x30\x00\xFC\x00\x00\x00\ +\x00\x60\x30\x18\x18\x30\x60\x00\xFC\x00\x00\x00\ +\x00\x18\x30\x60\x60\x30\x18\x00\xFC\x00\x00\x00\ +\x00\x00\x0E\x1B\x1B\x18\x18\x18\x18\x18\x18\x18\ +\x18\x18\x18\x18\x18\x18\x18\xD8\xD8\x70\x00\x00\ +\x00\x00\x30\x30\x00\xFC\x00\x30\x30\x00\x00\x00\ +\x00\x00\x73\xDB\xCE\x00\x73\xDB\xCE\x00\x00\x00\ +\x00\x3C\x66\x66\x66\x3C\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x1C\x1C\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\ +\x00\x07\x04\x04\x04\x44\x64\x34\x1C\x0C\x00\x00\ +\x00\xD8\x6C\x6C\x6C\x6C\x00\x00\x00\x00\x00\x00\ +\x00\x78\x0C\x18\x30\x7C\x00\x00\x00\x00\x00\x00\ +\x00\x00\x3C\x3C\x3C\x3C\x3C\x3C\x3C\x3C\x00\x00\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ +" + +assert len(chars) == len(charset) * 12 + + +glyphs = np.unpackbits(np.frombuffer(chars, np.uint8)).reshape(256, 12, 8) + + +def render(text, scale): + if isinstance(text, str): + inds = [charset.index(c) if c in charset else 255 for c in text] + else: + inds = list(text) + + if len(inds) == 0: + return np.array((), np.uint8) + + image = np.zeros((12, len(inds) * 8), np.uint8) + for i, ind in enumerate(inds): + a = i * 8 + b = a + 8 + # glyph = np.unpackbits(chars[a:b]) # BROKEN + # glyph.shape = (8, 12) + # image[:, a:b] = glyph + image[:, a:b] = glyphs[ind] + return image + + +# TODO: optional flip horizontal and vertical kwargs. +def render_to(text, image, *, x, y, scale=1, masked=0): + # TODO: maybe return whether or not + # the text had to be clipped within the image bounds? + assert scale > 0 + assert isinstance(scale, int) + assert masked in (-1, 0, 1) + text = render(text, scale) * 255 + if scale > 1: + text2 = np.repeat(text, scale) + text2.shape = (text.shape[0], text.shape[1] * scale) + x2 = x + text2.shape[1] + if masked == 0: + for yy in range(12): + for s in range(scale): + image[y + yy * scale + s, x:x2, ...] = text2[yy, :, None] + elif masked == 1: + for yy in range(12): + mask = text2[yy, :] != 0 + for s in range(scale): + image[y + yy * scale + s, x:x2, ...][mask] = 255 + elif masked == -1: + for yy in range(12): + mask = text2[yy, :] == 0 + for s in range(scale): + image[y + yy * scale + s, x:x2, ...][mask] = 0 + else: + x2 = x + text.shape[1] + y2 = y + text.shape[0] + if masked == 0: + image[y:y2, x:x2, ...] = text[:, :, None] + elif masked == 1: + mask = text[:, :] != 0 + image[y:y2, x:x2, ...][mask] = 255 + elif masked == -1: + mask = text[:, :] == 0 + image[y:y2, x:x2, ...][mask] = 0 + + +if __name__ == "__main__": + from sys import stderr + from base64 import b64encode + + glyphs = load("dwarf.png") + + for i, glyph in enumerate(glyphs): + print(f"<== {i} ==>", file=stderr) + for row in glyph: + print("".join("#" if col else "." for col in row), file=stderr) + packed = np.packbits(glyph) # 1 bit per pixel + formatted = "".join(f"\\x{byte:02X}" for byte in packed) + print(f'b"{formatted}",') + # print() + + print(b64encode(glyphs.tobytes()))