added invert color option

pull/28/head
Dan Krause 2020-04-01 09:38:35 -04:00
rodzic 5975b35883
commit 59ab110796
2 zmienionych plików z 33 dodań i 25 usunięć

Wyświetl plik

@ -80,6 +80,7 @@ $ font_to_py.py -k extended FreeSans.ttf 23 my_extended_font.py
default fonts are assumed to be variable pitch. default fonts are assumed to be variable pitch.
* -x or --xmap Specifies horizontal mapping (default is vertical). * -x or --xmap Specifies horizontal mapping (default is vertical).
* -r or --reverse Specifies bit reversal in each font byte. * -r or --reverse Specifies bit reversal in each font byte.
* -t or --invert Inverts the font color (white text on black background)
* -s or --smallest Ordinal value of smallest character to be stored. Default * -s or --smallest Ordinal value of smallest character to be stored. Default
32 (ASCII space). 32 (ASCII space).
* -l or --largest Ordinal value of largest character to be stored. Default 126. * -l or --largest Ordinal value of largest character to be stored. Default 126.

Wyświetl plik

@ -126,7 +126,7 @@ class Bitmap(object):
dstpixel += row_offset dstpixel += row_offset
# Horizontal mapping generator function # Horizontal mapping generator function
def get_hbyte(self, reverse): def get_hbyte(self, reverse, invert):
for row in range(self.height): for row in range(self.height):
col = 0 col = 0
while True: while True:
@ -142,11 +142,14 @@ class Bitmap(object):
# Normal map MSB of byte 0 is (0, 0) # Normal map MSB of byte 0 is (0, 0)
byte |= self.pixels[row * self.width + col] << (7 - bit) byte |= self.pixels[row * self.width + col] << (7 - bit)
if bit == 7: if bit == 7:
if invert:
yield 0xFF - byte
else:
yield byte yield byte
col += 1 col += 1
# Vertical mapping # Vertical mapping
def get_vbyte(self, reverse): def get_vbyte(self, reverse, invert):
for col in range(self.width): for col in range(self.width):
row = 0 row = 0
while True: while True:
@ -162,6 +165,9 @@ class Bitmap(object):
# Normal map MSB of byte 0 is (0, 7) # Normal map MSB of byte 0 is (0, 7)
byte |= self.pixels[row * self.width + col] << bit byte |= self.pixels[row * self.width + col] << bit
if bit == 7: if bit == 7:
if invert:
yield 0xFF - byte
else:
yield byte yield byte
row += 1 row += 1
@ -350,22 +356,22 @@ class Font(dict):
outbuffer.bitblt(glyph.bitmap, row, left) outbuffer.bitblt(glyph.bitmap, row, left)
self[char] = [outbuffer, width, char_width] self[char] = [outbuffer, width, char_width]
def stream_char(self, char, hmap, reverse): def stream_char(self, char, hmap, reverse, invert):
outbuffer, _, _ = self[char] outbuffer, _, _ = self[char]
if hmap: if hmap:
gen = outbuffer.get_hbyte(reverse) gen = outbuffer.get_hbyte(reverse, invert)
else: else:
gen = outbuffer.get_vbyte(reverse) gen = outbuffer.get_vbyte(reverse, invert)
yield from gen yield from gen
def build_arrays(self, hmap, reverse): def build_arrays(self, hmap, reverse, invert):
data = bytearray() data = bytearray()
index = bytearray() index = bytearray()
sparse = bytearray() sparse = bytearray()
def append_data(data, char): def append_data(data, char):
width = self[char][1] width = self[char][1]
data += (width).to_bytes(2, byteorder='little') data += (width).to_bytes(2, byteorder='little')
data += bytearray(self.stream_char(char, hmap, reverse)) data += bytearray(self.stream_char(char, hmap, reverse, invert))
# self.charset is contiguous with chars having ordinal values in the # self.charset is contiguous with chars having ordinal values in the
# inclusive range specified. Where the specified character set has gaps # inclusive range specified. Where the specified character set has gaps
@ -391,12 +397,12 @@ class Font(dict):
append_data(data, char) append_data(data, char)
return data, index, sparse return data, index, sparse
def build_binary_array(self, hmap, reverse, sig): def build_binary_array(self, hmap, reverse, invert, sig):
data = bytearray((0x3f + sig, 0xe7, self.max_width, self.height)) data = bytearray((0x3f + sig, 0xe7, self.max_width, self.height))
for char in self.charset: for char in self.charset:
width = self[char][2] width = self[char][2]
data += bytes((width,)) data += bytes((width,))
data += bytearray(self.stream_char(char, hmap, reverse)) data += bytearray(self.stream_char(char, hmap, reverse, invert))
return data return data
# PYTHON FILE WRITING # PYTHON FILE WRITING
@ -468,7 +474,7 @@ def glyphs():
def write_func(stream, name, arg): def write_func(stream, name, arg):
stream.write('def {}():\n return {}\n\n'.format(name, arg)) stream.write('def {}():\n return {}\n\n'.format(name, arg))
def write_font(op_path, font_path, height, monospaced, hmap, reverse, minchar, maxchar, defchar, charset, iterate): def write_font(op_path, font_path, height, monospaced, hmap, reverse, invert, minchar, maxchar, defchar, charset, iterate):
try: try:
fnt = Font(font_path, height, minchar, maxchar, monospaced, defchar, charset) fnt = Font(font_path, height, minchar, maxchar, monospaced, defchar, charset)
except freetype.ft_errors.FT_Exception: except freetype.ft_errors.FT_Exception:
@ -476,13 +482,13 @@ def write_font(op_path, font_path, height, monospaced, hmap, reverse, minchar, m
return False return False
try: try:
with open(op_path, 'w', encoding='utf-8') as stream: with open(op_path, 'w', encoding='utf-8') as stream:
write_data(stream, fnt, font_path, hmap, reverse, iterate, charset) write_data(stream, fnt, font_path, hmap, reverse, invert, iterate, charset)
except OSError: except OSError:
print("Can't open", op_path, 'for writing') print("Can't open", op_path, 'for writing')
return False return False
return True return True
def write_data(stream, fnt, font_path, hmap, reverse, iterate, charset): def write_data(stream, fnt, font_path, hmap, reverse, invert, iterate, charset):
height = fnt.height # Actual height, not target height height = fnt.height # Actual height, not target height
minchar = min(fnt.crange) minchar = min(fnt.crange)
maxchar = max(fnt.crange) maxchar = max(fnt.crange)
@ -500,7 +506,7 @@ def write_data(stream, fnt, font_path, hmap, reverse, iterate, charset):
write_func(stream, 'max_ch', maxchar) write_func(stream, 'max_ch', maxchar)
if iterate: if iterate:
stream.write(STR03.format(''.join(sorted(fnt.keys())))) stream.write(STR03.format(''.join(sorted(fnt.keys()))))
data, index, sparse = fnt.build_arrays(hmap, reverse) data, index, sparse = fnt.build_arrays(hmap, reverse, invert)
bw_font = ByteWriter(stream, '_font') bw_font = ByteWriter(stream, '_font')
bw_font.odata(data) bw_font.odata(data)
bw_font.eot() bw_font.eot()
@ -525,7 +531,7 @@ def write_data(stream, fnt, font_path, hmap, reverse, iterate, charset):
# 1 0 0x40 0xe7 # 1 0 0x40 0xe7
# 0 1 0x41 0xe7 # 0 1 0x41 0xe7
# 1 1 0x42 0xe7 # 1 1 0x42 0xe7
def write_binary_font(op_path, font_path, height, hmap, reverse): def write_binary_font(op_path, font_path, height, hmap, reverse, invert):
try: try:
fnt = Font(font_path, height, 32, 126, True, None, '') # All chars have same width fnt = Font(font_path, height, 32, 126, True, None, '') # All chars have same width
except freetype.ft_errors.FT_Exception: except freetype.ft_errors.FT_Exception:
@ -536,7 +542,7 @@ def write_binary_font(op_path, font_path, height, hmap, reverse):
sig += 2 sig += 2
try: try:
with open(op_path, 'wb') as stream: with open(op_path, 'wb') as stream:
data = fnt.build_binary_array(hmap, reverse, sig) data = fnt.build_binary_array(hmap, reverse, invert, sig)
stream.write(data) stream.write(data)
except OSError: except OSError:
print("Can't open", op_path, 'for writing') print("Can't open", op_path, 'for writing')
@ -579,6 +585,8 @@ if __name__ == "__main__":
help='Horizontal (x) mapping') help='Horizontal (x) mapping')
parser.add_argument('-r', '--reverse', action='store_true', parser.add_argument('-r', '--reverse', action='store_true',
help='Bit reversal') help='Bit reversal')
parser.add_argument('-t', '--invert', action='store_true',
help='Invert font color (white text on black background)')
parser.add_argument('-f', '--fixed', action='store_true', parser.add_argument('-f', '--fixed', action='store_true',
help='Fixed width (monospaced) font') help='Fixed width (monospaced) font')
parser.add_argument('-b', '--binary', action='store_true', parser.add_argument('-b', '--binary', action='store_true',
@ -630,7 +638,7 @@ if __name__ == "__main__":
print('Writing binary font file.') print('Writing binary font file.')
if not write_binary_font(args.outfile, args.infile, args.height, if not write_binary_font(args.outfile, args.infile, args.height,
args.xmap, args.reverse): args.xmap, args.reverse, args.invert):
sys.exit(1) sys.exit(1)
else: else:
if not os.path.splitext(args.outfile)[1].upper() == '.PY': if not os.path.splitext(args.outfile)[1].upper() == '.PY':
@ -665,9 +673,8 @@ if __name__ == "__main__":
cset = ''.join(cs) # Back to string cset = ''.join(cs) # Back to string
print('Writing Python font file.') print('Writing Python font file.')
if not write_font(args.outfile, args.infile, args.height, args.fixed, if not write_font(args.outfile, args.infile, args.height, args.fixed,
args.xmap, args.reverse, args.smallest, args.largest, args.xmap, args.reverse, args.invert, args.smallest,
args.errchar, cset, args.iterate): args.largest, args.errchar, cset, args.iterate):
sys.exit(1) sys.exit(1)
print(args.outfile, 'written successfully.') print(args.outfile, 'written successfully.')