[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
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 }
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 |