src/bdf.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. BDF_Init
  2. BDF_Open
  3. BDF_Close
  4. bdf_release
  5. bdf_load_file
  6. bdf_sort_index
  7. bdf_sort_index
  8. bdf_partition
  9. BDF_GetBitmap
  10. X_TO_D
  11. read_bitmap
  12. bdf_char_index
  13. BDF_GetProp
  14. BDF_GetBDFChar

   1 /*
   2  * bdf.c - low level bdf file interface 
   3  * by Hirotsugu Kakugawa
   4  *
   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. 
   9  */
  10 /*
  11  * Copyright (C) 1996-1998  Hirotsugu Kakugawa. 
  12  * All rights reserved.
  13  *
  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.
  25  */
  26 
  27 
  28 
  29 Private VF_TABLE       bdf_table       = NULL;
  30 
  31 
  32 Private int
  33 BDF_Init(void)
     /* [<][>][^][v][top][bottom][index][help] */
  34 {
  35   static int init_flag = 0;
  36 
  37   if (init_flag == 0){
  38     init_flag = 1;
  39     BDF_GetBDF(-1);
  40     if ((bdf_table = vf_table_create()) == NULL){
  41       vf_error = VF_ERR_NO_MEMORY;
  42       return -1;
  43     }
  44   }
  45 
  46   return 0;
  47 }
  48 
  49 
  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);
  56 
  57 Private int
  58 BDF_Open(char *font_file, SEXP fontdirs)
     /* [<][>][^][v][top][bottom][index][help] */
  59 {
  60   char   *path_name, *uncomp_prog;
  61   int     bdf_id;
  62   BDF     bdf;
  63 
  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;
  68     return -1;
  69   }
  70 
  71   if (bdf_debug('F')){
  72     printf("BDF Font File: %s ==> %s\n", font_file, path_name);
  73   }
  74 
  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);
  80     vf_free(path_name);
  81     return bdf_id;
  82   }
  83 
  84 
  85   ALLOC_IF_ERR(bdf, struct s_bdf){
  86     vf_error = VF_ERR_NO_MEMORY;
  87     vf_free(path_name);
  88     return -1;
  89   }
  90 
  91   bdf->point_size   = -1;
  92   bdf->pixel_size   = -1;
  93   bdf->size         = -1;
  94   bdf->dpi_x        = -1;
  95   bdf->dpi_y        = -1;
  96   bdf->nchars       = 0;
  97   bdf->char_table   = NULL;
  98   bdf->char_table_x = NULL;
  99   bdf->path_name    = path_name;
 100   bdf->uncompress   = NULL;
 101   bdf->props        = NULL;
 102 
 103   if ((uncomp_prog != NULL) &&
 104       ((bdf->uncompress = vf_strdup(uncomp_prog)) == NULL)){
 105     vf_error = VF_ERR_NO_MEMORY;
 106     goto Error;
 107   }
 108   if ((bdf->props = vf_sexp_empty_list()) == NULL){
 109     vf_error = VF_ERR_NO_MEMORY;
 110     goto Error;
 111   }
 112 
 113   if (bdf_load_file(bdf) < 0)
 114     goto Error;
 115 
 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;
 119     goto Error;
 120   }
 121 
 122   BDF_SetBDF(bdf_id, bdf);
 123 
 124   return bdf_id;
 125 
 126 Error:
 127   bdf_release(bdf);
 128   return -1;
 129 }
 130 
 131 
 132 Private void
 133 BDF_Close(int bdf_id)
     /* [<][>][^][v][top][bottom][index][help] */
 134 {
 135   BDF  bdf;
 136 
 137   if ((bdf = BDF_GetBDF(bdf_id)) == NULL){
 138     fprintf(stderr, "VFlib internal error: BDF_Close()\n");
 139     vf_error = VF_ERR_INTERNAL;
 140     return;
 141   }
 142   if ((bdf_table->unlink_by_id)(bdf_table, bdf_id) > 0){
 143     return;
 144   }
 145 
 146   bdf_release(bdf);
 147 }
 148 
 149 
 150 Private void
 151 bdf_release(BDF bdf)
     /* [<][>][^][v][top][bottom][index][help] */
 152 {
 153   int  ch;
 154 
 155   if (bdf != NULL){
 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);
 161     }
 162     vf_free(bdf->char_table);
 163     vf_free(bdf->char_table_x);
 164     vf_sexp_free(&bdf->props);
 165     vf_free(bdf);
 166   }
 167   BDF_GetBDF(-1);
 168 }
 169 
 170 
 171 Private int
 172 bdf_load_file(BDF bdf)
     /* [<][>][^][v][top][bottom][index][help] */
 173 {
 174   FILE   *fp;
 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;
 180 
 181   if (bdf->uncompress == NULL){
 182     if ((fp = vf_fm_OpenTextFileStream(bdf->path_name)) == NULL){
 183       vf_error = VF_ERR_NO_FONT_FILE;
 184       return -1;
 185     } 
 186   } else {
 187     if ((fp = vf_open_uncompress_stream(bdf->path_name, 
 188                                         bdf->uncompress)) == NULL){
 189       vf_error = VF_ERR_UNCOMPRESS;
 190       return -1;
 191     } 
 192   }
 193 
 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;
 203   bdf->ascent  = 0;
 204   bdf->descent = 0;
 205 
 206   if (bdf_debug('R'))
 207     printf(">> BDF reading header\n");
 208 
 209   for (;;){
 210     if (fgets(linebuf, sizeof(linebuf), fp) == NULL){
 211       vf_error = VF_ERR_ILL_FONT_FILE;
 212       goto Unexpected_Error;
 213     }
 214     { int l = strlen(linebuf);
 215       if ((l > 0) && (linebuf[l-1] == '\n'))
 216         linebuf[l-1] = '\0';
 217     }
 218     if (strncmp(linebuf, "ENDPROPERTIES", 13) == 0)
 219       break;
 220     if (strncmp(linebuf, "STARTFONT", 9) == 0)
 221       continue;
 222     if (strncmp(linebuf, "COMMENT", 7) == 0)
 223       continue;
 224 
 225 #if 0
 226     { int  x;
 227       for (x = strlen(linebuf)-1; x >= 0; x--){
 228         switch (linebuf[x]){
 229         case '\n':
 230         case '\r':
 231           linebuf[x] = '\0';
 232         }
 233       }
 234     }
 235 #endif
 236 
 237     {
 238       char *prop_name, *prop_value, *p, *p0, c0;
 239 
 240       prop_name = linebuf;
 241       for (p = linebuf; (c0 = *p) != '\0'; p++)
 242         if (isspace((int)c0))
 243           break;
 244       p0 = p;
 245       *p = '\0';
 246       if (c0 != '\0'){
 247         p++;
 248         while (isspace((int)(*p)))
 249           p++;
 250       }
 251       if (*p == '\0'){
 252         prop_value = "";
 253       } else {
 254         prop_value = p;
 255         if (prop_value[0] == '"'){
 256           prop_value = &prop_value[1];
 257           prop_value[strlen(prop_value)-1] = '\0';
 258         }
 259         bdf->props = vf_sexp_alist_put(prop_name, prop_value, bdf->props);
 260         if (bdf_debug('P'))
 261           printf(">> BDF Prop \"%s\" = \"%s\"\n", prop_name, prop_value);
 262       }
 263       *p0 = c0;
 264     }
 265 
 266 #if 0
 267     printf("*** %s\n", linebuf);
 268 #endif
 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];
 283       } else
 284         name = prop_string;
 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];          
 291       } else
 292         name = prop_string;
 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];          
 312       } else
 313         name = prop_string;
 314       for (p = name; *p != '\0'; p++)
 315         *p = toupper(*p);
 316       bdf->slant = 0.0;
 317       if ((strcmp(name, "I") == 0) || (strcmp(name, "O") == 0)){
 318         bdf->slant = 0.17;
 319       } else if ((strcmp(name, "RI") == 0) || (strcmp(name, "RO") == 0)){
 320         bdf->slant = -0.17;
 321       }
 322     }
 323   }
 324   if ((strcmp(charset_enc, "") != 0) && ((strcmp(charset_enc, "0") != 0)))
 325     sprintf(charset, "%s-%s", charset_name, charset_enc); 
 326   else
 327     sprintf(charset, "%s", charset_name); 
 328   if (bdf_debug('C'))
 329     printf(">> BDF Charset (ID=%d) %s\n", bdf->charset, charset);
 330 
 331   if (bdf->dpi_x < 0)
 332     bdf->dpi_x = DEFAULT_DPI;
 333   if (bdf->dpi_y < 0)
 334     bdf->dpi_y = DEFAULT_DPI;
 335 
 336   for (;;){
 337     if (fgets(linebuf, sizeof(linebuf), fp) == NULL){
 338       vf_error = VF_ERR_ILL_FONT_FILE;
 339       goto Unexpected_Error;
 340     }
 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;
 346       }
 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;
 351       }
 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;
 356       }
 357       for (ch_index = 0; ch_index < bdf->nchars; ch_index++)
 358         bdf->char_table_x[ch_index] = ch_index;
 359       break;
 360     }
 361   }
 362 
 363   if (bdf_debug('R'))
 364     printf(">> BDF reading chars\n");
 365 
 366   last_ch = -1L;
 367   nchars = 0;
 368   need_sorting = 0;
 369   for (ch_index = 0; ch_index < bdf->nchars; ch_index++){
 370 NextChar:
 371     for (;;){
 372       if (fgets(linebuf, sizeof(linebuf), fp) == NULL){
 373         vf_error = VF_ERR_ILL_FONT_FILE;
 374         goto Unexpected_Error;
 375       }
 376       if (strncmp(linebuf, "ENDFONT", 7) == 0)
 377         goto EndFont;
 378       if (strncmp(linebuf, "STARTCHAR", 9) == 0)
 379         break;
 380     }
 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;
 389     for (;;){
 390       if (fgets(linebuf, sizeof(linebuf), fp) == NULL){
 391         vf_error = VF_ERR_ILL_FONT_FILE;
 392         goto Unexpected_Error;
 393       }
 394       if (strncmp(linebuf, "ENDCHAR", 7) == 0)
 395         break;
 396       if (strncmp(linebuf, "ENCODING", 8) == 0){
 397         sscanf(linebuf, "%*s%ld", &code_point);
 398         if (code_point < 0L)
 399           goto NextChar;
 400         bdf->char_table[ch_index].code_point = code_point;
 401 #if 0
 402         if ((code_point % 0x21) == 0)
 403           printf("BDF Reading Char: Encoding=0x%x\n", code_point);
 404 #endif
 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;
 416         }
 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;
 434             }
 435           }
 436         }
 437       } else {
 438         ;  /* ignore other keywords */
 439       }
 440     } /* end char */
 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;
 446       break;
 447     }
 448     nchars++;
 449     if (bdf->char_table[ch_index].code_point < last_ch)
 450       need_sorting = 1;
 451     last_ch = bdf->char_table[ch_index].code_point;
 452   }
 453 
 454 EndFont:
 455   bdf->nchars = nchars;
 456   if (need_sorting == 1){ /* for binary search */
 457     if (bdf_debug('R'))
 458       printf(">> BDF sorting\n");
 459     bdf_sort_index(bdf, 0, ch_index-1);
 460   } else {
 461     if (bdf_debug('R'))
 462       printf(">> BDF need not sorting\n");
 463   }
 464 #if 0
 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);
 468   }
 469 #endif
 470 
 471   if ((bdf->uncompress != NULL) && (fp != NULL))
 472     vf_close_uncompress_stream(fp);
 473 
 474   if (bdf_debug('R'))
 475     printf(">> BDF done\n");
 476 
 477   return 0; 
 478 
 479 
 480 Unexpected_Error:
 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);
 486   }
 487   vf_free(bdf->char_table);
 488   vf_free(bdf->char_table_x);
 489   bdf->char_table = NULL;
 490   bdf->char_table_x = NULL;
 491   
 492   return -1;
 493 }
 494 
 495 #if 0
 496 
 497 /* Shell sort */
 498 Private int
 499 bdf_sort_index(BDF bdf, int x, int y)
     /* [<][>][^][v][top][bottom][index][help] */
 500 {
 501   int    gap, i, j, temp, len;
 502   long     *chx;
 503   BDF_CHAR  cht;
 504 
 505   cht = bdf->char_table;
 506   chx = bdf->char_table_x;
 507 
 508   len = bdf->nchars;
 509   for (gap = len/2; gap > 0; gap = gap / 2){
 510     for (i = gap; i < len; i++){
 511       for (j = i - gap; 
 512            (j >= 0) && (cht[chx[j]].code_point > cht[chx[j+gap]].code_point);
 513            j -= gap){
 514         temp = chx[j];
 515         chx[j] = chx[j+gap];
 516         chx[j+gap] = temp;
 517       }
 518     }
 519   }
 520 
 521   return 0;
 522 }
 523 
 524 #else
 525 
 526 /* Quick sort */ 
 527 Private int
 528 bdf_sort_index(BDF bdf, int x, int y)
     /* [<][>][^][v][top][bottom][index][help] */
 529 {
 530   int      z;
 531 
 532 Loop:
 533 
 534   if (x < y){
 535     z = bdf_partition(bdf, x, y);
 536 
 537 #if 0
 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);
 542 #endif
 543 
 544     if (x < z-1){
 545       (void) bdf_sort_index(bdf, x,   z-1);
 546     }
 547 
 548     if (z+1 < y){
 549       /*(void) bdf_sort_index(bdf, z+1, y);*/
 550       x = z+1; 
 551       goto Loop;
 552     }
 553 
 554   }
 555   return 0;
 556 }
 557 
 558 Private int
 559 bdf_partition(BDF bdf, int x, int y)
     /* [<][>][^][v][top][bottom][index][help] */
 560 {
 561   long      t;
 562   int       i, p, tmp;
 563   BDF_CHAR  cht;
 564   long     *chx;
 565 
 566   cht = bdf->char_table;
 567   chx = bdf->char_table_x;
 568 
 569   t = cht[chx[x]].code_point;
 570   i = x+1; 
 571   p = x;
 572 
 573   for (;;){
 574     if (y < i)
 575       return p;
 576     if (cht[chx[i]].code_point < t){
 577       /* swap( d[i], d[p+1]) */
 578       tmp = chx[i];
 579       chx[i] = chx[p+1];
 580       chx[p+1] = tmp;
 581       i++; p++;
 582     } else {
 583       i++;
 584     }
 585   }
 586 }
 587 #endif
 588 
 589 Private BDF_CHAR
 590 BDF_GetBitmap(int bdf_id, long code_point)
     /* [<][>][^][v][top][bottom][index][help] */
 591 {
 592   int            index;
 593   FILE           *fp;
 594   BDF            bdf;
 595   BDF_CHAR       bdf_char;
 596  
 597   if ((bdf = BDF_GetBDF(bdf_id)) == NULL){
 598     fprintf(stderr, "VFlib internal error: BDF_GetBitmap()\n");
 599     vf_error = VF_ERR_INTERNAL;
 600     return NULL;
 601   }
 602 
 603   if ((index = bdf_char_index(bdf, code_point)) < 0){
 604     vf_error = VF_ERR_ILL_CODE_POINT;
 605     return NULL;
 606   }
 607   bdf_char = &bdf->char_table[index];
 608 
 609   if (bdf_char->bitmap != NULL)
 610     return bdf_char;
 611 
 612   if ((fp = vf_fm_OpenTextFileStream(bdf->path_name)) == NULL){
 613     /* --- font file is lost (maybe) */
 614     vf_error = VF_ERR_NO_FONT_FILE;
 615     return NULL;
 616   }
 617   fseek(fp, bdf_char->f_offset, SEEK_SET);
 618   return read_bitmap(bdf_char, fp);
 619 }
 620 
 621 #define X_TO_D(c)     ((isxdigit((int)(c)))?(Xc_To_Dec_Tbl[c-0x30]):16)
     /* [<][>][^][v][top][bottom][index][help] */
 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,... */
 628 
 629 Private BDF_CHAR
 630 read_bitmap(BDF_CHAR bdf_char, FILE *fp)
     /* [<][>][^][v][top][bottom][index][help] */
 631 {
 632   int            bm_size, h, i;
 633   char           linebuf[(2*2048)/8];       /* Is this really enough? */
 634   unsigned char  ch1, ch2, *bmp, *lbp;
 635 
 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;
 640     return NULL;
 641   }
 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;
 648       return NULL;
 649     }
 650     for (i = 0, lbp = (unsigned char *)linebuf; i < bdf_char->raster; i++){
 651       ch1 = *(lbp++);
 652       ch2 = *(lbp++);
 653       *(bmp++) = X_TO_D(ch1)*16 + X_TO_D(ch2);
 654     }
 655   }
 656   return bdf_char;
 657 }
 658 
 659 Private int
 660 bdf_char_index(BDF bdf, long code_point)
     /* [<][>][^][v][top][bottom][index][help] */
 661 {
 662   int   hi, lo, m, x1, x2;
 663 
 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))
 668     return -1;
 669   
 670   /* binary search */
 671   lo = 0;
 672   hi = bdf->nchars;
 673   if (lo >= hi)
 674     return -1;
 675   while (lo < hi){
 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)
 678       lo = m+1;
 679     else 
 680       hi = m;
 681   }
 682   if (bdf->char_table[bdf->char_table_x[hi]].code_point != code_point)
 683     return -1;
 684 
 685   return bdf->char_table_x[hi];
 686 }
 687 
 688 
 689 Private char*
 690 BDF_GetProp(BDF bdf, char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 691 {
 692   SEXP  v;
 693   char  *r;
 694 
 695   if ((v = vf_sexp_assoc(name, bdf->props)) == NULL)
 696     return NULL;
 697   if ((r = vf_strdup(vf_sexp_get_cstring(vf_sexp_cadr(v)))) == NULL){
 698     vf_error = VF_ERR_NO_MEMORY;
 699     return NULL;
 700   }
 701 
 702   return r;     /* CALLER MUST RELEASE THIS STRING LATER */
 703 }
 704 
 705 
 706 Private BDF_CHAR
 707 BDF_GetBDFChar(BDF bdf, long code_point)
     /* [<][>][^][v][top][bottom][index][help] */
 708 {
 709   int  index;
 710 
 711   if ((index = bdf_char_index(bdf, code_point)) < 0){
 712     vf_error = VF_ERR_ILL_CODE_POINT;
 713     return NULL;
 714   }
 715   return &bdf->char_table[index];
 716 }
 717 
 718 
 719 /*EOF*/

/* [<][>][^][v][top][bottom][index][help] */