[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

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

   1  /*
   2   * The font parser using the FreeType library version 2.
   3   *
   4   * see COPYRIGHT
   5   *
   6   */
   7  
   8  #ifdef USE_FREETYPE
   9  
  10  #include <stdio.h>
  11  #include <string.h>
  12  #include <stdlib.h>
  13  #include <ctype.h>
  14  #include <sys/types.h>
  15  #include <freetype/freetype.h>
  16  #include <freetype/ftglyph.h>
  17  #include <freetype/ftsnames.h>
  18  #include <freetype/ttnameid.h>
  19  #include <freetype/ftoutln.h>
  20  #include "pt1.h"
  21  #include "global.h"
  22  
  23  /* prototypes of call entries */
  24  static void openfont(char *fname, char *arg);
  25  static void closefont( void);
  26  static int getnglyphs ( void);
  27  static int glnames( GLYPH *glyph_list);
  28  static void glmetrics( GLYPH *glyph_list);
  29  static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
  30  static void fnmetrics( struct font_metrics *fm);
  31  static void glpath( int glyphno, GLYPH *glyph_list);
  32  static void kerning( GLYPH *glyph_list);
  33  
  34  /* globals */
  35  
  36  /* front-end descriptor */
  37  struct frontsw freetype_sw = {
  38      /*name*/       "ft",
  39      /*descr*/      "based on the FreeType library",
  40      /*suffix*/     { "ttf", "otf", "pfa", "pfb" },
  41      /*open*/       openfont,
  42      /*close*/      closefont,
  43      /*nglyphs*/    getnglyphs,
  44      /*glnames*/    glnames,
  45      /*glmetrics*/  glmetrics,
  46      /*glenc*/      glenc,
  47      /*fnmetrics*/  fnmetrics,
  48      /*glpath*/     glpath,
  49      /*kerning*/    kerning,
  50  };
  51  
  52  /* statics */
  53  
  54  static FT_Library library;
  55  static FT_Face face;
  56  
  57  static int enc_type, enc_found;
  58  
  59  /* SFNT functions do not seem to be included by default in FT2beta8 */
  60  #define ENABLE_SFNT
  61  
  62  /*
  63   * Open font and prepare to return information to the main driver.
  64   * May print error and warning messages.
  65   * Exit on error.
  66   */
  67  
  68  static void
  69  openfont(
  70      char *fname,
  71      char *arg /* unused now */
  72  )
  73  {
  74      FT_Error error;
  75  
  76      if( FT_Init_FreeType( &library ) ) {
  77          fprintf(stderr, "** FreeType initialization failed\n");
  78          exit(1);
  79      }
  80  
  81      if( error = FT_New_Face( library, fname, 0, &face ) ) {
  82          if ( error == FT_Err_Unknown_File_Format )
  83              fprintf(stderr, "**** %s has format unknown to FreeType\n", fname);
  84          else
  85              fprintf(stderr, "**** Cannot access %s ****\n", fname);
  86          exit(1);
  87      }
  88  
  89      if(FT_HAS_FIXED_SIZES(face)) {
  90          WARNING_1 fprintf(stderr, "Font contains bitmaps\n");
  91      }
  92      if(FT_HAS_MULTIPLE_MASTERS(face)) {
  93          WARNING_1 fprintf(stderr, "Font contains multiple masters, using default\n");
  94      }
  95  
  96      if(ISDBG(FT)) fprintf(stderr," %d units per EM\n", face->units_per_EM);
  97  
  98      enc_found = 0;
  99  }
 100  
 101  /*
 102   * Close font.
 103   * Exit on error.
 104   */
 105  
 106  static void
 107  closefont(
 108      void
 109  )
 110  {
 111      if( FT_Done_Face(face) ) {
 112          WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n");
 113      }
 114      if( FT_Done_FreeType(library) ) {
 115          WARNING_1 fprintf(stderr, "Errors when stopping FreeType, ignored\n");
 116      }
 117  }
 118  
 119  /*
 120   * Get the number of glyphs in font.
 121   */
 122  
 123  static int
 124  getnglyphs (
 125      void
 126  )
 127  {
 128      if(ISDBG(FT)) fprintf(stderr, "%d glyphs in font\n", face->num_glyphs);
 129      return (int)face->num_glyphs;
 130  }
 131  
 132  /*
 133   * Get the names of the glyphs.
 134   * Returns 0 if the names were assigned, non-zero if the font
 135   * provides no glyph names.
 136   */
 137  
 138  static int
 139  glnames(
 140      GLYPH *glyph_list
 141  )
 142  {
 143  #define MAX_NAMELEN    1024
 144      unsigned char bf[1024];
 145      int i;
 146  
 147      if( ! FT_HAS_GLYPH_NAMES(face) ) {
 148          WARNING_1 fprintf(stderr, "Font has no glyph names\n");
 149          return 1;
 150      }
 151  
 152      for(i=0; i < face->num_glyphs; i++) {
 153          if( FT_Get_Glyph_Name(face, i, bf, MAX_NAMELEN) || bf[0]==0 ) {
 154              sprintf(bf, "_g_%d", i);
 155              WARNING_2 fprintf(stderr,
 156                  "Glyph No. %d has no postscript name, becomes %s\n", i, bf);
 157          }
 158          glyph_list[i].name = strdup(bf);
 159          if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, bf);
 160          if (glyph_list[i].name == NULL) {
 161              fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
 162              exit(255);
 163          }
 164      }
 165      return 0;
 166  }
 167  
 168  /*
 169   * Get the metrics of the glyphs.
 170   */
 171  
 172  static void
 173  glmetrics(
 174      GLYPH *glyph_list
 175  )
 176  {
 177      GLYPH          *g;
 178      int i;
 179      FT_Glyph_Metrics *met;
 180      FT_BBox bbox;
 181      FT_Glyph gly;
 182  
 183      for(i=0; i < face->num_glyphs; i++) {
 184          g = &(glyph_list[i]);
 185  
 186          if( FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE) ) {
 187              fprintf(stderr, "Can't load glyph %s, skipped\n", g->name);
 188              continue;
 189          }
 190  
 191          met = &face->glyph->metrics;
 192  
 193          if(FT_HAS_HORIZONTAL(face)) {
 194              g->width = met->horiAdvance;
 195              g->lsb = met->horiBearingX;
 196          } else {
 197              WARNING_2 fprintf(stderr, "Glyph %s has no horizontal metrics, guessed them\n", g->name);
 198              g->width = met->width;
 199              g->lsb = 0;
 200          }
 201  
 202          if( FT_Get_Glyph(face->glyph, &gly) ) {
 203              fprintf(stderr, "Can't access glyph %s bbox, skipped\n", g->name);
 204              continue;
 205          }
 206  
 207          FT_Glyph_Get_CBox(gly, ft_glyph_bbox_unscaled, &bbox);
 208          g->xMin = bbox.xMin;
 209          g->yMin = bbox.yMin;
 210          g->xMax = bbox.xMax;
 211          g->yMax = bbox.yMax;
 212  
 213          g->ttf_pathlen = face->glyph->outline.n_points;
 214      }
 215  }
 216  
 217  /*
 218   * Get the original encoding of the font. 
 219   * Returns 1 for if the original encoding is Unicode, 2 if the
 220   * original encoding is other 16-bit, 0 if 8-bit.
 221   */
 222  
 223  static int
 224  glenc(
 225      GLYPH *glyph_list,
 226      int *encoding,
 227      int *unimap
 228  )
 229  {
 230      int i, e;
 231      unsigned code;
 232  
 233      if(ISDBG(FT)) 
 234          for(e=0; e < face->num_charmaps; e++) {
 235              fprintf(stderr, "found encoding pid=%d eid=%d\n", 
 236                  face->charmaps[e]->platform_id,
 237                  face->charmaps[e]->encoding_id);
 238          }
 239  
 240      if(enc_found)
 241          goto populate_map;
 242  
 243      enc_type = 0;
 244  
 245      /* first check for an explicit PID/EID */
 246  
 247      if(force_pid != -1) {
 248          for(e=0; e < face->num_charmaps; e++) {
 249              if(face->charmaps[e]->platform_id == force_pid
 250              && face->charmaps[e]->encoding_id == force_eid) {
 251                  WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n", 
 252                      force_pid, force_eid);
 253                  if( !face->charmaps || FT_Set_Charmap(face, face->charmaps[e]) ) {
 254                      fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
 255                      exit(1);
 256                  }
 257                  enc_type = 1;
 258                  goto populate_map;
 259              }
 260          }
 261          fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n", 
 262              force_pid, force_eid);
 263          exit(1);
 264      }
 265  
 266      /* next check for a direct Adobe mapping */
 267  
 268      if(!forcemap) {
 269          for(e=0; e < face->num_charmaps; e++) {
 270              if(face->charmaps[e]->encoding == ft_encoding_adobe_custom) {
 271                  WARNING_1 fputs("Found Adobe Custom Encoding\n", stderr);
 272                  if( FT_Set_Charmap(face, face->charmaps[e]) ) {
 273                      fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
 274                      exit(1);
 275                  }
 276                  goto populate_map;
 277              }
 278          }
 279      }
 280  
 281      for(e=0; e < face->num_charmaps; e++) {
 282          if(face->charmaps[e]->platform_id == 3) {
 283              switch(face->charmaps[e]->encoding_id) {
 284              case 0:
 285                  WARNING_1 fputs("Found Symbol Encoding\n", stderr);
 286                  break;
 287              case 1:
 288                  WARNING_1 fputs("Found Unicode Encoding\n", stderr);
 289                  enc_type = 1;
 290                  break;
 291              default:
 292                  WARNING_1 {
 293                      fprintf(stderr,
 294                      "****MS Encoding ID %d not supported****\n",
 295                          face->charmaps[e]->encoding_id);
 296                      fputs("Treating it like Symbol encoding\n", stderr);
 297                  }
 298                  break;
 299              }
 300              break;
 301          }
 302      }
 303      if(e >= face->num_charmaps) {
 304          WARNING_1 fputs("No Microsoft encoding, using first encoding available\n", stderr);
 305          e = 0;
 306      }
 307      
 308      if( FT_Set_Charmap(face, face->charmaps[e]) ) {
 309          fprintf(stderr, "**** Cannot set charmap in FreeType ****\n");
 310          exit(1);
 311      }
 312  
 313  populate_map:
 314      enc_found = 1;
 315      for(i=0; i<ENCTABSZ; i++) {
 316          if(encoding[i] != -1)
 317              continue;
 318          if(enc_type == 1 || forcemap) {
 319              code = unimap[i];
 320              if(code == (unsigned) -1)
 321                  continue;
 322          } else
 323              code = i;
 324  
 325          code = FT_Get_Char_Index(face, code);
 326          if(0 && ISDBG(FT)) fprintf(stderr, "code of %3d is %3d\n", i, code);
 327          if(code == 0)
 328              continue; /* .notdef */
 329          encoding[i] = code;
 330      }
 331  
 332      return enc_type;
 333  }
 334  
 335  /*
 336   * Get the font metrics
 337   */
 338  static void 
 339  fnmetrics(
 340      struct font_metrics *fm
 341  )
 342  {
 343      char *str;
 344      static char *fieldstocheck[3];
 345  #ifdef ENABLE_SFNT
 346      FT_SfntName sn;
 347  #endif /* ENABLE_SFNT */
 348      int i, j, len;
 349  
 350      fm->italic_angle = 0.0; /* FreeType hides the angle */
 351      fm->underline_position = face->underline_position;
 352      fm->underline_thickness = face->underline_thickness;
 353      fm->is_fixed_pitch = FT_IS_FIXED_WIDTH(face);
 354  
 355      fm->ascender = face->ascender;
 356      fm->descender = face->descender;
 357  
 358      fm->units_per_em =  face->units_per_EM;
 359  
 360      fm->bbox[0] = face->bbox.xMin;
 361      fm->bbox[1] = face->bbox.yMin;
 362      fm->bbox[2] = face->bbox.xMax;
 363      fm->bbox[3] = face->bbox.yMax;
 364  
 365  #ifdef ENABLE_SFNT
 366      if( FT_Get_Sfnt_Name(face, TT_NAME_ID_COPYRIGHT, &sn) )
 367  #endif /* ENABLE_SFNT */
 368          fm->name_copyright = "";
 369  #ifdef ENABLE_SFNT
 370      else
 371          fm->name_copyright = dupcnstring(sn.string, sn.string_len);
 372  #endif /* ENABLE_SFNT */
 373  
 374      fm->name_family = face->family_name;
 375  
 376      fm->name_style = face->style_name;
 377      if(fm->name_style == NULL)
 378          fm->name_style = "";
 379  
 380  #ifdef ENABLE_SFNT
 381      if( FT_Get_Sfnt_Name(face, TT_NAME_ID_FULL_NAME, &sn) ) 
 382  #endif /* ENABLE_SFNT */
 383      {
 384          int len;
 385  
 386          len = strlen(fm->name_family) + strlen(fm->name_style) + 2;
 387          if(( fm->name_full = malloc(len) )==NULL) {
 388              fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
 389              exit(255);
 390          }
 391          strcpy(fm->name_full, fm->name_family);
 392          if(strlen(fm->name_style) != 0) {
 393              strcat(fm->name_full, " ");
 394              strcat(fm->name_full, fm->name_style);
 395          }
 396      } 
 397  #ifdef ENABLE_SFNT
 398      else
 399          fm->name_full = dupcnstring(sn.string, sn.string_len);
 400  #endif /* ENABLE_SFNT */
 401  
 402  #ifdef ENABLE_SFNT
 403      if( FT_Get_Sfnt_Name(face, TT_NAME_ID_VERSION_STRING, &sn) )
 404  #endif /* ENABLE_SFNT */
 405          fm->name_version = "1.0";
 406  #ifdef ENABLE_SFNT
 407      else
 408          fm->name_version = dupcnstring(sn.string, sn.string_len);
 409  #endif /* ENABLE_SFNT */
 410  
 411  #ifdef ENABLE_SFNT
 412      if( FT_Get_Sfnt_Name(face, TT_NAME_ID_PS_NAME , &sn) ) {
 413  #endif /* ENABLE_SFNT */
 414          if(( fm->name_ps = strdup(fm->name_full) )==NULL) {
 415              fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
 416              exit(255);
 417          }
 418  #ifdef ENABLE_SFNT
 419      } else
 420          fm->name_ps = dupcnstring(sn.string, sn.string_len);
 421  #endif /* ENABLE_SFNT */
 422      for(i=0; fm->name_ps[i]!=0; i++)
 423          if(fm->name_ps[i] == ' ')
 424              fm->name_ps[i] = '_'; /* no spaces in the Postscript name *m
 425  
 426      /* guess the boldness from the font names */
 427      fm->force_bold=0;
 428  
 429      fieldstocheck[0] = fm->name_style;
 430      fieldstocheck[1] = fm->name_full;
 431      fieldstocheck[2] = fm->name_ps;
 432  
 433      for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(fieldstocheck[0]); i++) {
 434          str=fieldstocheck[i];
 435          len = strlen(str);
 436          for(j=0; j<len; j++) {
 437              if( (str[j]=='B'
 438                  || str[j]=='b' 
 439                      && ( j==0 || !isalpha(str[j-1]) )
 440                  )
 441              && !strncmp("old",&str[j+1],3)
 442              && (j+4 >= len || !islower(str[j+4]))
 443              ) {
 444                  fm->force_bold=1;
 445                  break;
 446              }
 447          }
 448      }
 449  }
 450  
 451  /*
 452   * Functions to decompose the outlines
 453   */
 454  
 455  static GLYPH *curg;
 456  static double lastx, lasty;
 457  
 458  static int
 459  outl_moveto(
 460      FT_Vector *to,
 461      void *unused
 462  )
 463  {
 464      double tox, toy;
 465  
 466      tox = fscale((double)to->x); toy = fscale((double)to->y);
 467  
 468      /* FreeType does not do explicit closepath() */
 469      if(curg->lastentry) {
 470          g_closepath(curg);
 471      }
 472      fg_rmoveto(curg, tox, toy);
 473      lastx = tox; lasty = toy;
 474  
 475      return 0;
 476  }
 477  
 478  static int
 479  outl_lineto(
 480      FT_Vector *to,
 481      void *unused
 482  )
 483  {
 484      double tox, toy;
 485  
 486      tox = fscale((double)to->x); toy = fscale((double)to->y);
 487  
 488      fg_rlineto(curg, tox, toy);
 489      lastx = tox; lasty = toy;
 490  
 491      return 0;
 492  }
 493  
 494  static int
 495  outl_conicto(
 496      FT_Vector *control1,
 497      FT_Vector *to,
 498      void *unused
 499  )
 500  {
 501      double c1x, c1y, tox, toy;
 502  
 503      c1x = fscale((double)control1->x); c1y = fscale((double)control1->y);
 504      tox = fscale((double)to->x); toy = fscale((double)to->y);
 505  
 506      fg_rrcurveto(curg,
 507          (lastx + 2.0 * c1x) / 3.0, (lasty + 2.0 * c1y) / 3.0,
 508          (2.0 * c1x + tox) / 3.0, (2.0 * c1y + toy) / 3.0,
 509          tox, toy );
 510      lastx = tox; lasty = toy;
 511  
 512      return 0;
 513  }
 514  
 515  static int
 516  outl_cubicto(
 517      FT_Vector *control1,
 518      FT_Vector *control2,
 519      FT_Vector *to,
 520      void *unused
 521  )
 522  {
 523      double c1x, c1y, c2x, c2y, tox, toy;
 524  
 525      c1x = fscale((double)control1->x); c1y = fscale((double)control1->y);
 526      c2x = fscale((double)control2->x); c2y = fscale((double)control2->y);
 527      tox = fscale((double)to->x); toy = fscale((double)to->y);
 528  
 529      fg_rrcurveto(curg, c1x, c1y, c2x, c2y, tox, toy);
 530      lastx = tox; lasty = toy;
 531  
 532      return 0;
 533  }
 534  
 535  static FT_Outline_Funcs ft_outl_funcs = {
 536      outl_moveto,
 537      outl_lineto,
 538      outl_conicto,
 539      outl_cubicto,
 540      0,
 541      0
 542  };
 543  
 544  /*
 545   * Get the path of contrours for a glyph.
 546   */
 547  
 548  static void
 549  glpath(
 550      int glyphno,
 551      GLYPH *glyf_list
 552  )
 553  {
 554      FT_Outline *ol;
 555  
 556      curg = &glyf_list[glyphno];
 557  
 558      if( FT_Load_Glyph(face, glyphno, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING) 
 559      || face->glyph->format != ft_glyph_format_outline ) {
 560          fprintf(stderr, "Can't load glyph %s, skipped\n", curg->name);
 561          return;
 562      }
 563  
 564      ol = &face->glyph->outline;
 565      lastx = 0.0; lasty = 0.0;
 566  
 567      if( FT_Outline_Decompose(ol, &ft_outl_funcs, NULL) ) {
 568          fprintf(stderr, "Can't decompose outline of glyph %s, skipped\n", curg->name);
 569          return;
 570      }
 571  
 572      /* FreeType does not do explicit closepath() */
 573      if(curg->lastentry) {
 574          g_closepath(curg);
 575      }
 576  
 577      if(ol->flags & ft_outline_reverse_fill) {
 578          assertpath(curg->entries, __FILE__, __LINE__, curg->name);
 579          reversepaths(curg);
 580      }
 581  }
 582  
 583  /*
 584   * Get the kerning data.
 585   */
 586  
 587  static void
 588  kerning(
 589      GLYPH *glyph_list
 590  )
 591  {
 592      int    i, j, n;
 593      int    nglyphs = face->num_glyphs;
 594      FT_Vector k;
 595      GLYPH *gl;
 596  
 597      if( nglyphs == 0 || !FT_HAS_KERNING(face) ) {
 598          WARNING_1 fputs("No Kerning data\n", stderr);
 599          return;
 600      }
 601  
 602      for(i=0; i<nglyphs; i++)  {
 603          if( (glyph_list[i].flags & GF_USED) ==0)
 604              continue;
 605          for(j=0; j<nglyphs; j++) {
 606              if( (glyph_list[j].flags & GF_USED) ==0)
 607                  continue;
 608              if( FT_Get_Kerning(face, i, j, ft_kerning_unscaled, &k) )
 609                  continue;
 610              if( k.x == 0 )
 611                  continue;
 612  
 613              addkernpair(i, j, k.x);
 614          }
 615      }
 616  }
 617  
 618  #endif


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