src/pcf.c

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

FUNCTIONS

This source file includes following functions.
  1. PCF_Init
  2. PCF_Open
  3. PCF_Close
  4. pcf_release
  5. pcf_load_file
  6. pcf_read_toc
  7. pcf_read_props
  8. pcf_read_metrics
  9. pcf_read_metric_item
  10. pcf_read_compressed_metric_item
  11. pcf_read_bitmaps
  12. pcf_read_ink_metrics
  13. pcf_read_encodings
  14. pcf_read_accel
  15. pcf_seek_to_type
  16. pcf_type_index
  17. pcf_bit_order_invert
  18. pcf_swap_2byte
  19. pcf_swap_4byte
  20. pcf_skip_file
  21. pcf_read_lsb4
  22. pcf_read_int4
  23. pcf_read_int2
  24. pcf_read_int1
  25. pcf_read_nbyte
  26. PCF_GetBitmap
  27. pcf_char_index
  28. PCF_GetProp
  29. PCF_GetPCFChar

   1 /*
   2  * pcf.c - a low level interface for PCF format fonts
   3  * by Hirotsugu Kakugawa
   4  *
   5  * 25 Apr 1997  Added multiple file extension feature.
   6  * 23 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  pcf_table       = NULL;
  30 
  31 
  32 Private int
  33 PCF_Init(void)
     /* [<][>][^][v][top][bottom][index][help] */
  34 {
  35   PCF_GetPCF(-1);
  36 
  37   if ((pcf_table = vf_table_create()) == NULL){
  38     vf_error = VF_ERR_NO_MEMORY;
  39     return -1;
  40   }
  41 
  42   return 0;
  43 }
  44 
  45 
  46 Private void   pcf_release(PCF);
  47 Private int    pcf_char_index(PCF,long);
  48 Private int    pcf_load_file(PCF);
  49 Private PCF_TABLE  pcf_read_toc(FILE*,int*);
  50 Private int          pcf_read_props(PCF,FILE*,PCF_TABLE,int);
  51 Private int          pcf_read_metrics(PCF,FILE*,PCF_TABLE,int);
  52 Private void           pcf_read_metric_item(FILE*,INT4,PCF_CHAR);
  53 Private void           pcf_read_compressed_metric_item(FILE*,INT4,PCF_CHAR);
  54 Private int          pcf_read_bitmaps(PCF,FILE*,PCF_TABLE,int);
  55 Private int          pcf_read_ink_metrics(PCF,FILE*,PCF_TABLE,int);
  56 Private int          pcf_read_encodings(PCF,FILE*,PCF_TABLE,int);
  57 Private int          pcf_read_accel(PCF,FILE*,PCF_TABLE,int,INT4);
  58 Private PCF_TABLE  pcf_seek_to_type(FILE*,PCF_TABLE,int,int);
  59 Private int        pcf_type_index(PCF_TABLE,int,int);
  60 Private void       pcf_bit_order_invert(unsigned char*,int);
  61 Private void       pcf_swap_2byte(unsigned char*,int);
  62 Private void       pcf_swap_4byte(unsigned char*,int);
  63 Private int    pcf_skip_file(FILE*,long);
  64 Private INT4   pcf_read_lsb4(FILE*);
  65 Private INT4   pcf_read_int4(FILE*,INT4);
  66 Private INT4   pcf_read_int2(FILE*,INT4);
  67 Private INT4   pcf_read_int1(FILE*,INT4);
  68 Private int    pcf_read_nbyte(FILE*,unsigned char*,int);
  69 
  70 Private int
  71 PCF_Open(char *font_file, SEXP fontdirs)
     /* [<][>][^][v][top][bottom][index][help] */
  72 {
  73   char   *path_name, *uncomp_prog;
  74   int     pcf_id;
  75   PCF     pcf;
  76 
  77   path_name = vf_search_file(font_file, -1, NULL, FALSE, -1, fontdirs, 
  78                              default_compressed_ext, &uncomp_prog);
  79   if (path_name == NULL){
  80     vf_error = VF_ERR_NO_FONT_FILE;
  81     return -1;
  82   }
  83 
  84   if (pcf_debug('F')){
  85     printf("PCF Font File: %s ==> %s\n", font_file, path_name);
  86   }
  87 
  88   /* Check the cache here. (Never forget that the fontdir is 
  89    * not always the same. */
  90   if ((pcf_id = (pcf_table->get_id_by_key)(pcf_table, path_name, 
  91                                            strlen(path_name)+1)) >= 0){
  92     vf_free(path_name);
  93     if ((pcf = PCF_GetPCF(pcf_id)) == NULL){
  94       fprintf(stderr, "VFlib internal error: in PCF_Open()\n");
  95       abort();
  96     }
  97     (pcf_table->link_by_id)(pcf_table, pcf_id);
  98     return pcf_id;
  99   }
 100 
 101   ALLOC_IF_ERR(pcf, struct s_pcf){
 102     vf_free(path_name);
 103     vf_error = VF_ERR_NO_MEMORY;
 104     return -1;
 105   }
 106 
 107   pcf->point_size   = -1;
 108   pcf->pixel_size   = -1;
 109   pcf->size         = -1;
 110   pcf->ascent       = -1;
 111   pcf->descent      = -1;
 112   pcf->dpi_x        = -1;
 113   pcf->dpi_y        = -1;
 114   pcf->nchars       = 0;
 115   pcf->char_table   = NULL;
 116   pcf->bitmap_block = NULL;
 117   pcf->encoding     = NULL;
 118   pcf->font_bbx_width  = 0;
 119   pcf->font_bbx_height = 0;
 120   pcf->font_bbx_xoff   = 0;
 121   pcf->font_bbx_yoff   = 0;
 122   pcf->path_name    = path_name;
 123   pcf->uncompress   = NULL;
 124   pcf->props        = NULL;
 125 
 126   if ((uncomp_prog != NULL) &&
 127       ((pcf->uncompress = vf_strdup(uncomp_prog)) == NULL)){
 128     vf_error = VF_ERR_NO_MEMORY;
 129     goto Error;
 130   }
 131   if ((pcf->props = vf_sexp_empty_list()) == NULL){
 132     vf_error = VF_ERR_NO_MEMORY;
 133     goto Error;
 134   }
 135 
 136   if (pcf_load_file(pcf) < 0)
 137     goto Error;
 138 
 139   if ((pcf_id = (pcf_table->put)(pcf_table, pcf, 
 140                                  path_name, strlen(path_name)+1)) < 0){
 141     vf_error = VF_ERR_NO_MEMORY;
 142     goto Error;
 143   }
 144 
 145   PCF_SetPCF(pcf_id, pcf);
 146 
 147   return pcf_id;
 148 
 149 Error:
 150   pcf_release(pcf);
 151   return -1;
 152 }
 153 
 154 
 155 Private void
 156 PCF_Close(int pcf_id)
     /* [<][>][^][v][top][bottom][index][help] */
 157 {
 158   PCF  pcf;
 159 
 160   if ((pcf = PCF_GetPCF(pcf_id)) == NULL){
 161     fprintf(stderr, "VFlib Internal error: PCF_Close()\n");
 162     vf_error = VF_ERR_INTERNAL;
 163     return;
 164   }
 165   if ((pcf_table->unlink_by_id)(pcf_table, pcf_id) > 0)
 166     return;
 167 
 168   pcf_release(pcf);
 169 }
 170 
 171 
 172 Private void
 173 pcf_release(PCF pcf)
     /* [<][>][^][v][top][bottom][index][help] */
 174 {
 175   if (pcf != NULL){
 176     vf_free(pcf->path_name);
 177     vf_free(pcf->uncompress);
 178     vf_free(pcf->char_table);
 179     vf_free(pcf->bitmap_block);
 180     vf_free(pcf->encoding);
 181     vf_sexp_free(&pcf->props);
 182     vf_free(pcf);
 183   }
 184   PCF_GetPCF(-1);
 185 }
 186 
 187 
 188 
 189 static int    pcf_file_pos;
 190 
 191 Private int
 192 pcf_load_file(PCF pcf)
     /* [<][>][^][v][top][bottom][index][help] */
 193 {
 194   FILE      *fp;
 195   PCF_TABLE  tbl;
 196   int        has_bdf_accel, ntbl, val;
 197 
 198   pcf_file_pos = 0;
 199   if (pcf->uncompress == NULL){
 200     if ((fp = vf_fm_OpenBinaryFileStream(pcf->path_name)) == NULL){
 201       vf_error = VF_ERR_NO_FONT_FILE;
 202       return -1;
 203     } 
 204   } else {
 205 #if 0
 206     printf("** PCF \"%s\", \"%s\"\n", pcf->path_name, pcf->uncompress);
 207 #endif
 208     if ((fp = vf_open_uncompress_stream(pcf->path_name, 
 209                                         pcf->uncompress)) == NULL){
 210       vf_error = VF_ERR_UNCOMPRESS;
 211       return -1;
 212     }
 213   }
 214 
 215   val = -1;
 216   if ((tbl = pcf_read_toc(fp, &ntbl)) == NULL)
 217     goto Error;
 218   if (pcf_read_props(pcf, fp, tbl, ntbl) < 0)
 219     goto Error;
 220   if ((has_bdf_accel = pcf_type_index(tbl, ntbl, PCF_BDF_ACCELERATORS)) >= 0)
 221     if (pcf_read_accel(pcf, fp, tbl, ntbl, PCF_ACCELERATORS) < 0)
 222       goto Error;
 223   if (pcf_read_metrics(pcf, fp, tbl, ntbl) < 0)
 224     goto Error;
 225   if (pcf_read_bitmaps(pcf, fp, tbl, ntbl) < 0)
 226     goto Error;
 227   if (pcf_read_ink_metrics(pcf, fp, tbl, ntbl) < 0)
 228     goto Error;
 229   if (pcf_read_encodings(pcf, fp, tbl, ntbl) < 0)
 230     goto Error;
 231   if (has_bdf_accel > 0)
 232     if (pcf_read_accel(pcf, fp, tbl, ntbl, PCF_BDF_ACCELERATORS) < 0)
 233       goto Error;
 234   val = 0;
 235   
 236 Error:
 237   vf_free(tbl);
 238   if (pcf->uncompress != NULL)
 239     vf_close_uncompress_stream(fp);
 240   fp = NULL;
 241 
 242   return val;
 243 }
 244 
 245 
 246 Private PCF_TABLE
 247 pcf_read_toc(FILE *fp, int *ntbl)
     /* [<][>][^][v][top][bottom][index][help] */
 248 {
 249   PCF_TABLE  tbl;
 250   INT4       pcf_version;
 251   int        i;
 252 
 253   pcf_version = pcf_read_lsb4(fp);
 254   if (pcf_version != PCF_FILE_VERSION){
 255     *ntbl = 0;
 256     return NULL;
 257   }
 258   if ((*ntbl = pcf_read_lsb4(fp)) < 0)
 259     return NULL;
 260   ALLOCN_IF_ERR(tbl, struct s_pcf_table, *ntbl)
 261     return NULL;
 262   for (i = 0; i < *ntbl; i++){
 263     tbl[i].type   = pcf_read_lsb4(fp);
 264     tbl[i].format = pcf_read_lsb4(fp);
 265     tbl[i].size   = pcf_read_lsb4(fp);
 266     tbl[i].offset = pcf_read_lsb4(fp);
 267   }
 268   return tbl;
 269 }
 270 
 271 Private int
 272 pcf_read_props(PCF pcf, FILE *fp, PCF_TABLE tbl, int ntbl)
     /* [<][>][^][v][top][bottom][index][help] */
 273 {
 274   int    i, pad, val;
 275   INT4   format, nprops;
 276   INT4  *prop_name  = NULL;
 277   char  *prop_isstr = NULL;
 278   INT4  *prop_value = NULL;
 279   char  *propstr    = NULL;
 280   INT4   propstr_size;
 281   char  *prop, *value, *p;
 282   char   charset_name[256], charset_enc[64], value_str[256];
 283   
 284   if (pcf_seek_to_type(fp, tbl, ntbl, PCF_PROPERTIES) == NULL)
 285     return -1;
 286   format = pcf_read_lsb4(fp);
 287   if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
 288     return -1;
 289 
 290   val = -1;
 291 
 292   nprops = pcf_read_int4(fp, format);
 293   ALLOCN_IF_ERR(prop_name,  INT4, nprops)
 294     goto Error;
 295   ALLOCN_IF_ERR(prop_isstr, char, nprops)
 296     goto Error;
 297   ALLOCN_IF_ERR(prop_value, INT4, nprops)
 298     goto Error;    
 299   for (i = 0; i < nprops; i++){
 300     prop_name[i]  = pcf_read_int4(fp, format);
 301     prop_isstr[i] = pcf_read_int1(fp, format);
 302     prop_value[i] = pcf_read_int4(fp, format);
 303   }
 304   if ((i = (nprops % 4)) != 0){
 305     pad = 4 - i;
 306     pcf_skip_file(fp, (long)pad);
 307   }
 308   
 309   propstr_size = pcf_read_int4(fp, format);
 310   ALLOCN_IF_ERR(propstr, char, propstr_size+1)
 311     goto Error;    
 312   pcf_read_nbyte(fp, (unsigned char*)propstr, propstr_size);
 313 
 314   strcpy(charset_name, "");
 315   strcpy(charset_enc,  "");
 316   for (i = 0; i < nprops; i++){
 317     prop  = &propstr[prop_name[i]];
 318     value = &propstr[prop_value[i]];
 319     if (prop_isstr[i]){
 320       pcf->props = vf_sexp_alist_put(prop, value, pcf->props);
 321     } else {
 322       sprintf(value_str, "%ld", (long)prop_value[i]);
 323       pcf->props = vf_sexp_alist_put(prop, value_str, pcf->props);
 324     }
 325     if (pcf_debug('P')){
 326       if (prop_isstr[i])
 327         printf("PCF Prop %s: \"%s\"\n", prop, value);
 328       else  
 329         printf("PCF Prop %s: %ld\n", prop, (long)prop_value[i]);
 330     }
 331     if (STRCMP(prop, "CHARSET_REGISTRY") == 0){
 332       strncpy(charset_name, value, sizeof(charset_name)-sizeof(charset_enc));
 333     } else if (STRCMP(prop, "CHARSET_ENCODING") == 0){
 334       strncpy(charset_enc, value, sizeof(charset_enc));
 335     } else if (STRCMP(prop, "POINT_SIZE") == 0){
 336       if (prop_isstr[i])  sscanf(value, "%i", &pcf->pixel_size);
 337       else                pcf->point_size = (double)prop_value[i] / 10.0;
 338     } else if (STRCMP(prop, "PIXEL_SIZE") == 0){
 339       if (prop_isstr[i])  sscanf(value, "%i", &pcf->pixel_size);
 340       else                pcf->pixel_size = prop_value[i];
 341     } else if (STRCMP(prop, "FONT_ASCENT") == 0){
 342       if (prop_isstr[i])  sscanf(value, "%i", &pcf->ascent);
 343       else                pcf->ascent = prop_value[i];
 344     } else if (STRCMP(prop, "FONT_DESCENT") == 0){
 345       if (prop_isstr[i])  sscanf(value, "%i", &pcf->descent);
 346       else                pcf->descent = prop_value[i];
 347     } else if (STRCMP(prop, "RESOLUTION_X") == 0){
 348       if (prop_isstr[i])  sscanf(value, "%lf", &pcf->dpi_x);
 349       else                pcf->dpi_x = prop_value[i];
 350     } else if (STRCMP(prop, "RESOLUTION_Y") == 0){
 351       if (prop_isstr[i])  sscanf(value, "%lf", &pcf->dpi_y);
 352       else                pcf->dpi_y = prop_value[i];
 353     } else if (STRCMP(prop, "SLANT") == 0){
 354       for (p = value; *p != '\0'; p++)
 355         *p = toupper(*p);
 356       pcf->slant = 0.0;
 357       if ((strcmp(value, "I") == 0) || (strcmp(value, "O") == 0)){
 358         pcf->slant = 0.17;
 359       } else if ((strcmp(value, "RI") == 0) || (strcmp(value, "RO") == 0)){
 360         pcf->slant = -0.17;
 361       }
 362     }
 363   }
 364 
 365   if ((strcmp(charset_enc, "") != 0) && ((strcmp(charset_enc, "0") != 0))){
 366     strcat(charset_name, "-");
 367     strcat(charset_name, charset_enc); 
 368   }
 369 
 370   if ((pcf->size = pcf->point_size) < 0)
 371     pcf->size = pcf->ascent + pcf->descent;
 372   if (pcf->dpi_x < 0)
 373     pcf->dpi_x = DEFAULT_DPI;
 374   if (pcf->dpi_y < 0)
 375     pcf->dpi_y = DEFAULT_DPI;
 376 
 377   val = 0;
 378 
 379 Error:
 380   vf_free(prop_name);
 381   vf_free(prop_isstr);
 382   vf_free(prop_value);
 383   vf_free(propstr);
 384 
 385   return val;
 386 }
 387 
 388 Private int
 389 pcf_read_metrics(PCF pcf, FILE *fp, PCF_TABLE tbl, int ntbl)
     /* [<][>][^][v][top][bottom][index][help] */
 390 {
 391   INT4   format, nmetrics;
 392   int    i;
 393 
 394   if (pcf_seek_to_type(fp, tbl, ntbl, PCF_METRICS) == NULL)
 395     return -1;
 396   format = pcf_read_lsb4(fp);
 397   if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)
 398       && !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS))
 399     return -1;
 400   if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
 401     nmetrics = pcf_read_int4(fp, format);
 402   else
 403     nmetrics = pcf_read_int2(fp, format);
 404   ALLOCN_IF_ERR(pcf->char_table, struct s_pcf_char, nmetrics)
 405     goto Error;
 406   for (i = 0; i < nmetrics; i++){
 407     PCF_CHAR  pch;
 408     pch = &pcf->char_table[i];
 409     if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
 410       pcf_read_metric_item(fp, format, pch);
 411     else
 412       pcf_read_compressed_metric_item(fp, format, pch);
 413     if (pcf_debug('M')){
 414       printf("PCF  rightSideBearing: %d\n", pch->rightSideBearing);
 415       printf("PCF  leftSideBearing: %d\n", pch->leftSideBearing);
 416       printf("PCF  ascent: %d\n", pch->ascent);
 417       printf("PCF  descent: %d\n", pch->descent);
 418       printf("PCF  characterWidth: %d\n", pch->characterWidth);
 419     }
 420     pch->bbx_width  = pch->rightSideBearing - pch->leftSideBearing;
 421     pch->bbx_height = pch->ascent + pch->descent;
 422     pch->off_x = pch->leftSideBearing;
 423     pch->off_y = -pch->descent;
 424     pch->mv_x  = pch->characterWidth;
 425     pch->mv_y  = 0;
 426 
 427     if (pch->bbx_width  > pcf->font_bbx_width)
 428       pcf->font_bbx_width  = pch->bbx_width;
 429     if (pch->bbx_height > pcf->font_bbx_height)
 430       pcf->font_bbx_height = pch->bbx_height;
 431     if (pch->off_x < pcf->font_bbx_xoff)
 432       pcf->font_bbx_xoff = pch->off_x;
 433     if (pch->off_y < pcf->font_bbx_yoff)
 434       pcf->font_bbx_yoff = pch->off_y;
 435   }
 436   if (pcf_debug('B')){
 437     printf("PCF FONT BOUNDINGBOX %d %d %d %d\n", 
 438            pcf->font_bbx_width, pcf->font_bbx_height, 
 439            pcf->font_bbx_xoff, pcf->font_bbx_yoff); 
 440   }
 441   pcf->nchars = nmetrics;
 442   return 0;
 443 
 444 Error:  
 445   pcf->nchars = 0;
 446   return -1;
 447 }
 448 Private void
 449 pcf_read_metric_item(FILE *fp, INT4 format, PCF_CHAR pch)
     /* [<][>][^][v][top][bottom][index][help] */
 450 {
 451   pch->leftSideBearing  = pcf_read_int2(fp, format);
 452   pch->rightSideBearing = pcf_read_int2(fp, format);
 453   pch->characterWidth   = pcf_read_int2(fp, format);
 454   pch->ascent           = pcf_read_int2(fp, format);
 455   pch->descent          = pcf_read_int2(fp, format);
 456   pch->attributes       = pcf_read_int2(fp, format);
 457 }
 458 Private void
 459 pcf_read_compressed_metric_item(FILE *fp, INT4 format, PCF_CHAR pch)
     /* [<][>][^][v][top][bottom][index][help] */
 460 {
 461   pch->leftSideBearing  = pcf_read_int1(fp, format) - 0x80;
 462   pch->rightSideBearing = pcf_read_int1(fp, format) - 0x80;
 463   pch->characterWidth   = pcf_read_int1(fp, format) - 0x80;
 464   pch->ascent           = pcf_read_int1(fp, format) - 0x80;
 465   pch->descent          = pcf_read_int1(fp, format) - 0x80;
 466   pch->attributes       = 0;
 467 }
 468 
 469 Private int
 470 pcf_read_bitmaps(PCF pcf, FILE *fp, PCF_TABLE tbl, int ntbl)
     /* [<][>][^][v][top][bottom][index][help] */
 471 {
 472   INT4     format, nbitmaps;
 473   CARD4   *offsets = NULL;
 474   CARD4    bitmap_sizes[PCF_GLYPHPADOPTIONS];
 475   int      i, xsize;
 476   int      bitmap_block_size;
 477 
 478   if (pcf_seek_to_type(fp, tbl, ntbl, PCF_BITMAPS) == NULL)
 479     return -1;
 480   format = pcf_read_lsb4(fp);
 481   if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
 482     return -1;
 483   if ((nbitmaps = pcf_read_int4(fp, format)) != pcf->nchars)
 484     return -1;
 485   if (pcf_debug('B')){
 486     printf("PCF %ld bitmaps\n", (long)nbitmaps);
 487   }
 488 
 489   ALLOCN_IF_ERR(offsets, CARD4, nbitmaps)
 490     goto Error;
 491   for (i = 0; i < nbitmaps; i++)
 492     offsets[i] = pcf_read_int4(fp, format);
 493 
 494   for (i = 0; i < PCF_GLYPHPADOPTIONS; i++)
 495     bitmap_sizes[i] = pcf_read_int4(fp, format);
 496   bitmap_block_size = bitmap_sizes[PCF_GLYPH_PAD_INDEX(format)];
 497   xsize = (bitmap_block_size > 0) ? bitmap_block_size : 1;
 498   if (pcf_debug('B')){
 499     printf("PCF Bitmaps: %d bytes\n", xsize);
 500   }
 501   ALLOCN_IF_ERR(pcf->bitmap_block, unsigned char, xsize)
 502     goto Error;
 503   pcf_read_nbyte(fp, pcf->bitmap_block, bitmap_block_size);
 504   
 505   if (PCF_BIT_ORDER(format) != PCF_MSB_FIRST)
 506     pcf_bit_order_invert(pcf->bitmap_block, bitmap_block_size);
 507   if (PCF_BYTE_ORDER(format) != PCF_MSB_FIRST){
 508     switch (PCF_SCAN_UNIT(format)){
 509     case 1:
 510       break;
 511     case 2:
 512       pcf_swap_2byte(pcf->bitmap_block, bitmap_block_size);
 513       break;
 514     case 4:
 515       pcf_swap_4byte(pcf->bitmap_block, bitmap_block_size);
 516       break;
 517     }
 518   }
 519   
 520   for (i = 0; i < nbitmaps; i++){
 521     PCF_CHAR     pch;
 522     int          w, h, pad;
 523 
 524     pch = &pcf->char_table[i];
 525     w = pch->rightSideBearing - pch->leftSideBearing;
 526     h = pch->ascent + pch->descent;
 527     pad = PCF_GLYPH_PAD(format);
 528     pch->bitmap = &pcf->bitmap_block[offsets[i]];
 529     pch->raster = ((w + 8*pad - 1)/(8 * pad)) * pad;
 530 
 531     if (pcf_debug('D')){
 532       struct   vf_s_bitmap bm;
 533       printf("PCF Bitmap #%d\n", i);
 534       bm.bbx_width = w;
 535       bm.bbx_height = h;
 536       bm.bitmap =  pch->bitmap;
 537       bm.raster =  pch->raster;
 538       bm.off_x = bm.off_y = bm.mv_x = bm.mv_y = 0;
 539       VF_DumpBitmap(&bm);
 540     }      
 541   }
 542 
 543   vf_free(offsets);
 544   return 0;
 545 
 546 Error:
 547   vf_free(offsets);
 548   vf_free(pcf->char_table);
 549   pcf->char_table = NULL;
 550   vf_free(pcf->bitmap_block);
 551   pcf->bitmap_block = NULL;
 552   return -1;
 553 }
 554 
 555 Private int
 556 pcf_read_ink_metrics(PCF pcf, FILE *fp, PCF_TABLE tbl, int ntbl)
     /* [<][>][^][v][top][bottom][index][help] */
 557 {
 558   return 0;  /* ignore */
 559 }
 560 
 561 Private int
 562 pcf_read_encodings(PCF pcf, FILE *fp, PCF_TABLE tbl, int ntbl)
     /* [<][>][^][v][top][bottom][index][help] */
 563 {
 564   INT4     format;
 565   INT2     i, jth, ne;
 566 
 567   if (pcf_seek_to_type(fp, tbl, ntbl, PCF_BDF_ENCODINGS) == NULL)
 568     goto Error;
 569   format = pcf_read_lsb4(fp);
 570   if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
 571     goto Error;
 572 
 573   pcf->firstCol    = pcf_read_int2(fp, format);
 574   pcf->lastCol     = pcf_read_int2(fp, format);
 575   pcf->firstRow    = pcf_read_int2(fp, format);
 576   pcf->lastRow     = pcf_read_int2(fp, format);
 577   pcf->defaultCh   = pcf_read_int2(fp, format);
 578   pcf->nencodings
 579     = (pcf->lastCol - pcf->firstCol + 1) * (pcf->lastRow - pcf->firstRow + 1);
 580   ne = (pcf->nencodings > 0) ? pcf->nencodings : 1;
 581   ALLOCN_IF_ERR(pcf->encoding, INT2, ne)
 582     goto Error;
 583   for (i = 0; i < pcf->nencodings; i++){
 584     if ((jth = pcf_read_int2(fp, format)) == 0xffff)
 585       pcf->encoding[i] = -1;
 586     else 
 587       pcf->encoding[i] = jth;
 588   }
 589   return 0;
 590 
 591 Error:
 592   vf_free(pcf->encoding);
 593   pcf->encoding   = NULL;
 594   pcf->nencodings = 0;
 595   return -1;
 596 }
 597 
 598 Private int
 599 pcf_read_accel(PCF pcf, FILE *fp, PCF_TABLE tbl, int ntbl, INT4 type)
     /* [<][>][^][v][top][bottom][index][help] */
 600 {
 601   INT4     format, junk;
 602 
 603   if (pcf_seek_to_type(fp, tbl, ntbl, type) == NULL)
 604     goto Error;
 605   format = pcf_read_lsb4(fp);
 606   if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)
 607       && !PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS))
 608     goto Error;
 609 
 610   junk = (INT4)pcf_read_int1(fp, format); /* noOverlap */
 611   junk = (INT4)pcf_read_int1(fp, format); /* constantMetrics */
 612   junk = (INT4)pcf_read_int1(fp, format); /* terminalFont */
 613   junk = (INT4)pcf_read_int1(fp, format); /* constantWidth */
 614   junk = (INT4)pcf_read_int1(fp, format); /* inkInside */
 615   junk = (INT4)pcf_read_int1(fp, format); /* inkMetrics */
 616   junk = (INT4)pcf_read_int1(fp, format); /* drawDirection */
 617                                           /* anamorphic */
 618                                           /* cachable */
 619   junk = (INT4)pcf_read_int1(fp, format); /* (alignment) */
 620   pcf->ascent  = pcf_read_int4(fp, format); /* fontAscent */
 621   pcf->descent = pcf_read_int4(fp, format); /* fontDescent */
 622   junk = (INT4)pcf_read_int4(fp, format); /* maxOverlap */
 623   /* Metrics minbounds, maxbounds, (ink_minbounds, and ink_maxbounds)
 624      come here */ 
 625   return 0;
 626 
 627 Error:
 628   return -1;
 629 }
 630  
 631 Private PCF_TABLE
 632 pcf_seek_to_type(FILE *fp, PCF_TABLE tbl, int ntbl, int type)
     /* [<][>][^][v][top][bottom][index][help] */
 633 {
 634   int  i;
 635   
 636   if ((i = pcf_type_index(tbl, ntbl, type)) < 0)
 637     return NULL;
 638 
 639   if (pcf_file_pos > tbl[i].offset)
 640     return NULL;
 641   if (pcf_skip_file(fp, tbl[i].offset - pcf_file_pos) < 0)
 642     return NULL;
 643 
 644   return &tbl[i];
 645 }
 646 
 647 Private int
 648 pcf_type_index(PCF_TABLE tbl, int ntbl, int type)
     /* [<][>][^][v][top][bottom][index][help] */
 649 {
 650   int   i;
 651 
 652   for (i = 0; i < ntbl; i++){
 653     if (tbl[i].type == type)
 654       return i;
 655   }
 656   return -1;
 657 }
 658 
 659 
 660 Private void
 661 pcf_bit_order_invert(unsigned char *bitmap, int size)
     /* [<][>][^][v][top][bottom][index][help] */
 662 {
 663   unsigned char  c1, c2, *p;
 664   static unsigned char  inv_tbl[] = {
 665     0x0, /*0000=>0000*/   0x8, /*0001=>1000*/
 666     0x4, /*0010=>0100*/   0xc, /*0011=>1100*/
 667     0x2, /*0100=>0010*/   0xa, /*0101=>1010*/
 668     0x6, /*0110=>0110*/   0xe, /*0111=>1110*/
 669     0x1, /*1000=>0001*/   0x9, /*1001=>1001*/
 670     0x5, /*1010=>0101*/   0xd, /*1011=>1101*/
 671     0x3, /*1100=>0011*/   0xb, /*1101=>1011*/
 672     0x7, /*1110=>0111*/   0xf, /*1111=>1111*/
 673   };
 674 
 675   for (p = bitmap; size > 0; --size, p++){
 676     c1 = inv_tbl[(*p&0xf0) >> 4];
 677     c2 = inv_tbl[(*p&0x0f)];
 678     *p = (c2<<4)|c1;
 679   }
 680 }
 681 
 682 Private void
 683 pcf_swap_2byte(unsigned char *bitmap, int size)
     /* [<][>][^][v][top][bottom][index][help] */
 684 {
 685   unsigned char  *p, p0;
 686 
 687   for (p = bitmap; size > 0; p += 2, size -= 2){
 688     p0 = *(p+0);
 689     *(p+0) = *(p+1);
 690     *(p+1) = p0;
 691   }
 692 }
 693 
 694 Private void
 695 pcf_swap_4byte(unsigned char *bitmap, int size)
     /* [<][>][^][v][top][bottom][index][help] */
 696 {
 697   unsigned char *p, p0, p1;
 698 
 699   for (p = bitmap; size > 0; p += 4, size -= 4){
 700     p0 = *(p+0);
 701     p1 = *(p+1);
 702     *(p+0) = *(p+3);
 703     *(p+1) = *(p+2);
 704     *(p+2) = p1;
 705     *(p+3) = p0;
 706   }
 707 }
 708 
 709 
 710 Private int
 711 pcf_skip_file(FILE *fp, long nskip)
     /* [<][>][^][v][top][bottom][index][help] */
 712 {
 713   for ( ; nskip > 0; nskip--){
 714     if (getc(fp) < 0)
 715       return -1;
 716     pcf_file_pos++;
 717   }
 718   return 0;
 719 }
 720 
 721 Private INT4
 722 pcf_read_lsb4(FILE *fp)
     /* [<][>][^][v][top][bottom][index][help] */
 723 {
 724   INT4  n;
 725   
 726   n  = (INT4)getc(fp);
 727   n += (INT4)getc(fp) * 0x00000100;
 728   n += (INT4)getc(fp) * 0x00010000;
 729   n += (INT4)getc(fp) * 0x01000000;
 730   pcf_file_pos += 4;
 731   return n;
 732 }
 733 
 734 Private INT4
 735 pcf_read_int4(FILE *fp, INT4 format)
     /* [<][>][^][v][top][bottom][index][help] */
 736 {
 737   INT4  n;
 738 
 739   if (PCF_BYTE_ORDER(format) == PCF_MSB_FIRST){
 740     n  = (INT4)getc(fp) * 0x01000000;
 741     n += (INT4)getc(fp) * 0x00010000;
 742     n += (INT4)getc(fp) * 0x00000100;
 743     n += (INT4)getc(fp);
 744   } else { 
 745     n  = (INT4)getc(fp);
 746     n += (INT4)getc(fp) * 0x00000100;
 747     n += (INT4)getc(fp) * 0x00010000;
 748     n += (INT4)getc(fp) * 0x01000000;
 749   }
 750   pcf_file_pos += 4;
 751   return n;
 752 }
 753 
 754 Private INT4
 755 pcf_read_int2(FILE *fp, INT4 format)
     /* [<][>][^][v][top][bottom][index][help] */
 756 {
 757   INT4  n;
 758 
 759   if (PCF_BYTE_ORDER(format) == PCF_MSB_FIRST){
 760     n  = (INT4)getc(fp) * 0x100;
 761     n += (INT4)getc(fp);
 762   } else { 
 763     n  = (INT4)getc(fp);
 764     n += (INT4)getc(fp) * 0x100;
 765   }
 766   pcf_file_pos += 2;
 767   return n;
 768 }
 769 
 770 Private INT4
 771 pcf_read_int1(FILE *fp, INT4 format)
     /* [<][>][^][v][top][bottom][index][help] */
 772 {
 773   pcf_file_pos++;
 774   return (INT4)getc(fp);
 775 }
 776 
 777 Private int
 778 pcf_read_nbyte(FILE *fp, unsigned char *buff, int size)
     /* [<][>][^][v][top][bottom][index][help] */
 779 {
 780   unsigned char *p;
 781   int  c;
 782 
 783   for (p = buff; size > 0; size--, p++){
 784     if ((c = getc(fp)) < 0)
 785       return -1;
 786     *p = (unsigned char) c;
 787     pcf_file_pos++;
 788   }
 789   return 0;
 790 }
 791 
 792 
 793 Private PCF_CHAR
 794 PCF_GetBitmap(int pcf_id, long code_point)
     /* [<][>][^][v][top][bottom][index][help] */
 795 {
 796   int            index;
 797   PCF            pcf;
 798  
 799   if ((pcf = PCF_GetPCF(pcf_id)) == NULL){
 800     fprintf(stderr, "VFlib internal error: BDF_GetBitmap()\n");
 801     vf_error = VF_ERR_INTERNAL;
 802     return NULL;
 803   }
 804 
 805   if ((index = pcf_char_index(pcf, code_point)) < 0){
 806     vf_error = VF_ERR_ILL_CODE_POINT;
 807     return NULL;
 808   }
 809   return &pcf->char_table[index];
 810 }
 811 
 812 Private int
 813 pcf_char_index(PCF pcf, long code_point)
     /* [<][>][^][v][top][bottom][index][help] */
 814 {
 815   int  char_row, char_col, ncol, i;
 816   
 817   char_row = code_point / 0x100;
 818   char_col = code_point % 0x100;
 819   if ((char_row < pcf->firstRow) || (pcf->lastRow < char_row)
 820       || (char_col < pcf->firstCol) || (pcf->lastCol < char_col))
 821     return -1;
 822 
 823   ncol = (pcf->lastCol - pcf->firstCol + 1);
 824   i = (char_col - pcf->firstCol) + ncol * (char_row - pcf->firstRow);
 825   return pcf->encoding[i];
 826 }
 827 
 828 
 829 Private char*
 830 PCF_GetProp(PCF pcf, char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 831 {
 832   SEXP  v;
 833   char  *r;
 834 
 835 #if 0
 836   char  *prop_value, *val, str[160];
 837 
 838   if (strcmp(name, "DEFAULT_CHAR") == 0){
 839     sprintf(str, "%d", pcf->defaultCh);
 840     return vf_strdup(str);
 841   } else if (strcmp(name, "FONT_ASCENT") == 0){
 842     sprintf(str, "%d", pcf->ascent);
 843     return vf_strdup(str);
 844   } else if (strcmp(name, "FONT_DESCENT") == 0){
 845     sprintf(str, "%d", pcf->descent);
 846     return vf_strdup(str);
 847   }
 848 #endif
 849 
 850   if ((v = vf_sexp_assoc(name, pcf->props)) == NULL)
 851     return NULL;
 852   if ((r = vf_strdup(vf_sexp_get_cstring(vf_sexp_cadr(v)))) == NULL){
 853     vf_error = VF_ERR_NO_MEMORY;
 854     return NULL;
 855   }
 856 
 857   return r;     /* CALLER MUST RELEASE THIS STRING LATER */
 858 }
 859 
 860 
 861 Private PCF_CHAR
 862 PCF_GetPCFChar(PCF pcf, long code_point)
     /* [<][>][^][v][top][bottom][index][help] */
 863 {
 864   int  index;
 865 
 866   if ((index = pcf_char_index(pcf, code_point)) < 0){
 867     vf_error = VF_ERR_ILL_CODE_POINT;
 868     return NULL;
 869   }
 870   return &pcf->char_table[index];
 871 }
 872 
 873 
 874 /*EOF*/

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