#!/usr/bin/env python # -*- coding: utf8 -*- import codecs,os,gzip,ctypes,ctypes.util,sys from struct import * from PIL import Image, ImageDraw, ImageFont # ====== Python script to convert TrueTypeFonts to TWRP's .dat format ====== # This script was originally made by https://github.com/suky for his chinese version of TWRP # and then translated to English by feilplane at #twrp of irc.freenode.net. # However, it was not compatible with vanilla TWRP, so https://github.com/Tasssadar rewrote # most of it and it now has very little in common with the original script. class Reference(): def __init__(self, val): self.__value = val def get(self): return self.__value def set(self, val): self.__value = val quiet = Reference(False) def log(text): if not quiet.get(): sys.stdout.write(text) def write_data(f, width, height, offsets, data): f.write(pack(" cheight: cheight = h ichr = Image.new('L', (w, cheight*2)) ichr_draw = ImageDraw.Draw(ichr) ichr_draw.text((padding.get(), 0), chr(i), 255, font) renders.append(ichr) # Twice the height to account for under-the-baseline characters cheight *= 2 # Create the result bitmap log("Creating result bitmap...\n") res = Image.new('L', (cwidth, cheight), 0) res_draw = ImageDraw.Draw(res) # Paste all characters into result bitmap for i in range(len(renders)): res.paste(renders[i], (offsets[i], 0)) # uncomment to draw lines separating each character (for debug) #res_draw.rectangle([offsets[i], 0, offsets[i], cheight], outline="blue") # crop the blank areas on top and bottom (_, start_y, _, end_y) = res.getbbox() res = res.crop((0, start_y, cwidth, end_y)) cheight = (end_y - start_y) + voffset.get() new_res = Image.new('L', (cwidth, cheight)) new_res.paste(res, (0, voffset.get())) res = new_res # save the preview if preview.get(): log("Saving preview to %s...\n" % preview.get()) res.save(preview.get()) # Pack the data. # The "data" is a B/W bitmap with all 96 characters next to each other # on one line. It is as wide as all the characters combined and as # high as the tallest character, plus padding. # Each byte contains info about eight pixels, starting from # highest to lowest bit: # bits: | 7 6 5 4 3 2 1 0 | 15 14 13 12 11 10 9 8 | ... # pixels: | 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 | ... log("Packing data...\n") bit = 0 bit_itr = 0 for c in res.tostring(): # FIXME: How to handle antialiasing? # if c != '\x00': # In Python3, c is int, in Python2, c is string. Because of reasons. try: fill = (ord(c) >= 127) except TypeError: fill = (c >= 127) if fill: bit |= (1 << (7-bit_itr)) bit_itr += 1 if bit_itr >= 8: data += pack("