Use xrange() rather than range() for loop iterations.
[blender.git] / intern / bmfont / intern / BDF2BMF.py
1 #!/usr/bin/python
2
3 # ***** BEGIN GPL LICENSE BLOCK *****
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software Foundation,
17 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 #
19 # ***** END GPL LICENCE BLOCK *****
20 # --------------------------------------------------------------------------
21
22 HELP_TXT = \
23 '''
24 Convert BDF pixmap fonts into C++ files Blender can read.
25 Use to replace bitmap fonts or add new ones.
26
27 Usage
28         python bdf2bmf.py -name=SomeName myfile.bdf
29
30 Blender currently supports fonts with a maximum width of 8 pixels.
31 '''
32
33 # -------- Simple BDF parser
34 import sys
35 def parse_bdf(f, MAX_CHARS=256):
36         lines = [l.strip().upper().split() for l in f.readlines()]
37
38         is_bitmap = False
39         dummy = {'BITMAP':[]}
40         char_data = [dummy.copy() for i in xrange(MAX_CHARS)]
41         context_bitmap = []
42
43         for l in lines:
44                 if l[0]=='ENCODING':            enc = int(l[1])
45                 elif l[0]=='BBX':                       bbx = [int(c) for c in l[1:]]
46                 elif l[0]=='DWIDTH':            dwidth = int(l[1])
47                 elif l[0]=='BITMAP':            is_bitmap = True
48                 elif l[0]=='ENDCHAR':
49                         if enc < MAX_CHARS:
50                                 char_data[enc]['BBX'] = bbx
51                                 char_data[enc]['DWIDTH'] = dwidth
52                                 char_data[enc]['BITMAP'] = context_bitmap
53                                 
54                         context_bitmap = []
55                         enc = bbx = None
56                         is_bitmap = False
57                 else:
58                         # None of the above, Ok, were reading a bitmap
59                         if is_bitmap and enc < MAX_CHARS:
60                                 context_bitmap.append( int(l[0], 16) )
61         
62         return char_data
63 # -------- end simple BDF parser
64
65 def bdf2cpp_name(path):
66         return path.split('.')[0] + '.cpp'
67
68 def convert_to_blender(bdf_dict, font_name, origfilename, MAX_CHARS=256):
69         
70         # first get a global width/height, also set the offsets
71         xmin = ymin =  10000000
72         xmax = ymax = -10000000
73         
74         bitmap_offsets = [-1] * MAX_CHARS
75         bitmap_tot = 0
76         for i, c in enumerate(bdf_dict):
77                 if c.has_key('BBX'):
78                         bbx = c['BBX']
79                         xmax = max(bbx[0], xmax)
80                         ymax = max(bbx[1], ymax)
81                         xmin = min(bbx[2], xmin)
82                         ymin = min(bbx[3], ymin)
83                         
84                         bitmap_offsets[i] = bitmap_tot
85                         bitmap_tot += len(c['BITMAP'])
86                 
87                 c['BITMAP'].reverse()
88         
89         # Now we can write. Ok if we have no .'s in the path.
90         f = open(bdf2cpp_name(origfilename), 'w')
91         
92         f.write('''
93 #ifdef HAVE_CONFIG_H
94 #include <config.h>
95 #endif
96
97 #include "BMF_FontData.h"
98
99 #include "BMF_Settings.h"
100 ''')
101         
102         f.write('#if BMF_INCLUDE_%s\n\n' % font_name.upper())
103         f.write('static unsigned char bitmap_data[]= {')
104         newline = 8
105         
106         for i, c in enumerate(bdf_dict):
107         
108                 for cdata in c['BITMAP']:
109                         # Just formatting
110                         newline+=1
111                         if newline >= 8:
112                                 newline = 0
113                                 f.write('\n\t')
114                         # End formatting
115                         
116                         f.write('0x%.2hx,' % cdata) # 0x80 <- format
117                         
118         f.write("\n};\n")
119         
120         f.write("BMF_FontData BMF_font_%s = {\n" % font_name)
121         f.write('\t%d, %d,\n' % (xmin, ymin))
122         f.write('\t%d, %d,\n' % (xmax, ymax))
123         
124         f.write('\t{\n')
125         
126
127         for i, c in enumerate(bdf_dict):
128                 if bitmap_offsets[i] == -1 or c.has_key('BBX') == False:
129                         f.write('\t\t{0,0,0,0,0, -1},\n')
130                 else:
131                         bbx = c['BBX']
132                         f.write('\t\t{%d,%d,%d,%d,%d, %d},\n' % (bbx[0], bbx[1], -bbx[2], -bbx[3], c['DWIDTH'], bitmap_offsets[i]))
133         
134         f.write('''
135         },
136         bitmap_data
137 };
138
139 #endif
140 ''')
141
142 def main():
143         # replace "[-name=foo]" with  "[-name] [foo]"
144         args = []
145         for arg in sys.argv:
146                 for a in arg.replace('=', ' ').split():
147                         args.append(a)
148         
149         name = 'untitled'
150         done_anything = False
151         for i, arg in enumerate(args):
152                 if arg == '-name':
153                         if i==len(args)-1:
154                                 print 'no arg given for -name, aborting'
155                                 return
156                         else:
157                                 name = args[i+1]
158                 
159                 elif arg.lower().endswith('.bdf'):
160                         try:
161                                 f = open(arg)
162                                 print '...Writing to:', bdf2cpp_name(arg)
163                         except:
164                                 print 'could not open "%s", aborting' % arg
165                         
166                         
167                         bdf_dict = parse_bdf(f)
168                         convert_to_blender(bdf_dict, name, arg)
169                         done_anything = True
170         
171         if not done_anything:
172                 print HELP_TXT
173                 print '...nothing to do'
174
175 if __name__ == '__main__':
176         main()
177