def main(): args = get_args() draw = Drawing() draw.font = args.font_file draw.font_size = args.font_size font_name = args.font_name out_dir = args.out_dir img_ref = Image(width=1000, height=1000) if args.verbose: print "Writing " + out_dir + "/" + font_name + ".c" f = open(out_dir + "/" + font_name + ".c", 'wb+') write_comment(f) f.write("#include \"font.h\"\n\n") font_height = 0 range_first = 0x20 range_last = 0x7d font_width = [] max_width = 0 for x in range(range_first, range_last + 1): letter = chr(x) metrics = draw.get_font_metrics(img_ref, letter) text_height = int(round(metrics.text_height + 2)) if font_height == 0: font_height = text_height assert (font_height == text_height), "font height changed!" if max_width == 0: max_width = metrics.maximum_horizontal_advance + 2 assert (max_width == metrics.maximum_horizontal_advance + 2), \ "font advance width changed!" text_width = int(round(metrics.text_width + 2)) font_width.append(text_width) img = Image(width=text_width, height=text_height) d = draw.clone() d.text(0, int(metrics.ascender), letter) d(img) img.depth = 1 f.write("static const unsigned char ") f.write("letter_" + str(hex(x)[2:]) + "[] = {\n") c_hex_print(f, img.make_blob(format='A')) f.write("};\n\n") img.close() f.write("static const struct font_letter letters[] = {\n") for x in range(range_first, range_last + 1): letter_var_name = "letter_" + str(hex(x)[2:]) f.write("\t{ " + letter_var_name + ", ") f.write("sizeof(" + letter_var_name + "), ") f.write(str(font_width[x - range_first]) + "},\n") f.write("};\n\n") f.write("const struct font font_" + font_name + " = {\n") f.write("\t.first = " + str(hex(range_first)) + ",\n") f.write("\t.last = " + str(hex(range_last)) + ",\n") f.write("\t.letters = letters,\n") f.write("\t.height = " + str(font_height) + ",\n") f.write("\t.max_width = " + str(max_width) + ",\n") f.write("};\n") f.close() if args.verbose: print "Writing " + out_dir + "/" + font_name + ".h" f = open(out_dir + "/" + font_name + ".h", 'wb+') write_comment(f) f.write("#ifndef __" + font_name.upper() + "_H\n") f.write("#define __" + font_name.upper() + "_H\n") f.write("#include \"font.h\"\n") f.write("extern const struct font font_" + font_name + ";\n") f.write("#endif /*__" + font_name.upper() + "_H*/\n") f.close()
def main(): args = get_args() draw = Drawing() draw.font = args.font_file draw.font_size = args.font_size font_name = args.font_name out_dir = args.out_dir img_ref = Image(width=1000, height=1000) if args.verbose: print "Writing " + out_dir + "/" + font_name + ".c" f = open(out_dir + "/" + font_name + ".c", 'wb+') write_comment(f) f.write("#include \"font.h\"\n\n") font_height = 0 range_first = 0x20 range_last = 0x7d font_width = [] max_width = 0 for x in range(range_first, range_last + 1): letter = chr(x) metrics = draw.get_font_metrics(img_ref, letter) text_height = int(round(metrics.text_height + 2)) if font_height == 0: font_height = text_height assert (font_height == text_height), "font height changed!" if max_width == 0: max_width = metrics.maximum_horizontal_advance + 2 assert (max_width == metrics.maximum_horizontal_advance + 2), \ "font advance width changed!" text_width = int(round(metrics.text_width + 2)) font_width.append(text_width) img = Image(width=text_width, height=text_height) d = draw.clone() d.text(0, int(metrics.ascender), letter) d(img) img.depth = 1; f.write("static const unsigned char ") f.write("letter_" + str(hex(x)[2:]) + "[] = {\n") c_hex_print(f, img.make_blob(format='A')) f.write("};\n\n") img.close() f.write("static const struct font_letter letters[] = {\n") for x in range(range_first, range_last + 1): letter_var_name = "letter_" + str(hex(x)[2:]) f.write("\t{ " + letter_var_name + ", ") f.write("sizeof(" + letter_var_name + "), ") f.write(str(font_width[x - range_first]) + "},\n") f.write("};\n\n") f.write("const struct font font_" + font_name + " = {\n") f.write("\t.first = " + str(hex(range_first)) + ",\n") f.write("\t.last = " + str(hex(range_last)) + ",\n") f.write("\t.letters = letters,\n") f.write("\t.height = " + str(font_height) + ",\n") f.write("\t.max_width = " + str(max_width) + ",\n") f.write("};\n") f.close() if args.verbose: print "Writing " + out_dir + "/" + font_name + ".h" f = open(out_dir + "/" + font_name + ".h", 'wb+') write_comment(f) f.write("#ifndef __" + font_name.upper() + "_H\n"); f.write("#define __" + font_name.upper() + "_H\n"); f.write("#include \"font.h\"\n") f.write("extern const struct font font_" + font_name + ";\n") f.write("#endif /*__" + font_name.upper() + "_H*/\n"); f.close()
class CenteredParagraph(PropCache): def __init__(self, text, font, font_size=15, center=(0,0), spacing=4, line_height=None, antialias=True, metrics=None, full_init=True, **kwargs): super().__init__(**kwargs) self.text= text split= self.text.split("\n") self.num_lines= len(split) if line_height is None: self.line_height= 3*font_size/4 + spacing # assume 72(?) dpi self.spacing= spacing else: self.line_height= line_height self.spacing= line_height - 3*font_size/4 self.draw= None if full_init: self.draw= Drawing() self.draw.font= font self.draw.font_size= font_size self.draw.text_antialias= antialias # leave this at end of init self.lines= [] self.lines= self._get_lines(split, center, metrics=metrics) def invalidate(self): for x in ["bbox", "center"]: try: delattr(self, x) except AttributeError: pass # attr= getattr(self, x, None) # if attr is not None: # delattr(self, x) def copy(self, deepcopy=False): ret= self.__class__( text=self.text, center=self.bbox.center, spacing=self.spacing, font="", metrics=[x.metrics for x in self.lines], full_init=deepcopy ) if deepcopy: ret.draw= self.draw.clone() else: ret.draw= self.draw return ret def render(self, image, as_numpy=False): d= self.draw.clone() for l in self.lines: pos= l.bbox.pos d.text(int(pos[0]), int(pos[1]), l.text) d(image) if as_numpy: image= np.array(image)[:,:,:3] return image def _get_lines(self, lst, center, metrics=None): # create lines ret= [] for i,x in enumerate(lst): m= None if isinstance(metrics, list): m= metrics[i] ret.append(CenteredLine(x, self, para_center=center, metrics=m, linked=[self])) # adjust position total_height= self.num_lines * self.line_height current_height= 0 for i,l in enumerate(ret): if i == 0: topmost_height= l.bbox.height current_height+= l.bbox.height total_height-= (self.line_height - topmost_height) # exclude whitespace for topmost line else: current_height+= self.line_height ypos= current_height + center[1] ypos-= total_height/2 # centering l.bbox.pos= (None, ypos) # clean up for x in ret: x.linked.append(self) return ret def shift(self, x=0, y=0): if x != 0 or y != 0: c= list(self.bbox.center) c= [c[0]+x if x else None, c[1]+y if y else None] self.bbox.center= tuple(c) return self # todo: test recache @cached_property def bbox(self): # if not self.lines: # return Bbox(0,0,0,0, linked=[self]) x= min(x.bbox.pos[0] for x in self.lines) y= max(x.bbox.pos[1] for x in self.lines) w= max(x.bbox.size[0] for x in self.lines) h= (self.num_lines-1) * self.line_height # height of all lines except top h+= self.lines[0].bbox.height # height of top-most line return Bbox(x=x, y=y, w=w, h=h, linked_bbox=[x.bbox for x in self.lines], linked=[self]) @cached_property def center(self): return self.bbox.center def __str__(self): t= self.text.replace("\n","\\n") return f'"{t}" | {self.bbox}' def debug(self): t= self.text.replace("\n","\\n") ret= f'"{t}" | line_height={self.line_height} | spacing={self.spacing} | {self.bbox}' ret+= "\n\t" + "\n\t".join(str(x) for x in self.lines) return ret