ra8-firmware
0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
font_to_c.py
Go to the documentation of this file.
1
#!/usr/bin/env python3
2
# SPDX-License-Identifier: MIT
3
# Copyright (c) 2026 Brighton Sikarskie
4
"""Emit a C source file embedding a binary font blob as a byte array.
5
6
Dependency-free (stdlib only) so it runs at build time on any host without a
7
venv. The generated .c is written to the build directory and is NOT committed,
8
which keeps the large hex array out of the QC gates (magic-numbers / format).
9
10
Usage:
11
font_to_c.py <input-font> <output.c> <symbol_name> <header_name>
12
13
The output defines, against the declarations in <header_name> (one header per
14
baked font, named after the font -- e.g. literata_latin1.h):
15
const unsigned char <symbol_name>[] = { ... };
16
const unsigned int <symbol_name>_len = <N>;
17
18
The Latin-1 subset checked in at libs/ra8_fonts/literata_latin1.ttf was produced
19
with fonttools (in a throwaway venv) from libs/ra8_fonts/Literata-Regular.ttf
20
(Literata Regular, SIL OFL 1.1, googlefonts/literata):
21
pyftsubset Literata-Regular.ttf \
22
--unicodes='0020-00FF,2013,2014,2018,2019,201C,201D,2026' \
23
--output-file=literata_latin1.ttf \
24
--no-hinting --desubroutinize --glyph-names --notdef-outline
25
26
Copyright (c) 2026 Brighton Sikarskie
27
SPDX-License-Identifier: MIT
28
"""
29
30
import
pathlib
31
import
sys
32
33
# Expected number of CLI arguments: script + 4 positional args.
34
EXPECTED_ARGC = 5
35
36
37
def
main
() -> int:
38
"""Convert a font file to a C array, or exit 2 on a usage error.
39
40
Rejects an EMPTY input rather than emitting a zero-length array: a
41
zero-length font links cleanly and fails only at render time, where the
42
cause is far from the effect.
43
44
Returns 0 on success, 2 on wrong argument count.
45
"""
46
if
len(sys.argv) != EXPECTED_ARGC:
47
sys.stderr.write(
48
"usage: font_to_c.py <input-font> <output.c> <symbol_name> <header_name>\n"
49
)
50
return
2
51
src, dst, name, header = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]
52
data = pathlib.Path(src).read_bytes()
53
if
not
data:
54
sys.stderr.write(f
"font_to_c.py: empty input {src}\n"
)
55
return
1
56
57
out = []
58
out.append(
"/* GENERATED by scripts/gen/font_to_c.py -- do not edit. */"
)
59
out.append(f
"/* Source: {pathlib.Path(src).name} ({len(data)} bytes). */"
)
60
out.append(f
'#include "{header}"'
)
61
out.append(
""
)
62
out.append(f
"const unsigned char {name}[] = {{"
)
63
# 16 bytes per line keeps the file readable; it is build-only, not committed.
64
for
i
in
range(0, len(data), 16):
65
chunk = data[i : i + 16]
66
out.append(
" "
+
""
.join(f
"0x{b:02X}, "
for
b
in
chunk).rstrip())
67
out.append(
"};"
)
68
out.append(f
"const unsigned int {name}_len = {len(data)}U;"
)
69
out.append(
""
)
70
71
pathlib.Path(dst).write_text(
"\n"
.join(out))
72
return
0
73
74
75
if
__name__ ==
"__main__"
:
76
raise
SystemExit(
main
())
main
void main(void)
The application entry point Reset_Handler hands control to.
Definition
main.c:298
scripts
gen
font_to_c.py
Generated by
1.16.1