diff options
Diffstat (limited to 'tools/bdf2ajf.c')
-rw-r--r-- | tools/bdf2ajf.c | 918 |
1 files changed, 918 insertions, 0 deletions
diff --git a/tools/bdf2ajf.c b/tools/bdf2ajf.c new file mode 100644 index 0000000000..fcd44785cb --- /dev/null +++ b/tools/bdf2ajf.c | |||
@@ -0,0 +1,918 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alex Gitelman | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include "bdf2ajf.h" | ||
20 | #include <stdio.h> | ||
21 | #include <malloc.h> | ||
22 | #include <string.h> | ||
23 | #include <errno.h> | ||
24 | |||
25 | int _font_error_code = 0; | ||
26 | char _font_error_msg[1024]; | ||
27 | #ifndef VC | ||
28 | #define strcmpi(x,y) strcasecmp(x,y) | ||
29 | #endif | ||
30 | |||
31 | short win_alt_map[] = { | ||
32 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00 - 0f */ | ||
33 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10 - 1f */ | ||
34 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20 - 2f */ | ||
35 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 30 - 3f */ | ||
36 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 40 - 4f */ | ||
37 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 50 - 5f */ | ||
38 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 60 - 6f */ | ||
39 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 70 - 7f */ | ||
40 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80 - 8f */ | ||
41 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90 - 9f */ | ||
42 | -1, -1, -1, -1, -1, -1, -1, -1, 0x85, -1, -1, -1, -1, -1, -1, -1, /* A0 - Af */ | ||
43 | -1, -1, -1, -1, -1, -1, -1, -1, 0xA5, -1, -1, -1, -1, -1, -1, -1, /* B0 - Bf */ | ||
44 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, /* C0 - Cf */ | ||
45 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, /* D0 - Df */ | ||
46 | 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, /* E0 - Ef */ | ||
47 | 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, /* F0 - Ff */ | ||
48 | }; | ||
49 | |||
50 | char* bufcat(char* buf1, char *buf2, int len1, int len2) | ||
51 | { | ||
52 | char *newbuf = malloc(len1+len2); | ||
53 | if (newbuf==0) | ||
54 | { | ||
55 | fprintf(stderr, "Can't allocate storage in bufcat (malloc returned 0)\n"); | ||
56 | return NULL; | ||
57 | } | ||
58 | memcpy(newbuf, buf1, len1); | ||
59 | memcpy(&newbuf[len1], buf2, len2); | ||
60 | return newbuf; | ||
61 | } | ||
62 | |||
63 | void write_short(unsigned short s, unsigned char* buf) | ||
64 | { | ||
65 | WRITE_SHORT(s, buf); | ||
66 | } | ||
67 | |||
68 | |||
69 | void usage() | ||
70 | { | ||
71 | printf("bdf2ajf - compile BDF font for use with Rockbox\n"); | ||
72 | printf("Usage: bdf2ajf -f <font> -o <outfile>\n"); | ||
73 | printf("Options:\n"); | ||
74 | printf(" -f - input BDF file\n"); | ||
75 | printf(" -o - output AJF file\n"); | ||
76 | printf(" -h - print help\n"); | ||
77 | printf(" -t <string> - print string as bitmap\n"); | ||
78 | printf(" -t2 <string> - print string as Archos bitmap (must be the same result as -t)\n"); | ||
79 | exit(0); | ||
80 | |||
81 | } | ||
82 | |||
83 | int do_test1 = 0; | ||
84 | int do_test2 = 0; | ||
85 | |||
86 | int main(int argc, char** argv) | ||
87 | { | ||
88 | FILE *outfd = 0; | ||
89 | unsigned char outbuf[20000]; | ||
90 | unsigned char buf[1000]; | ||
91 | unsigned char test_str1[300]; | ||
92 | unsigned char test_str2[300]; | ||
93 | int height = 8, rows; | ||
94 | int size = 0; | ||
95 | int i, offset; | ||
96 | unsigned char *p, *p1; | ||
97 | int c; | ||
98 | char in_file[1024]; | ||
99 | char out_file[1024]; | ||
100 | BDF *bdf = 0; | ||
101 | in_file[0] = 0; | ||
102 | out_file[0] = 0; | ||
103 | |||
104 | for(i=1;i<argc;i++) | ||
105 | { | ||
106 | if (!strcmpi(argv[i], "-f")) | ||
107 | { | ||
108 | i++; | ||
109 | if (i==argc) usage(); | ||
110 | strcpy(in_file, argv[i]); | ||
111 | } | ||
112 | else if (!strcmpi(argv[i], "-o")) | ||
113 | { | ||
114 | i++; | ||
115 | if (i==argc) usage(); | ||
116 | strcpy(out_file, argv[i]); | ||
117 | } | ||
118 | else if (!strcmpi(argv[i], "-t")) | ||
119 | { | ||
120 | i++; | ||
121 | if (i==argc) usage(); | ||
122 | do_test1 = 1; | ||
123 | strcpy(test_str1, argv[i]); | ||
124 | } | ||
125 | else if (!strcmpi(argv[i], "-t2")) | ||
126 | { | ||
127 | i++; | ||
128 | if (i==argc) usage(); | ||
129 | do_test2 = 1; | ||
130 | strcpy(test_str2, argv[i]); | ||
131 | } | ||
132 | else | ||
133 | usage(); | ||
134 | } | ||
135 | if (strlen(in_file)==0 || strlen(out_file)==0) | ||
136 | usage(); | ||
137 | |||
138 | bdf = readFont(in_file); | ||
139 | if (do_test1) | ||
140 | { | ||
141 | unsigned char *p = test_str1; | ||
142 | printf("Begin Test Print1 for %s", test_str1); | ||
143 | while(p[0]) | ||
144 | test_print(p++[0], bdf, win_alt_map); | ||
145 | |||
146 | } | ||
147 | if (do_test2) | ||
148 | { | ||
149 | unsigned char *p = test_str2; | ||
150 | printf("Begin Test Print2 for %s", test_str2); | ||
151 | while(p[0]) | ||
152 | { | ||
153 | BDF_GLYPH *g = getGlyph(p++[0], bdf, win_alt_map); | ||
154 | int rows = (g->bbx_height-1)/8+1; | ||
155 | |||
156 | unsigned char tst_src[100]; | ||
157 | if (!g) | ||
158 | { | ||
159 | printf("No Glyph for %c", p[-1]); | ||
160 | continue; | ||
161 | } | ||
162 | getBitmap(g, tst_src); | ||
163 | test_print2(tst_src, g->bbx_height, g->bitmap_len*rows); | ||
164 | } | ||
165 | |||
166 | } | ||
167 | |||
168 | writeAJF(bdf, out_file); | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | |||
173 | void writeAJF(BDF* bdf, const char* out_file) | ||
174 | { | ||
175 | FILE *outfd = 0; | ||
176 | unsigned char outbuf[20000]; | ||
177 | unsigned char char_map[20000]; | ||
178 | unsigned char buf[1000]; | ||
179 | unsigned char test_str1[300]; | ||
180 | unsigned char test_str2[300]; | ||
181 | unsigned short height = 8, rows, width; | ||
182 | unsigned short first_char = 0; | ||
183 | unsigned short char_count = 255; | ||
184 | int size = 0; | ||
185 | int i, offset; | ||
186 | unsigned char *p, *p1; | ||
187 | int c, idx, chars_offset; | ||
188 | |||
189 | memset(outbuf,0, sizeof(outbuf)); | ||
190 | height = bdf->bound_height; | ||
191 | rows = (bdf->bound_height-1)/8 + 1; | ||
192 | width = bdf->bound_width; | ||
193 | |||
194 | idx = 0; | ||
195 | outbuf[idx++] = MAGIC1; | ||
196 | outbuf[idx++] = MAGIC2; | ||
197 | if (bdf->name) | ||
198 | { | ||
199 | int len = strlen(bdf->name); | ||
200 | if (len<FONT_NAME_LEN) | ||
201 | strcpy(&outbuf[FONT_NAME_OFFSET], bdf->name); | ||
202 | else | ||
203 | memcpy(&outbuf[FONT_NAME_OFFSET], bdf->name, FONT_NAME_LEN); | ||
204 | |||
205 | } | ||
206 | |||
207 | idx = MAX_WIDTH_OFFSET; | ||
208 | write_short(width, &outbuf[idx]); | ||
209 | /* outbuf[idx] = (unsigned short)width; */ | ||
210 | idx = HEIGHT_OFFSET; | ||
211 | write_short(height, &outbuf[idx]); | ||
212 | /* outbuf[idx] = (unsigned short)height; */ | ||
213 | |||
214 | idx = FIRST_CHAR_OFFSET; | ||
215 | write_short(first_char, &outbuf[idx]); | ||
216 | |||
217 | idx = SIZE_OFFSET; | ||
218 | write_short(char_count, &outbuf[idx]); | ||
219 | |||
220 | chars_offset = LOOKUP_MAP_OFFSET + char_count*3; | ||
221 | idx = chars_offset; | ||
222 | |||
223 | /* Put bitmaps in outbuf */ | ||
224 | for (c=first_char;c<=char_count;c++) | ||
225 | { | ||
226 | int map_offset = LOOKUP_MAP_OFFSET + (c-first_char)*3; /* index in char map. Takes 3 bytes - 1 width, 2 - offset */ | ||
227 | unsigned char bmp_bytes = 0; | ||
228 | BDF_GLYPH *glyph = getGlyph((unsigned int)c, bdf, win_alt_map); | ||
229 | |||
230 | if (glyph) | ||
231 | { | ||
232 | bmp_bytes = rows*glyph->dwidth_x; | ||
233 | getBitmap(glyph, &outbuf[idx]); | ||
234 | } | ||
235 | else | ||
236 | { | ||
237 | bmp_bytes = 0; | ||
238 | } | ||
239 | |||
240 | outbuf[map_offset++] = bmp_bytes; | ||
241 | write_short((unsigned short)(idx-chars_offset), &outbuf[map_offset]); | ||
242 | idx+=bmp_bytes; | ||
243 | } | ||
244 | |||
245 | outfd = fopen(out_file,"wb"); | ||
246 | if (!outfd) | ||
247 | { | ||
248 | fprintf(stderr, "Can't create output file\n"); | ||
249 | } | ||
250 | |||
251 | i = 0; | ||
252 | for (p1=outbuf; p1 < &outbuf[idx]; p1++) | ||
253 | { | ||
254 | if (i==sizeof(buf)) | ||
255 | { | ||
256 | fwrite(buf, sizeof(unsigned char), sizeof(buf), outfd); | ||
257 | i=0; | ||
258 | } | ||
259 | |||
260 | i++; | ||
261 | buf[i-1] = p1[0]; | ||
262 | } | ||
263 | if (i>0) | ||
264 | fwrite(buf, sizeof(unsigned char), i, outfd); | ||
265 | |||
266 | fclose(outfd); | ||
267 | } | ||
268 | |||
269 | void freeGlyph(BDF_GLYPH* glyph) | ||
270 | { | ||
271 | if ( glyph->glyph_name ) | ||
272 | free( glyph->glyph_name ); | ||
273 | |||
274 | if ( glyph->bitmap ) | ||
275 | free( glyph->bitmap ); | ||
276 | |||
277 | free(glyph); | ||
278 | } | ||
279 | |||
280 | void freeBDF(BDF* bdf) | ||
281 | { | ||
282 | int i; | ||
283 | if ( bdf->bdf_ver ) | ||
284 | free( bdf->bdf_ver ); | ||
285 | if ( bdf->name ) | ||
286 | free( bdf->name ); | ||
287 | |||
288 | for (i=0; i<bdf->prop_count; i++) | ||
289 | { | ||
290 | if ( bdf->prop_name && bdf->prop_name[i] ) | ||
291 | free( bdf->prop_name[i] ); | ||
292 | if ( bdf->prop_value && bdf->prop_value[i] ) | ||
293 | free( bdf->prop_value[i] ); | ||
294 | } | ||
295 | if ( bdf->prop_name ) | ||
296 | free( bdf->prop_name ); | ||
297 | if ( bdf->prop_name ) | ||
298 | free( bdf->prop_value ); | ||
299 | for (i=0; i<bdf->char_count; i++) | ||
300 | { | ||
301 | if ( bdf->glyph && bdf->glyph[i] ) | ||
302 | freeGlyph( bdf->glyph[i] ); | ||
303 | } | ||
304 | if ( bdf->glyph ) | ||
305 | free( bdf->glyph ); | ||
306 | free( bdf ); | ||
307 | } | ||
308 | |||
309 | char *readLine(char *buf, char* line) | ||
310 | { | ||
311 | while (buf[0]=='\n' || buf[0]=='\r') | ||
312 | buf++; | ||
313 | while (buf[0]!='\n' && buf[0]!='\r' && (buf[0])) | ||
314 | { | ||
315 | line++[0] = buf++[0]; | ||
316 | } | ||
317 | line[0] = 0; | ||
318 | return buf; | ||
319 | } | ||
320 | |||
321 | char* readNextToken() | ||
322 | { | ||
323 | char *ret; | ||
324 | char *tok = strtok(0, " "); | ||
325 | if (!tok) | ||
326 | { | ||
327 | fprintf(stderr, "Next token is NULL\n"); | ||
328 | return NULL; | ||
329 | } | ||
330 | |||
331 | ret = malloc(strlen(tok)+1); | ||
332 | if (!ret) | ||
333 | { | ||
334 | fprintf(stderr, "malloc returned 0 in readNextToken\n"); | ||
335 | return NULL; | ||
336 | } | ||
337 | strcpy(ret, tok); | ||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | |||
342 | int readNextIntToken() | ||
343 | { | ||
344 | int ret; | ||
345 | char* tok = readNextToken(); | ||
346 | if (!tok) | ||
347 | { | ||
348 | fprintf(stderr, "Could not int token\n"); | ||
349 | return 0; | ||
350 | } | ||
351 | ret = atoi(tok); | ||
352 | free(tok); | ||
353 | return ret; | ||
354 | } | ||
355 | |||
356 | unsigned char getHexDigit(char c) | ||
357 | { | ||
358 | if (c<='F' && c>='A') | ||
359 | return c-'A'+10; | ||
360 | if (c<='f' && c>='a') | ||
361 | return c-'a'+10; | ||
362 | if (c<='9' && c>='0') | ||
363 | return c-'0'; | ||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | void toHex(char *str, unsigned char *out) | ||
368 | { | ||
369 | int len = strlen(str); | ||
370 | out[0] = (unsigned char)16*getHexDigit(str[0]) + getHexDigit(str[1]); | ||
371 | out[1] = 0; | ||
372 | |||
373 | if (str[2] && len>2) | ||
374 | out[1] += (unsigned char)16*getHexDigit(str[2]); | ||
375 | if (str[3] && len>3) | ||
376 | out[1] += (unsigned char)getHexDigit(str[3]); | ||
377 | |||
378 | } | ||
379 | |||
380 | BDF* parseBDF(char *bdf) | ||
381 | { | ||
382 | char *p = bdf; | ||
383 | char line[255]; | ||
384 | char *tok = NULL; | ||
385 | int i=0; | ||
386 | int reading_font = 0; | ||
387 | int reading_properties = 0; | ||
388 | int reading_glyph = 0; | ||
389 | int reading_bitmap = 0; | ||
390 | int current_glyph_idx = 0; | ||
391 | int current_property = 0; | ||
392 | unsigned char bitmap[255]; | ||
393 | short bitmap_idx = 0; | ||
394 | |||
395 | BDF *ret = malloc(sizeof(BDF)); | ||
396 | if (!ret) | ||
397 | return NULL; | ||
398 | |||
399 | memset(ret,0,sizeof(BDF)); | ||
400 | |||
401 | while(p[0]) | ||
402 | { | ||
403 | p = readLine(p, line); | ||
404 | tok = strtok(line, " "); | ||
405 | if (tok) | ||
406 | { | ||
407 | if (strcmp(tok, COMMENT)==0) | ||
408 | continue; | ||
409 | |||
410 | if (strcmp(tok, STARTFONT)==0) | ||
411 | { | ||
412 | if (reading_font) | ||
413 | { | ||
414 | fprintf(stderr, "Only one STARTFONT allowed\n"); | ||
415 | freeBDF(ret); | ||
416 | return NULL; | ||
417 | } | ||
418 | reading_font = 1; | ||
419 | ret->bdf_ver = readNextToken(); | ||
420 | if (ret->bdf_ver==0) | ||
421 | { | ||
422 | fprintf(stderr, "Could not read version of BDF\n"); | ||
423 | freeBDF(ret); | ||
424 | return NULL; | ||
425 | } | ||
426 | /* Ignore the rest */ | ||
427 | } | ||
428 | else | ||
429 | { | ||
430 | if (!reading_font) | ||
431 | { | ||
432 | fprintf(stderr, "Font must start with STARTFONT\n"); | ||
433 | freeBDF(ret); | ||
434 | return NULL; | ||
435 | } | ||
436 | |||
437 | if (!strcmp(tok, ENDFONT)) | ||
438 | { | ||
439 | break; | ||
440 | } | ||
441 | else if (!strcmp(tok, FONT)) | ||
442 | { | ||
443 | ret->name = readNextToken(); | ||
444 | if (ret->name==0) | ||
445 | { | ||
446 | fprintf(stderr, "Could not read name font\n"); | ||
447 | freeBDF(ret); | ||
448 | return NULL; | ||
449 | } | ||
450 | } | ||
451 | else if (!strcmp(tok, SIZE)) | ||
452 | { | ||
453 | ret->point_size = readNextIntToken(); | ||
454 | if (ret->point_size<=0) | ||
455 | { | ||
456 | fprintf(stderr, "Font point size is invalid\n"); | ||
457 | freeBDF(ret); | ||
458 | return NULL; | ||
459 | } | ||
460 | |||
461 | ret->x_res = readNextIntToken(); | ||
462 | if (ret->x_res<=0) | ||
463 | { | ||
464 | fprintf(stderr, "Device x resolution is invalid\n"); | ||
465 | freeBDF(ret); | ||
466 | return NULL; | ||
467 | } | ||
468 | ret->y_res = readNextIntToken(); | ||
469 | if (ret->y_res<=0) | ||
470 | { | ||
471 | fprintf(stderr, "Device y resolution is invalid\n"); | ||
472 | freeBDF(ret); | ||
473 | return NULL; | ||
474 | } | ||
475 | } | ||
476 | else if (!strcmp(tok, FONTBOUNDINGBOX)) | ||
477 | { | ||
478 | ret->bound_width = readNextIntToken(); | ||
479 | if (ret->bound_width<=0) | ||
480 | { | ||
481 | fprintf(stderr, "Bounding width is invalid\n"); | ||
482 | freeBDF(ret); | ||
483 | return NULL; | ||
484 | } | ||
485 | ret->bound_height = readNextIntToken(); | ||
486 | if (ret->bound_height<=0) | ||
487 | { | ||
488 | fprintf(stderr, "Bounding height is invalid\n"); | ||
489 | freeBDF(ret); | ||
490 | return NULL; | ||
491 | } | ||
492 | ret->bound_disp_x = readNextIntToken(); | ||
493 | ret->bound_disp_y = readNextIntToken(); | ||
494 | } | ||
495 | else if (!strcmp(tok, STARTPROPERTIES)) | ||
496 | { | ||
497 | ret->prop_count = readNextIntToken(); | ||
498 | if (ret->prop_count<=0) | ||
499 | { | ||
500 | fprintf(stderr, "Number of properties must be > 0\n"); | ||
501 | freeBDF(ret); | ||
502 | return NULL; | ||
503 | } | ||
504 | ret->prop_name = malloc(ret->prop_count*sizeof(char*)); | ||
505 | if (ret->prop_name == 0) | ||
506 | { | ||
507 | fprintf(stderr, "Can't allocate storage for properties (malloc returns 0)\n"); | ||
508 | freeBDF(ret); | ||
509 | return NULL; | ||
510 | } | ||
511 | memset(ret->prop_name, 0, ret->prop_count*sizeof(char*)); | ||
512 | |||
513 | ret->prop_value = malloc(ret->prop_count*sizeof(char*)); | ||
514 | if (ret->prop_value==0) | ||
515 | { | ||
516 | fprintf(stderr, "Can't allocate storage for properties (malloc returns 0)\n"); | ||
517 | freeBDF(ret); | ||
518 | return NULL; | ||
519 | } | ||
520 | memset(ret->prop_value, 0, ret->prop_count*sizeof(char*)); | ||
521 | current_property = 0; | ||
522 | reading_properties = 1; | ||
523 | } | ||
524 | else if (!strcmp(tok, ENDPROPERTIES)) | ||
525 | { | ||
526 | if (!reading_properties) | ||
527 | { | ||
528 | fprintf(stderr, "ENDPROPERTIES found while not reading properties\n"); | ||
529 | freeBDF(ret); | ||
530 | return NULL; | ||
531 | } | ||
532 | if (current_property!=ret->prop_count) | ||
533 | { | ||
534 | fprintf(stderr, "Property count mismatch\n"); | ||
535 | freeBDF(ret); | ||
536 | return NULL; | ||
537 | } | ||
538 | reading_properties = 0; | ||
539 | } | ||
540 | else if (!strcmp(tok, CHARS)) | ||
541 | { | ||
542 | ret->char_count = readNextIntToken(); | ||
543 | if (ret->char_count<=0) | ||
544 | { | ||
545 | fprintf(stderr, "Font must have >0 char glyphs\n"); | ||
546 | freeBDF(ret); | ||
547 | return NULL; | ||
548 | } | ||
549 | |||
550 | ret->glyph = malloc(ret->char_count*sizeof(BDF_GLYPH*)); | ||
551 | if (!ret->glyph) | ||
552 | { | ||
553 | fprintf(stderr, "Can't allocate storage for glyphs (malloc returns 0)\n"); | ||
554 | freeBDF(ret); | ||
555 | return NULL; | ||
556 | } | ||
557 | memset(ret->glyph, 0, ret->char_count*sizeof(BDF_GLYPH*)); | ||
558 | } | ||
559 | else if (!strcmp(tok, STARTCHAR)) | ||
560 | { | ||
561 | if (reading_glyph) | ||
562 | { | ||
563 | fprintf(stderr, "Nested STARTCHAR is not allowed\n"); | ||
564 | freeBDF(ret); | ||
565 | return NULL; | ||
566 | } | ||
567 | if (current_glyph_idx>=ret->char_count) | ||
568 | { | ||
569 | fprintf(stderr, "Too many glyphs (more than defined by CHARS)\n"); | ||
570 | freeBDF(ret); | ||
571 | return NULL; | ||
572 | } | ||
573 | |||
574 | reading_glyph = 1; | ||
575 | ret->glyph[current_glyph_idx] = malloc(sizeof(BDF_GLYPH)); | ||
576 | if (ret->glyph[current_glyph_idx]==0) | ||
577 | { | ||
578 | fprintf(stderr, "Can't allocate storage for one glyph (malloc returns 0)\n"); | ||
579 | freeBDF(ret); | ||
580 | return NULL; | ||
581 | } | ||
582 | memset(ret->glyph[current_glyph_idx],0, sizeof(BDF_GLYPH)); | ||
583 | ret->glyph[current_glyph_idx]->glyph_name = readNextToken(); | ||
584 | |||
585 | memset(bitmap, 0, sizeof(bitmap)); | ||
586 | bitmap_idx = 0; | ||
587 | |||
588 | } | ||
589 | else if (!strcmp(tok, ENDCHAR)) | ||
590 | { | ||
591 | if (!reading_glyph) | ||
592 | { | ||
593 | fprintf(stderr, "ENDCHAR only allowed after STARTCHAR\n"); | ||
594 | freeBDF(ret); | ||
595 | return NULL; | ||
596 | } | ||
597 | reading_glyph = 0; | ||
598 | reading_bitmap = 0; | ||
599 | ret->glyph[current_glyph_idx]->bitmap_len = bitmap_idx/2; | ||
600 | ret->glyph[current_glyph_idx]->bitmap = malloc(bitmap_idx); | ||
601 | if (ret->glyph[current_glyph_idx]->bitmap==0) | ||
602 | { | ||
603 | fprintf(stderr, "Can't allocate storage for bitmap (malloc returns 0)\n"); | ||
604 | freeBDF(ret); | ||
605 | return NULL; | ||
606 | } | ||
607 | |||
608 | for(i=0;i<bitmap_idx;i+=2) | ||
609 | { | ||
610 | ret->glyph[current_glyph_idx]->bitmap[i] = bitmap[i]; | ||
611 | ret->glyph[current_glyph_idx]->bitmap[i+1] = bitmap[i+1]; | ||
612 | } | ||
613 | if (ret->glyph[current_glyph_idx] ==0) | ||
614 | _font_error_code = 3; | ||
615 | |||
616 | if (ret->glyph[current_glyph_idx]->encoding>=0) | ||
617 | { | ||
618 | ret->enc_table[ret->glyph[current_glyph_idx]->encoding] = ret->glyph[current_glyph_idx]; | ||
619 | } | ||
620 | |||
621 | current_glyph_idx++; | ||
622 | } | ||
623 | else if (!strcmp(tok, ENCODING)) | ||
624 | { | ||
625 | if (!reading_glyph) | ||
626 | { | ||
627 | fprintf(stderr, "ENCODING only allowed after STARTCHAR\n"); | ||
628 | freeBDF(ret); | ||
629 | return NULL; | ||
630 | } | ||
631 | ret->glyph[current_glyph_idx]->encoding = readNextIntToken(); | ||
632 | /* TODO: Consider encoding ? */ | ||
633 | } | ||
634 | else if (!strcmp(tok, SWIDTH)) | ||
635 | { | ||
636 | if (!reading_glyph) | ||
637 | { | ||
638 | fprintf(stderr, "SWIDTH only allowed after STARTCHAR\n"); | ||
639 | freeBDF(ret); | ||
640 | return NULL; | ||
641 | } | ||
642 | ret->glyph[current_glyph_idx]->swidth_x = readNextIntToken(); | ||
643 | ret->glyph[current_glyph_idx]->swidth_y = readNextIntToken(); | ||
644 | } | ||
645 | else if (!strcmp(tok, DWIDTH)) | ||
646 | { | ||
647 | if (!reading_glyph) | ||
648 | { | ||
649 | fprintf(stderr, "DWIDTH only allowed after STARTCHAR\n"); | ||
650 | freeBDF(ret); | ||
651 | return NULL; | ||
652 | } | ||
653 | ret->glyph[current_glyph_idx]->dwidth_x = readNextIntToken(); | ||
654 | ret->glyph[current_glyph_idx]->dwidth_y = readNextIntToken(); | ||
655 | } | ||
656 | else if (!strcmp(tok, BBX)) | ||
657 | { | ||
658 | if (!reading_glyph) | ||
659 | { | ||
660 | fprintf(stderr, "BBX only allowed after STARTCHAR\n"); | ||
661 | freeBDF(ret); | ||
662 | return NULL; | ||
663 | } | ||
664 | ret->glyph[current_glyph_idx]->bbx_width = readNextIntToken(); | ||
665 | ret->glyph[current_glyph_idx]->bbx_height = readNextIntToken(); | ||
666 | ret->glyph[current_glyph_idx]->bbx_disp_x = readNextIntToken(); | ||
667 | ret->glyph[current_glyph_idx]->bbx_disp_y = readNextIntToken(); | ||
668 | } | ||
669 | else if (!strcmp(tok, BITMAP)) | ||
670 | { | ||
671 | if (!reading_glyph) | ||
672 | { | ||
673 | fprintf(stderr, "BITMAP only allowed after STARTCHAR\n"); | ||
674 | freeBDF(ret); | ||
675 | return NULL; | ||
676 | } | ||
677 | reading_bitmap = 1; | ||
678 | |||
679 | } | ||
680 | else /* Last one reading properties and bitmaps */ | ||
681 | { | ||
682 | if (reading_glyph && reading_bitmap) | ||
683 | { | ||
684 | toHex(tok, &bitmap[bitmap_idx]); | ||
685 | bitmap_idx+=2; | ||
686 | continue; | ||
687 | } | ||
688 | |||
689 | |||
690 | if (!reading_properties) | ||
691 | { | ||
692 | fprintf(stderr, "Unknown token %s", tok); | ||
693 | continue; | ||
694 | } | ||
695 | if (current_property>=ret->prop_count) | ||
696 | { | ||
697 | fprintf(stderr, "Too many properties\n"); | ||
698 | freeBDF(ret); | ||
699 | return NULL; | ||
700 | } | ||
701 | ret->prop_name[current_property] = malloc(strlen(tok)+1); | ||
702 | if (ret->prop_name[current_property]==0) | ||
703 | { | ||
704 | fprintf(stderr, "Can't allocate storage for one property name (malloc returned 0)\n"); | ||
705 | freeBDF(ret); | ||
706 | return NULL; | ||
707 | } | ||
708 | strcpy(ret->prop_name[current_property], tok); | ||
709 | ret->prop_value[current_property] = readNextToken(); | ||
710 | if (ret->prop_value[current_property]==0) | ||
711 | { | ||
712 | fprintf(stderr, "Can't allocate storage for one property value (malloc returned 0)\n"); | ||
713 | freeBDF(ret); | ||
714 | return NULL; | ||
715 | } | ||
716 | current_property++; | ||
717 | } | ||
718 | |||
719 | } | ||
720 | } | ||
721 | |||
722 | } | ||
723 | |||
724 | return ret; | ||
725 | } | ||
726 | |||
727 | |||
728 | |||
729 | BDF* readFont(const char *name) | ||
730 | { | ||
731 | char buf[1001]; | ||
732 | int count; | ||
733 | char *font_buf = 0; | ||
734 | char *new_buf; | ||
735 | int len = 0; | ||
736 | |||
737 | FILE *fd = fopen(name, "rt"); | ||
738 | if (!fd) | ||
739 | { | ||
740 | fprintf(stderr, "%d %s. ", errno, name); | ||
741 | return NULL; | ||
742 | } | ||
743 | |||
744 | count = fread(buf, sizeof(char), 1000, fd); | ||
745 | |||
746 | new_buf = malloc(count); | ||
747 | if (!new_buf) | ||
748 | { | ||
749 | fprintf(stderr, "mlc=0. len %d.", count); | ||
750 | fclose(fd); | ||
751 | return NULL; | ||
752 | } | ||
753 | |||
754 | memcpy(new_buf, buf, count); | ||
755 | len = count; | ||
756 | font_buf = new_buf; | ||
757 | while (count>0) | ||
758 | { | ||
759 | char *p; | ||
760 | count = fread( buf, sizeof(char), sizeof(buf)-1, fd); | ||
761 | if (count<=0) | ||
762 | break; | ||
763 | p = new_buf; | ||
764 | new_buf = bufcat(new_buf, buf, len, count); | ||
765 | if (!new_buf) | ||
766 | { | ||
767 | fclose(fd); | ||
768 | return NULL; | ||
769 | } | ||
770 | free(p); | ||
771 | len+=count; | ||
772 | font_buf = new_buf; | ||
773 | } | ||
774 | |||
775 | close(fd); | ||
776 | font_buf[len-1] =0; | ||
777 | return parseBDF(font_buf); | ||
778 | } | ||
779 | |||
780 | |||
781 | |||
782 | void test_print(unsigned char c, BDF* font, short* enc_map) | ||
783 | { | ||
784 | int i,j; | ||
785 | BDF_GLYPH *g; | ||
786 | |||
787 | if (enc_map && enc_map[c]>0) | ||
788 | c = enc_map[c]; | ||
789 | g = font->enc_table[c]; | ||
790 | if (!g) | ||
791 | g = font->glyph[c]; | ||
792 | if (!g) | ||
793 | { | ||
794 | fprintf(stderr,"Missing %d \n",c); | ||
795 | return; | ||
796 | } | ||
797 | else | ||
798 | printf("%s %d enc: %d %x \n", | ||
799 | g->glyph_name,c, c, g->encoding, g->encoding); | ||
800 | for (i=0; i < g->bitmap_len; i++) | ||
801 | { | ||
802 | unsigned short bmp = 0; | ||
803 | unsigned short sh; | ||
804 | DOUBLE_BYTE db; | ||
805 | db.db[0] = g->bitmap[i*2]; | ||
806 | db.db[1] = g->bitmap[i*2+1]; | ||
807 | |||
808 | sh = 1 << 7; /*g->dwidth_x;*/ | ||
809 | |||
810 | for(j=0; j < g->dwidth_x; j++) | ||
811 | { | ||
812 | int b; | ||
813 | unsigned short bit = sh>>j; | ||
814 | if (bit==0) | ||
815 | { | ||
816 | sh = 1 << (sizeof(unsigned short)*8-1); | ||
817 | bit = sh>>(j - 8); | ||
818 | } | ||
819 | b = bit & db.sval; | ||
820 | printf( b ? "*" : " " ); | ||
821 | } | ||
822 | |||
823 | printf("\n"); | ||
824 | } | ||
825 | |||
826 | |||
827 | } | ||
828 | |||
829 | BDF_GLYPH* getGlyph(unsigned char c, BDF* bdf, short* enc_map) | ||
830 | { | ||
831 | BDF_GLYPH* ret; | ||
832 | if (enc_map && enc_map[c]>0) | ||
833 | c = enc_map[c]; | ||
834 | |||
835 | ret = bdf->enc_table[c]; | ||
836 | if (!ret && c < bdf->char_count) | ||
837 | ret = bdf->glyph[c]; | ||
838 | |||
839 | if (!ret) | ||
840 | fprintf(stderr, "Glyph %d is 0.\n", c); | ||
841 | |||
842 | return ret; | ||
843 | } | ||
844 | |||
845 | void test_print2(unsigned char *src, int height, int len) | ||
846 | { | ||
847 | int rows = (height-1)/8+1; | ||
848 | int r,c, bit; | ||
849 | int rp = 0; | ||
850 | int i; | ||
851 | printf("Bitmap: "); | ||
852 | for (i=0;i<len;i++) | ||
853 | printf("0x%x ", src[i]); | ||
854 | printf("\n"); | ||
855 | |||
856 | for (r=0; r < rows; r++) | ||
857 | { | ||
858 | for (bit=0; bit < 8; bit++) | ||
859 | { | ||
860 | int sh = 1 << bit; | ||
861 | for (c=0; c < len/rows; c++) | ||
862 | { | ||
863 | int tst = src[c*rows+r]&sh; | ||
864 | if (tst) | ||
865 | printf("*"); | ||
866 | else | ||
867 | printf(" "); | ||
868 | } | ||
869 | printf("\n"); | ||
870 | if (rp++ > height) | ||
871 | return; | ||
872 | } | ||
873 | } | ||
874 | |||
875 | } | ||
876 | |||
877 | void getBitmap(BDF_GLYPH* g, unsigned char* src) | ||
878 | { | ||
879 | int i,j,k; | ||
880 | int d = 0; | ||
881 | int map_shift = 0; | ||
882 | int rows = (g->bbx_height-1)/8+1; | ||
883 | memset(src, 0, g->bitmap_len*rows); | ||
884 | |||
885 | for (i=0; i < g->bitmap_len; i++) | ||
886 | { | ||
887 | unsigned short bmp = 0; | ||
888 | unsigned short sh, srcmap; | ||
889 | DOUBLE_BYTE db; | ||
890 | db.db[0] = g->bitmap[i*2]; | ||
891 | db.db[1] = g->bitmap[i*2+1]; | ||
892 | |||
893 | sh = 1 << 7; /*g->dwidth_x;*/ | ||
894 | |||
895 | if (i>0 && (i%8==0)) | ||
896 | { | ||
897 | d++; | ||
898 | map_shift = 0; | ||
899 | } | ||
900 | srcmap = 1<<map_shift++; | ||
901 | |||
902 | for(j=0; j < g->dwidth_x; j++) | ||
903 | { | ||
904 | int b; | ||
905 | unsigned short bit = sh>>j; | ||
906 | if (bit==0) | ||
907 | { | ||
908 | sh = 1 << (sizeof(unsigned short)*8-1); | ||
909 | bit = sh>>(j - 8); | ||
910 | } | ||
911 | b = bit&db.sval; | ||
912 | |||
913 | if (b) | ||
914 | src[j*rows+d] |= srcmap; | ||
915 | } | ||
916 | } | ||
917 | } | ||
918 | |||