[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 /* 2 * True Type Font to Adobe Type 1 font converter 3 * By Mark Heath <[email protected]> 4 * Based on ttf2pfa by Andrew Weeks <[email protected]> 5 * With help from Frank M. Siegert <[email protected]> 6 * 7 * see COPYRIGHT 8 * 9 */ 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <sys/types.h> 14 #include <sys/stat.h> 15 #include <fcntl.h> 16 #include <time.h> 17 #include <ctype.h> 18 #include <math.h> 19 20 #ifndef WINDOWS 21 # include <unistd.h> 22 # include <netinet/in.h> 23 #else 24 # include "windows.h" 25 #endif 26 27 #include "ttf.h" 28 #include "pt1.h" 29 #include "global.h" 30 31 /* prototypes of call entries */ 32 static void openfont(char *fname, char *arg); 33 static void closefont( void); 34 static int getnglyphs ( void); 35 static int glnames( GLYPH *glyph_list); 36 static void glmetrics( GLYPH *glyph_list); 37 static int glenc( GLYPH *glyph_list, int *encoding, int *unimap); 38 static void fnmetrics( struct font_metrics *fm); 39 static void glpath( int glyphno, GLYPH *glyph_list); 40 static void kerning( GLYPH *glyph_list); 41 42 /* globals */ 43 44 /* front-end descriptor */ 45 struct frontsw ttf_sw = { 46 /*name*/ "ttf", 47 /*descr*/ "built-in TTF support", 48 /*suffix*/ { "ttf" }, 49 /*open*/ openfont, 50 /*close*/ closefont, 51 /*nglyphs*/ getnglyphs, 52 /*glnames*/ glnames, 53 /*glmetrics*/ glmetrics, 54 /*glenc*/ glenc, 55 /*fnmetrics*/ fnmetrics, 56 /*glpath*/ glpath, 57 /*kerning*/ kerning, 58 }; 59 60 /* statics */ 61 62 static FILE *ttf_file; 63 static int ttf_nglyphs, long_offsets; 64 65 static TTF_DIRECTORY *directory; 66 static TTF_DIR_ENTRY *dir_entry; 67 static char *filebuffer; 68 static char *filebuffer_end; 69 static TTF_NAME *name_table = NULL; 70 static TTF_NAME_REC *name_record; 71 static TTF_HEAD *head_table = NULL; 72 static TTF_HHEA *hhea_table = NULL; 73 static TTF_KERN *kern_table = NULL; 74 static TTF_CMAP *cmap_table = NULL; 75 static LONGHORMETRIC *hmtx_table = NULL; 76 static TTF_GLYF *glyf_table; 77 static BYTE *glyf_start = NULL; 78 static TTF_MAXP *maxp_table = NULL; 79 static TTF_POST_HEAD *post_table = NULL; 80 static union { 81 USHORT *sp; 82 ULONG *lp; 83 } loca_table; 84 #define short_loca_table loca_table.sp 85 #define long_loca_table loca_table.lp 86 87 static short cmap_n_segs; 88 static USHORT *cmap_seg_start, *cmap_seg_end; 89 static short *cmap_idDelta, *cmap_idRangeOffset; 90 static TTF_CMAP_FMT0 *encoding0; 91 static int enc_type; 92 93 static char *name_fields[8]; 94 95 static int enc_found_ms, enc_found_mac; 96 97 static char *mac_glyph_names[258] = { 98 ".notdef", ".null", "CR", 99 "space", "exclam", "quotedbl", "numbersign", 100 "dollar", "percent", "ampersand", "quotesingle", 101 "parenleft", "parenright", "asterisk", "plus", 102 "comma", "hyphen", "period", "slash", 103 "zero", "one", "two", "three", 104 "four", "five", "six", "seven", 105 "eight", "nine", "colon", "semicolon", 106 "less", "equal", "greater", "question", 107 "at", "A", "B", "C", 108 "D", "E", "F", "G", 109 "H", "I", "J", "K", 110 "L", "M", "N", "O", 111 "P", "Q", "R", "S", 112 "T", "U", "V", "W", 113 "X", "Y", "Z", "bracketleft", 114 "backslash", "bracketright", "asciicircum", "underscore", 115 "grave", "a", "b", "c", 116 "d", "e", "f", "g", 117 "h", "i", "j", "k", 118 "l", "m", "n", "o", 119 "p", "q", "r", "s", 120 "t", "u", "v", "w", 121 "x", "y", "z", "braceleft", 122 "bar", "braceright", "asciitilde", "Adieresis", 123 "Aring", "Ccedilla", "Eacute", "Ntilde", 124 "Odieresis", "Udieresis", "aacute", "agrave", 125 "acircumflex", "adieresis", "atilde", "aring", 126 "ccedilla", "eacute", "egrave", "ecircumflex", 127 "edieresis", "iacute", "igrave", "icircumflex", 128 "idieresis", "ntilde", "oacute", "ograve", 129 "ocircumflex", "odieresis", "otilde", "uacute", 130 "ugrave", "ucircumflex", "udieresis", "dagger", 131 "degree", "cent", "sterling", "section", 132 "bullet", "paragraph", "germandbls", "registered", 133 "copyright", "trademark", "acute", "dieresis", 134 "notequal", "AE", "Oslash", "infinity", 135 "plusminus", "lessequal", "greaterequal", "yen", 136 "mu", "partialdiff", "summation", "product", 137 "pi", "integral", "ordfeminine", "ordmasculine", 138 "Omega", "ae", "oslash", "questiondown", 139 "exclamdown", "logicalnot", "radical", "florin", 140 "approxequal", "increment", "guillemotleft", "guillemotright", 141 "ellipsis", "nbspace", "Agrave", "Atilde", 142 "Otilde", "OE", "oe", "endash", 143 "emdash", "quotedblleft", "quotedblright", "quoteleft", 144 "quoteright", "divide", "lozenge", "ydieresis", 145 "Ydieresis", "fraction", "currency", "guilsinglleft", 146 "guilsinglright", "fi", "fl", "daggerdbl", 147 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", 148 "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", 149 "Egrave", "Iacute", "Icircumflex", "Idieresis", 150 "Igrave", "Oacute", "Ocircumflex", "applelogo", 151 "Ograve", "Uacute", "Ucircumflex", "Ugrave", 152 "dotlessi", "circumflex", "tilde", "macron", 153 "breve", "dotaccent", "ring", "cedilla", 154 "hungarumlaut", "ogonek", "caron", "Lslash", 155 "lslash", "Scaron", "scaron", "Zcaron", 156 "zcaron", "brokenbar", "Eth", "eth", 157 "Yacute", "yacute", "Thorn", "thorn", 158 "minus", "multiply", "onesuperior", "twosuperior", 159 "threesuperior", "onehalf", "onequarter", "threequarters", 160 "franc", "Gbreve", "gbreve", "Idot", 161 "Scedilla", "scedilla", "Cacute", "cacute", 162 "Ccaron", "ccaron", "dmacron" 163 }; 164 165 /* other prototypes */ 166 static void draw_composite_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno, 167 double *matrix, int level); 168 static void draw_simple_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno, 169 double *matrix); 170 static double f2dot14( short x); 171 172 /* get the TTF description table address and length for this index */ 173 174 static void 175 get_glyf_table( 176 int glyphno, 177 TTF_GLYF **tab, 178 int *len 179 ) 180 { 181 if(tab!=NULL) { 182 if (long_offsets) { 183 *tab = (TTF_GLYF *) (glyf_start + ntohl(long_loca_table[glyphno])); 184 } else { 185 *tab = (TTF_GLYF *) (glyf_start + (ntohs(short_loca_table[glyphno]) << 1)); 186 } 187 } 188 if(len!=NULL) { 189 if (long_offsets) { 190 *len = ntohl(long_loca_table[glyphno + 1]) - ntohl(long_loca_table[glyphno]); 191 } else { 192 *len = (ntohs(short_loca_table[glyphno + 1]) - ntohs(short_loca_table[glyphno])) << 1; 193 } 194 } 195 } 196 197 static void 198 handle_name(void) 199 { 200 int j, k, lang, len, platform; 201 char *p, *string_area; 202 int found3 = 0; 203 204 string_area = (char *) name_table + ntohs(name_table->offset); 205 name_record = &(name_table->nameRecords); 206 207 for (j = 0; j < 8; j++) { 208 name_fields[j] = ""; 209 } 210 211 for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) { 212 213 platform = ntohs(name_record->platformID); 214 215 if (platform == 3) { 216 217 found3 = 1; 218 lang = ntohs(name_record->languageID) & 0xff; 219 len = ntohs(name_record->stringLength); 220 if (lang == 0 || lang == 9) { 221 k = ntohs(name_record->nameID); 222 if (k < 8) { 223 p = string_area + ntohs(name_record->stringOffset); 224 name_fields[k] = dupcnstring(p, len); 225 } 226 } 227 } 228 name_record++; 229 } 230 231 string_area = (char *) name_table + ntohs(name_table->offset); 232 name_record = &(name_table->nameRecords); 233 234 if (!found3) { 235 for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) { 236 237 platform = ntohs(name_record->platformID); 238 239 if (platform == 1) { 240 241 found3 = 1; 242 lang = ntohs(name_record->languageID) & 0xff; 243 len = ntohs(name_record->stringLength); 244 if (lang == 0 || lang == 9) { 245 k = ntohs(name_record->nameID); 246 if (k < 8) { 247 p = string_area + ntohs(name_record->stringOffset); 248 name_fields[k] = dupcnstring(p, len); 249 } 250 } 251 } 252 name_record++; 253 } 254 } 255 if (!found3) { 256 fprintf(stderr, "**** Cannot decode font name fields ****\n"); 257 exit(1); 258 } 259 if (name_fields[4][0] == 0) { /* Full Name empty, use Family Name */ 260 name_fields[4] = name_fields[1]; 261 } 262 if (name_fields[6][0] == 0) { /* Font Name empty, use Full Name */ 263 name_fields[6] = name_fields[4]; 264 if (name_fields[6][0] == 0) { /* oops, empty again */ 265 WARNING_1 fprintf(stderr, "Font name is unknown, setting to \"Unknown\"\n"); 266 name_fields[6] = "Unknown"; 267 } 268 } 269 p = name_fields[6]; 270 /* must not start with a digit */ 271 if(isdigit(*p)) 272 *p+= 'A'-'0'; /* change to a letter */ 273 while (*p != '\0') { 274 if (!isalnum(*p) || *p=='_') { 275 *p = '-'; 276 } 277 p++; 278 } 279 } 280 281 static void 282 handle_head(void) 283 { 284 long_offsets = ntohs(head_table->indexToLocFormat); 285 if (long_offsets != 0 && long_offsets != 1) { 286 fprintf(stderr, "**** indexToLocFormat wrong ****\n"); 287 exit(1); 288 } 289 } 290 291 /* limit the recursion level to avoid cycles */ 292 #define MAX_COMPOSITE_LEVEL 20 293 294 static void 295 draw_composite_glyf( 296 GLYPH *g, 297 GLYPH *glyph_list, 298 int glyphno, 299 double *orgmatrix, 300 int level 301 ) 302 { 303 int len; 304 short ncontours; 305 USHORT flagbyte, glyphindex; 306 double arg1, arg2; 307 BYTE *ptr; 308 char *bptr; 309 SHORT *sptr; 310 double matrix[6], newmatrix[6]; 311 312 get_glyf_table(glyphno, &glyf_table, &len); 313 314 if(len<=0) /* nothing to do */ 315 return; 316 317 ncontours = ntohs(glyf_table->numberOfContours); 318 if (ncontours >= 0) { /* simple case */ 319 draw_simple_glyf(g, glyph_list, glyphno, orgmatrix); 320 return; 321 } 322 323 if(ISDBG(COMPOSITE) && level ==0) 324 fprintf(stderr, "* %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n", g->name, 325 orgmatrix[0], orgmatrix[1], orgmatrix[2], orgmatrix[3], 326 orgmatrix[4], orgmatrix[5]); 327 328 /* complex case */ 329 if(level >= MAX_COMPOSITE_LEVEL) { 330 WARNING_1 fprintf(stderr, 331 "*** Glyph %s: stopped (possibly infinite) recursion at depth %d\n", 332 g->name, level); 333 return; 334 } 335 336 ptr = ((BYTE *) glyf_table + sizeof(TTF_GLYF)); 337 sptr = (SHORT *) ptr; 338 do { 339 flagbyte = ntohs(*sptr); 340 sptr++; 341 glyphindex = ntohs(*sptr); 342 sptr++; 343 344 if (flagbyte & ARG_1_AND_2_ARE_WORDS) { 345 arg1 = (short)ntohs(*sptr); 346 sptr++; 347 arg2 = (short)ntohs(*sptr); 348 sptr++; 349 } else { 350 bptr = (char *) sptr; 351 arg1 = (signed char) bptr[0]; 352 arg2 = (signed char) bptr[1]; 353 sptr++; 354 } 355 matrix[1] = matrix[2] = 0.0; 356 357 if (flagbyte & WE_HAVE_A_SCALE) { 358 matrix[0] = matrix[3] = f2dot14(*sptr); 359 sptr++; 360 } else if (flagbyte & WE_HAVE_AN_X_AND_Y_SCALE) { 361 matrix[0] = f2dot14(*sptr); 362 sptr++; 363 matrix[3] = f2dot14(*sptr); 364 sptr++; 365 } else if (flagbyte & WE_HAVE_A_TWO_BY_TWO) { 366 matrix[0] = f2dot14(*sptr); 367 sptr++; 368 matrix[2] = f2dot14(*sptr); 369 sptr++; 370 matrix[1] = f2dot14(*sptr); 371 sptr++; 372 matrix[3] = f2dot14(*sptr); 373 sptr++; 374 } else { 375 matrix[0] = matrix[3] = 1.0; 376 } 377 378 /* 379 * See * 380 * http://fonts.apple.com/TTRefMan/RM06/Chap6g 381 * lyf.html * matrix[0,1,2,3,4,5]=a,b,c,d,m,n 382 */ 383 384 if (fabs(matrix[0]) > fabs(matrix[1])) 385 matrix[4] = fabs(matrix[0]); 386 else 387 matrix[4] = fabs(matrix[1]); 388 if (fabs(fabs(matrix[0]) - fabs(matrix[2])) <= 33. / 65536.) 389 matrix[4] *= 2.0; 390 391 if (fabs(matrix[2]) > fabs(matrix[3])) 392 matrix[5] = fabs(matrix[2]); 393 else 394 matrix[5] = fabs(matrix[3]); 395 if (fabs(fabs(matrix[2]) - fabs(matrix[3])) <= 33. / 65536.) 396 matrix[5] *= 2.0; 397 398 /* 399 * fprintf (stderr,"Matrix Opp %hd 400 * %hd\n",arg1,arg2); 401 */ 402 #if 0 403 fprintf(stderr, "Matrix: %f %f %f %f %f %f\n", 404 matrix[0], matrix[1], matrix[2], matrix[3], 405 matrix[4], matrix[5]); 406 fprintf(stderr, "Offset: %f %f (%s)\n", 407 arg1, arg2, 408 ((flagbyte & ARGS_ARE_XY_VALUES) ? "XY" : "index")); 409 #endif 410 411 if (flagbyte & ARGS_ARE_XY_VALUES) { 412 matrix[4] *= arg1; 413 matrix[5] *= arg2; 414 } else { 415 WARNING_1 fprintf(stderr, 416 "*** Glyph %s: reusing scale from another glyph is unsupported\n", 417 g->name); 418 /* 419 * must extract values from a glyph 420 * but it seems to be too much pain 421 * and it's not clear now that it 422 * would be really used in any 423 * interesting font 424 */ 425 } 426 427 /* at this point arg1,arg2 contain what logically should be matrix[4,5] */ 428 429 /* combine matrices */ 430 431 newmatrix[0] = orgmatrix[0]*matrix[0] + orgmatrix[2]*matrix[1]; 432 newmatrix[1] = orgmatrix[0]*matrix[2] + orgmatrix[2]*matrix[3]; 433 434 newmatrix[2] = orgmatrix[1]*matrix[0] + orgmatrix[3]*matrix[1]; 435 newmatrix[3] = orgmatrix[1]*matrix[2] + orgmatrix[3]*matrix[3]; 436 437 newmatrix[4] = orgmatrix[0]*matrix[4] + orgmatrix[2]*matrix[5] + orgmatrix[4]; 438 newmatrix[5] = orgmatrix[1]*matrix[4] + orgmatrix[3]*matrix[5] + orgmatrix[5]; 439 440 if(ISDBG(COMPOSITE)) { 441 fprintf(stderr, "%*c+-> %2d %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n", 442 level+1, ' ', level, glyph_list[glyphindex].name, 443 matrix[0], matrix[1], matrix[2], matrix[3], 444 matrix[4], matrix[5]); 445 fprintf(stderr, "%*c = [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n", 446 level+1, ' ', 447 newmatrix[0], newmatrix[1], newmatrix[2], newmatrix[3], 448 newmatrix[4], newmatrix[5]); 449 } 450 draw_composite_glyf(g, glyph_list, glyphindex, newmatrix, level+1); 451 452 } while (flagbyte & MORE_COMPONENTS); 453 } 454 455 static void 456 draw_simple_glyf( 457 GLYPH *g, 458 GLYPH *glyph_list, 459 int glyphno, 460 double *matrix 461 ) 462 { 463 int i, j, k, k1, len, first, cs, ce; 464 /* We assume that hsbw always sets to(0, 0) */ 465 double xlast = 0, ylast = 0; 466 int finished, nguide, contour_start, contour_end; 467 short ncontours, n_inst, last_point; 468 USHORT *contour_end_pt; 469 BYTE *ptr; 470 #define GLYFSZ 2000 471 short xabs[GLYFSZ], yabs[GLYFSZ], xrel[GLYFSZ], yrel[GLYFSZ]; 472 double xcoord[GLYFSZ], ycoord[GLYFSZ]; 473 BYTE flags[GLYFSZ]; 474 double tx, ty; 475 int needreverse = 0; /* transformation may require 476 * that */ 477 GENTRY *lge; 478 479 lge = g->lastentry; 480 481 get_glyf_table(glyphno, &glyf_table, &len); 482 483 if (len <= 0) { 484 WARNING_1 fprintf(stderr, 485 "**** Composite glyph %s refers to non-existent glyph %s, ignored\n", 486 g->name, 487 glyph_list[glyphno].name); 488 return; 489 } 490 ncontours = ntohs(glyf_table->numberOfContours); 491 if (ncontours < 0) { 492 WARNING_1 fprintf(stderr, 493 "**** Composite glyph %s refers to composite glyph %s, ignored\n", 494 g->name, 495 glyph_list[glyphno].name); 496 return; 497 } 498 contour_end_pt = (USHORT *) ((char *) glyf_table + sizeof(TTF_GLYF)); 499 500 last_point = ntohs(contour_end_pt[ncontours - 1]); 501 n_inst = ntohs(contour_end_pt[ncontours]); 502 503 ptr = ((BYTE *) contour_end_pt) + (ncontours << 1) + n_inst + 2; 504 j = k = 0; 505 while (k <= last_point) { 506 flags[k] = ptr[j]; 507 508 if (ptr[j] & REPEAT) { 509 for (k1 = 0; k1 < ptr[j + 1]; k1++) { 510 k++; 511 flags[k] = ptr[j]; 512 } 513 j++; 514 } 515 j++; 516 k++; 517 } 518 519 for (k = 0; k <= last_point; k++) { 520 if (flags[k] & XSHORT) { 521 if (flags[k] & XSAME) { 522 xrel[k] = ptr[j]; 523 } else { 524 xrel[k] = -ptr[j]; 525 } 526 j++; 527 } else if (flags[k] & XSAME) { 528 xrel[k] = 0.0; 529 } else { 530 xrel[k] = (short)( ptr[j] * 256 + ptr[j + 1] ); 531 j += 2; 532 } 533 if (k == 0) { 534 xabs[k] = xrel[k]; 535 } else { 536 xabs[k] = xrel[k] + xabs[k - 1]; 537 } 538 539 } 540 541 for (k = 0; k <= last_point; k++) { 542 if (flags[k] & YSHORT) { 543 if (flags[k] & YSAME) { 544 yrel[k] = ptr[j]; 545 } else { 546 yrel[k] = -ptr[j]; 547 } 548 j++; 549 } else if (flags[k] & YSAME) { 550 yrel[k] = 0; 551 } else { 552 yrel[k] = ptr[j] * 256 + ptr[j + 1]; 553 j += 2; 554 } 555 if (k == 0) { 556 yabs[k] = yrel[k]; 557 } else { 558 yabs[k] = yrel[k] + yabs[k - 1]; 559 } 560 } 561 562 if (matrix) { 563 for (i = 0; i <= last_point; i++) { 564 tx = xabs[i]; 565 ty = yabs[i]; 566 xcoord[i] = fscale(matrix[0] * tx + matrix[2] * ty + matrix[4]); 567 ycoord[i] = fscale(matrix[1] * tx + matrix[3] * ty + matrix[5]); 568 } 569 } else { 570 for (i = 0; i <= last_point; i++) { 571 xcoord[i] = fscale(xabs[i]); 572 ycoord[i] = fscale(yabs[i]); 573 } 574 } 575 576 i = j = 0; 577 first = 1; 578 579 while (i <= ntohs(contour_end_pt[ncontours - 1])) { 580 contour_end = ntohs(contour_end_pt[j]); 581 582 if (first) { 583 fg_rmoveto(g, xcoord[i], ycoord[i]); 584 xlast = xcoord[i]; 585 ylast = ycoord[i]; 586 contour_start = i; 587 first = 0; 588 } else if (flags[i] & ONOROFF) { 589 fg_rlineto(g, xcoord[i], ycoord[i]); 590 xlast = xcoord[i]; 591 ylast = ycoord[i]; 592 } else { 593 cs = i - 1; 594 finished = nguide = 0; 595 while (!finished) { 596 if (i == contour_end + 1) { 597 ce = contour_start; 598 finished = 1; 599 } else if (flags[i] & ONOROFF) { 600 ce = i; 601 finished = 1; 602 } else { 603 i++; 604 nguide++; 605 } 606 } 607 608 switch (nguide) { 609 case 0: 610 fg_rlineto(g, xcoord[ce], ycoord[ce]); 611 xlast = xcoord[ce]; 612 ylast = ycoord[ce]; 613 break; 614 615 case 1: 616 fg_rrcurveto(g, 617 (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0, 618 (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0, 619 (2.0 * xcoord[cs + 1] + xcoord[ce]) / 3.0, 620 (2.0 * ycoord[cs + 1] + ycoord[ce]) / 3.0, 621 xcoord[ce], 622 ycoord[ce] 623 ); 624 xlast = xcoord[ce]; 625 ylast = ycoord[ce]; 626 627 break; 628 629 case 2: 630 fg_rrcurveto(g, 631 (-xcoord[cs] + 4.0 * xcoord[cs + 1]) / 3.0, 632 (-ycoord[cs] + 4.0 * ycoord[cs + 1]) / 3.0, 633 (4.0 * xcoord[cs + 2] - xcoord[ce]) / 3.0, 634 (4.0 * ycoord[cs + 2] - ycoord[ce]) / 3.0, 635 xcoord[ce], 636 ycoord[ce] 637 ); 638 xlast = xcoord[ce]; 639 ylast = ycoord[ce]; 640 break; 641 642 case 3: 643 fg_rrcurveto(g, 644 (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0, 645 (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0, 646 (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0, 647 (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0, 648 (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0, 649 (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0 650 ); 651 652 fg_rrcurveto(g, 653 (xcoord[cs + 1] + 5.0 * xcoord[cs + 2]) / 6.0, 654 (ycoord[cs + 1] + 5.0 * ycoord[cs + 2]) / 6.0, 655 (5.0 * xcoord[cs + 2] + xcoord[cs + 3]) / 6.0, 656 (5.0 * ycoord[cs + 2] + ycoord[cs + 3]) / 6.0, 657 (xcoord[cs + 3] + xcoord[cs + 2]) / 2.0, 658 (ycoord[cs + 3] + ycoord[cs + 2]) / 2.0 659 ); 660 661 fg_rrcurveto(g, 662 (xcoord[cs + 2] + 5.0 * xcoord[cs + 3]) / 6.0, 663 (ycoord[cs + 2] + 5.0 * ycoord[cs + 3]) / 6.0, 664 (2.0 * xcoord[cs + 3] + xcoord[ce]) / 3.0, 665 (2.0 * ycoord[cs + 3] + ycoord[ce]) / 3.0, 666 xcoord[ce], 667 ycoord[ce] 668 ); 669 ylast = ycoord[ce]; 670 xlast = xcoord[ce]; 671 672 break; 673 674 default: 675 k1 = cs + nguide; 676 fg_rrcurveto(g, 677 (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0, 678 (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0, 679 (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0, 680 (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0, 681 (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0, 682 (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0 683 ); 684 685 for (k = cs + 2; k <= k1 - 1; k++) { 686 fg_rrcurveto(g, 687 (xcoord[k - 1] + 5.0 * xcoord[k]) / 6.0, 688 (ycoord[k - 1] + 5.0 * ycoord[k]) / 6.0, 689 (5.0 * xcoord[k] + xcoord[k + 1]) / 6.0, 690 (5.0 * ycoord[k] + ycoord[k + 1]) / 6.0, 691 (xcoord[k] + xcoord[k + 1]) / 2.0, 692 (ycoord[k] + ycoord[k + 1]) / 2.0 693 ); 694 695 } 696 697 fg_rrcurveto(g, 698 (xcoord[k1 - 1] + 5.0 * xcoord[k1]) / 6.0, 699 (ycoord[k1 - 1] + 5.0 * ycoord[k1]) / 6.0, 700 (2.0 * xcoord[k1] + xcoord[ce]) / 3.0, 701 (2.0 * ycoord[k1] + ycoord[ce]) / 3.0, 702 xcoord[ce], 703 ycoord[ce] 704 ); 705 xlast = xcoord[ce]; 706 ylast = ycoord[ce]; 707 708 break; 709 } 710 } 711 if (i >= contour_end) { 712 g_closepath(g); 713 first = 1; 714 i = contour_end + 1; 715 j++; 716 } else { 717 i++; 718 } 719 } 720 721 if (matrix) { 722 /* guess whether do we need to reverse the results */ 723 724 double x[3], y[3]; 725 int max = 0, from, to; 726 727 /* transform a triangle going in proper direction */ 728 /* 729 * the origin of triangle is in (0,0) so we know it in 730 * advance 731 */ 732 733 x[0] = y[0] = 0; 734 x[1] = matrix[0] * 0 + matrix[2] * 300; 735 y[1] = matrix[1] * 0 + matrix[3] * 300; 736 x[2] = matrix[0] * 300 + matrix[2] * 0; 737 y[2] = matrix[1] * 300 + matrix[3] * 0; 738 739 /* then find the topmost point */ 740 for (i = 0; i < 3; i++) 741 if (y[i] > y[max]) 742 max = i; 743 from = (max + 3 - 1) % 3; 744 to = (max + 1) % 3; 745 746 needreverse = 0; 747 748 /* special cases for horizontal lines */ 749 if (y[max] == y[from]) { 750 if (x[max] < y[from]) 751 needreverse = 1; 752 } else if (y[to] == y[from]) { 753 if (x[to] < x[max]) 754 needreverse = 1; 755 } else { /* generic case */ 756 if ((x[to] - x[max]) * (y[max] - y[from]) 757 > (x[max] - x[from]) * (y[to] - y[max])) 758 needreverse = 1; 759 } 760 761 if (needreverse) { 762 if (lge) { 763 assertpath(lge->next, __FILE__, __LINE__, g->name); 764 reversepathsfromto(lge->next, NULL); 765 } else { 766 assertpath(g->entries, __FILE__, __LINE__, g->name); 767 reversepaths(g); 768 } 769 } 770 } 771 } 772 773 static double 774 f2dot14( 775 short x 776 ) 777 { 778 short y = ntohs(x); 779 return (y >> 14) + ((y & 0x3fff) / 16384.0); 780 } 781 782 783 /* check that the pointer points within the file */ 784 /* returns 0 if pointer is good, 1 if bad */ 785 static int 786 badpointer( 787 void *ptr 788 ) 789 { 790 return (ptr < (void *)filebuffer || ptr >= (void *)filebuffer_end); 791 } 792 793 /* 794 * Externally accessible methods 795 */ 796 797 /* 798 * Open font and prepare to return information to the main driver. 799 * May print error and warning messages. 800 * Exit on error. 801 */ 802 803 static void 804 openfont( 805 char *fname, 806 char *arg /* unused now */ 807 ) 808 { 809 int i, j; 810 struct stat statbuf; 811 static struct { 812 void **tbpp; /* pointer to pointer to the table */ 813 char name[5]; /* table name */ 814 char optional; /* flag: table may be missing */ 815 } tables[] = { 816 { (void **)&name_table, "name", 0 }, 817 { (void **)&head_table, "head", 0 }, 818 { (void **)&hhea_table, "hhea", 0 }, 819 { (void **)&post_table, "post", 0 }, 820 { (void **)&glyf_start, "glyf", 0 }, 821 { (void **)&cmap_table, "cmap", 0 }, 822 { (void **)&kern_table, "kern", 1 }, 823 { (void **)&maxp_table, "maxp", 0 }, 824 { (void **)&hmtx_table, "hmtx", 0 }, 825 { (void **)&long_loca_table, "loca", 0 }, 826 { NULL, "", 0 } /* end of table */ 827 }; 828 829 if (stat(fname, &statbuf) == -1) { 830 fprintf(stderr, "**** Cannot access %s ****\n", fname); 831 exit(1); 832 } 833 if ((filebuffer = malloc(statbuf.st_size)) == NULL) { 834 fprintf(stderr, "**** Cannot malloc space for file ****\n"); 835 exit(1); 836 } 837 838 filebuffer_end = filebuffer + statbuf.st_size; 839 840 if ((ttf_file = fopen(fname, "rb")) == NULL) { 841 fprintf(stderr, "**** Cannot open file '%s'\n", fname); 842 exit(1); 843 } else { 844 WARNING_2 fprintf(stderr, "Processing file %s\n", fname); 845 } 846 847 if (fread(filebuffer, 1, statbuf.st_size, ttf_file) != statbuf.st_size) { 848 fprintf(stderr, "**** Could not read whole file \n"); 849 exit(1); 850 } 851 fclose(ttf_file); 852 853 directory = (TTF_DIRECTORY *) filebuffer; 854 855 if (ntohl(directory->sfntVersion) != 0x00010000) { 856 fprintf(stderr, 857 "**** Unknown File Version number [%x], or not a TrueType file\n", 858 directory->sfntVersion); 859 exit(1); 860 } 861 862 /* clear the tables */ 863 for(j=0; tables[j].tbpp != NULL; j++) 864 *(tables[j].tbpp) = NULL; 865 866 dir_entry = &(directory->list); 867 868 for (i = 0; i < ntohs(directory->numTables); i++) { 869 870 for(j=0; tables[j].tbpp != NULL; j++) 871 if (memcmp(dir_entry->tag, tables[j].name, 4) == 0) { 872 *(tables[j].tbpp) = (void *) (filebuffer + ntohl(dir_entry->offset)); 873 break; 874 } 875 876 if (memcmp(dir_entry->tag, "EBDT", 4) == 0 || 877 memcmp(dir_entry->tag, "EBLC", 4) == 0 || 878 memcmp(dir_entry->tag, "EBSC", 4) == 0) { 879 WARNING_1 fprintf(stderr, "Font contains bitmaps\n"); 880 } 881 dir_entry++; 882 } 883 884 for(j=0; tables[j].tbpp != NULL; j++) 885 if(!tables[j].optional && badpointer( *(tables[j].tbpp) )) { 886 fprintf(stderr, "**** File contains no required table '%s'\n", tables[j].name); 887 exit(1); 888 } 889 890 handle_name(); 891 892 handle_head(); 893 894 ttf_nglyphs = ntohs(maxp_table->numGlyphs); 895 896 enc_found_ms = enc_found_mac = 0; 897 } 898 899 /* 900 * Close font. 901 * Exit on error. 902 */ 903 904 static void 905 closefont( 906 void 907 ) 908 { 909 return; /* empty operation */ 910 } 911 912 /* 913 * Get the number of glyphs in font. 914 */ 915 916 static int 917 getnglyphs ( 918 void 919 ) 920 { 921 return ttf_nglyphs; 922 } 923 924 /* 925 * Get the names of the glyphs. 926 * Returns 0 if the names were assigned, non-zero if the font 927 * provides no glyph names. 928 */ 929 930 static int 931 glnames( 932 GLYPH *glyph_list 933 ) 934 { 935 int i, len, n, npost; 936 unsigned int format; 937 USHORT *name_index; 938 char *ptr, *p; 939 char **ps_name_ptr = (char **) malloc(ttf_nglyphs * sizeof(char *)); 940 int n_ps_names; 941 int ps_fmt_3 = 0; 942 943 format = ntohl(post_table->formatType); 944 945 if (format == 0x00010000) { 946 for (i = 0; i < 258 && i < ttf_nglyphs; i++) { 947 glyph_list[i].name = mac_glyph_names[i]; 948 } 949 } else if (format == 0x00020000) { 950 npost = ntohs(post_table->numGlyphs); 951 if (ttf_nglyphs != npost) { 952 /* This is an error in the font, but we can now cope */ 953 WARNING_1 fprintf(stderr, "**** Postscript table size mismatch %d/%d ****\n", 954 npost, ttf_nglyphs); 955 } 956 n_ps_names = 0; 957 name_index = &(post_table->glyphNameIndex); 958 959 /* This checks the integrity of the post table */ 960 for (i=0; i<npost; i++) { 961 n = ntohs(name_index[i]); 962 if (n > n_ps_names + 257) { 963 n_ps_names = n - 257; 964 } 965 } 966 967 ptr = (char *) post_table + 34 + (ttf_nglyphs << 1); 968 i = 0; 969 while (*ptr > 0 && i < n_ps_names) { 970 len = *ptr; 971 /* previously the program wrote nulls into the table. If the table 972 was corrupt, this could put zeroes anywhere, leading to obscure bugs, 973 so now I malloc space for the names. Yes it is much less efficient */ 974 975 if ((p = malloc(len+1)) == NULL) { 976 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); 977 exit(255); 978 } 979 980 ps_name_ptr[i] = p; 981 strncpy(p, ptr+1, len); 982 p[len] = '\0'; 983 i ++; 984 ptr += len + 1; 985 } 986 987 if (i != n_ps_names) 988 { 989 WARNING_2 fprintf (stderr, "** Postscript Name mismatch %d != %d **\n", 990 i, n_ps_names); 991 n_ps_names = i; 992 } 993 994 /* 995 * for (i=0; i<n_ps_names; i++) { fprintf(stderr, "i=%d, 996 * len=%d, name=%s\n", i, ps_name_len[i], ps_name_ptr[i]); } 997 */ 998 999 for (i = 0; i < npost; i++) { 1000 n = ntohs(name_index[i]); 1001 if (n < 258) { 1002 glyph_list[i].name = mac_glyph_names[n]; 1003 } else if (n < 258 + n_ps_names) { 1004 glyph_list[i].name = ps_name_ptr[n - 258]; 1005 } else { 1006 glyph_list[i].name = malloc(16); 1007 sprintf(glyph_list[i].name, "_g_%d", i); 1008 WARNING_2 fprintf(stderr, 1009 "Glyph No. %d has no postscript name, becomes %s\n", 1010 i, glyph_list[i].name); 1011 } 1012 } 1013 /* Now fake postscript names for all those beyond the end of the table */ 1014 if (npost < ttf_nglyphs) { 1015 for (i=npost; i<ttf_nglyphs; i++) { 1016 if ((glyph_list[i].name = malloc(16)) == NULL) 1017 { 1018 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); 1019 exit(255); 1020 } 1021 sprintf(glyph_list[i].name, "_g_%d", i); 1022 WARNING_2 fprintf(stderr, 1023 "Glyph No. %d has no postscript name, becomes %s\n", 1024 i, glyph_list[i].name); 1025 } 1026 } 1027 } else if (format == 0x00030000) { 1028 WARNING_3 fputs("No postscript table, using default\n", stderr); 1029 ps_fmt_3 = 1; 1030 } else if (format == 0x00028000) { 1031 ptr = (char *) &(post_table->numGlyphs); 1032 for (i = 0; i < ttf_nglyphs; i++) { 1033 glyph_list[i].name = mac_glyph_names[i + ptr[i]]; 1034 } 1035 } else { 1036 fprintf(stderr, 1037 "**** Postscript table in wrong format %x ****\n", 1038 format); 1039 exit(1); 1040 } 1041 1042 return ps_fmt_3; 1043 } 1044 1045 /* 1046 * Get the metrics of the glyphs. 1047 */ 1048 1049 static void 1050 glmetrics( 1051 GLYPH *glyph_list 1052 ) 1053 { 1054 int i; 1055 int n_hmetrics = ntohs(hhea_table->numberOfHMetrics); 1056 GLYPH *g; 1057 LONGHORMETRIC *hmtx_entry = hmtx_table; 1058 FWORD *lsblist; 1059 1060 for (i = 0; i < n_hmetrics; i++) { 1061 g = &(glyph_list[i]); 1062 g->width = ntohs(hmtx_entry->advanceWidth); 1063 g->lsb = ntohs(hmtx_entry->lsb); 1064 hmtx_entry++; 1065 } 1066 1067 lsblist = (FWORD *) hmtx_entry; 1068 hmtx_entry--; 1069 1070 for (i = n_hmetrics; i < ttf_nglyphs; i++) { 1071 g = &(glyph_list[i]); 1072 g->width = ntohs(hmtx_entry->advanceWidth); 1073 g->lsb = ntohs(lsblist[i - n_hmetrics]); 1074 } 1075 1076 for (i = 0; i < ttf_nglyphs; i++) { 1077 g = &(glyph_list[i]); 1078 get_glyf_table(i, &glyf_table, &g->ttf_pathlen); 1079 1080 g->xMin = (short)ntohs(glyf_table->xMin); 1081 g->xMax = (short)ntohs(glyf_table->xMax); 1082 g->yMin = (short)ntohs(glyf_table->yMin); 1083 g->yMax = (short)ntohs(glyf_table->yMax); 1084 } 1085 1086 } 1087 1088 1089 static void 1090 handle_ms_encoding( 1091 GLYPH *glyph_list, 1092 int *encoding, 1093 int *unimap 1094 ) 1095 { 1096 int j, k, kk, set_ok; 1097 USHORT start, end, ro; 1098 short delta, n; 1099 1100 for (j = 0; j < cmap_n_segs - 1; j++) { 1101 start = ntohs(cmap_seg_start[j]); 1102 end = ntohs(cmap_seg_end[j]); 1103 delta = ntohs(cmap_idDelta[j]); 1104 ro = ntohs(cmap_idRangeOffset[j]); 1105 1106 for (k = start; k <= end; k++) { 1107 if (ro == 0) { 1108 n = k + delta; 1109 } else { 1110 n = ntohs(*((ro >> 1) + (k - start) + 1111 &(cmap_idRangeOffset[j]))); 1112 if (delta != 0) 1113 { 1114 /* Not exactly sure how to deal with this circumstance, 1115 I suspect it never occurs */ 1116 n += delta; 1117 fprintf (stderr, 1118 "rangeoffset and delta both non-zero - %d/%d", 1119 ro, delta); 1120 } 1121 } 1122 if(n<0 || n>=ttf_nglyphs) { 1123 WARNING_1 fprintf(stderr, "Font contains a broken glyph code mapping, ignored\n"); 1124 continue; 1125 } 1126 if (glyph_list[n].orig_code != -1) { 1127 #if 0 1128 if (strcmp(glyph_list[n].name, ".notdef") != 0) { 1129 WARNING_2 fprintf(stderr, 1130 "Glyph %s has >= two encodings (A), %4.4x & %4.4x\n", 1131 glyph_list[n].name, 1132 glyph_list[n].orig_code, 1133 k); 1134 } 1135 #endif 1136 set_ok = 0; 1137 } else { 1138 set_ok = 1; 1139 } 1140 if (enc_type==1 || forcemap) { 1141 kk = unicode_rev_lookup(k); 1142 if(ISDBG(UNICODE)) 1143 fprintf(stderr, "Unicode %s - 0x%04x\n",glyph_list[n].name,k); 1144 if (set_ok) { 1145 glyph_list[n].orig_code = k; 1146 /* glyph_list[n].char_no = kk; */ 1147 } 1148 if (kk >= 0 && kk < ENCTABSZ && encoding[kk] == -1) 1149 encoding[kk] = n; 1150 } else { 1151 if ((k & 0xff00) == 0xf000) { 1152 if( encoding[k & 0x00ff] == -1 ) { 1153 encoding[k & 0x00ff] = n; 1154 if (set_ok) { 1155 /* glyph_list[n].char_no = k & 0x00ff; */ 1156 glyph_list[n].orig_code = k; 1157 } 1158 } 1159 } else { 1160 if (set_ok) { 1161 /* glyph_list[n].char_no = k; */ 1162 glyph_list[n].orig_code = k; 1163 } 1164 WARNING_2 fprintf(stderr, 1165 "Glyph %s has non-symbol encoding %4.4x\n", 1166 glyph_list[n].name, 1167 k & 0xffff); 1168 /* 1169 * just use the code 1170 * as it is 1171 */ 1172 if ((k & ~0xff) == 0 && encoding[k] == -1 ) 1173 encoding[k] = n; 1174 } 1175 } 1176 } 1177 } 1178 } 1179 1180 static void 1181 handle_mac_encoding( 1182 GLYPH *glyph_list, 1183 int *encoding, 1184 int *unimap 1185 ) 1186 { 1187 short n; 1188 int j, size; 1189 1190 size = ntohs(encoding0->length) - 6; 1191 for (j = 0; j < size; j++) { 1192 n = encoding0->glyphIdArray[j]; 1193 if (glyph_list[n].char_no != -1) { 1194 WARNING_2 fprintf(stderr, 1195 "Glyph %s has >= two encodings (B), %4.4x & %4.4x\n", 1196 glyph_list[n].name, 1197 glyph_list[n].char_no, 1198 j); 1199 } else { 1200 if (j < ENCTABSZ) { 1201 if(encoding[j] == -1) { 1202 glyph_list[n].char_no = j; 1203 encoding[j] = n; 1204 } 1205 } 1206 } 1207 } 1208 } 1209 1210 /* 1211 * Get the original encoding of the font. 1212 * Returns 1 for if the original encoding is Unicode, 2 if the 1213 * original encoding is other 16-bit, 0 if 8-bit. 1214 */ 1215 1216 static int 1217 glenc( 1218 GLYPH *glyph_list, 1219 int *encoding, 1220 int *unimap 1221 ) 1222 { 1223 int num_tables = ntohs(cmap_table->numberOfEncodingTables); 1224 BYTE *ptr; 1225 int i, format, offset, seg_c2, found; 1226 int platform, encoding_id; 1227 TTF_CMAP_ENTRY *table_entry; 1228 TTF_CMAP_FMT4 *encoding4; 1229 1230 if(enc_found_ms) { 1231 handle_ms_encoding(glyph_list, encoding, unimap); 1232 return enc_type; 1233 } else if(enc_found_mac) { 1234 handle_mac_encoding(glyph_list, encoding, unimap); 1235 return 0; 1236 } 1237 1238 enc_type = 0; 1239 found = 0; 1240 1241 for (i = 0; i < num_tables && !found; i++) { 1242 table_entry = &(cmap_table->encodingTable[i]); 1243 offset = ntohl(table_entry->offset); 1244 encoding4 = (TTF_CMAP_FMT4 *) ((BYTE *) cmap_table + offset); 1245 format = ntohs(encoding4->format); 1246 platform = ntohs(table_entry->platformID); 1247 encoding_id = ntohs(table_entry->encodingID); 1248 1249 if (format != 4) 1250 continue; 1251 1252 if(force_pid != -1) { 1253 if(force_pid != platform || encoding_id != force_eid) 1254 continue; 1255 WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n", 1256 force_pid, force_eid); 1257 enc_type = 1; 1258 } else { 1259 if (platform == 3 ) { 1260 switch (encoding_id) { 1261 case 0: 1262 WARNING_1 fputs("Found Symbol Encoding\n", stderr); 1263 break; 1264 case 1: 1265 WARNING_1 fputs("Found Unicode Encoding\n", stderr); 1266 enc_type = 1; 1267 break; 1268 default: 1269 WARNING_1 { 1270 fprintf(stderr, 1271 "****MS Encoding ID %d not supported****\n", 1272 encoding_id); 1273 fputs("Treating it like Symbol encoding\n", stderr); 1274 } 1275 break; 1276 } 1277 } else 1278 continue; 1279 } 1280 1281 found = 1; 1282 seg_c2 = ntohs(encoding4->segCountX2); 1283 cmap_n_segs = seg_c2 >> 1; 1284 ptr = (BYTE *) encoding4 + 14; 1285 cmap_seg_end = (USHORT *) ptr; 1286 cmap_seg_start = (USHORT *) (ptr + seg_c2 + 2); 1287 cmap_idDelta = (short *) (ptr + (seg_c2 * 2) + 2); 1288 cmap_idRangeOffset = (short *) (ptr + (seg_c2 * 3) + 2); 1289 enc_found_ms = 1; 1290 1291 handle_ms_encoding(glyph_list, encoding, unimap); 1292 } 1293 1294 if (!found && force_pid == -1) { 1295 WARNING_1 fputs("No Microsoft encoding, looking for MAC encoding\n", stderr); 1296 for (i = 0; i < num_tables && !found; i++) { 1297 table_entry = &(cmap_table->encodingTable[i]); 1298 offset = ntohl(table_entry->offset); 1299 encoding0 = (TTF_CMAP_FMT0 *) ((BYTE *) cmap_table + offset); 1300 format = ntohs(encoding0->format); 1301 platform = ntohs(table_entry->platformID); 1302 encoding_id = ntohs(table_entry->encodingID); 1303 1304 if (format == 0) { 1305 found = 1; 1306 enc_found_mac = 1; 1307 1308 handle_mac_encoding(glyph_list, encoding, unimap); 1309 } 1310 } 1311 } 1312 1313 if (!found && force_pid == -1) { 1314 WARNING_1 fputs("No MAC encoding either, looking for any format 4 encoding\n", stderr); 1315 for (i = 0; i < num_tables && !found; i++) { 1316 table_entry = &(cmap_table->encodingTable[i]); 1317 offset = ntohl(table_entry->offset); 1318 encoding4 = (TTF_CMAP_FMT4 *) ((BYTE *) cmap_table + offset); 1319 format = ntohs(encoding4->format); 1320 platform = ntohs(table_entry->platformID); 1321 encoding_id = ntohs(table_entry->encodingID); 1322 1323 if (format != 4) 1324 continue; 1325 1326 WARNING_1 fprintf(stderr, "Found a last ditch encoding PID=%d/EID=%d, treating it as Unicode.\n", 1327 platform, encoding_id); 1328 found = 1; 1329 enc_type = 1; 1330 seg_c2 = ntohs(encoding4->segCountX2); 1331 cmap_n_segs = seg_c2 >> 1; 1332 ptr = (BYTE *) encoding4 + 14; 1333 cmap_seg_end = (USHORT *) ptr; 1334 cmap_seg_start = (USHORT *) (ptr + seg_c2 + 2); 1335 cmap_idDelta = (short *) (ptr + (seg_c2 * 2) + 2); 1336 cmap_idRangeOffset = (short *) (ptr + (seg_c2 * 3) + 2); 1337 enc_found_ms = 1; 1338 1339 handle_ms_encoding(glyph_list, encoding, unimap); 1340 1341 } 1342 } 1343 1344 if (!found) { 1345 if(force_pid != -1) { 1346 fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n", 1347 force_pid, force_eid); 1348 } 1349 fprintf(stderr, "**** No Recognised Encoding Table ****\n"); 1350 if(warnlevel >= 2) { 1351 fprintf(stderr, "Font contains the following unsupported encoding tables:\n"); 1352 for (i = 0; i < num_tables && !found; i++) { 1353 table_entry = &(cmap_table->encodingTable[i]); 1354 offset = ntohl(table_entry->offset); 1355 encoding0 = (TTF_CMAP_FMT0 *) ((BYTE *) cmap_table + offset); 1356 format = ntohs(encoding0->format); 1357 platform = ntohs(table_entry->platformID); 1358 encoding_id = ntohs(table_entry->encodingID); 1359 1360 fprintf(stderr, " format=%d platform=%d encoding_id=%d\n", 1361 format, platform, encoding_id); 1362 } 1363 } 1364 exit(1); 1365 } 1366 1367 return enc_type; 1368 } 1369 1370 /* 1371 * Get the font metrics 1372 */ 1373 static void 1374 fnmetrics( 1375 struct font_metrics *fm 1376 ) 1377 { 1378 char *str; 1379 static int fieldstocheck[]= {2,4,6}; 1380 int i, j, len; 1381 1382 fm->italic_angle = (short) (ntohs(post_table->italicAngle.upper)) + 1383 ((short) ntohs(post_table->italicAngle.lower) / 65536.0); 1384 fm->underline_position = (short) ntohs(post_table->underlinePosition); 1385 fm->underline_thickness = (short) ntohs(post_table->underlineThickness); 1386 fm->is_fixed_pitch = ntohl(post_table->isFixedPitch); 1387 1388 fm->ascender = (short)ntohs(hhea_table->ascender); 1389 fm->descender = (short)ntohs(hhea_table->descender); 1390 1391 fm->units_per_em = ntohs(head_table->unitsPerEm); 1392 1393 fm->bbox[0] = (short) ntohs(head_table->xMin); 1394 fm->bbox[1] = (short) ntohs(head_table->yMin); 1395 fm->bbox[2] = (short) ntohs(head_table->xMax); 1396 fm->bbox[3] = (short) ntohs(head_table->yMax); 1397 1398 fm->name_copyright = name_fields[0]; 1399 fm->name_family = name_fields[1]; 1400 fm->name_style = name_fields[2]; 1401 fm->name_full = name_fields[4]; 1402 fm->name_version = name_fields[5]; 1403 fm->name_ps = name_fields[6]; 1404 1405 /* guess the boldness from the font names */ 1406 fm->force_bold=0; 1407 1408 for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(int); i++) { 1409 str = name_fields[fieldstocheck[i]]; 1410 len = strlen(str); 1411 for(j=0; j<len; j++) { 1412 if( (str[j]=='B' 1413 || str[j]=='b' 1414 && ( j==0 || !isalpha(str[j-1]) ) 1415 ) 1416 && !strncmp("old",&str[j+1],3) 1417 && (j+4 >= len || !islower(str[j+4])) 1418 ) { 1419 fm->force_bold=1; 1420 break; 1421 } 1422 } 1423 } 1424 } 1425 1426 /* 1427 * Get the path of contrours for a glyph. 1428 */ 1429 1430 static void 1431 glpath( 1432 int glyphno, 1433 GLYPH *glyf_list 1434 ) 1435 { 1436 double matrix[6]; 1437 GLYPH *g; 1438 1439 g = &glyph_list[glyphno]; 1440 1441 matrix[0] = matrix[3] = 1.0; 1442 matrix[1] = matrix[2] = matrix[4] = matrix[5] = 0.0; 1443 draw_composite_glyf(g, glyf_list, glyphno, matrix, 0 /*level*/); 1444 } 1445 1446 /* 1447 * Get the kerning data. 1448 */ 1449 1450 static void 1451 kerning( 1452 GLYPH *glyph_list 1453 ) 1454 { 1455 TTF_KERN_SUB *subtable; 1456 TTF_KERN_ENTRY *kern_entry; 1457 int i, j; 1458 int ntables; 1459 int npairs; 1460 char *ptr; 1461 1462 if(kern_table == NULL) { 1463 WARNING_1 fputs("No Kerning data\n", stderr); 1464 return; 1465 } 1466 if(badpointer(kern_table)) { 1467 fputs("**** Defective Kerning table, ignored\n", stderr); 1468 return; 1469 } 1470 1471 ntables = ntohs(kern_table->nTables); 1472 ptr = (char *) kern_table + 4; 1473 1474 for (i = 0; i < ntables; i++) { 1475 subtable = (TTF_KERN_SUB *) ptr; 1476 if ((ntohs(subtable->coverage) & 0xff00) == 0) { 1477 npairs = (short) ntohs(subtable->nPairs); 1478 kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB)); 1479 1480 kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB)); 1481 for (j = 0; j < npairs; j++) { 1482 if( kern_entry->value != 0) 1483 addkernpair(ntohs(kern_entry->left), 1484 ntohs(kern_entry->right), (short)ntohs(kern_entry->value)); 1485 kern_entry++; 1486 } 1487 } 1488 ptr += subtable->length; 1489 } 1490 } 1491
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 |