[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/libraries/tcpdf/fonts/ttf2ufm/ttf2ufm-src/ -> bdf.c (source)

   1  /*
   2   * The font parser for the BDF files
   3   *
   4   * Copyright (c) 2001 by the TTF2PT1 project
   5   * Copyright (c) 2001 by Sergey Babkin
   6   *
   7   * see COPYRIGHT for the full copyright notice
   8   */
   9  
  10  #include <stdio.h>
  11  #include <string.h>
  12  #include <stdlib.h>
  13  #include <ctype.h>
  14  #include "pt1.h"
  15  #include "global.h"
  16  
  17  /* prototypes of call entries */
  18  static void openfont(char *fname, char *arg);
  19  static void closefont( void);
  20  static int getnglyphs ( void);
  21  static int glnames( GLYPH *glyph_list);
  22  static void readglyphs( GLYPH *glyph_list);
  23  static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
  24  static void fnmetrics( struct font_metrics *fm);
  25  static void glpath( int glyphno, GLYPH *glyph_list);
  26  static void kerning( GLYPH *glyph_list);
  27  
  28  /* globals */
  29  
  30  /* front-end descriptor */
  31  struct frontsw bdf_sw = {
  32      /*name*/       "bdf",
  33      /*descr*/      "BDF bitmapped fonts",
  34      /*suffix*/     { "bdf" },
  35      /*open*/       openfont,
  36      /*close*/      closefont,
  37      /*nglyphs*/    getnglyphs,
  38      /*glnames*/    glnames,
  39      /*glmetrics*/  readglyphs,
  40      /*glenc*/      glenc,
  41      /*fnmetrics*/  fnmetrics,
  42      /*glpath*/     glpath,
  43      /*kerning*/    kerning,
  44  };
  45  
  46  /* statics */
  47  
  48  #define MAXLINE    10240 /* maximal line length in the input file */
  49  
  50  static int lineno; /* line number */
  51  
  52  #define GETLEN(s)    s, (sizeof(s)-1)
  53  #define LENCMP(str, txt)    strncmp(str, txt, sizeof(txt)-1)
  54  
  55  static FILE *bdf_file;
  56  static int nglyphs;
  57  static struct font_metrics fmet;
  58  
  59  /* many BDF fonts are of small pixel size, so we better try
  60   * to scale them by an integer to keep the dimensions in
  61   * whole pixels. However if the size is too big and a non-
  62   * integer scaling is needed, we use the standard ttf2pt1's
  63   * scaling abilities.
  64   */
  65  static int pixel_size;
  66  static int scale;
  67  static int scale_external;
  68  
  69  static char *slant;
  70  static char xlfdname[201];
  71  static char *spacing;
  72  static char *charset_reg;
  73  static char *charset_enc;
  74  static char *fnwidth;
  75  static int is_unicode = 0;
  76  
  77  /* tempoary storage for returning data to ttf2pt1 later on request */
  78  static int maxenc = 0;
  79  static int *fontenc;
  80  static GENTRY **glpaths;
  81  
  82  static int got_glyphs = 0;
  83  static GLYPH *glyphs;
  84  static int curgl;
  85  
  86  static int readfile(FILE *f, int (*strfunc)(int len, char *str));
  87  
  88  /*
  89   * Read the file and parse each string with strfunc(),
  90   * until strfunc() returns !=0 or the end of file happens.
  91   * Returns -1 on EOF or strfunc() returning <0, else 0
  92   */
  93  
  94  static int
  95  readfile(
  96      FILE *f,
  97      int (*strfunc)(int len, char *str)
  98  )
  99  {
 100      static char str[MAXLINE]; /* input line, maybe should be dynamic ? */
 101      char *s;
 102      int len, c, res;
 103  
 104      len=0;
 105      while(( c=getc(f) )!=EOF) {
 106          if(c=='\n') {
 107              str[len]=0;
 108  
 109              res = strfunc(len, str);
 110              lineno++;
 111              if(res<0)
 112                  return -1;
 113              else if(res!=0)
 114                  return 0;
 115  
 116              len=0;
 117          } else if(len<MAXLINE-1) {
 118              if(c!='\r')
 119                  str[len++]=c;
 120          } else {
 121              fprintf(stderr, "**** bdf: line %d is too long (>%d)\n", lineno, MAXLINE-1);
 122              exit(1);
 123          }
 124      }
 125      return -1; /* EOF */
 126  }
 127  
 128  /*
 129   * Parse the header of the font file. 
 130   * Stop after the line CHARS is encountered. Ignore the unknown lines.
 131   */
 132  
 133  struct line {
 134      char *name; /* property name with trailing space */
 135      int namelen; /* length of the name string */
 136      enum {
 137          ALLOW_REPEAT = 0x01, /* this property may be repeated in multiple lines */
 138          IS_SEEN = 0x02, /* this property has been seen already */
 139          MUST_SEE = 0x04, /* this property must be seen */
 140          IS_LAST = 0x08 /* this is the last property to be read */
 141      } flags;
 142      char *fmt; /* format string for the arguments, NULL means a string arg */
 143      int nvals; /* number of values to be read by sscanf */
 144      void *vp[4]; /* pointers to values to be read */
 145  };
 146          
 147  static struct line header[] = {
 148      { GETLEN("FONT "), 0, " %200s", 1, {&xlfdname} },
 149      { GETLEN("SIZE "), MUST_SEE, " %d", 1, {&pixel_size} },
 150      { GETLEN("FONTBOUNDINGBOX "), MUST_SEE, " %hd %hd %hd %hd", 4, 
 151          {&fmet.bbox[2], &fmet.bbox[3], &fmet.bbox[0], &fmet.bbox[1]} },
 152      { GETLEN("FAMILY_NAME "), MUST_SEE, NULL, 1, {&fmet.name_family} },
 153      { GETLEN("WEIGHT_NAME "), MUST_SEE, NULL, 1, {&fmet.name_style} },
 154      { GETLEN("COPYRIGHT "), 0, NULL, 1, {&fmet.name_copyright} },
 155      { GETLEN("SLANT "), MUST_SEE, NULL, 1, {&slant} },
 156      { GETLEN("SPACING "), 0, NULL, 1, {&spacing} },
 157      { GETLEN("SETWIDTH_NAME "), 0, NULL, 1, {&fnwidth} },
 158      { GETLEN("CHARSET_REGISTRY "), 0, NULL, 1, {&charset_reg} },
 159      { GETLEN("CHARSET_ENCODING "), 0, NULL, 1, {&charset_enc} },
 160      { GETLEN("FONT_ASCENT "), 0, " %hd", 1, {&fmet.ascender} },
 161      { GETLEN("FONT_DESCENT "), 0, " %hd", 1, {&fmet.descender} },
 162  
 163      /* these 2 must go in this order for post-processing */
 164      { GETLEN("UNDERLINE_THICKNESS "), 0, " %hd", 1, {&fmet.underline_thickness} },
 165      { GETLEN("UNDERLINE_POSITION "), 0, " %hd", 1, {&fmet.underline_position} },
 166  
 167      { GETLEN("CHARS "), MUST_SEE|IS_LAST, " %d", 1, {&nglyphs} },
 168      { NULL, 0, 0 } /* end mark: name==NULL */
 169  };
 170  
 171  static int
 172  handle_header(
 173      int len,
 174      char *str
 175  )
 176  {
 177      struct line *cl;
 178      char *s, *p;
 179      char bf[2000];
 180      int c;
 181  
 182  #if 0
 183      fprintf(stderr, "line: %s\n", str);
 184  #endif
 185      for(cl = header; cl->name != 0; cl++) {
 186          if(strncmp(str, cl->name, cl->namelen))
 187              continue;
 188  #if 0
 189          fprintf(stderr, "match: %s\n", cl->name);
 190  #endif
 191          if(cl->flags & IS_SEEN) {
 192              if(cl->flags & ALLOW_REPEAT)
 193                  continue;
 194              
 195              fprintf(stderr, "**** input line %d redefines the property %s\n", lineno, cl->name);
 196              exit(1);
 197          }
 198          cl->flags |= IS_SEEN;
 199          if(cl->fmt == 0) {
 200              if(len - cl->namelen + 1 > sizeof bf)
 201                  len = sizeof bf; /* cut it down */
 202  
 203              s = bf; /* a temporary buffer to extract the value */
 204  
 205              /* skip until a quote */
 206              for(p = str+cl->namelen; len!=0 && (c = *p)!=0; p++, len--) {
 207                  if(c == '"') {
 208                      p++;
 209                      break;
 210                  }
 211              }
 212              for(; len!=0 && (c = *p)!=0; p++, len--) {
 213                  if(c == '"') {
 214                      c = *++p;
 215                      if(c == '"')
 216                          *s++ = c;
 217                      else
 218                          break;
 219                  } else
 220                      *s++ = c;
 221              }
 222              *s = 0; /* end of line */
 223  
 224              *((char **)(cl->vp[0])) = dupcnstring(bf, s-bf);
 225          } else {
 226              c = sscanf(str+cl->namelen, cl->fmt, cl->vp[0], cl->vp[1], cl->vp[2], cl->vp[3]);
 227              if(c != cl->nvals) {
 228                  fprintf(stderr, "**** property %s at input line %d must have %d arguments\n", 
 229                      cl->name, lineno, cl->nvals);
 230                  exit(1);
 231              }
 232          }
 233          if(cl->flags & IS_LAST)
 234              return 1;
 235          else
 236              return 0;
 237      }
 238      return 0;
 239  }
 240  
 241  /*
 242   * Parse the description of the glyphs
 243   */
 244  
 245  static int
 246  handle_glyphs(
 247      int len,
 248      char *str
 249  )
 250  {
 251      static int inbmap=0;
 252      static char *bmap;
 253      static int xsz, ysz, xoff, yoff;
 254      static int curln;
 255      int i, c;
 256      char *p, *plim, *psz;
 257  
 258      if(!LENCMP(str, "ENDFONT")) {
 259          if(curgl < nglyphs) {
 260              fprintf(stderr, "**** unexpected end of font file after %d glyphs\n", curgl);
 261              exit(1);
 262          } else
 263              return 1;
 264      }
 265      if(curgl >= nglyphs) {
 266          fprintf(stderr, "**** file contains more glyphs than advertised (%d)\n", nglyphs);
 267          exit(1);
 268      }
 269      if(!LENCMP(str, "STARTCHAR")) {
 270          /* sizeof will count \0 instead of ' ' */
 271          for(i=sizeof("STARTCHAR"); str[i] == ' '; i++) 
 272              {}
 273  
 274          glyphs[curgl].name = strdup(str + i);
 275          if(glyphs[curgl].name == 0) {
 276              fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
 277              exit(255);
 278          }
 279      } else if(!LENCMP(str, "ENCODING")) {
 280          if(sscanf(str, "ENCODING %d", &fontenc[curgl])!=1) {
 281              fprintf(stderr,"**** weird ENCODING statement at line %d\n", lineno);
 282              exit(1);
 283          }
 284          if(fontenc[curgl] == -1)  /* compatibility format */
 285              sscanf(str, "ENCODING -1 %d", &fontenc[curgl]);
 286          if(fontenc[curgl] > maxenc)
 287              maxenc = fontenc[curgl];
 288      } else if(!LENCMP(str, "DWIDTH")) {
 289          if(sscanf(str, "DWIDTH %d %d", &xsz, &ysz)!=2) {
 290              fprintf(stderr,"**** weird DWIDTH statement at line %d\n", lineno);
 291              exit(1);
 292          }
 293          glyphs[curgl].width = xsz*scale;
 294      } else if(!LENCMP(str, "BBX")) {
 295          if(sscanf(str, "BBX %d %d %d %d", &xsz, &ysz, &xoff, &yoff)!=4) {
 296              fprintf(stderr,"**** weird BBX statement at line %d\n", lineno);
 297              exit(1);
 298          }
 299          bmap=malloc(xsz*ysz);
 300          if(bmap==0) {
 301              fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
 302              exit(255);
 303          }
 304          glyphs[curgl].lsb = -xoff*scale;
 305          glyphs[curgl].xMin = -xoff*scale;
 306          glyphs[curgl].xMax = (xsz-xoff)*scale;
 307          glyphs[curgl].yMin = -yoff*scale;
 308          glyphs[curgl].yMax = (ysz-xoff)*scale;
 309      } else if(!LENCMP(str, "BITMAP")) {
 310          inbmap=1; 
 311          curln=ysz-1; /* the lowest line has index 0 */
 312      } else if(!LENCMP(str, "ENDCHAR")) {
 313          inbmap=0;
 314          if(bmap) {
 315              glyphs[curgl].lastentry = 0;
 316              glyphs[curgl].path = 0;
 317              glyphs[curgl].entries = 0;
 318              bmp_outline(&glyphs[curgl], scale, bmap, xsz, ysz, xoff, yoff);
 319              free(bmap);
 320              /* remember in a static table or it will be erased */
 321              glpaths[curgl] = glyphs[curgl].entries;
 322              glyphs[curgl].entries = 0;
 323  
 324              if(glpaths[curgl])
 325                  glyphs[curgl].ttf_pathlen = 1;
 326              else
 327                  glyphs[curgl].ttf_pathlen = 0;
 328          }
 329          curgl++;
 330      } else if(inbmap) {
 331          if(curln<0) {
 332              fprintf(stderr,"**** bitmap is longer than %d lines at line %d\n", ysz, lineno);
 333              exit(1);
 334          }
 335  
 336          i=0;
 337          p=&bmap[curln*xsz]; psz=p+xsz;
 338          while(i<len) {
 339              c=str[i++];
 340              if(!isxdigit(c)) {
 341                  fprintf(stderr,"**** non-hex digit in bitmap at line %d\n", lineno);
 342                  exit(1);
 343              }
 344              if(c<='9')
 345                  c-='0';
 346              else 
 347                  c= tolower(c)-'a'+10;
 348  
 349              for(plim=p+4; p<psz && p<plim; c<<=1) 
 350                  *p++ = (( c & 0x08 )!=0);
 351          }
 352          if(p<psz) {
 353              fprintf(stderr,"**** bitmap line is too short at line %d\n", lineno);
 354              exit(1);
 355          }
 356          curln--;
 357      }
 358      return 0;
 359  }
 360  
 361  /*
 362   * Read all the possible information about the glyphs
 363   */
 364  
 365  static void
 366  readglyphs(
 367      GLYPH *glyph_list
 368  )
 369  {
 370      int i;
 371      GLYPH *g;
 372  
 373      if(got_glyphs)
 374          return;
 375  
 376      /* pass them to handle_glyphs() through statics */
 377      glyphs = glyph_list;
 378      curgl = 2; /* skip the empty glyph and .notdef */
 379  
 380      /* initialize the empty glyph and .notdef */
 381  
 382      for(i=0; i<2; i++) {
 383          g = &glyphs[i];
 384          g->lsb = 0;
 385          g->width = fmet.bbox[2];
 386          g->xMin = 0;
 387          g->yMin = 0;
 388      }
 389      g = &glyphs[0];
 390      g->name = ".notdef";
 391      g->xMax = fmet.bbox[2]*4/5;
 392      g->yMax = fmet.bbox[3]*4/5;
 393      g->entries = g->path = g->lastentry = 0;
 394      /* make it look as a black square */
 395      fg_rmoveto(g, 0.0, 0.0);
 396      fg_rlineto(g, 0.0, (double)g->yMax);
 397      fg_rlineto(g, (double)g->xMax, (double)g->yMax);
 398      fg_rlineto(g, (double)g->xMax, 0.0);
 399      fg_rlineto(g, 0.0, 0.0);
 400      g_closepath(g);
 401      glpaths[0] = g->entries;
 402      g->entries = 0;
 403      g->ttf_pathlen = 4;
 404  
 405      g = &glyphs[1];
 406      g->name = ".null";
 407      g->xMax = g->yMax = 0;
 408      g->ttf_pathlen = 0;
 409  
 410      if(readfile(bdf_file, handle_glyphs) < 0) {
 411          fprintf(stderr, "**** file does not contain the ENDFONT line\n");
 412          exit(1);
 413      }
 414      got_glyphs = 1;
 415  }
 416  
 417  /*
 418   * Open font and prepare to return information to the main driver.
 419   * May print error and warning messages.
 420   * Exit on error.
 421   */
 422  
 423  static void
 424  openfont(
 425      char *fname,
 426      char *arg /* unused now */
 427  )
 428  {
 429      struct line *cl;
 430      int i, l;
 431  
 432      if ((bdf_file = fopen(fname, "r")) == NULL) {
 433          fprintf(stderr, "**** Cannot open file '%s'\n", fname);
 434          exit(1);
 435      } else {
 436          WARNING_2 fprintf(stderr, "Processing file %s\n", fname);
 437      }
 438  
 439      lineno = 1;
 440  
 441      for(cl = header; cl->name != 0; cl++)
 442          cl->flags &= ~IS_SEEN;
 443      if(readfile(bdf_file, handle_header) < 0) {
 444          fprintf(stderr, "**** file does not contain the CHARS definition\n");
 445          exit(1);
 446      }
 447      for(cl = header; cl->name != 0; cl++) {
 448          if( (cl->flags & MUST_SEE) && !(cl->flags & IS_SEEN) ) {
 449              fprintf(stderr, "**** mandatory property %sis not found in the input line\n", 
 450                  cl->name); /* cl->name has a space at the end */
 451              exit(1);
 452          }
 453  
 454          /* set a few defaults */
 455          if( !(cl->flags & IS_SEEN) ) {
 456              if(cl->vp[0] == &fmet.underline_thickness) {
 457                  fmet.underline_thickness = 1;
 458              } else if(cl->vp[0] == &fmet.underline_position) {
 459                  fmet.underline_position = fmet.bbox[1] + fmet.underline_thickness
 460                      - (pixel_size - fmet.bbox[3]);
 461              } else if(cl->vp[0] == &fmet.ascender) {
 462                  fmet.ascender = fmet.bbox[2] + fmet.bbox[0];
 463              } else if(cl->vp[0] == &fmet.descender) {
 464                  fmet.descender = fmet.bbox[0];
 465              }
 466          }
 467      }
 468  
 469      nglyphs += 2; /* add empty glyph and .notdef */
 470  
 471      /* postprocessing to compensate for the differences in the metric formats */
 472      fmet.bbox[2] += fmet.bbox[0];
 473      fmet.bbox[3] += fmet.bbox[1];
 474  
 475      scale = 1000/pixel_size; /* XXX ? */
 476      if(scale*pixel_size < 950) {
 477          scale = 1;
 478          scale_external = 1;
 479          fmet.units_per_em = pixel_size;
 480      } else {
 481          scale_external = 0;
 482          fmet.units_per_em = scale*pixel_size;
 483  
 484          fmet.underline_position *= scale;
 485          fmet.underline_thickness *= scale;
 486          fmet.ascender *= scale;
 487          fmet.descender *= scale;
 488          for(i=0; i<4; i++)
 489              fmet.bbox[i] *= scale;
 490      }
 491  
 492      fmet.italic_angle = 0.0;
 493      if(spacing == 0 /* possibly an old font */ 
 494      || toupper(spacing[0]) != 'P') /* or anything non-proportional */
 495          fmet.is_fixed_pitch = 1;
 496      else
 497          fmet.is_fixed_pitch = 0;
 498  
 499      if(fmet.name_copyright==NULL)
 500          fmet.name_copyright = "";
 501      
 502      /* create the full name */
 503      l = strlen(fmet.name_family) 
 504          + (fmet.name_style? strlen(fmet.name_style) : 0)
 505          + (fnwidth? strlen(fnwidth) : 0)
 506          + strlen("Oblique") + 1;
 507  
 508      if(( fmet.name_full = malloc(l) )==NULL) {
 509          fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
 510          exit(255);
 511      }
 512      strcpy(fmet.name_full, fmet.name_family);
 513      if(fnwidth && strcmp(fnwidth, "Normal")) {
 514          strcat(fmet.name_full, fnwidth);
 515      }
 516      if(fmet.name_style && strcmp(fmet.name_style, "Medium")) {
 517          strcat(fmet.name_full, fmet.name_style);
 518      }
 519      switch(toupper(slant[0])) {
 520      case 'O':
 521          strcat(fmet.name_full, "Oblique");
 522          break;
 523      case 'I':
 524          strcat(fmet.name_full, "Italic");
 525          break;
 526      }
 527  
 528      fmet.name_ps = fmet.name_full;
 529      fmet.name_version = "1.0";
 530  
 531      if(charset_reg && charset_enc
 532      && !strcmp(charset_reg, "iso10646") && !strcmp(charset_enc, "1"))
 533          is_unicode = 1;
 534  
 535      if(( fontenc = calloc(nglyphs, sizeof *fontenc) )==NULL) {
 536          fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
 537          exit(255);
 538      }
 539      for(i=0; i<nglyphs; i++)
 540          fontenc[i] = -1;
 541      if(( glpaths = calloc(nglyphs, sizeof *glpaths) )==NULL) {
 542          fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
 543          exit(255);
 544      }
 545  }
 546  
 547  /*
 548   * Close font.
 549   * Exit on error.
 550   */
 551  
 552  static void
 553  closefont(
 554      void
 555  )
 556  {
 557      if(fclose(bdf_file) < 0) {
 558          WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n");
 559      }
 560  }
 561  
 562  /*
 563   * Get the number of glyphs in font.
 564   */
 565  
 566  static int
 567  getnglyphs (
 568      void
 569  )
 570  {
 571      return nglyphs;
 572  }
 573  
 574  /*
 575   * Get the names of the glyphs.
 576   * Returns 0 if the names were assigned, non-zero if the font
 577   * provides no glyph names.
 578   */
 579  
 580  static int
 581  glnames(
 582      GLYPH *glyph_list
 583  )
 584  {
 585      readglyphs(glyph_list);
 586      return 0;
 587  }
 588  
 589  /*
 590   * Get the original encoding of the font. 
 591   * Returns 1 for if the original encoding is Unicode, 2 if the
 592   * original encoding is other 16-bit, 0 if 8-bit.
 593   */
 594  
 595  static int
 596  glenc(
 597      GLYPH *glyph_list,
 598      int *encoding,
 599      int *unimap
 600  )
 601  {
 602      int i, douni, e;
 603  
 604      if(is_unicode || forcemap)
 605          douni = 1;
 606      else
 607          douni = 0;
 608  
 609      for(i=0; i<nglyphs; i++) {
 610          e = fontenc[i];
 611          if(douni)
 612              e = unicode_rev_lookup(e);
 613          if(e>=0 && e<ENCTABSZ && encoding[e] == -1)
 614              encoding[e] = i;
 615      }
 616  
 617      if(is_unicode)
 618          return 1;
 619      else if(maxenc > 255)
 620          return 2;
 621      else
 622          return 0;
 623  }
 624      
 625  /*
 626   * Get the font metrics
 627   */
 628  static void 
 629  fnmetrics(
 630      struct font_metrics *fm
 631  )
 632  {
 633      *fm = fmet;
 634  }
 635  
 636  /*
 637   * Get the path of contrours for a glyph.
 638   */
 639  
 640  static void
 641  glpath(
 642      int glyphno,
 643      GLYPH *glyf_list
 644  )
 645  {
 646      readglyphs(glyf_list);
 647      glyf_list[glyphno].entries = glpaths[glyphno];
 648      glpaths[glyphno] = 0;
 649  }
 650  
 651  /*
 652   * Get the kerning data.
 653   */
 654  
 655  static void
 656  kerning(
 657      GLYPH *glyph_list
 658  )
 659  {
 660      return; /* no kerning in BDF */
 661  }


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