[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/libraries/tcpdf/fonts/ttf2ufm/ttf2ufm-src/app/netscape/ -> nsfix.c (source)

   1  /*
   2   * Fix the Netscape executable for specified font widths
   3   *
   4   * (c) 1999 Copyright by Sergey Babkin
   5   * see COPYRIGHT
   6   */
   7  
   8  #include <sys/types.h>
   9  #include <fcntl.h>
  10  #include <stdio.h>
  11  #include <locale.h>
  12  #include <unistd.h>
  13  
  14  /************************** DEFINES *************************/
  15  
  16  #undef DEBUG
  17  
  18  /* we can handle at most this many fonts */
  19  #define MAXFONTS    20
  20  
  21  /* maximal line buffer size */
  22  #define MAXLINE 512
  23  
  24  /* there may be multiple strings with the same contents */
  25  #define MAXDUPS 10
  26  
  27  /* file read buffer size */
  28  #define FILEBF    40960
  29  
  30  /* bits in the hardware page offset */
  31  #define BITSPERPAGE    12
  32  
  33  /* size of page in bytes */
  34  #define PAGESIZE (1<<BITSPERPAGE)
  35  
  36  /* mask of the in-page offset */
  37  #define PAGEMASK (PAGESIZE-1)
  38  
  39  /* this is machine-dependent! */
  40  typedef short t2b; /* 2-byte type */
  41  typedef int t4b; /* 4-byte type */
  42  typedef int tptr; /* integer type with the same size as pointer */
  43  
  44  struct bbox { /* bounding box */
  45      t2b llx; /* lower-left-x */
  46      t2b lly;
  47      t2b urx;
  48      t2b ury; /* upper-right-y */
  49  };
  50  
  51  struct glyphmetrics { /* metrics of one glyph */
  52      t2b    width;
  53      t2b    unknown;
  54      struct bbox bbox;
  55  };
  56  
  57  struct fontmetrics { /* metrics of the wholefont */
  58      tptr name;
  59      struct bbox bbox;
  60      t2b underlinepos;
  61      t2b underlinethick;
  62      struct glyphmetrics glyphs[256];
  63  };
  64  
  65  struct font {
  66      char nsname[MAXLINE]; /* name in the Netscape binary */
  67      char afmname[MAXLINE]; /* name of the .afm file */
  68      char pfaname[MAXLINE]; /* name of the .pfa (or .pfb) file */
  69      struct fontmetrics metrics;
  70      off_t binoff; /* offset in the binary */
  71  };
  72  
  73  #define SCONST(x)    (x), ((sizeof (x))-1)
  74  
  75  /************************** GLOBALS *************************/
  76  
  77  struct font font[MAXFONTS];
  78  int nfonts=0;
  79  
  80  char msg[MAXLINE];
  81  
  82  /*************************** PROTOTYPES **********************/
  83  
  84  void usage(void);
  85  void readconfig( char *fn);
  86  void readmetrics(void);
  87  void replacefonts( char *fn);
  88  
  89  /************************** main ****************************/
  90  
  91  main(ac, av)
  92      int ac;
  93      char **av;
  94  {
  95      setlocale(LC_ALL, "");
  96  
  97      if(ac!=3) {
  98          usage(); exit(1);
  99      }
 100  
 101      readconfig(av[2]);
 102      readmetrics();
 103      replacefonts( av[1]);
 104  }
 105  
 106  /************************** usage ***************************/
 107  
 108  void
 109  usage(void)
 110  {
 111      fprintf(stderr,"Use:\n");
 112      fprintf(stderr,"   nsfix <netscape.bin> <config-file>\n");
 113  }
 114  
 115  
 116  /************************** readconfig **********************/
 117  
 118  void
 119  readconfig(fn)
 120      char *fn;
 121  {
 122      char s[MAXLINE];
 123      char afmsuffix[MAXLINE], pfasuffix[MAXLINE];
 124      int lineno=0;
 125      FILE *f;
 126  
 127      if(( f=fopen(fn, "r") )==NULL) {
 128          sprintf(msg,"nsfix: open %s",fn);
 129          perror(msg);
 130          exit(1);
 131      }
 132  
 133      while( fgets(s, MAXLINE, f) ) {
 134          lineno++;
 135          if(s[0]=='#' || s[0]=='\n')
 136              continue;
 137  
 138          if(nfonts>=MAXFONTS) {
 139              fprintf(stderr, "nsfix: only %d fonts are supported at once\n", 
 140                  MAXFONTS);
 141              exit(1);
 142          }
 143  
 144          if( sscanf(s, "%s %s %s %s", font[nfonts].nsname, 
 145                  font[nfonts].afmname, afmsuffix, pfasuffix) != 4 ) {
 146              fprintf(stderr, "nsfix: syntax error at line %d of %s\n",
 147                  lineno, fn);
 148              exit(1);
 149          }
 150          strcpy(font[nfonts].pfaname, font[nfonts].afmname);
 151          strcat(font[nfonts].afmname, afmsuffix);
 152          strcat(font[nfonts].pfaname, pfasuffix);
 153          nfonts++;
 154      }
 155  
 156      if(nfonts==0) {
 157          fprintf(stderr, "nsfix: no fonts are defined in %s\n", fn);
 158          exit(1);
 159      }
 160      fclose(f);
 161  }
 162  
 163  /************************** readmetrics *********************/
 164  
 165  void
 166  readmetrics(void)
 167  {
 168      int i;
 169      char s[MAXLINE];
 170      FILE *f;
 171      int n;
 172      int lineno;
 173      int code, width, llx, lly, urx, ury;
 174      char gn[MAXLINE];
 175      struct glyphmetrics *gm;
 176  
 177      for(i=0; i<nfonts; i++) {
 178          if(( f=fopen(font[i].afmname, "r") )==NULL) {
 179              sprintf(msg,"nsfix: open %s", font[i].afmname);
 180              perror(msg);
 181              exit(1);
 182          }
 183          lineno=0;
 184          while( fgets(s, MAXLINE, f) ) {
 185              lineno++;
 186              if( !strncmp(s, SCONST("UnderlineThickness ")) ) {
 187                  if( sscanf(s, "UnderlineThickness %d", &n) <1) {
 188                      fprintf(stderr, "nsfix: weird UnderlineThickness at line %d in %s\n",
 189                          lineno, font[i].afmname);
 190                      exit(1);
 191                  }
 192                  font[i].metrics.underlinethick=n;
 193              } else if( !strncmp(s, SCONST("UnderlinePosition ")) ) {
 194                  if( sscanf(s, "UnderlinePosition %d", &n) <1) {
 195                      fprintf(stderr, "nsfix: weird UnderlinePosition at line %d in %s\n",
 196                          lineno, font[i].afmname);
 197                      exit(1);
 198                  }
 199                  font[i].metrics.underlinepos=n;
 200              } else if( !strncmp(s, SCONST("FontBBox ")) ) {
 201                  if( sscanf(s, "FontBBox %d %d %d %d", &llx, &lly, &urx, &ury) <4) {
 202                      fprintf(stderr, "nsfix: weird FontBBox at line %d in %s\n",
 203                          lineno, font[i].afmname);
 204                      exit(1);
 205                  }
 206                  font[i].metrics.bbox.llx=llx;
 207                  font[i].metrics.bbox.lly=lly;
 208                  font[i].metrics.bbox.urx=urx;
 209                  font[i].metrics.bbox.ury=ury;
 210              } else if( !strncmp(s, SCONST("C ")) ) {
 211                  if( sscanf(s, "C %d ; WX %d ; N %s ; B %d %d %d %d", 
 212                      &code, &width, &gn, &llx, &lly, &urx, &ury) <7) 
 213                  {
 214                      fprintf(stderr, "nsfix: weird metrics at line %d in %s\n",
 215                          lineno, font[i].afmname);
 216                      exit(1);
 217                  }
 218                  if(code>=32 && code<=255) {
 219                      font[i].metrics.glyphs[code].width=width;
 220                      font[i].metrics.glyphs[code].bbox.llx=llx;
 221                      font[i].metrics.glyphs[code].bbox.lly=lly;
 222                      font[i].metrics.glyphs[code].bbox.urx=urx;
 223                      font[i].metrics.glyphs[code].bbox.ury=ury;
 224                  }
 225              }
 226          }
 227          fclose(f);
 228      }
 229  
 230  #ifdef DEBUG
 231      for(i=0; i<nfonts; i++) {
 232          printf("Font %s\n", font[i].nsname);
 233          for(n=0; n<256; n++) {
 234              gm= &font[i].metrics.glyphs[n];
 235              printf("  %d w=%4d [%4d %4d %4d %4d]", n, gm->width,
 236                  gm->bbox.llx, gm->bbox.lly, gm->bbox.urx, gm->bbox.ury);
 237              printf("  w=0x%04x [0x%04x 0x%04x 0x%04x 0x%04x]\n", gm->width & 0xffff,
 238                  gm->bbox.llx & 0xffff, gm->bbox.lly & 0xffff, gm->bbox.urx & 0xffff, gm->bbox.ury & 0xffff);
 239          }
 240      }
 241  
 242      exit(0);
 243  #endif
 244  
 245  }
 246  
 247  /************************** replacefonts ********************/
 248  
 249  void
 250  replacefonts(fn)
 251      char *fn;
 252  {
 253      int f; /* don't use stdio */
 254      char bf[FILEBF];
 255      char *bfend, *p;
 256      int len;
 257      off_t pos;
 258  
 259      off_t zerooff[MAXFONTS*MAXDUPS]; /* offset of zero strings */
 260      tptr nameaddr[MAXFONTS*MAXDUPS]; /* name pointers before these zero strings */
 261      int zeroid[MAXFONTS*MAXDUPS]; /* font number for this zero block */
 262      int nzeroes;
 263      short matched[MAXFONTS]; /* counters how many matches we have for each requested font */
 264      struct fontmetrics *fp;
 265  
 266      struct {
 267          int noff;
 268          int nz;
 269          off_t off[MAXDUPS]; /* there may be multiple strings with the same contents */
 270      } o[MAXFONTS];
 271      int maxnlen;
 272      int i, j, k, n;
 273  
 274      static struct glyphmetrics gm[32]; /* 0-initialized */
 275  
 276  
 277      if(( f=open(fn, O_RDWR) )<0) {
 278          sprintf(msg,"nsfix: open %s",fn);
 279          perror(msg);
 280          exit(1);
 281      }
 282  
 283  
 284      /* get the maximal font name length */
 285      maxnlen=0;
 286      for(i=0; i<nfonts; i++) {
 287          o[i].noff=o[i].nz=0;
 288          matched[i]=0;
 289          len=strlen(font[i].nsname)+1;
 290          if(len>maxnlen)
 291              maxnlen=len;
 292      }
 293  
 294      /* fprintf(stderr,"maxnlen= 0x%x\n", maxnlen); /* */
 295      /* try to find the literal strings of the font names */
 296      pos=0; bfend=bf;
 297      while(( len=read(f, bfend, FILEBF-(bfend-bf)) )>=0 ) {
 298          /* fprintf(stderr,"looking at 0x%lx\n", (long)pos); /* */
 299          /* the last position to check */
 300          if(len>=maxnlen) 
 301              /* leave the rest with the next block */
 302              bfend+= len-maxnlen; 
 303          else {
 304              /* we are very near to the end of file, check
 305               * up to the very last byte */
 306              bfend+= len-2;
 307              memset(bfend+2, 0, maxnlen);
 308          }
 309  
 310          for(p=bf; p<=bfend; p++)
 311              for(i=0; i<nfonts; i++)
 312                  if(!strcmp(font[i].nsname, p) && o[i].noff<MAXDUPS) {
 313                      o[i].off[ o[i].noff++ ] = pos + (p-bf);
 314                      fprintf(stderr,"found %s at 0x%lx\n", font[i].nsname, (long)pos + (p-bf));
 315                  }
 316  
 317          if(len==0)
 318              break;
 319  
 320          memmove(bf, bfend, maxnlen);
 321          pos+= (bfend-bf);
 322          bfend= (bf+maxnlen);
 323      }
 324      if(len<0) {
 325          sprintf(msg,"nsfix: read %s",fn);
 326          perror(msg);
 327          exit(1);
 328      }
 329      fprintf(stderr,"---\n");
 330      /* if there are any dups try to resolve them */
 331      for(i=0; i<nfonts; i++) {
 332          if(o[i].noff==0) {
 333              fprintf(stderr, "nsfix: font %s (%d of %d) is missing in %s\n", 
 334                  font[i].nsname, i, nfonts, fn);
 335              exit(1);
 336          }
 337          if(o[i].noff!=1)
 338              continue;
 339          /* good, only one entry */
 340          fprintf(stderr,"found unique %s at 0x%lx\n", font[i].nsname, (long)o[i].off[0] );
 341          /* if any dupped entry is right after this one then it's good */
 342          /* if it's farther than PAGESIZE/2 then it's bad */
 343          pos=o[i].off[0]+strlen(font[i].nsname)+1;
 344          for(j=0; j<MAXFONTS; j++) {
 345              if(o[j].noff<=1)
 346                  continue;
 347              for(k=0; k<o[j].noff; k++) {
 348                  if(o[j].off[k]==pos) { /* good */
 349                      fprintf(stderr,"got unique %s at 0x%lx\n", font[j].nsname, (long)pos );
 350                      o[j].off[0]=pos;
 351                      o[j].noff=1;
 352                      break;
 353                  }
 354                  if(o[j].off[k] < pos - PAGESIZE/2
 355                  || o[j].off[k] > pos + PAGESIZE/2) { /* bad */
 356                      fprintf(stderr, "eliminated %s at 0x%lx\n", font[j].nsname, (long)o[j].off[k] );
 357                      for(n=k+1; n<o[j].noff; n++)
 358                          o[j].off[n-1]=o[j].off[n];
 359                      o[j].noff--;
 360                      k--;
 361                  }
 362              }
 363              if(o[j].noff==1 && j<i) { /* have to revisit this font */
 364                  i=j-1; /* compensate for i++ */
 365                  break; 
 366              }
 367          }
 368      }
 369  
 370  
 371      /* try to find the metric tables in the executable */
 372      if(lseek(f, (off_t)0, SEEK_SET)<0) {
 373          sprintf(msg,"nsfix: rewind %s",fn);
 374          perror(msg);
 375          exit(1);
 376      }
 377  
 378      /*
 379       * search for the zeroes in place of the metrics for the codes 0-31:
 380       * 4-byte aligned strings of (32*sizeof(struct glyphmetrics)) zero bytes
 381       */
 382      maxnlen=sizeof(struct fontmetrics);
 383  
 384      pos=0; bfend=bf; nzeroes=0;
 385      while(( len=read(f, bfend, FILEBF-(bfend-bf)) )>=0 ) {
 386          /* fprintf(stderr,"looking at 0x%lx\n", (long)pos); /* */
 387          /* the last position to check */
 388          bfend+= len-maxnlen; /* don't look beyond the EOF */
 389  
 390          for(p=bf; p<=bfend; p+=4 /* 4-byte aligned */ ) {
 391              fp=(struct fontmetrics *)p;
 392              if(fp->name==0)
 393                  continue;
 394              if( memcmp(gm, fp->glyphs, sizeof gm) )
 395                  continue;
 396  
 397              /* OK, looks like it, see if we can match it to any name */
 398              n= fp->name & PAGEMASK;
 399              for(i=0; i<nfonts; i++) {
 400                  for(j=0; j<o[i].noff; j++)
 401                      if( n==(o[i].off[j] & PAGEMASK) )  {
 402                          zerooff[nzeroes]= pos + (p-bf);
 403                          nameaddr[nzeroes]= fp->name;
 404                          zeroid[nzeroes]=i;
 405                          o[i].nz++;
 406                          fprintf(stderr, "matched %s at 0x%lx\n", 
 407                              font[i].nsname, (long) zerooff[nzeroes]);
 408                          nzeroes++;
 409                          matched[i]++;
 410                          break;
 411                      }
 412              }
 413  
 414          }
 415  
 416          if(len==0)
 417              break;
 418  
 419          memmove(bf, bfend, maxnlen);
 420          pos+= (bfend-bf);
 421          bfend= (bf+maxnlen);
 422      }
 423      if(len<0) {
 424          sprintf(msg,"nsfix: read %s",fn);
 425          perror(msg);
 426          exit(1);
 427      }
 428      fprintf(stderr,"---\n");
 429  
 430      /* make sure that all the fonts got one match */
 431      k=0; /* flag: have non-matched fonts */ n=0; /* flag: have ambiguities */
 432      for(i=0; i<nfonts; i++)
 433          if(matched[i]==0)
 434              k=1;
 435          else if(matched[i]>1)
 436              n=1;
 437  
 438      if(k) {
 439          fprintf(stderr,"nsfix: can't find match for some of the fonts\n");
 440          fprintf(stderr,"nsfix: maybe wrong byte order, aborting\n");
 441          exit(1);
 442      }
 443      if(n) {
 444          fprintf(stderr,"nsfix: got multiple matches for some of the fonts\n");
 445          fprintf(stderr,"nsfix: can't resolve, aborting\n");
 446          exit(1);
 447      }
 448  
 449      /* now finally write the updated tables */
 450      for(i=0; i<nzeroes; i++) {
 451          j=zeroid[i];
 452          fprintf(stderr, "nsfix: writing table for %s at 0x%lx\n", font[j].nsname,
 453              (long)zerooff[i]);
 454  
 455          font[j].metrics.name=nameaddr[i];
 456          if( lseek(f, zerooff[i], SEEK_SET)<0 ) {
 457              sprintf(msg,"nsfix: seek %s to 0x%lx",fn, (long)zerooff[i] );
 458              perror(msg);
 459              exit(1);
 460          }
 461          if( write(f, &font[j].metrics, sizeof font[j].metrics) != sizeof font[j].metrics ) {
 462              sprintf(msg,"nsfix: write to %s",fn );
 463              perror(msg);
 464              exit(1);
 465          }
 466      }
 467  
 468      close(f);
 469  }


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1