kopia lustrzana https://github.com/peterhinch/micropython-font-to-py
font_to_py.py Add --charset option.
rodzic
c341ee9bd2
commit
7f4f840dda
|
@ -55,13 +55,25 @@ Example usage to produce a file `myfont.py` with height of 23 pixels:
|
|||
* -l or --largest Ordinal value of largest character to be stored. Default 126.
|
||||
* -e or --errchar Ordinal value of character to be rendered if an attempt is
|
||||
made to display an out-of-range character. Default 63 (ASCII "?").
|
||||
* -c or --charset Option to restrict the characters in the font to a specific
|
||||
set. See below.
|
||||
|
||||
The -c option reduces the size of the font file. If the font file is frozen as
|
||||
bytecode this will not reduce RAM usage but it will conserve flash. An example
|
||||
usage for a digital clock font:
|
||||
|
||||
```shell
|
||||
font_to_py.py Arial.ttf 20 arial_clock.py -c 1234567890:
|
||||
```
|
||||
If a character set is specified, `--smallest` and `--largest` should not be
|
||||
specified: these values are computed from the charcater set.
|
||||
|
||||
Any requirement for arguments -xr will be specified in the device driver
|
||||
documentation. Bit reversal is required by some display hardware.
|
||||
|
||||
Note that producing extended ASCII characters (ordinal value > 127) from ttf
|
||||
files seems unreliable. If the expected results are not achieved, use an otf
|
||||
font. This appears to be a limitation of the `freetype` library.
|
||||
There have been reports that producing extended ASCII characters (ordinal
|
||||
value > 127) from ttf files is unreliable. If the expected results are not
|
||||
achieved, use an otf font. This may be a limitation of the `freetype` library.
|
||||
|
||||
### Output
|
||||
|
||||
|
|
|
@ -255,13 +255,22 @@ class Glyph(object):
|
|||
# height (in pixels) of all characters
|
||||
# width (in pixels) for monospaced output (advance width of widest char)
|
||||
class Font(dict):
|
||||
def __init__(self, filename, size, minchar, maxchar, monospaced, defchar):
|
||||
def __init__(self, filename, size, minchar, maxchar, monospaced, defchar, charset):
|
||||
super().__init__()
|
||||
self._face = freetype.Face(filename)
|
||||
self.minchar = minchar
|
||||
self.maxchar = maxchar
|
||||
self.monospaced = monospaced
|
||||
self.def_charset = charset
|
||||
if defchar is None: # Binary font
|
||||
self.charset = [chr(char) for char in range(minchar, maxchar + 1)]
|
||||
else:
|
||||
elif charset == '':
|
||||
self.charset = [chr(defchar)] + [chr(char) for char in range(minchar, maxchar + 1)]
|
||||
else:
|
||||
n = sorted([ord(x) for x in chr(defchar) + charset])
|
||||
self.minchar = n[0]
|
||||
self.maxchar = n[-1]
|
||||
self.charset = [chr(defchar)] + [chr(char) if chr(char) in charset else '' for char in range(n[0], n[-1] + 1)]
|
||||
self.max_width = self.get_dimensions(size)
|
||||
self.width = self.max_width if monospaced else 0
|
||||
for char in self.charset: # Populate dictionary
|
||||
|
@ -330,10 +339,13 @@ class Font(dict):
|
|||
data = bytearray()
|
||||
index = bytearray((0, 0))
|
||||
for char in self.charset:
|
||||
width = self[char][1]
|
||||
data += (width).to_bytes(2, byteorder='little')
|
||||
data += bytearray(self.stream_char(char, hmap, reverse))
|
||||
index += (len(data)).to_bytes(2, byteorder='little')
|
||||
if char == '':
|
||||
index += (len(data)).to_bytes(2, byteorder='little')
|
||||
else:
|
||||
width = self[char][1]
|
||||
data += (width).to_bytes(2, byteorder='little')
|
||||
data += bytearray(self.stream_char(char, hmap, reverse))
|
||||
index += (len(data)).to_bytes(2, byteorder='little')
|
||||
return data, index
|
||||
|
||||
def build_binary_array(self, hmap, reverse, sig):
|
||||
|
@ -347,7 +359,7 @@ class Font(dict):
|
|||
# PYTHON FILE WRITING
|
||||
|
||||
STR01 = """# Code generated by font-to-py.py.
|
||||
# Font: {}
|
||||
# Font: {}{}
|
||||
version = '0.2'
|
||||
"""
|
||||
|
||||
|
@ -372,30 +384,34 @@ def write_func(stream, name, arg):
|
|||
|
||||
# filename, size, minchar=32, maxchar=126, monospaced=False, defchar=ord('?'):
|
||||
|
||||
def write_font(op_path, font_path, height, monospaced, hmap, reverse, minchar, maxchar, defchar):
|
||||
def write_font(op_path, font_path, height, monospaced, hmap, reverse, minchar, maxchar, defchar, charset):
|
||||
try:
|
||||
fnt = Font(font_path, height, minchar, maxchar, monospaced, defchar)
|
||||
fnt = Font(font_path, height, minchar, maxchar, monospaced, defchar, charset)
|
||||
except freetype.ft_errors.FT_Exception:
|
||||
print("Can't open", font_path)
|
||||
return False
|
||||
try:
|
||||
with open(op_path, 'w') as stream:
|
||||
write_data(stream, fnt, font_path, monospaced, hmap, reverse, minchar, maxchar)
|
||||
write_data(stream, fnt, font_path, hmap, reverse)
|
||||
except OSError:
|
||||
print("Can't open", op_path, 'for writing')
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def write_data(stream, fnt, font_path, monospaced, hmap, reverse, minchar, maxchar):
|
||||
def write_data(stream, fnt, font_path, hmap, reverse):
|
||||
height = fnt.height # Actual height, not target height
|
||||
stream.write(STR01.format(os.path.split(font_path)[1]))
|
||||
minchar = fnt.minchar
|
||||
maxchar = fnt.maxchar
|
||||
charset = fnt.def_charset
|
||||
st = '' if charset == '' else ' Char set: {}'.format(charset)
|
||||
stream.write(STR01.format(os.path.split(font_path)[1], st))
|
||||
stream.write('\n')
|
||||
write_func(stream, 'height', height)
|
||||
write_func(stream, 'max_width', fnt.max_width)
|
||||
write_func(stream, 'hmap', hmap)
|
||||
write_func(stream, 'reverse', reverse)
|
||||
write_func(stream, 'monospaced', monospaced)
|
||||
write_func(stream, 'monospaced', fnt.monospaced)
|
||||
write_func(stream, 'min_ch', minchar)
|
||||
write_func(stream, 'max_ch', maxchar)
|
||||
data, index = fnt.build_arrays(hmap, reverse)
|
||||
|
@ -487,6 +503,11 @@ if __name__ == "__main__":
|
|||
help = 'Ordinal value of error character default %(default)i ("?")',
|
||||
default = 63)
|
||||
|
||||
parser.add_argument('-c', '--charset',
|
||||
type = str,
|
||||
help = 'Character set. e.g. 1234567890: to restrict for a clock display.',
|
||||
default = '')
|
||||
|
||||
args = parser.parse_args()
|
||||
if not args.infile[0].isalpha():
|
||||
quit('Font filenames must be valid Python variable names.')
|
||||
|
@ -501,7 +522,7 @@ if __name__ == "__main__":
|
|||
if os.path.splitext(args.outfile)[1].upper() == '.PY':
|
||||
quit('Binary file must not have a .py extension.')
|
||||
|
||||
if args.smallest != 32 or args.largest != 126 or args.errchar != ord('?'):
|
||||
if args.smallest != 32 or args.largest != 126 or args.errchar != ord('?') or args.charset:
|
||||
quit(BINARY)
|
||||
|
||||
print('Writing binary font file.')
|
||||
|
@ -522,11 +543,13 @@ if __name__ == "__main__":
|
|||
|
||||
if args.errchar < 0 or args.errchar > 255:
|
||||
quit('--errchar must be between 0 and 255')
|
||||
if args.charset and (args.smallest != 32 or args.largest != 126):
|
||||
print('WARNING: specified smallest and largest values ignored.')
|
||||
|
||||
print('Writing Python font file.')
|
||||
if not write_font(args.outfile, args.infile, args.height, args.fixed,
|
||||
args.xmap, args.reverse, args.smallest, args.largest,
|
||||
args.errchar):
|
||||
args.errchar, args.charset):
|
||||
sys.exit(1)
|
||||
|
||||
print(args.outfile, 'written successfully.')
|
||||
|
|
Ładowanie…
Reference in New Issue