2
* bdf.c - low level bdf file interface
3
* by Hirotsugu Kakugawa
5
* 25 Apr 1997 Added multiple file extension feature.
6
* 20 Jan 1998 VFlib 3.4 Changed API.
7
* 21 Apr 1998 Deleted multiple file extension feature.
8
* 17 Jun 1998 Support for 'font-directory' capability in font definition.
11
* Copyright (C) 1996-1998 Hirotsugu Kakugawa.
12
* All rights reserved.
14
* This file is part of the VFlib Library. This library is free
15
* software; you can redistribute it and/or modify it under the terms of
16
* the GNU Library General Public License as published by the Free
17
* Software Foundation; either version 2 of the License, or (at your
18
* option) any later version. This library is distributed in the hope
19
* that it will be useful, but WITHOUT ANY WARRANTY; without even the
20
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
21
* PURPOSE. See the GNU Library General Public License for more details.
22
* You should have received a copy of the GNU Library General Public
23
* License along with this library; if not, write to the Free Software
24
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29
Private VF_TABLE bdf_table = NULL;
35
static int init_flag = 0;
40
if ((bdf_table = vf_table_create()) == NULL){
41
vf_error = VF_ERR_NO_MEMORY;
50
Private void bdf_release(BDF bdf);
51
Private int bdf_char_index(BDF,long);
52
Private int bdf_load_file(BDF);
53
Private BDF_CHAR read_bitmap(BDF_CHAR,FILE*);
54
Private int bdf_sort_index(BDF,int,int);
55
Private int bdf_partition(BDF,int,int);
58
BDF_Open(char *font_file, SEXP fontdirs)
60
char *path_name, *uncomp_prog;
64
path_name = vf_search_file(font_file, -1, NULL, FALSE, -1, fontdirs,
65
default_compressed_ext, &uncomp_prog);
66
if (path_name == NULL){
67
vf_error = VF_ERR_NO_FONT_FILE;
72
printf("BDF Font File: %s ==> %s\n", font_file, path_name);
75
/* Check the cache here. (Never forget that the fontdir is
76
* not always the same. */
77
if ((bdf_id = (bdf_table->get_id_by_key)(bdf_table, path_name,
78
strlen(path_name)+1)) >= 0){
79
(bdf_table->link_by_id)(bdf_table, bdf_id);
85
ALLOC_IF_ERR(bdf, struct s_bdf){
86
vf_error = VF_ERR_NO_MEMORY;
97
bdf->char_table = NULL;
98
bdf->char_table_x = NULL;
99
bdf->path_name = path_name;
100
bdf->uncompress = NULL;
103
if ((uncomp_prog != NULL) &&
104
((bdf->uncompress = vf_strdup(uncomp_prog)) == NULL)){
105
vf_error = VF_ERR_NO_MEMORY;
108
if ((bdf->props = vf_sexp_empty_list()) == NULL){
109
vf_error = VF_ERR_NO_MEMORY;
113
if (bdf_load_file(bdf) < 0)
116
if ((bdf_id = (bdf_table->put)(bdf_table, bdf,
117
path_name, strlen(path_name)+1)) < 0){
118
vf_error = VF_ERR_NO_MEMORY;
122
BDF_SetBDF(bdf_id, bdf);
133
BDF_Close(int bdf_id)
137
if ((bdf = BDF_GetBDF(bdf_id)) == NULL){
138
fprintf(stderr, "VFlib internal error: BDF_Close()\n");
139
vf_error = VF_ERR_INTERNAL;
142
if ((bdf_table->unlink_by_id)(bdf_table, bdf_id) > 0){
156
vf_free(bdf->path_name);
157
vf_free(bdf->uncompress);
158
if (bdf->char_table != NULL){
159
for (ch = 0; ch < bdf->nchars; ch++)
160
vf_free(bdf->char_table[ch].bitmap);
162
vf_free(bdf->char_table);
163
vf_free(bdf->char_table_x);
164
vf_sexp_free(&bdf->props);
172
bdf_load_file(BDF bdf)
175
char linebuf[BUFSIZ], prop_string[160], *name;
176
char charset_name[256], charset_enc[256], charset[256], *p;
177
long code_point, last_ch;
178
int ch_index, need_sorting, nchars, i;
179
int have_fontboundingbox;
181
if (bdf->uncompress == NULL){
182
if ((fp = vf_fm_OpenTextFileStream(bdf->path_name)) == NULL){
183
vf_error = VF_ERR_NO_FONT_FILE;
187
if ((fp = vf_open_uncompress_stream(bdf->path_name,
188
bdf->uncompress)) == NULL){
189
vf_error = VF_ERR_UNCOMPRESS;
194
strcpy(charset_name, "");
195
strcpy(charset_enc, "");
196
bdf->char_table = NULL;
197
bdf->char_table_x = NULL;
198
have_fontboundingbox = 0;
199
bdf->font_bbx_width = 0;
200
bdf->font_bbx_height = 0;
201
bdf->font_bbx_xoff = 0;
202
bdf->font_bbx_yoff = 0;
207
printf(">> BDF reading header\n");
210
if (fgets(linebuf, sizeof(linebuf), fp) == NULL){
211
vf_error = VF_ERR_ILL_FONT_FILE;
212
goto Unexpected_Error;
214
{ int l = strlen(linebuf);
215
if ((l > 0) && (linebuf[l-1] == '\n'))
218
if (strncmp(linebuf, "ENDPROPERTIES", 13) == 0)
220
if (strncmp(linebuf, "STARTFONT", 9) == 0)
222
if (strncmp(linebuf, "COMMENT", 7) == 0)
227
for (x = strlen(linebuf)-1; x >= 0; x--){
238
char *prop_name, *prop_value, *p, *p0, c0;
241
for (p = linebuf; (c0 = *p) != '\0'; p++)
242
if (isspace((int)c0))
248
while (isspace((int)(*p)))
255
if (prop_value[0] == '"'){
256
prop_value = &prop_value[1];
257
prop_value[strlen(prop_value)-1] = '\0';
259
bdf->props = vf_sexp_alist_put(prop_name, prop_value, bdf->props);
261
printf(">> BDF Prop \"%s\" = \"%s\"\n", prop_name, prop_value);
267
printf("*** %s\n", linebuf);
269
if (strncmp(linebuf, "SIZE", 4) == 0){
270
sscanf(linebuf, "%*s%lf%lf%lf",
271
&bdf->point_size, &bdf->dpi_x, &bdf->dpi_y);
272
bdf->size = bdf->point_size;
273
} else if (strncmp(linebuf, "FONTBOUNDINGBOX", 15) == 0){
274
sscanf(linebuf, "%*s%d%d%d%d",
275
&bdf->font_bbx_width, &bdf->font_bbx_height,
276
&bdf->font_bbx_xoff, &bdf->font_bbx_yoff);
277
have_fontboundingbox = 1;
278
} else if (strncmp(linebuf, "CHARSET_REGISTRY", 16) == 0){
279
sscanf(linebuf, "%*s%s", prop_string);
280
if (prop_string[0] == '"'){ /* ignore `"' */
281
prop_string[strlen(prop_string)] = '\0';
282
name = &prop_string[1];
285
strncpy(charset_name, name, sizeof(charset_name));
286
} else if (strncmp(linebuf, "CHARSET_ENCODING", 16) == 0){
287
sscanf(linebuf, "%*s%s", prop_string);
288
if (prop_string[0] == '"'){/* ignore `"' */
289
prop_string[strlen(prop_string)] = '\0';
290
name = &prop_string[1];
293
strncpy(charset_enc, name, sizeof(charset_enc));
294
} else if (strncmp(linebuf, "PIXEL_SIZE", 10) == 0){
295
sscanf(linebuf, "%*s%d", &bdf->pixel_size);
296
} else if (strncmp(linebuf, "POINT_SIZE", 10) == 0){
297
sscanf(linebuf, "%*s%lf", &bdf->point_size);
298
bdf->point_size = bdf->point_size / 10.0;
299
} else if (strncmp(linebuf, "RESOLUTION_X", 12) == 0){
300
sscanf(linebuf, "%*s%lf", &bdf->dpi_x);
301
} else if (strncmp(linebuf, "RESOLUTION_Y", 12) == 0){
302
sscanf(linebuf, "%*s%lf", &bdf->dpi_y);
303
} else if (strncmp(linebuf, "FONT_ASCENT", 11) == 0){
304
sscanf(linebuf, "%*s%d", &bdf->ascent);
305
} else if (strncmp(linebuf, "FONT_DESCENT", 12) == 0){
306
sscanf(linebuf, "%*s%d", &bdf->descent);
307
} else if (strncmp(linebuf, "SLANT", 5) == 0){
308
sscanf(linebuf, "%*s%s", prop_string);
309
if (prop_string[0] == '"'){ /* ignore `"' */
310
prop_string[strlen(prop_string)] = '\0';
311
name = &prop_string[1];
314
for (p = name; *p != '\0'; p++)
317
if ((strcmp(name, "I") == 0) || (strcmp(name, "O") == 0)){
319
} else if ((strcmp(name, "RI") == 0) || (strcmp(name, "RO") == 0)){
324
if ((strcmp(charset_enc, "") != 0) && ((strcmp(charset_enc, "0") != 0)))
325
sprintf(charset, "%s-%s", charset_name, charset_enc);
327
sprintf(charset, "%s", charset_name);
329
printf(">> BDF Charset (ID=%d) %s\n", bdf->charset, charset);
332
bdf->dpi_x = DEFAULT_DPI;
334
bdf->dpi_y = DEFAULT_DPI;
337
if (fgets(linebuf, sizeof(linebuf), fp) == NULL){
338
vf_error = VF_ERR_ILL_FONT_FILE;
339
goto Unexpected_Error;
341
if (strncmp(linebuf, "CHARS", 5) == 0){
342
sscanf(linebuf, "%*s%d", &bdf->nchars);
343
if (bdf->nchars < 0){
344
vf_error = VF_ERR_ILL_FONT_FILE;
345
goto Unexpected_Error;
347
vf_free(bdf->char_table);
348
ALLOCN_IF_ERR(bdf->char_table, struct s_bdf_char, bdf->nchars){
349
vf_error = VF_ERR_NO_MEMORY;
350
goto Unexpected_Error;
352
vf_free(bdf->char_table_x);
353
ALLOCN_IF_ERR(bdf->char_table_x, long, bdf->nchars){
354
vf_error = VF_ERR_NO_MEMORY;
355
goto Unexpected_Error;
357
for (ch_index = 0; ch_index < bdf->nchars; ch_index++)
358
bdf->char_table_x[ch_index] = ch_index;
364
printf(">> BDF reading chars\n");
369
for (ch_index = 0; ch_index < bdf->nchars; ch_index++){
372
if (fgets(linebuf, sizeof(linebuf), fp) == NULL){
373
vf_error = VF_ERR_ILL_FONT_FILE;
374
goto Unexpected_Error;
376
if (strncmp(linebuf, "ENDFONT", 7) == 0)
378
if (strncmp(linebuf, "STARTCHAR", 9) == 0)
381
bdf->char_table[ch_index].f_offset = -1;
382
bdf->char_table[ch_index].bbx_width = -1;
383
bdf->char_table[ch_index].bbx_height = -1;
384
bdf->char_table[ch_index].off_x = 0;
385
bdf->char_table[ch_index].off_y = 0;
386
bdf->char_table[ch_index].mv_x = 0;
387
bdf->char_table[ch_index].mv_y = 0;
388
bdf->char_table[ch_index].bitmap = NULL;
390
if (fgets(linebuf, sizeof(linebuf), fp) == NULL){
391
vf_error = VF_ERR_ILL_FONT_FILE;
392
goto Unexpected_Error;
394
if (strncmp(linebuf, "ENDCHAR", 7) == 0)
396
if (strncmp(linebuf, "ENCODING", 8) == 0){
397
sscanf(linebuf, "%*s%ld", &code_point);
400
bdf->char_table[ch_index].code_point = code_point;
402
if ((code_point % 0x21) == 0)
403
printf("BDF Reading Char: Encoding=0x%x\n", code_point);
405
} else if (STRCMP(linebuf, "BBX") == 0){
406
sscanf(linebuf, "%*s%d%d%d%d",
407
&bdf->char_table[ch_index].bbx_width,
408
&bdf->char_table[ch_index].bbx_height,
409
&bdf->char_table[ch_index].off_x,
410
&bdf->char_table[ch_index].off_y);
411
if (have_fontboundingbox == 0){
412
if (bdf->font_bbx_width < bdf->char_table[ch_index].bbx_width)
413
bdf->font_bbx_width = bdf->char_table[ch_index].bbx_width;
414
if (bdf->font_bbx_height < bdf->char_table[ch_index].bbx_height)
415
bdf->font_bbx_height = bdf->char_table[ch_index].bbx_height;
417
} else if (strncmp(linebuf, "DWIDTH", 6) == 0){
418
sscanf(linebuf, "%*s%d%d",
419
&bdf->char_table[ch_index].mv_x,
420
&bdf->char_table[ch_index].mv_y);
421
} else if (strncmp(linebuf, "BITMAP", 6) == 0){
422
if ((bdf->uncompress != NULL)
423
|| (bdf->nchars < 512)){ /* LOAD BITMAP */
424
bdf->char_table[ch_index].f_offset = 0L;
425
if (read_bitmap(&bdf->char_table[ch_index], fp) == NULL)
426
goto Unexpected_Error;
427
} else { /* LAZY BITMAP LOADING */
428
bdf->char_table[ch_index].f_offset = (long)ftell(fp);
429
bdf->char_table[ch_index].bitmap = NULL;
430
for (i = 1; i <= bdf->char_table[ch_index].bbx_height; i++){
431
if (fgets(linebuf, sizeof(linebuf), fp) == NULL){
432
vf_error = VF_ERR_ILL_FONT_FILE;
433
goto Unexpected_Error;
438
; /* ignore other keywords */
441
if ( (bdf->char_table[ch_index].code_point < 0L)
442
|| (bdf->char_table[ch_index].f_offset < 0)
443
|| (bdf->char_table[ch_index].bbx_width < 0)
444
|| (bdf->char_table[ch_index].bbx_height < 0) ){
445
vf_error = VF_ERR_ILL_FONT_FILE;
449
if (bdf->char_table[ch_index].code_point < last_ch)
451
last_ch = bdf->char_table[ch_index].code_point;
455
bdf->nchars = nchars;
456
if (need_sorting == 1){ /* for binary search */
458
printf(">> BDF sorting\n");
459
bdf_sort_index(bdf, 0, ch_index-1);
462
printf(">> BDF need not sorting\n");
465
for (i = 0; i <= bdf->nchars; i++){
466
printf("** %d 0x%x\n",
467
i, bdf->char_table[bdf->char_table_x[i]].code_point);
471
if ((bdf->uncompress != NULL) && (fp != NULL))
472
vf_close_uncompress_stream(fp);
475
printf(">> BDF done\n");
481
if (bdf->uncompress != NULL)
482
vf_close_uncompress_stream(fp);
483
if (bdf->char_table != NULL){
484
for (ch_index = 0; ch_index < bdf->nchars; ch_index++)
485
vf_free(bdf->char_table[ch_index].bitmap);
487
vf_free(bdf->char_table);
488
vf_free(bdf->char_table_x);
489
bdf->char_table = NULL;
490
bdf->char_table_x = NULL;
499
bdf_sort_index(BDF bdf, int x, int y)
501
int gap, i, j, temp, len;
505
cht = bdf->char_table;
506
chx = bdf->char_table_x;
509
for (gap = len/2; gap > 0; gap = gap / 2){
510
for (i = gap; i < len; i++){
512
(j >= 0) && (cht[chx[j]].code_point > cht[chx[j+gap]].code_point);
528
bdf_sort_index(BDF bdf, int x, int y)
535
z = bdf_partition(bdf, x, y);
538
printf("** %d(%d) %d(%d) %d(%d)\n",
539
x, bdf->char_table[bdf->char_table_x[x]].code_point,
540
z, bdf->char_table[bdf->char_table_x[z]].code_point,
541
y, bdf->char_table[bdf->char_table_x[y]].code_point);
545
(void) bdf_sort_index(bdf, x, z-1);
549
/*(void) bdf_sort_index(bdf, z+1, y);*/
559
bdf_partition(BDF bdf, int x, int y)
566
cht = bdf->char_table;
567
chx = bdf->char_table_x;
569
t = cht[chx[x]].code_point;
576
if (cht[chx[i]].code_point < t){
577
/* swap( d[i], d[p+1]) */
590
BDF_GetBitmap(int bdf_id, long code_point)
597
if ((bdf = BDF_GetBDF(bdf_id)) == NULL){
598
fprintf(stderr, "VFlib internal error: BDF_GetBitmap()\n");
599
vf_error = VF_ERR_INTERNAL;
603
if ((index = bdf_char_index(bdf, code_point)) < 0){
604
vf_error = VF_ERR_ILL_CODE_POINT;
607
bdf_char = &bdf->char_table[index];
609
if (bdf_char->bitmap != NULL)
612
if ((fp = vf_fm_OpenTextFileStream(bdf->path_name)) == NULL){
613
/* --- font file is lost (maybe) */
614
vf_error = VF_ERR_NO_FONT_FILE;
617
fseek(fp, bdf_char->f_offset, SEEK_SET);
618
return read_bitmap(bdf_char, fp);
621
#define X_TO_D(c) ((isxdigit((int)(c)))?(Xc_To_Dec_Tbl[c-0x30]):16)
622
Private int Xc_To_Dec_Tbl[] = { /* (BDF files are encoded by ASCII) */
623
/* +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F */
624
/*30*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, /* 0,1,2,3,... */
625
/*40*/ -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* @,a,b,c,... */
626
/*50*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
627
/*60*/ -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1};/* `,A,B,C,... */
630
read_bitmap(BDF_CHAR bdf_char, FILE *fp)
633
char linebuf[(2*2048)/8]; /* Is this really enough? */
634
unsigned char ch1, ch2, *bmp, *lbp;
636
bdf_char->raster = (bdf_char->bbx_width+7)/8;
637
bm_size = bdf_char->raster * bdf_char->bbx_height;
638
if ((bdf_char->bitmap = (unsigned char*)calloc(1, bm_size)) == NULL){
639
vf_error = VF_ERR_NO_MEMORY;
642
bmp = bdf_char->bitmap;
643
for (h = 0; h < bdf_char->bbx_height; h++){
644
if (fgets(linebuf, sizeof(linebuf), fp) == NULL){
645
vf_free(bdf_char->bitmap);
646
bdf_char->bitmap = NULL;
647
vf_error = VF_ERR_ILL_FONT_FILE;
650
for (i = 0, lbp = (unsigned char *)linebuf; i < bdf_char->raster; i++){
653
*(bmp++) = X_TO_D(ch1)*16 + X_TO_D(ch2);
660
bdf_char_index(BDF bdf, long code_point)
662
int hi, lo, m, x1, x2;
664
x1 = bdf->char_table_x[0];
665
x2 = bdf->char_table_x[bdf->nchars-1];
666
if ((code_point < bdf->char_table[x1].code_point)
667
|| (bdf->char_table[x2].code_point < code_point))
676
m = (lo+hi)/2; /*printf("lo=%d hi=%d m=%d\n", lo, hi, m);*/
677
if (bdf->char_table[bdf->char_table_x[m]].code_point < code_point)
682
if (bdf->char_table[bdf->char_table_x[hi]].code_point != code_point)
685
return bdf->char_table_x[hi];
690
BDF_GetProp(BDF bdf, char *name)
695
if ((v = vf_sexp_assoc(name, bdf->props)) == NULL)
697
if ((r = vf_strdup(vf_sexp_get_cstring(vf_sexp_cadr(v)))) == NULL){
698
vf_error = VF_ERR_NO_MEMORY;
702
return r; /* CALLER MUST RELEASE THIS STRING LATER */
707
BDF_GetBDFChar(BDF bdf, long code_point)
711
if ((index = bdf_char_index(bdf, code_point)) < 0){
712
vf_error = VF_ERR_ILL_CODE_POINT;
715
return &bdf->char_table[index];