xen32os/gen/fontgen.py

86 lines
2.0 KiB
Python

import json
import struct
# generates:
# font_data.bin
# font_table.bin
# font_data.inc
#
# struct Char {
# width: u8, height: u8, baseline: u8,
# data_offset: offset into font_data
# } (7 bytes)
CODEPAGE = {
0: None,
128: 'Ξ',
129: '\U0001f41d', # bee emoji
}
for x in range(32, 127):
CODEPAGE[x] = chr(x)
BASELINE = 7
codepoints = json.load(open("ultlf/codepoints.json"))
font_data = json.load(open("ultlf/data.json"))
baselines = json.load(open("ultlf/trimmed_baselines.json"))
UNKNOWN = [
"# ### #",
"# # # #",
"# # #",
"# # #",
"# # #",
"# #",
"# # #",
]
SPACE = [" "]
SCALE = 2
def scale(glyph):
out = []
for line in glyph:
line_scaled = ""
for ch in line:
line_scaled += ch * SCALE
out.extend([line_scaled] * SCALE)
return out
with open("xenrom/data/font_table.dat", "wb") as table_file, open("xenrom/data/font_data.dat", "wb") as data_file, open("xenrom/data/font_data.inc", "w") as inc_file:
table = b''
data = b''
for i in range(256):
ch = CODEPAGE.get(i, None)
unicode_codepoint = ord(ch) if ch is not None else None
if unicode_codepoint is None:
glyph = UNKNOWN
baseline = 6
elif unicode_codepoint == 32:
glyph = SPACE
baseline = 1
else:
ultlf_idx = codepoints.index(unicode_codepoint)
glyph = font_data[ultlf_idx]
baseline = baselines[ultlf_idx]
if "X" in "".join(glyph):
glyph = UNKNOWN
baseline = 6
glyph = scale(glyph)
baseline *= SCALE
table += struct.pack("<BBBI", len(glyph[0]), len(glyph), baseline, len(data))
for line in glyph:
for ch in line:
data += b'\x00' if ch == ' ' else b'\x01'
table_file.write(table)
data_file.write(data)
inc_file.write(f"const FONT_SIZE: {SCALE}\n")
inc_file.write(f"const FONT_LINE_HEIGHT: {9 * SCALE}\n")