Add c_to_python_font.py.

pull/45/head
Peter Hinch 2022-01-14 14:48:04 +00:00
rodzic dcc97abc3f
commit eebd7307af
11 zmienionych plików z 227 dodań i 4 usunięć

Wyświetl plik

@ -33,13 +33,14 @@ The resultant file is usable with two varieties of display device drivers:
# 2. Solution # 2. Solution
This comprises three components, links to docs below: This comprises four components, links to docs below:
1. [font_to_py.py](./FONT_TO_PY.md) This utility runs on a PC and converts a 1. [font_to_py.py](./FONT_TO_PY.md) This utility runs on a PC and converts an
font file to Python source. See below. industry standard font file to Python source. See below.
2. [Writer and CWriter classes](./writer/WRITER.md) These facilitate rendering 2. [Writer and CWriter classes](./writer/WRITER.md) These facilitate rendering
text to a monochrome or colour display having a suitable device driver. text to a monochrome or colour display having a suitable device driver.
3. [Device driver notes](./writer/DRIVERS.md). Notes for authors of display 3. [Creating icon fonts](./icon_fonts/README.md)
4. [Device driver notes](./writer/DRIVERS.md). Notes for authors of display
device drivers. Provides details of the font file format and information on device drivers. Provides details of the font file format and information on
ensuring comptibility with the `Writer` classes. ensuring comptibility with the `Writer` classes.

164
c_to_python_font.py 100755
Wyświetl plik

