crocparty/pytools/font.py

55 lines
1.5 KiB
Python
Raw Normal View History

2024-02-26 20:42:07 +00:00
from typing import Tuple
from PIL import Image
import sys
2024-02-27 00:01:47 +00:00
import shared
TEMPLATE = """
// generated code! be nice!
#include "sys/sys.h"
sys_glyph font_{{ font_name }}[{{ n_glyphs }}] = { {{- glyphs|join(", ") -}} };
2024-02-27 00:01:47 +00:00
""".lstrip()
2024-02-26 20:42:07 +00:00
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:
2024-02-27 00:01:47 +00:00
output.write(
shared.templates.from_string(TEMPLATE).render(
font_name=font_name,
n_glyphs=n_glyphs,
glyphs=glyphs,
)
)
2024-02-26 20:42:07 +00:00
def load_glyphs(fname_png: str):
2024-02-27 00:05:07 +00:00
width, height, data = shared.load_image(fname_png)
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
2024-02-27 01:04:37 +00:00
if pixel_to_monochrome(data[y * width + x]):
2024-02-27 00:05:07 +00:00
glyph |= 1 << (py * 8 + px)
glyphs.append(glyph)
return glyphs
2024-02-26 20:42:07 +00:00
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])