diff --git a/font_to_py.py b/font_to_py.py index 8f8fb3d..ce30d6d 100755 --- a/font_to_py.py +++ b/font_to_py.py @@ -260,7 +260,7 @@ 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, charset): + def __init__(self, filename, size, minchar, maxchar, monospaced, defchar, charset, bitmapped): super().__init__() self._face = freetype.Face(filename) # .crange is the inclusive range of ordinal values spanning the character set. @@ -283,10 +283,35 @@ class Font(dict): self.charset = [chr(defchar)] + cs # Populate self with defined chars only self.update(dict.fromkeys([c for c in self.charset if c])) - self.max_width = self.get_dimensions(size) + self.max_width = self.bmp_dimensions(size) if bitmapped else self.get_dimensions(size) self.width = self.max_width if monospaced else 0 self._assign_values() # Assign values to existing keys + def bmp_dimensions(self, height): + #self._face.set_pixel_sizes(0, height) # TODO fails with PCF file: invalid pixel size + max_descent = 0 + # For each character in the charset string we get the glyph + # and update the overall dimensions of the resulting bitmap. + max_width = 0 + max_ascent = 0 + for char in self.keys(): + glyph = self._glyph_for_character(char) + max_ascent = max(max_ascent, glyph.ascent) + max_descent = max(max_descent, glyph.descent) + # for a few chars e.g. _ glyph.width > glyph.advance_width + max_width = int(max(max_width, glyph.advance_width, + glyph.width)) + + self.height = int(max_ascent + max_descent) + self._max_ascent = int(max_ascent) + self._max_descent = int(max_descent) + print('Requested height', height) + print('Actual height', self.height) + print('Max width', max_width) + print('Max descent', self._max_descent) + print('Max ascent', self._max_ascent) + return max_width + # n-pass solution to setting a precise height. def get_dimensions(self, required_height): error = 0 @@ -468,9 +493,11 @@ def glyphs(): def write_func(stream, 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, minchar, + maxchar, defchar, charset, iterate, bitmapped): +# fnt = Font(font_path, height, minchar, maxchar, monospaced, defchar, charset, bitmapped) try: - fnt = Font(font_path, height, minchar, maxchar, monospaced, defchar, charset) + fnt = Font(font_path, height, minchar, maxchar, monospaced, defchar, charset, bitmapped) except freetype.ft_errors.FT_Exception: print("Can't open", font_path) return False @@ -618,7 +645,7 @@ if __name__ == "__main__": if not os.path.isfile(args.infile): quit("Font filename does not exist") - if not os.path.splitext(args.infile)[1].upper() in ('.TTF', '.OTF'): + if not os.path.splitext(args.infile)[1].upper() in ('.TTF', '.OTF', '.BDF', '.PCF'): quit("Font file should be a ttf or otf file.") if args.binary: @@ -663,10 +690,18 @@ if __name__ == "__main__": cs = {c for c in cset if c.isprintable() or (0xE000 <= ord(c) <= 0xF8FF) } - {args.errchar} cs = sorted(list(cs)) cset = ''.join(cs) # Back to string + bitmapped = os.path.splitext(args.infile)[1].upper() in ('.BDF', '.PCF') + if bitmapped: + if args.height != 0: + print('Warning: height arg ignored for bitmapped fonts.') + chkface = freetype.Face(args.infile) + args.height = chkface._get_available_sizes()[0].height + print("Found font with size " + str(args.height)) + 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.iterate): + args.errchar, cset, args.iterate, bitmapped): sys.exit(1) print(args.outfile, 'written successfully.')