[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
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
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:08:37 2014 | Cross-referenced by PHPXref 0.7.1 |