Updated addon repository URL and improved debug output on download
[supertux.git] / tools / font-generator.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # Font Generator
5 # Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
6 #
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20
21 import argparse
22 import cairo
23 import codecs
24 import math
25 import re
26
27 class FontGenerator:
28
29     def __init__(self):
30         self.font_size = 24
31         self.letters = u"""!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"""
32         self.font_family = "WenQuanYi Micro Hei"
33         self.columns = 20
34         self.glyph_width = 20
35         self.glyph_height = 20
36         self.draw_outline = False
37         self.draw_shadow = False
38
39     def generate_image(self):
40         rows = (len(self.letters) + self.columns - 1) // self.columns
41         width = self.glyph_width * self.columns
42         height = self.glyph_height * rows
43
44         surface = cairo.ImageSurface (cairo.FORMAT_ARGB32, width, height)
45         cr = cairo.Context (surface)
46         # cr.translate(0.5, 0.5)
47         self.draw_glyphs(cr, self.columns, rows)
48         return surface
49
50     def draw_glyphs(self, cr, cols, rows):
51         if False:
52             cr.set_source_rgb(255, 255, 255)
53             cr.fill()
54         elif self.checkerboard:
55             for row in range(rows):
56                 for col in range(cols):
57                     idx = row * cols + col
58
59                     cr.rectangle(col * self.glyph_width,
60                                  row * self.glyph_height,
61                                  self.glyph_width,
62                                  self.glyph_height)
63                     if (col + row % 2) % 2 == 0 :
64                         cr.set_source_rgb(0.5, 0.5, 0.5)
65                     else:
66                         cr.set_source_rgb(0.75, 0.75, 0.75)
67                     cr.fill()
68
69         cr.select_font_face(self.font_family, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
70         cr.set_font_size(self.font_size)
71
72         fascent, fdescent, fheight, fxadvance, fyadvance = cr.font_extents()
73
74         print self.glyph_height, fheight
75
76         for row in range(rows):
77             for col in range(cols):
78                 idx = row * cols + col
79
80                 if idx < len(self.letters):
81                     letter = self.letters[idx]
82                     xbearing, ybearing, width, height, xadvance, yadvance = cr.text_extents(letter)
83
84                     #cr.move_to(cx + 0.5 - xbearing - width / 2,
85                     #           0.5 - fdescent + fheight / 2)
86                     gx = col * self.glyph_width + self.glyph_width/2.0 - xbearing - width/2.0
87                     gy = row * self.glyph_height + self.glyph_height/2.0 - fdescent + fheight/2
88
89                     if self.draw_outline or self.draw_shadow:
90                         cr.move_to(gx, gy)
91                         cr.set_line_width(2.0)
92                         cr.set_line_join(cairo.LINE_JOIN_ROUND)
93                         cr.set_source_rgb(0, 0, 0)
94                         cr.text_path(letter)
95                         cr.stroke_preserve()
96
97                         if self.draw_shadow:
98                             cr.set_source_rgb(0, 0, 0)
99                         else:
100                             cr.set_source_rgb(255, 255, 255)
101                         cr.fill()
102                     else:
103                         cr.set_source_rgb(255, 255, 255)
104                         cr.move_to(gx, gy)
105                         cr.show_text(letter)
106
107
108 if __name__ == "__main__":
109     parser = argparse.ArgumentParser(description='Font Generator')
110     parser.add_argument('-o', '--output', metavar='FILE', type=str, required=True,
111                         help="output file")
112     parser.add_argument('--font-size', metavar='INT', type=int,
113                         help="font size")
114     parser.add_argument('--font', metavar='NAME', type=str, help="font")
115     parser.add_argument('--columns', metavar='INT', type=int, help="font")
116     parser.add_argument('--letters', metavar='NAME', type=str, help="letters")
117     parser.add_argument('--letters-from-file', metavar='FILE', type=str, help="letters from file")
118     parser.add_argument('--outline', action="store_true", help="draw outline")
119     parser.add_argument('--shadow', action="store_true", help="draw shadow")
120     parser.add_argument('--glyph-width', type=int, help="glyph width")
121     parser.add_argument('--glyph-height', type=int, help="glyph height")
122     parser.add_argument('--checkerboard', action="store_true", help="draw checkerboard background")
123     args = parser.parse_args()
124
125     generator = FontGenerator()
126
127     if args.font_size is not None:
128         generator.font_size = args.font_size
129
130     if args.letters is not None:
131         generator.letters = args.letters
132
133     if args.letters_from_file is not None:
134         with codecs.open(args.letters_from_file, encoding='utf-8') as fin:
135             generator.letters = re.sub(r"\s", "", fin.read())
136
137     if args.font is not None:
138         generator.font_family = args.font
139
140     if args.letters is not None:
141         generator.letters = args.letters.decode('utf8')
142
143     if args.columns is not None:
144         generator.columns = args.columns
145
146     if args.outline is not None:
147         generator.draw_outline = args.outline
148
149     if args.shadow is not None:
150         generator.draw_shadow = args.shadow
151
152     if args.checkerboard is not None:
153         generator.checkerboard = args.checkerboard
154
155     if args.glyph_width is not None:
156         generator.glyph_width = args.glyph_width
157
158     if args.glyph_height is not None:
159         generator.glyph_height = args.glyph_height
160
161     img = generator.generate_image()
162
163     img.write_to_png(args.output)
164
165 # EOF #