#!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # # FreeType high-level python API - Copyright 2011-2015 Nicolas P. Rougier # Distributed under the terms of the new BSD license. # # ----------------------------------------------------------------------------- ''' Glyph bitmap monochrome rendering ''' import json import struct import sys import pprint from pathlib import Path import mimetypes from freetype import Face class EvueFontTool(object): FONT_DPI = 100 def __init__(self, freetypefile, output_dir, sizes=[10,20,30]): super().__init__() self.freetypefile = freetypefile self.sizes = sizes self.face = Face(self.freetypefile) self.infos = [] self.output_dir = Path(output_dir) if not self.output_dir.exists(): self.output_dir.mkdir() # raise Exception("{} not exists".format(output_dir)) @property def fontInfo(self): return { 'family': str(self.face.family_name, 'utf-8'), 'style': str(self.face.style_name, 'utf-8'), 'charmaps': [charmap.encoding_name for charmap in self.face.charmaps], 'face_number': self.face.num_faces, 'glyph_number': self.face.num_glyphs, 'available_sizes': list(map(lambda x: { 'width': x.width, 'height': x.height, 'size': x.size }, self.face.available_sizes)), 'units_per_em': self.face.units_per_EM, 'ascender': self.face.ascender, 'descender': self.face.descender, 'height': self.face.height, 'max_advance_width': self.face.max_advance_width, 'max_advance_height': self.face.max_advance_height, 'underline_position': self.face.underline_position, 'underline_thickness': self.face.underline_thickness, 'has_horizontal': self.face.has_horizontal, 'has_vertical': self.face.has_vertical, 'has_kerning': self.face.has_kerning, 'is_fixed_width': self.face.is_fixed_width, 'is_scalable': self.face.is_scalable } def charInfo(self, cur_char): self.face.load_char(cur_char) char_info = { 'glyph': ord(cur_char), 'left': self.face.glyph.bitmap_left, 'top': self.face.glyph.bitmap_top, 'advance': self.face.glyph.advance.x / 64, 'cols': self.face.glyph.bitmap.width, 'rows': self.face.glyph.bitmap.rows, 'bitmap': self.face.glyph.bitmap.buffer, # list[] 'count': len(self.face.glyph.bitmap.buffer), } return char_info def dump(self, used_string): # 遍历每一个字体 dump_json = { 'name': self.fontInfo.get("family"), 'info': self.fontInfo, 'text': used_string, 'size': self.sizes, 'bitmap': { 'total': 0 } } for cur_char in used_string: # 遍历每一个字体设定的大小值 for size in self.sizes: # 设置字体大小 self.face.set_char_size(size * 64, 0, self.FONT_DPI, 0) char_info = self.charInfo(cur_char) self.infos.append(char_info) # 文件命名规则:./<output_dir>/<font-size>/<unicode-number>.bin target_dir = self.output_dir.joinpath(str(size)).joinpath("{}.bin".format(char_info.get('glyph'))) if not target_dir.parent.exists(): target_dir.parent.mkdir() with open(target_dir.resolve().as_posix(), 'wb+') as f: f.write(struct.pack("%dB" % char_info['count'], *char_info['bitmap'])) dump_json['bitmap'].update({ size: dump_json.get('bitmap').get(size, 0) + target_dir.stat().st_size }) for key in dump_json['bitmap']: if key != 'total': dump_json['bitmap']['total'] += dump_json['bitmap'][key] pprint.pprint(dump_json) # 在输出目录下,生成一个json索引文件 with open(self.output_dir.joinpath("fonts.json").resolve().as_posix(), "wb+") as f: f.write(json.dumps(dump_json, ensure_ascii=False, indent=2).encode('utf-8')) def load(self, file): pass def show(self, info): import numpy import matplotlib.pyplot as plt data = info['bitmap'] rows = info['rows'] width = info['cols'] # for i in range(rows): # data.extend(bitmap.buffer[i*pitch:i*pitch+width]) Z = numpy.array(data,dtype=numpy.ubyte).reshape(rows, width) plt.imshow(Z, interpolation='nearest', cmap=plt.cm.gray) plt.show() def test(self, used_string): for cur_char in used_string: char_info = self.charInfo(cur_char) self.infos.append(char_info) self.show(char_info) if __name__ == '__main__': print(mimetypes.guess_type(sys.argv[1])[0]) evueFontTool = EvueFontTool(sys.argv[1], sys.argv[2]) text = '中国' # evueFontTool.test(text) evueFontTool.dump(text) pprint.pprint(evueFontTool.fontInfo)