src/vflmkt1.c

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

FUNCTIONS

This source file includes following functions.
  1. main
  2. gen_class_deafult
  3. translate
  4. get_token
  5. emit
  6. parse_pscmd
  7. read_gs_fontmap
  8. find_gs_font
  9. query_gs_db
  10. tfm_read_ds
  11. vf_tex_read_uintn
  12. vf_tex_read_intn
  13. vf_tex_skip_n

   1 /* 
   2  * vflmkt1.c 
   3  * - a vflibcap entry generator for PostScript Type 1 fonts
   4  *
   5  * - This program read "font map" file (e.g. psfonts.map) of dvips,
   6  *   and prints vflibcap entries to standard output.
   7  *
   8  * - Useful for generating vflibcap for TeX DVI drivers
   9  *
  10  *
  11  * by Hirotsugu Kakugawa
  12  *
  13  *   2 May 2001   
  14  *   3 May 2001  Support for kpathsea. 
  15  *   9 May 2001  Support for font file substitution by Ghostscript fonts
  16  *  10 May 2001  Support for font class geneeration, afm and encoding
  17  *               vector directories.
  18  */
  19 /*
  20  * Copyright (C) 2001  Hirotsugu Kakugawa. 
  21  * All rights reserved.
  22  *
  23  * This program is free software; you can redistribute it and/or modify
  24  * it under the terms of the GNU General Public License as published by
  25  * the Free Software Foundation; either version 2, or (at your option)
  26  * any later version.
  27  * 
  28  * This program is distributed in the hope that it will be useful,
  29  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  30  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  31  * GNU General Public License for more details.
  32  * 
  33  * You should have received a copy of the GNU General Public License
  34  * along with this program; if not, write to the Free Software
  35  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
  36  */
  37 
  38 
  39 #include "config.h"
  40 #include "with.h"
  41 #include <stdio.h>
  42 #include <stdlib.h>
  43 #include <ctype.h>
  44 #include <unistd.h>
  45 #ifdef HAVE_STRING_H
  46 #include <string.h>
  47 #endif
  48 #include <sys/param.h>
  49 #include <sys/time.h>
  50 
  51 #ifdef WITH_KPATHSEA
  52 # include  "kpathsea/kpathsea.h"
  53 #endif
  54 
  55 #include  "VFlib-3_6.h"
  56 #include  "VFsys.h"
  57 #include  "vflibcap.h"
  58 #include  "texfonts.h"
  59 #include  "t1.h"
  60 #include  "fsearch.h"
  61 #include  "vflmklib.h"
  62 
  63 
  64 
  65 void    gen_class_deafult(void);
  66 void    translate(FILE*,FILE*,char*);
  67 int     get_token(char *s, char *b, int *x);
  68 void    emit(void);
  69 
  70 int     parse_pscmd(char *cmds, double *val);
  71 
  72 void    read_gs_fontmap(void);
  73 char   *find_gs_font(char *f);
  74 int     query_gs_db(char *s);
  75 
  76 double  tfm_read_ds(char *name);
  77 
  78 
  79 
  80 
  81 #define MAXPSCODE   4
  82 char  texfont[BUFSIZ];
  83 char  psfont[BUFSIZ];
  84 char  t1font[BUFSIZ];
  85 char  encfile[BUFSIZ];
  86 char  pscode[MAXPSCODE][BUFSIZ];
  87 
  88 char  *mode  = DEFAULT_KPS_MODE;
  89 char  *dpi   = NULL;
  90 int    dpi_i = DEFAULT_KPS_DPI;
  91 
  92 #define NDIRS    64
  93 int   n_t1f; 
  94 char  *t1_fontdirs[NDIRS];
  95 int   n_t1e; 
  96 char  *t1_encdirs[NDIRS];
  97 int   n_t1a; 
  98 char  *t1_afmdirs[NDIRS];
  99 int   n_gsf; 
 100 char  *gs_fontdirs[NDIRS];
 101 char  *gs_fontmap;
 102 
 103 #define NGSFONTS   1024
 104 char *gs_db_f[NGSFONTS];
 105 char *gs_db_d[NGSFONTS];
 106 int   i_db; 
 107 
 108 char *cmdline = NULL; 
 109 char *font_suffix = "";
 110 int   gen_font = 0;
 111 int   with_tfm = 0;
 112 int   exist_only = 0; 
 113 
 114 
 115 
 116 
 117 int 
 118 main(int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
 119 {
 120   int     nmaps, i;
 121   FILE   *fp;
 122   int    xargc;
 123   char **xargv;
 124 #ifdef WITH_KPATHSEA
 125   int    f;
 126   char   *progname, *s;
 127 #endif
 128 
 129   dpi = malloc(256);
 130   sprintf(dpi, "%d", dpi_i);
 131 
 132   cmdline = copy_cmdline(argc, argv);
 133 
 134   n_t1f = n_t1a = n_t1e = 0;
 135   for (i = 0; i < NDIRS; i++){
 136     t1_fontdirs[i] = NULL;
 137     t1_afmdirs[i]  = NULL;
 138     t1_encdirs[i]  = NULL;
 139     gs_fontdirs[i] = NULL;
 140   }
 141   gs_fontmap = NULL;
 142 
 143   i_db = 0;
 144   for (i = 0; i < NGSFONTS; i++){
 145     gs_db_f[i] = NULL;
 146     gs_db_d[i] = NULL;
 147   }
 148 
 149   xargc = argc; 
 150   xargv = argv;
 151 
 152   nmaps = 0;
 153   for (xargc--,xargv++; xargc > 0; xargc--,xargv++){
 154     if ((strcmp(*xargv, "--help") == 0)
 155         || (strcmp(*xargv, "-help") == 0)){
 156       printf("vflmkt1: generates vflibcap entries for Type1 fonts from\n");
 157       printf("         a 'font map' file of dvips\n");
 158       printf("Usage: vflmkt1 [options] [map-file ...]\n");
 159       printf("Options\n");
 160       printf("  -d DIR   : Type 1 font file directory\n");
 161       printf("  -a DIR   : AFM file directory\n");
 162       printf("  -e DIR   : T1Lib encoding vector directory\n");
 163       printf("  -gf DIR  : Ghostscript font file directory\n");
 164       printf("  -gm FILE : Ghostscript font map file 'Fontmap' path\n");
 165       printf("  -r DPI   : Default device resolution\n");
 166       printf("  -n MODE  : Device mode name for kpathsea\n");
 167       printf("  -f       : Generate font entries\n");
 168       printf("  -z       : Generate font entries whose font file exists\n");
 169       printf("  -t       : Generate font entries with TeX TFM file\n");
 170       printf("  -x STR   : String added to the end of font name\n");
 171 
 172 #ifdef WITH_KPATHSEA
 173       printf("Example: vflmkt1 -d TEXMF -f psfonts.map\n");
 174 #else
 175       printf("Example: vflmkt1 -d TEXMF -f /usr/local/share/texmf/dvips/psfonts.map\n");
 176 #endif
 177       exit(0);
 178 
 179     } else if (strcmp(*xargv, "-r") == 0){
 180       xargv++; xargc--;
 181       check_argc(xargc);
 182       dpi = strdup(*xargv);
 183 
 184     } else if (strcmp(*xargv, "-n") == 0){
 185       /* mode */
 186       xargv++; xargc--;
 187       check_argc(xargc);
 188       mode = x_strdup(*xargv);
 189 
 190     } else if (strcmp(*xargv, "-d") == 0){
 191       /* type 1 font dir */
 192       if (n_t1f == NDIRS){
 193         fprintf(stderr, "Too many Type 1 font directories\n");
 194         exit(1);
 195       }
 196       xargv++; xargc--;
 197       check_argc(xargc);
 198       t1_fontdirs[n_t1f++] = x_strdup(*xargv);
 199 
 200     } else if (strcmp(*xargv, "-a") == 0){
 201       /* afm dir */
 202       if (n_t1a == NDIRS){
 203         fprintf(stderr, "Too many AFM directories\n");
 204         exit(1);
 205       }
 206       xargv++; xargc--;
 207       check_argc(xargc);
 208       t1_afmdirs[n_t1a++] = x_strdup(*xargv);
 209 
 210     } else if (strcmp(*xargv, "-e") == 0){
 211       /* encoding vector dir */
 212       if (n_t1e == NDIRS){
 213         fprintf(stderr, "Too many T1Lib Encoding Vector directories\n");
 214         exit(1);
 215       }
 216       xargv++; xargc--;
 217       check_argc(xargc);
 218       t1_encdirs[n_t1e++] = x_strdup(*xargv);
 219 
 220     } else if (strcmp(*xargv, "-gf") == 0){
 221       /* gs font dir */
 222       if (n_gsf == NDIRS){
 223         fprintf(stderr, "Too many Ghostscript font directories\n");
 224         exit(1);
 225       }
 226       xargv++; xargc--;
 227       check_argc(xargc);
 228       gs_fontdirs[n_gsf++] = x_strdup(*xargv);
 229 
 230     } else if (strcmp(*xargv, "-gm") == 0){
 231       /* gs font map */
 232       xargv++; xargc--;
 233       check_argc(xargc);
 234       gs_fontmap = x_strdup(*xargv);
 235 
 236     } else if (strcmp(*xargv, "-f") == 0){
 237       gen_font = 1;
 238 
 239     } else if (strcmp(*xargv, "-z") == 0){
 240       exist_only = 1;
 241 
 242     } else if (strcmp(*xargv, "-t") == 0){
 243       with_tfm = 1;
 244 
 245     } else if (strcmp(*xargv, "-x") == 0){
 246       xargv++; xargc--;
 247       check_argc(xargc);
 248       font_suffix = strdup(*xargv);
 249 
 250     } else {
 251       if (*xargv[0] == '-'){
 252         fprintf(stderr, "vflmkt1: unknown option %s\n", *xargv);
 253         exit(1);
 254       }
 255       break;
 256 
 257     }
 258   }
 259 
 260 #ifdef WITH_KPATHSEA
 261   progname = NULL;
 262   kpse_set_program_name (argv[0], progname);
 263   kpse_init_prog (uppercasify(kpse_program_name), atoi(dpi), mode, NULL);
 264   for (f = 0; f < kpse_last_format; f++) {
 265     kpse_init_format(f);
 266   }
 267 #endif
 268 
 269   banner("Type 1", "vflmkt1", cmdline);
 270 
 271   read_gs_fontmap();
 272 
 273   gen_class_deafult();    
 274 
 275   for ( ; xargc > 0; xargc--,xargv++){
 276     nmaps++;
 277     
 278     s = *xargv;
 279     if ((fp = fopen(s, "r")) == NULL){
 280 #ifdef WITH_KPATHSEA
 281       s = kpse_find_file(*xargv, kpse_dvips_config_format, 0);
 282       if (s == NULL){ 
 283         fprintf(stderr, "Cannot find: %s\n", *xargv);
 284         exit(1);
 285       }
 286       if (s != NULL){ 
 287         if ((fp = fopen(s, "r")) == NULL){
 288 #endif
 289           fprintf(stderr, "Cannot open: %s\n", *xargv);
 290           exit(1);
 291 #ifdef WITH_KPATHSEA
 292         }
 293       }
 294 #endif
 295     }
 296     translate(fp, stdout, s);
 297     fclose(fp);
 298   }
 299   
 300   if (nmaps == 0){
 301     translate(stdin, stdout, "<stdard input>");
 302   }
 303 
 304   printf("\n");
 305 
 306   return 0;
 307 }
 308 
 309 
 310 
 311 void
 312 gen_class_deafult(void)
     /* [<][>][^][v][top][bottom][index][help] */
 313 {
 314   int   i;
 315 
 316   printf("(%s %s", 
 317          VF_CAPE_VFLIBCAP_CLASS_DEFAULT_DEFINITION, FONTCLASS_NAME);
 318   printf("\n  (%s", VF_CAPE_FONT_DIRECTORIES);
 319   for (i = 0; i < n_t1f; i++)
 320     printf("\n       \"%s\"", t1_fontdirs[i]);
 321   for (i = 0; i < n_gsf; i++)
 322     printf("\n       \"%s\"", gs_fontdirs[i]);
 323   printf(")");
 324   printf("\n  (%s", VF_CAPE_TYPE1_AFM_DIRECTORIES);
 325   for (i = 0; i < n_t1a; i++)
 326     printf("\n       \"%s\"", t1_afmdirs[i]);
 327   printf(")");
 328   printf("\n  (%s", VF_CAPE_TYPE1_ENC_DIRECTORIES);
 329   for (i = 0; i < n_t1e; i++)
 330     printf("\n       \"%s\"", t1_encdirs[i]);
 331   printf(")");
 332   printf("\n  (%s \"none\")", VF_CAPE_TYPE1_LOG_LEVEL);
 333   printf("\n  (%s %s)", VF_CAPE_DPI, dpi);
 334   printf(")\n");
 335   printf("\n");
 336 }
 337 
 338 
 339 void
 340 translate(FILE *in, FILE *out, char *map)
     /* [<][>][^][v][top][bottom][index][help] */
 341 {
 342   int   lno, x, v, i;
 343   char  buff[BUFSIZ];
 344   char  opt[BUFSIZ];
 345   int   npscode;
 346 
 347   if (gen_font == 0)
 348     return;
 349 
 350   printf(";; dvips mapfile: %s\n", map);
 351 
 352   lno = 0;
 353   while (fgets(buff, sizeof(buff), in) != NULL){
 354     lno++;
 355     if (isspace(buff[0]))
 356       continue;
 357     switch (buff[0]){
 358     case '\0':
 359     case ' ':
 360     case '\t':
 361     case '%':
 362     case '*':
 363     case ';':
 364     case '#':
 365       continue;
 366     default:
 367       break;
 368     }
 369     x = 0;
 370     npscode = 0;
 371     *t1font = *encfile = *opt = '\0';
 372     for (i = 0; i < MAXPSCODE; i++)
 373       *pscode[i] = '\0';
 374     v = get_token(texfont, buff, &x); 
 375     v = get_token(psfont,  buff, &x); 
 376     while (v >= 0){
 377       v = get_token(opt, buff, &x);
 378       if (strncmp(opt, "<<", 2) == 0){
 379         if (*t1font != '\0') 
 380           fprintf(stderr, "Error: line %d: %s\n", lno, buff);
 381         strcpy(t1font, &opt[1]);
 382       } else if (strncmp(opt, "<[", 2) == 0){
 383         if (*encfile != '\0') 
 384           fprintf(stderr, "Error: line %d: %s\n", lno, buff);
 385         strcpy(encfile, &opt[1]);
 386       } else if (strncmp(opt, "<", 1) == 0){
 387         if ((strlen(opt) >= 4) && (strcmp(".enc", &opt[strlen(opt)-4]) == 0)){
 388           if (*encfile != '\0') 
 389             fprintf(stderr, "Error: line %d: %s\n", lno, buff);
 390           strcpy(encfile, &opt[1]);
 391         } else {
 392           if (*t1font != '\0') 
 393             fprintf(stderr, "Error: line %d: %s\n", lno, buff);
 394           strcpy(t1font, &opt[1]);
 395         }
 396       } else if (strncmp(opt, "\"", 1) == 0){
 397         strcpy(pscode[npscode], &opt[1]);
 398         pscode[npscode][strlen(pscode[npscode])-1] = '\0';
 399         npscode++;
 400         if (npscode == MAXPSCODE){
 401           fprintf(stderr, "Error (Too many PS code): line %d: %s\n",
 402                   lno, buff);
 403           exit(0);
 404         }
 405       }
 406     }
 407 
 408     emit(); 
 409   }
 410 
 411   printf(";; end of %s\n", map);
 412 }
 413 
 414 int 
 415 get_token(char *s, char *b, int *x)
     /* [<][>][^][v][top][bottom][index][help] */
 416 {
 417   int  d;
 418 
 419   if (b[*x] == '\0')
 420     return -1;
 421   while (isspace(b[*x])){
 422     (*x)++;
 423     if (b[*x] == '\0')
 424       return -1;
 425   }
 426 
 427   d = 0;
 428   if (b[*x] == '"')
 429     d = 1;
 430   for (;;){
 431     *s = b[*x];
 432     if (b[*x] == '\0')
 433       return 0;
 434     s++;
 435     (*x)++;
 436     if ((d == 0) && isspace(b[*x])){
 437       *s = '\0';
 438       break;
 439     }
 440     if ((d == 1) && (b[*x] == '"'))
 441       d = 0;
 442   }
 443 
 444   while (isspace(b[*x])){
 445     (*x)++;
 446     if (b[*x] == '\0')
 447       return -1;
 448   }
 449 
 450   return 0;
 451 }
 452 
 453 void 
 454 emit(void)
     /* [<][>][^][v][top][bottom][index][help] */
 455 {
 456   char   *f, *ff;
 457   int     i, n, type, l;
 458   double  val, ds;
 459 
 460   if (*t1font != '\0'){
 461     ff = t1font;
 462   } else {
 463     ff = psfont;
 464   }
 465 
 466   if (exist_only == 1){
 467     f = check_font_exist(ff, t1_fontdirs, n_t1f, kpse_type1_format, NULL);
 468     ds = tfm_read_ds(texfont);
 469     if (ds < 0){
 470       free(f);
 471       f = NULL;
 472     }      
 473     if (f == NULL){
 474       /* search substitute font in Ghostscript font directory */
 475       f = find_gs_font(ff);    /* f is NULL if not found in gs Fontmap */
 476       if (f == NULL){
 477         return;
 478       } else {                 /* ignore .gsf font files */
 479         l = strlen(ff);
 480         if ((l >= strlen(".gsf")) && (strcmp(&f[l-4], ".gsf") == 0)){
 481           free(f); 
 482           f = NULL;
 483           return;
 484         }
 485       }
 486     }
 487     printf("(%s %s%s", VF_CAPE_VFLIBCAP_FONT_ENTRY_DEFINITION, 
 488            texfont, font_suffix); 
 489     printf("\t(%s %s)", VF_CAPE_FONT_CLASS, FONTCLASS_NAME); 
 490     if ((with_tfm == 1) && (ds > 0)){
 491       printf("\n  (%s %.2f)", VF_CAPE_POINT_SIZE, ds);
 492       printf(" (%s \"%s\")", VF_CAPE_TYPE1_TFM, texfont);
 493     }
 494     printf(" (%s \"%s\")", VF_CAPE_FONT_FILE, f);
 495 
 496   } else {
 497 
 498     /* search substitute font in Ghostscript font directory */
 499     f = find_gs_font(ff);    /* f is NULL if not found in gs Fontmap */
 500     ds = tfm_read_ds(texfont);
 501     if (f != NULL){
 502       /* ignore .gsf font files */
 503       l = strlen(ff);
 504       if ((l >= strlen(".gsf")) && (strcmp(&f[l-4], ".gsf") == 0)){
 505         free(f); f = NULL;
 506       }
 507     }
 508     printf("(%s %s%s", VF_CAPE_VFLIBCAP_FONT_ENTRY_DEFINITION, 
 509            texfont, font_suffix); 
 510     printf("\t(%s %s)", VF_CAPE_FONT_CLASS, FONTCLASS_NAME); 
 511     if ((with_tfm == 1) && (ds > 0)){
 512       printf("\n  (%s %.2f)", VF_CAPE_POINT_SIZE, ds);
 513       printf(" (%s \"%s\")", VF_CAPE_TYPE1_TFM, texfont);
 514     }
 515     if (f != NULL){
 516       printf("\n  (%s \"%s\" \"%s\")", VF_CAPE_FONT_FILE, ff, f);
 517     } else {
 518       printf("\n  (%s \"%s\")", VF_CAPE_FONT_FILE, ff);
 519     }
 520   }
 521 
 522   n = 0;
 523   for (i = 0; i < MAXPSCODE; i++){
 524     if (pscode[i][0] == '\0')
 525       continue;
 526     if ((type = parse_pscmd(pscode[i], &val)) < 0)
 527       continue;
 528     if (n == 0){
 529       printf("\n  "); 
 530     } else {
 531       printf(" ");
 532     }
 533     switch (type){
 534     case 1:
 535       if (*encfile != '\0')
 536         printf("(%s \"%s\")", VF_CAPE_TYPE1_ENC_VECT, encfile);
 537       break;
 538     case 2:
 539       printf("(%s %.3f)", VF_CAPE_SLANT_FACTOR, val);
 540       break;
 541     case 3:
 542       printf("(%s %.3f)", VF_CAPE_ASPECT_RATIO, val);
 543       break;
 544     }
 545     n++;
 546   }
 547   printf(")\n");
 548 
 549   if (f != NULL)
 550     free(f);
 551 }
 552 
 553 
 554 int
 555 parse_pscmd(char *cmds, double *val)
     /* [<][>][^][v][top][bottom][index][help] */
 556 {
 557   char  psc[2][256];
 558 
 559   if (sscanf(cmds, "%s %s", psc[0], psc[1]) == 2){
 560     if (strcmp(psc[1], "ReEncodeFont") == 0){
 561       return 1; 
 562     }
 563     if (strcmp(psc[1], "SlantFont") == 0){
 564       *val = atof(psc[0]);
 565       return 2; 
 566     }
 567     if (strcmp(psc[1], "ExtendFont") == 0){
 568       *val = atof(psc[0]);
 569       return 3; 
 570     }
 571     return -1;
 572   }
 573 
 574   return -1;
 575 }
 576 
 577 
 578 
 579 
 580 
 581 void
 582 read_gs_fontmap(void)
     /* [<][>][^][v][top][bottom][index][help] */
 583 {
 584   int   lno, i, j;
 585   char  f[BUFSIZ], d[BUFSIZ];
 586   char  buff[BUFSIZ];
 587   char  *p;
 588   FILE *fp; 
 589 
 590   if (n_gsf == 0)
 591     return;
 592 
 593   if ((fp = fopen(gs_fontmap, "r")) == NULL){
 594     fprintf(stderr, "Cannot open Ghostscript Fontmap file\n");
 595     exit(1);
 596   }
 597 
 598   lno = 0;
 599   while (fgets(buff, sizeof(buff), fp) != NULL){
 600     lno++;
 601     /* skip empty line */
 602     if ((p = strchr(buff, '%')) != NULL)
 603       *p = '\0';
 604     for (i = 0; buff[i] != '\0'; i++){
 605       if (!isspace(buff[i]))
 606         break;
 607     }
 608     if (buff[i] == '\0')
 609       continue;
 610     /* font name */
 611     for (j = 0; (buff[i] != '\0') && !isspace(buff[i]); i++, j++)
 612       f[j] = buff[i];
 613     f[j] = '\0';
 614     if (buff[i] == '\0'){
 615       fprintf(stderr, "Unexpected file format: gs_fontmap\n");
 616       continue;
 617     }
 618 
 619     /* skip space */
 620     for ( ; buff[i] != '\0'; i++){
 621       if (!isspace(buff[i]))
 622         break;
 623     }
 624     if (buff[i] == '\0'){
 625       fprintf(stderr, "Unexpected file format: Ghostscript Fontmap\n");
 626       continue;
 627     }
 628     /* font file or alias */
 629     for (j = 0; (buff[i] != '\0') && !isspace(buff[i]); i++, j++)
 630       d[j] = buff[i];
 631     d[j] = '\0';
 632     
 633     /* add to DB */
 634     if (i_db == NGSFONTS){
 635       fprintf(stderr, "Too many fonts in Ghostscript Fontmap\n");
 636       exit(1);
 637     }
 638 #if 0
 639     printf("*** GS Fontmap db %d: %s\t%s\n", i_db, f, d);
 640 #endif
 641     gs_db_f[i_db] = x_strdup(f);
 642     gs_db_d[i_db] = x_strdup(d);
 643     i_db++;
 644   }
 645 
 646   fclose(fp);
 647   fp = NULL;
 648 }
 649 
 650 
 651 char*
 652 find_gs_font(char *f)
     /* [<][>][^][v][top][bottom][index][help] */
 653 {
 654   int   j;
 655   char  *s;
 656 
 657   if ((j = query_gs_db(f)) < 0)
 658     return NULL;
 659 
 660   while (gs_db_d[j][0] == '/'){    /* resolve alias */
 661     if ((j = query_gs_db(&gs_db_d[j][1])) < 0)
 662       return NULL;
 663   } 
 664 
 665   s = x_strdup(&gs_db_d[j][1]);
 666   s[strlen(s)-1] = '\0';
 667 
 668   return s;
 669 }
 670 
 671 int
 672 query_gs_db(char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 673 {
 674   int  i;
 675 
 676   for (i = 0; i < i_db; i++){
 677     if (strcmp(&gs_db_f[i][1], s) == 0)
 678       return i;
 679   }
 680   return -1;  /* font not in db. */
 681 }
 682 
 683 
 684 
 685 
 686 double
 687 tfm_read_ds(char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 688 {
 689   FILE  *fp;
 690   char  tfm[1024];
 691   UINT4  lf, cs, ds, offset_header;
 692   UINT2  aux;
 693   int    type;
 694   char  *s;
 695 
 696   sprintf(tfm, "%s.%s", name, DEFAULT_EXTENSIONS_TFM);
 697 #ifdef WITH_KPATHSEA
 698   s = kpse_find_file(tfm, kpse_tfm_format, 0);
 699 #else
 700   s = name;
 701 #endif
 702   if (s == NULL)
 703     return -1;
 704   if ((fp = fopen(s, "r")) == NULL)
 705     return -1;
 706 
 707   lf = (UINT4)READ_UINT2(fp);
 708   if ((lf == 11) || (lf == 9)){
 709     /* JFM file of Japanese TeX by ASCII Coop. */
 710     type = METRIC_TYPE_JFM;
 711     (UINT4)READ_UINT2(fp);
 712     (UINT4)READ_UINT2(fp);
 713     (UINT4)READ_UINT2(fp);    
 714     offset_header = 4*7;
 715   } else if (lf == 0){
 716     /* Omega Metric File */
 717     type = METRIC_TYPE_OFM;
 718     aux = READ_INT2(fp);    /* ofm_level */
 719     READ_UINT4(fp);
 720     READ_UINT4(fp);
 721     if (aux == 0){   /* level 0 OFM */
 722       offset_header = 4*14;
 723     } else {                   /* level 1 OFM: *** NOT SUPPORTED YET *** */
 724       offset_header = 4*29;
 725     }
 726   } else {
 727     /* Traditional TeX Metric File */
 728     type = METRIC_TYPE_TFM;
 729     aux = 0;
 730     (int)READ_UINT2(fp);    
 731     offset_header    = 4*6;
 732   }
 733 
 734   if (type == METRIC_TYPE_OFM){
 735     READ_UINT4(fp);
 736     READ_UINT4(fp);
 737     READ_UINT4(fp);
 738     READ_UINT4(fp);
 739     READ_UINT4(fp);
 740     READ_UINT4(fp);
 741     READ_UINT4(fp);
 742     READ_UINT4(fp);
 743     READ_UINT4(fp);
 744     READ_UINT4(fp);
 745     READ_UINT4(fp); 
 746   } else {
 747     (int)READ_UINT2(fp); 
 748     (int)READ_UINT2(fp);
 749     (UINT4)READ_UINT2(fp);
 750     (UINT4)READ_UINT2(fp);
 751     (UINT4)READ_UINT2(fp);
 752     (UINT4)READ_UINT2(fp);
 753     (UINT4)READ_UINT2(fp);
 754     (UINT4)READ_UINT2(fp);
 755     (UINT4)READ_UINT2(fp);
 756     (UINT4)READ_UINT2(fp);
 757   }
 758 
 759   fseek(fp, offset_header, SEEK_SET);
 760   cs = READ_UINT4(fp); 
 761   ds = READ_UINT4(fp); 
 762 
 763   fclose(fp);
 764 
 765   return (double)(ds)/(double)(1<<20);
 766 }
 767 
 768 unsigned long
 769 vf_tex_read_uintn(FILE* fp, int size)
     /* [<][>][^][v][top][bottom][index][help] */
 770 {
 771   unsigned long  v;
 772 
 773   v = 0L;
 774   while (size >= 1){
 775     v = v*256L + (unsigned long)getc(fp);
 776     --size;
 777   }
 778   return v;
 779 }
 780 
 781 long
 782 vf_tex_read_intn(FILE* fp, int size)
     /* [<][>][^][v][top][bottom][index][help] */
 783 {
 784   long           v;
 785 
 786   v = (long)getc(fp) & 0xffL;
 787   if (v & 0x80L)
 788     v = v - 256L;
 789   --size;
 790   while (size >= 1){
 791     v = v*256L + (unsigned long)getc(fp);
 792     --size;
 793   }
 794 
 795   return v;
 796 }
 797 
 798 void
 799 vf_tex_skip_n(FILE* fp, int size)
     /* [<][>][^][v][top][bottom][index][help] */
 800 {
 801   while (size > 0){
 802     (void)getc(fp);
 803     --size;
 804   }
 805 }

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