|
1 /* |
|
2 * GraphLCD tool crtfont |
|
3 * |
|
4 * crtfont.c - a tool to create *.fnt files for use with the GraphLCD |
|
5 * graphics library |
|
6 * |
|
7 * based on graphlcd plugin 0.1.1 for the Video Disc Recorder |
|
8 * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de> |
|
9 * |
|
10 * This file is released under the GNU General Public License. Refer |
|
11 * to the COPYING file distributed with this package. |
|
12 * |
|
13 * (c) 2004 Andreas Regel <andreas.regel AT powarman.de> |
|
14 */ |
|
15 |
|
16 #include <getopt.h> |
|
17 #include <stdint.h> |
|
18 #include <stdio.h> |
|
19 #include <stdlib.h> |
|
20 #include <string.h> |
|
21 #include <glcdgraphics/bitmap.h> |
|
22 #include <glcdgraphics/font.h> |
|
23 |
|
24 static const char *prgname = "crtfont"; |
|
25 static const char *version = "0.1.6"; |
|
26 |
|
27 const int kMaxLineLength = 1024; |
|
28 |
|
29 enum ePicFormat |
|
30 { |
|
31 undefined, |
|
32 PBM |
|
33 }; |
|
34 |
|
35 |
|
36 void usage(void); |
|
37 |
|
38 char * trimleft(char * str) |
|
39 { |
|
40 char * s = str; |
|
41 while (*s == ' ' || *s == '\t') |
|
42 s++; |
|
43 strcpy(str, s); |
|
44 return str; |
|
45 } |
|
46 |
|
47 char * trimright(char * str) |
|
48 { |
|
49 char * s = str + strlen(str) - 1; |
|
50 while (s >= str && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')) |
|
51 *s-- = 0; |
|
52 return str; |
|
53 } |
|
54 |
|
55 char * trim(char * str) |
|
56 { |
|
57 return trimleft(trimright(str)); |
|
58 } |
|
59 |
|
60 |
|
61 int main(int argc, char *argv[]) |
|
62 { |
|
63 ePicFormat picFormat = undefined; |
|
64 GLCD::cFont font; |
|
65 char * picName = NULL; |
|
66 char * descName = NULL; |
|
67 char * fontName = NULL; |
|
68 FILE * descFile; |
|
69 bool error = false; |
|
70 GLCD::cBitmap * bitmap = NULL; |
|
71 GLCD::cBitmap * tmpBitmap = NULL; |
|
72 GLCD::cBitmap * charBitmap = NULL; |
|
73 char line[kMaxLineLength]; |
|
74 int l = 0; |
|
75 char * token; |
|
76 int startOffset, endOffset; |
|
77 int spaceWidth; |
|
78 int version; |
|
79 char * ptr; |
|
80 |
|
81 static struct option long_options[] = |
|
82 { |
|
83 { "format", required_argument, NULL, 'f'}, |
|
84 { "bmpfile", required_argument, NULL, 'b'}, |
|
85 { "descfile", required_argument, NULL, 'd'}, |
|
86 { "outfile", required_argument, NULL, 'o'}, |
|
87 { NULL} |
|
88 }; |
|
89 |
|
90 int c, option_index = 0; |
|
91 while ((c = getopt_long(argc, argv, "f:b:d:o:", long_options, &option_index)) != -1) |
|
92 { |
|
93 switch (c) |
|
94 { |
|
95 case 'f': |
|
96 if (strcasecmp(optarg, "PBM") == 0) |
|
97 picFormat = PBM; |
|
98 break; |
|
99 |
|
100 case 'b': |
|
101 picName = strdup(optarg); |
|
102 break; |
|
103 |
|
104 case 'd': |
|
105 descName = strdup(optarg); |
|
106 break; |
|
107 |
|
108 case 'o': |
|
109 fontName = strdup(optarg); |
|
110 break; |
|
111 |
|
112 default: |
|
113 return 1; |
|
114 } |
|
115 } |
|
116 |
|
117 if (picFormat == undefined) |
|
118 { |
|
119 fprintf(stderr, "ERROR: You have to specify the format (-f <format>)\n"); |
|
120 error = true; |
|
121 } |
|
122 if (!picName) |
|
123 { |
|
124 fprintf(stderr, "ERROR: You have to specify the bmpfile (-b bmpfile)\n"); |
|
125 error = true; |
|
126 } |
|
127 if (!descName) |
|
128 { |
|
129 fprintf(stderr, "ERROR: You have to specify the descfile (-d descfile)\n"); |
|
130 error = true; |
|
131 } |
|
132 if (!fontName) |
|
133 { |
|
134 fprintf(stderr, "ERROR: You have to specify the outfile (-o outfile)\n"); |
|
135 error = true; |
|
136 } |
|
137 |
|
138 if (error) |
|
139 { |
|
140 usage(); |
|
141 return 1; |
|
142 } |
|
143 |
|
144 descFile = fopen(descName,"r"); |
|
145 if (!descFile) |
|
146 { |
|
147 fprintf(stderr, "Cannot open file: %s\n",descName); |
|
148 return 2; |
|
149 } |
|
150 |
|
151 // Load Picture |
|
152 switch (picFormat) |
|
153 { |
|
154 case PBM: |
|
155 bitmap = new GLCD::cBitmap(0, 0); |
|
156 bitmap->LoadPBM(picName); |
|
157 if (!bitmap) |
|
158 { |
|
159 fprintf(stderr, "Cannot open file: %s\n",picName); |
|
160 return 2; |
|
161 } |
|
162 break; |
|
163 |
|
164 default: |
|
165 return 2; |
|
166 } |
|
167 |
|
168 if (!bitmap) |
|
169 return 3; |
|
170 |
|
171 spaceWidth = 0; |
|
172 |
|
173 version = 0; |
|
174 fgets(line, sizeof(line), descFile); |
|
175 trim(line); |
|
176 if (strstr(line, "version") != NULL) |
|
177 { |
|
178 ptr = strstr(line, ":"); |
|
179 version = atoi(ptr + 1); |
|
180 } |
|
181 if (version != 1) |
|
182 { |
|
183 fprintf(stderr, "Wrong description file format version (found %d, expected 1)!\n", version); |
|
184 return 2; |
|
185 } |
|
186 while (!feof(descFile)) |
|
187 { |
|
188 fgets(line, sizeof(line), descFile); |
|
189 trim(line); |
|
190 if (strstr(line, "fontheight") != NULL) |
|
191 { |
|
192 ptr = strstr(line, ":"); |
|
193 font.SetTotalHeight(atoi(ptr + 1)); |
|
194 } |
|
195 else if (strstr(line, "fontascent") != NULL) |
|
196 { |
|
197 ptr = strstr(line, ":"); |
|
198 font.SetTotalAscent(atoi(ptr + 1)); |
|
199 } |
|
200 else if (strstr(line, "lineheight") != NULL) |
|
201 { |
|
202 ptr = strstr(line, ":"); |
|
203 font.SetLineHeight(atoi(ptr + 1)); |
|
204 } |
|
205 else if (strstr(line, "spacebetween") != NULL) |
|
206 { |
|
207 ptr = strstr(line, ":"); |
|
208 font.SetSpaceBetween(atoi(ptr + 1)); |
|
209 } |
|
210 else if (strstr(line, "spacewidth") != NULL) |
|
211 { |
|
212 ptr = strstr(line, ":"); |
|
213 spaceWidth = atoi(ptr + 1); |
|
214 } |
|
215 else |
|
216 { |
|
217 token = strtok(line, " "); |
|
218 if (token) |
|
219 { |
|
220 startOffset = atoi(token); |
|
221 |
|
222 // get character |
|
223 token = strtok(NULL, " "); |
|
224 while (token) |
|
225 { |
|
226 uint16_t character; |
|
227 if (strlen(token) == 1) |
|
228 character = (uint8_t) token[0]; |
|
229 else |
|
230 character = atoi(token); |
|
231 |
|
232 // get EndOffset |
|
233 token = strtok(NULL, " "); |
|
234 endOffset = atoi(token); |
|
235 tmpBitmap = bitmap->SubBitmap(startOffset, l * font.TotalHeight(), endOffset - 1, (l + 1) * font.TotalHeight() - 1); |
|
236 if (spaceWidth > 0) |
|
237 { |
|
238 // calculate width of this character |
|
239 int x; |
|
240 int y; |
|
241 int left = 255; |
|
242 int right = 0; |
|
243 for (y = 0; y < tmpBitmap->Height(); y++) |
|
244 { |
|
245 for (x = 0; x < tmpBitmap->Width(); x++) |
|
246 { |
|
247 if (tmpBitmap->GetPixel(x, y)) |
|
248 break; |
|
249 } |
|
250 if (x < tmpBitmap->Width() && x < left) |
|
251 left = x; |
|
252 for (x = tmpBitmap->Width() - 1; x >= 0; x--) |
|
253 { |
|
254 if (tmpBitmap->GetPixel(x, y)) |
|
255 break; |
|
256 } |
|
257 if (x >= 0 && x > right) |
|
258 right = x; |
|
259 } |
|
260 if (left > right) |
|
261 { |
|
262 left = 0; |
|
263 right = spaceWidth - 1; |
|
264 } |
|
265 charBitmap = tmpBitmap->SubBitmap(left, 0, right, font.TotalHeight() - 1); |
|
266 font.SetCharacter(character, charBitmap); |
|
267 delete tmpBitmap; |
|
268 } |
|
269 else |
|
270 { |
|
271 font.SetCharacter(character, tmpBitmap); |
|
272 } |
|
273 startOffset = endOffset; |
|
274 |
|
275 // get next character |
|
276 token = strtok(NULL, " "); |
|
277 } |
|
278 } |
|
279 l++; |
|
280 } |
|
281 } |
|
282 fclose(descFile); |
|
283 delete bitmap; |
|
284 |
|
285 if (font.SaveFNT(fontName)) |
|
286 fprintf(stdout,"Font '%s' created successfully\n", fontName); |
|
287 |
|
288 return 0; |
|
289 } |
|
290 |
|
291 void usage(void) |
|
292 { |
|
293 fprintf(stdout, "\n"); |
|
294 fprintf(stdout, "%s v%s\n", prgname, version); |
|
295 fprintf(stdout, "%s is a tool to create *.fnt files that are used by the\n", prgname); |
|
296 fprintf(stdout, " graphlcd plugin for VDR.\n\n"); |
|
297 fprintf(stdout, " Usage: %s -f <format> -b bmpfile -d descfile -o outfile\n\n", prgname); |
|
298 fprintf(stdout, " -f --format specifies the format of the bitmap. Possible values are:\n"); |
|
299 fprintf(stdout, " PBM : file is an binary PBM file\n" ); |
|
300 fprintf(stdout, " -b --bmpfile specifies the name of the bitmap file (*.pbm)\n"); |
|
301 fprintf(stdout, " -d --descfile specifies the name of the description file (*.desc)\n"); |
|
302 fprintf(stdout, " -o --outfile specifies the name of the output file (*.fnt)\n"); |
|
303 fprintf(stdout, "\n" ); |
|
304 fprintf(stdout, " example: %s -f PBM -b f12.pbm -d f12.desc -o f12.fnt\n", prgname); |
|
305 } |