Add --iterate argument.

pull/16/head
Peter Hinch 2018-09-06 11:38:52 +01:00
rodzic 6eb8adb31c
commit 793c805f4f
3 zmienionych plików z 51 dodań i 7 usunięć

Wyświetl plik

@ -56,6 +56,7 @@ 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 "?").
* -i or --iterate Specialist use. See below.
* -c or --charset Option to restrict the characters in the font to a specific
set. See below.
* -k or --charset_file Obtain the character set from a file. Typical use is
@ -85,6 +86,11 @@ value > 127) from ttf files is unreliable. If the expected results are not
achieved, use an otf font. However I have successfully created the Cyrillic
font from a `ttf`. Perhaps not all fonts are created equal...
The `-i` or `--iterate` argument. For specialist applications. Specifying this
causes a generator function `glyphs` to be included in the Python font file. A
generator instantiated with this will yield `bitmap`, `height`, and `width` for
every glyph in the font.
### Output
The specified height is a target. The algorithm gets as close to the target

Wyświetl plik

@ -261,6 +261,7 @@ class Font(dict):
self.minchar = minchar
self.maxchar = maxchar
self.monospaced = monospaced
self.defchar = defchar
# .def_charset is requested charset or '' if -c was not specified
self.def_charset = charset
# .charset has all defined characters with '' for those in range but undefined.
@ -369,7 +370,7 @@ class Font(dict):
STR01 = """# Code generated by font-to-py.py.
# Font: {}{}
version = '0.25'
version = '0.26'
"""
STR02 = """_mvfont = memoryview(_font)
@ -390,7 +391,7 @@ 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, charset):
def write_font(op_path, font_path, height, monospaced, hmap, reverse, minchar, maxchar, defchar, charset, iterate):
try:
fnt = Font(font_path, height, minchar, maxchar, monospaced, defchar, charset)
except freetype.ft_errors.FT_Exception:
@ -398,17 +399,24 @@ def write_font(op_path, font_path, height, monospaced, hmap, reverse, minchar, m
return False
try:
with open(op_path, 'w') as stream:
write_data(stream, fnt, font_path, hmap, reverse)
write_data(stream, fnt, font_path, hmap, reverse, iterate)
except OSError:
print("Can't open", op_path, 'for writing')
return False
return True
STR03 = '''
def glyphs():
for c in """{}""":
yield c, get_ch(c)
def write_data(stream, fnt, font_path, hmap, reverse):
'''
def write_data(stream, fnt, font_path, hmap, reverse, iterate):
height = fnt.height # Actual height, not target height
minchar = fnt.minchar
maxchar = fnt.maxchar
defchar = fnt.defchar
charset = fnt.def_charset
st = '' if charset == '' else ' Char set: {}'.format(charset)
stream.write(STR01.format(os.path.split(font_path)[1], st))
@ -420,6 +428,8 @@ def write_data(stream, fnt, font_path, hmap, reverse):
write_func(stream, 'monospaced', fnt.monospaced)
write_func(stream, 'min_ch', minchar)
write_func(stream, 'max_ch', maxchar)
if iterate:
stream.write(STR03.format(''.join(fnt.pop_charset)))
data, index = fnt.build_arrays(hmap, reverse)
bw_font = ByteWriter(stream, '_font')
bw_font.odata(data)
@ -427,7 +437,7 @@ def write_data(stream, fnt, font_path, hmap, reverse):
bw_index = ByteWriter(stream, '_index')
bw_index.odata(index)
bw_index.eot()
stream.write(STR02.format(minchar, maxchar, minchar, minchar, height))
stream.write(STR02.format(minchar, maxchar, defchar, minchar, height))
# BINARY OUTPUT
# hmap reverse magic bytes
@ -493,6 +503,8 @@ if __name__ == "__main__":
help='Fixed width (monospaced) font')
parser.add_argument('-b', '--binary', action='store_true',
help='Produce binary (random access) font file.')
parser.add_argument('-i', '--iterate', action='store_true',
help='Include generator function to iterate over character set.')
parser.add_argument('-s', '--smallest',
type = int,
@ -566,10 +578,13 @@ if __name__ == "__main__":
sys.exit(1)
else:
cset = args.charset
cs = {c for c in cset if c.isprintable()} - {args.errchar} # dedupe and remove default char
cs = sorted(list(cs))
cset = ''.join(cs) # Back to string
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, cset):
args.errchar, cset, args.iterate):
sys.exit(1)
print(args.outfile, 'written successfully.')

Wyświetl plik

@ -140,7 +140,8 @@ def get_ch(ch):
return mvfont[offset + 2, next_offset], height, width
```
`height` and `width` are specified in bits (pixels).
`height` and `width` are specified in bits (pixels). See Appendix 1 for extra
code in fonts created with the `--iterate` arg.
In the case of monospaced fonts the `max_width` function returns the width of
every character. For variable pitch fonts it returns the width of the widest
@ -235,3 +236,25 @@ Fonts created with the `font_to_py` utility have been extensively tested with
each of the mapping options. They are used with drivers for SSD1306 OLEDs,
SSD1963 LCD displays, the official LCD160CR and the Digital Artists 2.7 inch
e-paper display.
# Appendix 1. The -i --iterate argument
This specialist arg causes extra code to be included in the font file, to
provide for iterating over all the glyphs in the file. The following sample of
the extra code assumes a font comprising '0123456789:'
```python
def glyphs():
for c in """0123456789:""":
yield c, get_ch(c)
```
Typical usage under CPython 3 (for a font `cyrillic.py`) is
```python
import cyrillic
res = []
for glyph in cyrillic.glyphs():
res.append(list(glyph)) # Each element is [char, glyph, height, width]
```