[fb] Add default hard-coded font

For the fb driver to have a font before loading from disk is available,
create a hard-coded font as a byte array.

To create this, added a new scripts/psf_to_cpp.py which also refactored
out much of scripts/parse_font.py into a new shared module
scripts/fontpsf.py.
This commit is contained in:
Justin C. Miller
2021-01-02 15:52:26 -08:00
parent 327cd93c04
commit f6b4a4a103
5 changed files with 387 additions and 25 deletions

75
scripts/fontpsf.py Normal file
View File

@@ -0,0 +1,75 @@
_MAGIC = (0x72, 0xb5, 0x4a, 0x86)
_VERSION = 0
class PSF2:
from collections import namedtuple
Header = namedtuple("PSF2Header",
["version", "offset", "flags", "count", "charsize", "height", "width"])
def __init__(self, filename, header, data):
self.__filename = filename
self.__header = header
self.__data = data
data = property(lambda self: self.__data)
header = property(lambda self: self.__header)
count = property(lambda self: self.__header.count)
charsize = property(lambda self: self.__header.charsize)
dimension = property(lambda self: (self.__header.width, self.__header.height))
filename = property(lambda self: self.__filename)
@classmethod
def load(cls, filename):
from os.path import basename
from struct import unpack_from
data = open(filename, 'rb').read()
fmt = "BBBBIIIIIII"
values = unpack_from(fmt, data)
if values[:len(_MAGIC)] != _MAGIC:
raise Exception("Bad magic number in header")
header = PSF2.Header(*values[len(_MAGIC):])
if header.version != _VERSION:
raise Exception(f"Bad version {header.version} in header")
return cls(basename(filename), header, data)
class Glyph:
__slots__ = ['index', 'data']
def __init__(self, i, data):
self.index = i
self.data = data
def __index__(self):
return self.index
def empty(self):
return not bool([b for b in self.data if b != 0])
def description(self):
c = chr(self.index)
if c.isprintable():
return "Glyph {:02x}: '{}'".format(self.index, c)
else:
return "Glyph {:02x}".format(self.index)
def __getitem__(self, i):
c = self.__header.charsize
n = i * c + self.__header.offset
return PSF2.Glyph(i, self.__data[n:n+c])
class __iter:
__slots__ = ['font', 'n']
def __init__(self, font):
self.font = font
self.n = 0
def __next__(self):
if self.n < self.font.count:
glyph = self.font[self.n]
self.n += 1
return glyph
else:
raise StopIteration
def __iter__(self):
return PSF2.__iter(self)

34
scripts/parse_font.py Normal file → Executable file
View File

@@ -1,21 +1,6 @@
#!/usr/bin/env python3
MAGIC = (0x72, 0xb5, 0x4a, 0x86)
from collections import namedtuple
PSF2 = namedtuple("PSF2", ["version", "offset", "flags", "count", "charsize", "height", "width"])
def read_header(data):
from struct import unpack_from, calcsize
fmt = "BBBBIIIIIII"
values = unpack_from(fmt, data)
if values[:len(MAGIC)] != MAGIC:
raise Exception("Bad magic number in header")
return PSF2(*values[len(MAGIC):])
from fontpsf import PSF2
def print_glyph(header, data):
bw = (header.width + 7) // 8
@@ -28,16 +13,15 @@ def print_glyph(header, data):
def display_font(filename):
data = open(filename, 'rb').read()
font = PSF2.load(filename)
print(font.header)
header = read_header(data)
print(header)
c = header.charsize
for i in range(0, header.count):
n = i * c + header.offset
print("Glyph {}:".format(i))
print_glyph(header, data[n:n+c])
for glyph in font:
if glyph.empty():
print("{}: BLANK".format(glyph.description()))
else:
print("{}:".format(glyph.description()))
print_glyph(font.header, glyph.data)
if __name__ == "__main__":

27
scripts/psf_to_cpp.py Executable file
View File

@@ -0,0 +1,27 @@
#!/usr/bin/env python3
from fontpsf import PSF2
def print_header(filename):
font = PSF2.load(filename)
print("#pragma once")
print(f"// This file was autogenerated by psf_to_cpp.py from {font.filename}\n")
print(f"const uint8_t font_glyph_size = {font.charsize};")
print(f"const uint8_t font_glyph_width = {font.dimension[0]};")
print(f"const uint8_t font_glyph_height = {font.dimension[1]};")
print(f"const uint16_t font_glyph_count = {font.count};\n")
print('const uint8_t font_glyph_data[] = {')
for glyph in font:
print(" ", "".join([f"0x{b:02x}," for b in glyph.data]), end="")
print(" // {}".format(glyph.description()))
print("};")
if __name__ == "__main__":
import sys
for filename in sys.argv[1:]:
print_header(filename)