@ -0,0 +1,164 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2022 Peter Hinch
import sys
from font_to_py import ByteWriter, var_write, write_func, STR02, STR02H
STR01 = """# Code generated by c_to_python_font.py.
# Char set: {}
# Cmd: {}
version = '0.10'
"""
class Glyph:
dstart = 0 # Start index of next glyph
def __init__(self):
self.width = 0
self.height = 0
def populate(self, fn, data, idx):
try:
with open(fn, "r") as f:
s = f.readline()
elements = s.split(" ")
if elements[1].endswith("width"):
self.width = int(elements[2])
data.extend((self.width).to_bytes(2, 'little'))
else:
return False
s = f.readline()
elements = s.split(" ")
if elements[1].endswith("height"):
self.height = int(elements[2])
else:
return False
s = f.readline()
if not s.startswith("static"):
return False
while s := f.readline():
if (lb := s.find("}")) != -1:
s = s[:lb] # Strip trailing };
p = s.strip().split(',')
if not p[-1]:
p = p[: -1]
z = [int(x, 16) for x in p]
data.extend(bytearray(z))
# index points to start of current data block
idx.extend((Glyph.dstart).to_bytes(2, 'little'))
Glyph.dstart += ((self.width - 1)//8 + 1) * self.height + 2
except OSError:
return False
return True
class Font:
def __init__(self):
self.glyphs = []
self.height = 0
self.max_width = 0
self.data = bytearray()
self.index = bytearray()
def __getitem__(self, glyph_index):
return self.glyphs[glyph_index]
def populate(self, filename="filenames.txt"):
try:
with open(filename, "r") as f:
while fn := f.readline().strip(): # Get current C file
if (lc := fn.find("#")) != -1:
if (fn := fn[:lc].strip()) == "":
continue
g = Glyph()
if g.populate(fn, self.data, self.index):
if ht := self.height:
if ht != g.height:
print(f"Fatal: file {fn} height is {g.height} while font height is {ht}")
return False
else:
self.height = g.height
self.glyphs.append(g)
self.max_width = max(self.max_width, g.width)
else:
print('Failed to read', fn)
return False
except OSError:
print("Failed to read", filename)
return False
return True
def output(self, stream):
minchar = ord("A")
nglyphs = len(self.glyphs) - 1 # Number less default glyph
maxchar = minchar + nglyphs - 1
st = ""
for z in range(nglyphs):
st = "".join((st, chr(minchar + z)))
cl = ' '.join(sys.argv)
stream.write(STR01.format(st, cl))
write_func(stream, 'height', self.height)
write_func(stream, 'baseline', self.height)
write_func(stream, 'max_width', self.max_width)
write_func(stream, 'hmap', True)
write_func(stream, 'reverse', True) # ????
write_func(stream, 'monospaced', False)
write_func(stream, 'min_ch', minchar)
write_func(stream, 'max_ch', maxchar)
bw_font = ByteWriter(stream, '_font')
bw_font.odata(self.data)
bw_font.eot()
bw_index = ByteWriter(stream, '_index')
bw_index.odata(self.index)
bw_index.eot()
stream.write(STR02.format(minchar, maxchar))
stream.write(STR02H.format(self.height))
def make_font(infile="filenames.txt", outfile="icofont.py"):
try:
with open(outfile, "w") as f:
font = Font()
if font.populate(infile):
font.output(f)
else:
return # Failed
except OSError:
print(f"Failed to open {outfile} for writing.")
print(f"{outfile} successfully written.")
def version_check():
n = sys.implementation.name
v = sys.implementation.version
if n == "cpython":
if v[0] == 3:
return v[1] >= 8
return v[0] > 3
return False # Requires CPython
usage = """Convert a set of C bitmaps to a Python font file. Usage:
c_to_python_font.py [infile [outfile]]
infile contains a list of C bitmap files, one per line.
outfile is the name of the output Python font.
Default args:
infile: filenames.txt
outfile: icofont.py
e.g.
$ ./c_to_python_font.py my_file_list.txt my_font.py
"""
if __name__ == "__main__":
a = sys.argv
if len(a) >= 2 and a[1] in ("--help", "-h", "help"):
print(usage)
elif not version_check():
print("This script requires Python 3.8 or above.")
else:
infile = a[1] if len(a) >= 2 else "filenames.txt"
outfile = a[2] if len(a) >= 3 else "icofont.py"
make_font(infile, outfile)

Wyświetl plik

@ -0,0 +1,8 @@
#define back_width 19
#define back_height 19
static unsigned char back_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04,
0x80, 0x03, 0x06, 0xc0, 0x83, 0x07, 0xf0, 0xc3, 0x07, 0xf8, 0xe3, 0x07,
0xfe, 0xfb, 0x07, 0xff, 0xff, 0x07, 0xfe, 0xfb, 0x07, 0xf8, 0xf3, 0x07,
0xf0, 0xc3, 0x07, 0xc0, 0x83, 0x07, 0x80, 0x03, 0x07, 0x00, 0x02, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

Wyświetl plik

@ -0,0 +1,8 @@
#define default_width 19
#define default_height 19
static unsigned char default_bits[] = {
0x01, 0x00, 0x04, 0x02, 0x00, 0x02, 0x04, 0x00, 0x01, 0x08, 0x80, 0x00,
0x10, 0x40, 0x00, 0x20, 0x20, 0x00, 0x40, 0x10, 0x00, 0x80, 0x08, 0x00,
0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x80, 0x08, 0x00,
0x40, 0x10, 0x00, 0x20, 0x20, 0x00, 0x10, 0x40, 0x00, 0x08, 0x80, 0x00,
0x04, 0x00, 0x01, 0x02, 0x00, 0x02, 0x01, 0x00, 0x04};

Wyświetl plik

@ -0,0 +1,7 @@
# Filenames for media player icons
default.c
play.c # Test
stop.c
pause.c
back.c
fwd.c

8
icon_fonts/fwd.c 100644
Wyświetl plik

@ -0,0 +1,8 @@
#define fwd_width 19
#define fwd_height 19
static unsigned char fwd_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00,
0x03, 0x0e, 0x00, 0x0f, 0x1e, 0x00, 0x1f, 0x7e, 0x00, 0x3f, 0xfe, 0x00,
0xff, 0xfe, 0x03, 0xff, 0xff, 0x07, 0xff, 0xff, 0x07, 0xff, 0xfe, 0x03,
0x7f, 0xfe, 0x00, 0x1f, 0x3e, 0x00, 0x0f, 0x0e, 0x00, 0x07, 0x02, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 31 KiB

Wyświetl plik

@ -0,0 +1,8 @@
#define pause_width 19
#define pause_height 19
static unsigned char pause_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf8, 0x00, 0xf8, 0xf8, 0x00,
0xf8, 0xf8, 0x00, 0xf8, 0xf8, 0x00, 0xf8, 0xf8, 0x00, 0xf8, 0xf8, 0x00,
0xf8, 0xf8, 0x00, 0xf8, 0xf8, 0x00, 0xf8, 0xf8, 0x00, 0xf8, 0xf8, 0x00,
0xf8, 0xf8, 0x00, 0xf8, 0xf8, 0x00, 0xf8, 0xf8, 0x00, 0xf8, 0xf8, 0x00,
0xf8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

Wyświetl plik

@ -0,0 +1,8 @@
#define play_width 19
#define play_height 19
static unsigned char play_bits[] = {
0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x7e, 0x00, 0x00,
0xfe, 0x01, 0x00, 0xfe, 0x07, 0x00, 0xfe, 0x1f, 0x00, 0xfe, 0x7f, 0x00,
0xfe, 0xff, 0x01, 0xfe, 0xff, 0x07, 0xfe, 0xff, 0x01, 0xfe, 0x7f, 0x00,
0xfe, 0x1f, 0x00, 0xfe, 0x07, 0x00, 0xfe, 0x01, 0x00, 0x7e, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00};

Wyświetl plik

@ -0,0 +1,8 @@
#define stop_width 19
#define stop_height 19
static unsigned char stop_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x00, 0xfc, 0xff, 0x00,
0xfc, 0xff, 0x00, 0xfc, 0xff, 0x00, 0xfc, 0xff, 0x00, 0xfc, 0xff, 0x00,
0xfc, 0xff, 0x00, 0xfc, 0xff, 0x00, 0xfc, 0xff, 0x00, 0xfc, 0xff, 0x00,
0xfc, 0xff, 0x00, 0xfc, 0xff, 0x00, 0xfc, 0xff, 0x00, 0xfc, 0xff, 0x00,
0xfc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

Wyświetl plik

@ -369,6 +369,9 @@ Save this modified font under a new name. Then run `font_to_py` to create a
Python font in a chosen size and comprising only those characters (`-c ABCDE`). Python font in a chosen size and comprising only those characters (`-c ABCDE`).
Instantiate the buttons with e.g. `text="A"`. Instantiate the buttons with e.g. `text="A"`.
Alternatively icons can be created as bitmaps and converted to Python font
files as [described here](../icon_fonts/README.md).
# 4. Notes # 4. Notes
Possible future enhancements: Possible future enhancements: