Skip to content

Instantly share code, notes, and snippets.

@Ismael-VC
Created September 16, 2024 18:01
Show Gist options
  • Save Ismael-VC/6e922426853e58f2bc96d4464ea5fe16 to your computer and use it in GitHub Desktop.
Save Ismael-VC/6e922426853e58f2bc96d4464ea5fe16 to your computer and use it in GitHub Desktop.
Dirty little hack to convert fonts to Uxn's .uf2 font format.
#!/usr/bin/env python3
import fontforge
import os
import sys
import subprocess
def convert_to_bdf(directory):
print("Converting font files to BDF...")
supported_formats = ('.ttf', '.otf', '.pfb', '.pcf', '.FON')
bdf_files = []
for filename in os.listdir(directory):
if filename.endswith(supported_formats):
filepath = os.path.join(directory, filename)
font = fontforge.open(filepath)
bdf_filename = os.path.splitext(filename)[0] + '.bdf'
bdf_filepath = os.path.join(directory, bdf_filename)
print(f"Converting {filename} to {bdf_filename}")
font.generate(bdf_filepath)
bdf_files.append(bdf_filepath)
return bdf_files
def bdf_to_uf2(bdf_file):
print(f"Processing BDF file: {bdf_file}")
def process_font_file(input_file):
try:
subprocess.call(f"bin/uf2fier.py {bdf_file}",shell=True)
except Exception as e:
print(e)
process_font_file(bdf_file)
def main(directory):
bdf_files = convert_to_bdf(directory)
print("Converting BDF files to UF2...")
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith('.bdf'):
bdf_file = os.path.join(root, file)
bdf_to_uf2(bdf_file)
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python3 font_to_uf2.py <directory>")
sys.exit(1)
input_directory = sys.argv[1]
if not os.path.isdir(input_directory):
print(f"Error: {input_directory} is not a valid directory.")
sys.exit(1)
main(input_directory)
#!/usr/bin/env python3
import subprocess
from sys import argv
class UF2Font:
def __init__(self, name, data):
self.data = {encoding: UF2Char(encoding, 0x00, [0x00] * 0x20)
for encoding in range(0x100)}
self.name = name
self.widths = [0x00] * 0x100
for k, v in data.items():
self.data[k] = v
self.widths[k] = v.width
def __repr__(self):
width_lines = []
for i in range(0, len(self.widths), 16):
line = " ".join(
f"{self.widths[j]:02x}{self.widths[j + 1]:02x}"
for j in range(i, i + 16, 2)
)
width_lines.append(f"\t\t{line}")
glyph_lines = "\n".join(str(char) for char in self.data.values())
return (
f"@Font-{self.name}\n"
"\t&widths [\n"
+ "\n".join(width_lines) + " ]\n"
"\t&glyphs [\n"
+ glyph_lines + " ]\n"
)
class UF2Char:
def __init__(self, code, width, data):
self.code = code
self.width = width
self.data = tuple(data)
def __repr__(self):
return (
("\t\t( code: %02x, width: %02x )\n" % (self.code, self.width)) +
"\t\t%02x%02x %02x%02x %02x%02x %02x%02x "
"%02x%02x %02x%02x %02x%02x %02x%02x\n\t\t"
"%02x%02x %02x%02x %02x%02x %02x%02x "
"%02x%02x %02x%02x %02x%02x %02x%02x"
) % self.data
return (
f"( code: {self.code:02x}, width: {self.width:02x} )\n"
"{data_lines}\n"
)
def parse_bdf_file(input_file):
with open(input_file, 'r') as file:
data = {}
name = input_file.split('.')[0]
encoding = None
width = 0
bitmap = []
in_bitmap = False
i = 0
for line in file:
line = line.strip()
if line.startswith('ENCODING'):
encoding = int(line.split()[1])
if encoding > 255:
encoding = None
elif encoding is not None and line.startswith('DWIDTH'):
width = int(line.split()[1])
elif encoding is not None and line.startswith('BITMAP'):
bitmap = [0x00] * 0x20
in_bitmap = True
i = 0
elif in_bitmap:
if line.startswith('ENDCHAR'):
data[encoding] = UF2Char(encoding, width, bitmap)
encoding = None
width = None
in_bitmap = False
else:
bitmap[i] = int(line, 16)
i += 1
return UF2Font(name, data)
def main(input_file):
font = parse_bdf_file(input_file)
tal_file = f"{input_file.split('.bdf')[0]}.tal"
with open(tal_file, 'w') as file:
file.write(str(font))
uf2_file = f"{input_file.split('.tal')[0]}.uf2"
try:
subprocess.run(['uxnasm', tal_file, uf2_file], check=True)
except Exception as e:
print(e)
if __name__ == "__main__":
if len(argv) != 2:
print("Usage: python uf2fier.py <input-file.bdf>")
else:
main(argv[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment