2024-02-26 20:42:07 +00:00
|
|
|
from typing import Tuple
|
|
|
|
from PIL import Image
|
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
|
|
def main(font_name, n_glyphs, fname_png, fname_c):
|
|
|
|
glyphs = load_glyphs(fname_png)
|
|
|
|
assert(len(glyphs) == n_glyphs), f"must be exactly {n_glyphs} glyphs"
|
|
|
|
|
|
|
|
with open(fname_c, "wt") as output:
|
|
|
|
output.writelines([
|
|
|
|
"// generated code! be nice!\n",
|
2024-02-26 23:27:05 +00:00
|
|
|
"#include \"sys/sys.h\"\n",
|
2024-02-26 20:42:07 +00:00
|
|
|
f"sys_glyph {font_name}[{n_glyphs}] = {{{', '.join(str(g) for g in glyphs)}}};\n"
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
|
|
def load_glyphs(fname_png: str):
|
|
|
|
with Image.open(fname_png) as im:
|
|
|
|
width = im.width
|
|
|
|
height = im.height
|
|
|
|
|
|
|
|
assert width % 8 == 0, "width must be a multiple of 8"
|
|
|
|
assert height % 8 == 0, "height must be a multiple of 8"
|
|
|
|
|
|
|
|
data = list(im.convert("RGBA").getdata())
|
|
|
|
monochrome = [pixel_to_monochrome(p) for p in data]
|
|
|
|
|
|
|
|
glyphs = []
|
|
|
|
for gy in range(0, height, 8):
|
|
|
|
for gx in range(0, width, 8):
|
|
|
|
glyph = 0
|
|
|
|
for py in range(0, 8):
|
|
|
|
for px in range(0, 8):
|
|
|
|
x = gx + px
|
|
|
|
y = gy + py
|
|
|
|
if monochrome[y * width + x]:
|
|
|
|
glyph |= 1 << (py * 8 + px)
|
|
|
|
glyphs.append(glyph)
|
|
|
|
|
|
|
|
return glyphs
|
|
|
|
|
|
|
|
|
|
|
|
def pixel_to_monochrome(rgba: Tuple[int, int, int, int]):
|
|
|
|
if rgba[3] < 128: return False
|
|
|
|
if (rgba[0] + rgba[1] + rgba[2])/3 < 128: return False
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
assert len(sys.argv) == 5, \
|
|
|
|
"there must be four args (font name, n glyphs, src png, out c)"
|
|
|
|
main(sys.argv[1], int(sys.argv[2]), sys.argv[3], sys.argv[4])
|