kopia lustrzana https://github.com/peterhinch/micropython-font-to-py
Add c_to_python_font.py.
rodzic
dcc97abc3f
commit
eebd7307af
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
@ -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};
|
|
@ -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};
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Filenames for media player icons
|
||||||
|
default.c
|
||||||
|
play.c # Test
|
||||||
|
stop.c
|
||||||
|
pause.c
|
||||||
|
back.c
|
||||||
|
fwd.c
|
|
@ -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 |
|
@ -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};
|
|
@ -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};
|
|
@ -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};
|
|
@ -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:
|
||||||
|
|
Ładowanie…
Reference in New Issue