-
Notifications
You must be signed in to change notification settings - Fork 60
/
text_font_converter.py
executable file
·169 lines (135 loc) · 5.29 KB
/
text_font_converter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#!/usr/bin/env python3
"""
Convert fonts from the font-bin directory of spacerace's https://github.com/spacerace/romfont
VGA and BIOS rom font repo. Optionally limiting the characters included to -first-char (-f) thru
-last-char (-l).
Input can be a file or a directory containing multiple font files. If input is a directory, output
must also be a directory. If input is a file, output can be a file or a directory.
.. seealso::
- :ref:`color_test.py<color_test>`.
- :ref:`fonts.py<fonts>`.
- :ref:`hello.py<hello>`.
- :ref:`rotations.py<rotations>`.
- :ref:`scroll.py<scroll>`.
- :ref:`tiny_toasters.py<tiny_toasters>`.
Example
^^^^^^^
.. code-block:: console
# convert the IBM_VGA_8x8.bin font to a python module with 8x8 characters
text_font_converter.py romfont/font-bin/IBM_VGA_8x8.bin vga_8x8.py -f 32 -l 127
.. code-block:: python
import tft_config
import vga_8x8
tft = tft_config.config(1)
tft.bitmap(vga_8x8, "Hello World!", 0, 0)
Usage
^^^^^
.. code-block:: console
usage: text_font_converter.py [-h] [-f FIRST_CHAR] [-l LAST_CHAR] input output
Convert romfont.bin file or directory to python module(s).
positional arguments:
input file or directory containing binary font file(s).
output file or directory to contain python font file(s).
optional arguments:
-h, --help show this help message and exit
-f FIRST_CHAR, --first-char FIRST_CHAR
The first character code to include in the conversion (default: 0x20).
-l LAST_CHAR, --last-char LAST_CHAR
The last character code to include in the conversion (default: 0x7F).
"""
import os
import re
import argparse
def convert_font(file_in, file_out, width, height, first=0x0, last=0xFF):
"""
Convert a font file to a python font file.
Args:
file_in (str): Path to the input font file or directory to convert.
file_out (str): Path to the output python font file or directory.
width (int): Width of the font.
height (int): Height of the font.
first (int): The first character code to include in the conversion (default: 0x0).
last (int): The last character code to include in the conversion (default: 0xFF).
Returns:
None
"""
chunk_size = height
with open(file_in, "rb") as bin_file, open(
file_out, "wt", encoding="utf-8"
) as font_file:
bin_file.seek(first * height)
print(f'# converted from {file_in}\n\n_FONT =\\', file=font_file)
for i in range(first, last + 1):
chunk = bin_file.read(chunk_size)
if not chunk:
last = i - 1
break
font_data = "".join(f"\\x{byte:02x}" for byte in chunk)
print(f"b'{font_data}'\\", file=font_file)
print(
"\n"
f"WIDTH = {width}\n"
f"HEIGHT = {height}\n"
f"FIRST = 0x{first:02x}"
f"LAST = 0x{last:02x}",
"\nFONT = memoryview(_FONT)",
file=font_file,
)
def main():
"""
Convert fomfont.bin font file(s) in input to python module(s) in output.
Args:
input (str): File or directory containing binary font file(s).
output (str): File or directory to contain python font file(s).
first_char (int): The first character code to include in the conversion (default: 0x20).
last_char (int): The last character code to include in the conversion (default: 0x7F).
"""
parser = argparse.ArgumentParser(
description="Convert romfont.bin file or directory to python module(s)."
)
parser.add_argument(
"input", help="file or directory containing binary font file(s)."
)
parser.add_argument(
"output", help="file or directory to contain python font file(s)."
)
parser.add_argument(
"-f",
"--first-char",
type=lambda x: int(x, 0),
default=0x20,
help="The first character code to include in the conversion (default: 0x20).",
)
parser.add_argument(
"-l",
"--last-char",
type=lambda x: int(x, 0),
default=0x7F,
help="The last character code to include in the conversion (default: 0x7F).",
)
args = parser.parse_args()
file_re = re.compile(r"^(.*)(\d+)x(\d+)\.bin$")
is_dir = os.path.isdir(args.input)
bin_files = os.listdir(args.input) if is_dir else [args.input]
for bin_file_name in bin_files:
if match := file_re.match(bin_file_name):
font_width = int(match[2])
font_height = int(match[3])
base_name = match[1].rstrip("_").lower()
font_file_name = f"{base_name}_{font_width}x{font_height}.py"
if is_dir:
bin_file_name = os.path.join(args.input, bin_file_name)
font_file_name = os.path.join(args.output, font_file_name)
else:
font_file_name = args.output
print("converting", bin_file_name, "to", font_file_name)
convert_font(
bin_file_name,
font_file_name,
font_width,
font_height,
args.first_char,
args.last_char,
)
if __name__ == "__main__":
main()