[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 /******************************************************************** 2 * * 3 * Title: pfm2afm - Convert Windows .pfm files to .afm files * 4 * * 5 * Author: Ken Borgendale 10/9/91 Version 1.0 * 6 * * 7 * Function: * 8 * Convert a Windows .pfm (Printer Font Metrics) file to a * 9 * .afm (Adobe Font Metrics) file. The purpose of this is * 10 * to allow fonts put out for Windows to be used with OS/2. * 11 * * 12 * Syntax: * 13 * pfm2afm infile [outfile] -a * 14 * * 15 * Copyright: * 16 * pfm2afm - Copyright (C) IBM Corp., 1991 * 17 * * 18 * This code is released for public use as long as the * 19 * copyright remains intact. This code is provided asis * 20 * without any warrenties, express or implied. * 21 * * 22 * Notes: * 23 * 1. Much of the information in the original .afm file is * 24 * lost when the .pfm file is created, and thus cannot be * 25 * reconstructed by this utility. This is especially true * 26 * of data for characters not in the Windows character set. * 27 * * 28 * 2. This module is coded to be compiled by the MSC 6.0. * 29 * For other compilers, be careful of the packing of the * 30 * PFM structure. * 31 * * 32 ********************************************************************/ 33 34 35 /******************************************************************** 36 * Modified: Russell Lang <[email protected]> * 37 * 1994-01-06 Version 1.1 * 38 * Compiles with EMX/GCC * 39 * Changed to AFM 3.0 * 40 * Put PFM Copyright in Notice instead of Comment * 41 * Added ItalicAngle * 42 * Added UnderlinePosition * 43 * Added UnderlineThickness * 44 * * 45 * Modified 1995-03-10 rjl (fixes from Norman Walsh) * 46 * Dodge compiler bug when creating descender * 47 ********************************************************************/ 48 49 50 /******************************************************************** 51 * Modified: Olivier Plathey <[email protected]> * 52 * 2002-08-10 Version 1.11 * 53 * Compiles with MinGW * 54 * Output Descender as negative value * 55 * Removed double spaces in character entries * 56 * * 57 * 2005-03-12 Version 1.12 * 58 * Doubled size of BUFSIZE * 59 ********************************************************************/ 60 61 #include <stdio.h> 62 #include <string.h> 63 #include <stdlib.h> 64 #include "pfm2afm.h" 65 66 #define BUFSIZE 8192 67 /* 68 * Function Prototypes 69 */ 70 void help (void); 71 void parseargs (int argc, uchar * * argv); 72 void openpfm(void); 73 void openafm(void); 74 void putheader(void); 75 void putchartab(void); 76 void outchar(int code, ushort width, const uchar * name); 77 void putkerntab(KERN * kerntab, int kerncnt); 78 void puttrailer(void); 79 void outval(int val); 80 void outreal(float val); 81 82 /* 83 * Global variables 84 */ 85 FILE * inf; /* Input file */ 86 FILE * outf; /* Output file */ 87 uchar infname[272]; /* Input file name */ 88 uchar outfname[272]; /* Output file name */ 89 uchar * buffer; /* .pfm read buffer */ 90 PFM * pfm; /* .pfm header */ 91 PSX * psx; /* Metrics extension */ 92 93 uchar debugflag; /* Debug information flag */ 94 uchar allflag; 95 uchar isMono; /* Font is mono-spaced */ 96 97 /* 98 * Do the function 99 */ 100 MAINENT main(int argc, uchar * *argv) { 101 102 /* Parse arguments */ 103 parseargs(argc, argv); 104 105 /* Open and check input file */ 106 openpfm(); 107 108 /* Make output file name and open */ 109 openafm(); 110 111 /* Put out header information */ 112 putheader(); 113 114 /* Put out character table */ 115 putchartab(); 116 117 /* Put out kerning table */ 118 if (pfm->kernpairs) { 119 putkerntab((KERN *)(buffer+pfm->kernpairs+2), 120 *(ushort *)(buffer+pfm->kernpairs)); 121 } 122 if (pfm->kerntrack) { /* rjl */ 123 fprintf(stderr, "Ignoring track kern table\n"); 124 } 125 126 /* Put out trailer line */ 127 puttrailer(); 128 129 /* Cleanup */ 130 if (buffer) 131 free(buffer); 132 fclose(inf); 133 fclose(outf); 134 return 0; 135 } 136 137 /* 138 * Put out normal help 139 */ 140 void help (void) { 141 puts("\npfm2afm - Convert Windows pfm to afm - Version 1.11\n"); 142 puts("This utility converts Windows pfm files for Adobe type 1 fonts"); 143 puts("to afm files for use on OS/2. This allows fonts created for"); 144 puts("Windows, and shipped without the afm file to be used on OS/2.\n"); 145 puts("pfm2afm infile [outfile] -opts"); 146 puts(" The extension .pfm is added to the infile if it has none."); 147 puts(" The outfile is defaulted from the input file name."); 148 puts(" -a = All codepoints in range"); 149 puts("\nNote that pfm files are missing some of the data necessary to"); 150 puts("construct afm files, so the conversion may not be perfect.\n"); 151 puts("Ken Borgendale - [email protected]\n"); 152 puts("Russell Lang - [email protected]\n"); 153 exit (1); 154 } 155 156 157 /* 158 * Parse arguments. This is the full arg treatment, which is sort of 159 * overkill for one option, but it allows more to be added later. 160 */ 161 void parseargs (int argc, uchar * * argv) { 162 uchar swchar; 163 int argcnt; 164 int filecnt; 165 uchar * argp; 166 167 argcnt = 1; 168 filecnt = 0; 169 /* Read the arguments and decide what we are doing */ 170 while (argcnt<argc) { 171 argp = argv[argcnt]; 172 /* Check for switches. Files may not start with - or / */ 173 if (*argp == '-' || *argp == OPTSEP) { 174 /* Process switches */ 175 swchar = (uchar)tolower(argp[1]); 176 argp += 2; 177 switch (swchar) { 178 case '?': 179 help(); /* Does not return */ 180 181 /* All codepoints */ 182 case 'a': 183 allflag = 0; 184 break; 185 186 /* Debug option */ 187 case 'd': 188 debugflag = 1; 189 break; 190 191 default: 192 fputs("Unknown options: ", stderr); 193 fputs(argp-2, stderr); 194 fputc('\n', stderr); 195 } 196 } else { 197 if (*argp=='?') { 198 help(); /* Does not return */ 199 } 200 switch(++filecnt) { 201 case 1: 202 strcpy(infname, argp); 203 break; 204 case 2: 205 strcpy(outfname, argp); 206 break; 207 default: 208 fputs("Extra parameter ignored: ", stderr); 209 fputs(argp, stderr); 210 fputc('\n', stderr); 211 } 212 } 213 argcnt++; 214 } 215 216 /* We require the input file name */ 217 if (!filecnt) help(); 218 } 219 220 221 /* 222 * Open the .pfm file and check it 223 */ 224 void openpfm(void) { 225 uchar * cp; 226 int len; 227 228 /* Check for a file extension */ 229 cp = infname+strlen(infname)-1; 230 while (cp>=infname && *cp!='.' && *cp!='\\' && *cp!='/' && *cp!=':') 231 cp--; 232 if (*cp!='.') 233 strcat(infname, ".pfm"); 234 /* Open the file */ 235 inf = fopen(infname, "rb"); 236 if (!inf) { 237 fputs("Unable to open input file - ", stderr); 238 fputs(infname, stderr); 239 fputc('\n', stderr); 240 exit(4); 241 } 242 /* Read the file */ 243 buffer = malloc(BUFSIZE); 244 len = fread(buffer, 1, BUFSIZE, inf); 245 if (len<256 || len==BUFSIZE) { 246 fputs("Input file read error - ", stderr); 247 fputs(infname, stderr); 248 fputc('\n', stderr); 249 exit(6); 250 } 251 /* Do consistency check */ 252 pfm = (PFM *) buffer; 253 if (len != (int)pfm->len && /* Check length field matches file length */ 254 pfm->extlen != 30 && /* Check length of PostScript extension */ 255 pfm->fontname>75 && pfm->fontname<512) { /* Font name specified */ 256 fputs("Not a valid Windows type 1 .pfm file - ", stderr); 257 fputs(infname, stderr); 258 fputc('\n', stderr); 259 exit(6); 260 } 261 } 262 263 /* 264 * Create the .afm file 265 */ 266 void openafm(void) { 267 uchar * cp; 268 269 /* Add .pfm if there is none */ 270 if (!*outfname) { 271 strcpy(outfname, infname); 272 cp = outfname+strlen(outfname)-1; 273 while (cp >= outfname && *cp!='.' && *cp!='\\' && *cp!='/' && *cp!=':') 274 cp--; 275 if (*cp=='.') *cp=0; 276 strcat(outfname, ".afm"); 277 } 278 /* Open the file */ 279 outf = fopen(outfname, "w"); 280 if (!outf) { 281 fputs("Unable to open output file - ", stderr); 282 fputs(outfname, stderr); 283 fputc('\n', stderr); 284 exit(5); 285 } 286 } 287 288 /* 289 * Put out the header of the .afm file 290 */ 291 void putheader(void) { 292 uchar * cp; 293 int temp; /* rjl 1995-03-10 */ 294 295 fputs("StartFontMetrics 3.0\n", outf); 296 if (*pfm->copyright) { 297 fputs("Notice ", outf); 298 fputs(pfm->copyright, outf); 299 fputc('\n', outf); 300 } 301 fputs("FontName ", outf); 302 fputs(buffer+pfm->fontname, outf); 303 fputs("\nEncodingScheme ", outf); 304 if (pfm->charset) { 305 fputs("FontSpecific\n", outf); 306 } else { 307 fputs("AdobeStandardEncoding\n", outf); 308 } 309 /* 310 * The .pfm is missing full name, so construct from font name by 311 * changing the hyphen to a space. This actually works in a lot 312 * of cases. 313 */ 314 fputs("FullName ", outf); 315 cp = buffer+pfm->fontname; 316 while (*cp) { 317 if (*cp=='-') *cp=' '; 318 fputc(*cp, outf); 319 cp++; 320 } 321 if (pfm->face) { 322 fputs("\nFamilyName ", outf); 323 fputs(buffer+pfm->face, outf); 324 } 325 326 fputs("\nWeight ", outf); 327 if (pfm->weight>475) fputs("Bold", outf); 328 else if (pfm->weight<325 && pfm->weight) 329 fputs("Light", outf); 330 else fputs("Medium", outf); 331 332 /* 333 * The mono flag in the pfm actually indicates whether there is a 334 * table of font widths, not if they are all the same. 335 */ 336 fputs("\nIsFixedPitch ", outf); 337 if (!(pfm->kind&1) || /* Flag for mono */ 338 pfm->avgwidth == pfm->maxwidth ) { /* Avg width = max width */ 339 fputs("true", outf); 340 isMono = 1; 341 } else { 342 fputs("false", outf); 343 isMono = 0; 344 } 345 346 /* 347 * The font bounding box is lost, but try to reconstruct it. 348 * Much of this is just guess work. The bounding box is required in 349 * the .afm, but is not used by the PM font installer. 350 */ 351 psx = (PSX *)(buffer+pfm->psext); 352 fputs("\nFontBBox", outf); 353 if (isMono) outval(-20); /* Just guess at left bounds */ 354 else outval(-100); 355 temp = psx->descender; /* rjl 1995-03-10 */ 356 temp = -(temp+5); /* rjl 1995-03-10 */ 357 outval(temp); /* Descender is given as positive value */ /* rjl 1995-03-10 */ 358 /* outval(-(psx->descender+5)); /* Descender is given as positive value */ 359 outval(pfm->maxwidth+10); 360 outval(pfm->ascent+5); 361 362 /* 363 * Give other metrics that were kept 364 */ 365 fputs("\nCapHeight", outf); 366 outval((int)psx->capheight); 367 fputs("\nXHeight", outf); 368 outval((int)psx->xheight); 369 fputs("\nDescender", outf); 370 outval((int)-psx->descender); /* output negative value*/ 371 fputs("\nAscender", outf); 372 /* outval((int)psx->ascender); */ 373 outval((int)pfm->ascent); /* rjl */ 374 /* extra keys added by rjl */ 375 if (psx->len >= sizeof(psx)) { 376 fputs("\nItalicAngle", outf); 377 outreal(psx->slant/10.0); 378 fputs("\nUnderlinePosition", outf); 379 outval((int)-psx->underlineoffset); 380 fputs("\nUnderlineThickness", outf); 381 outval((int)psx->underlinewidth); 382 } 383 fputc('\n', outf); 384 } 385 386 /* 387 * Put out the character tables. According to the .afm spec, the 388 * characters must be put out sorted in encoding order. 389 * 390 * Most Windows .pfm files have the characters in the range 20-ff in 391 * the Windows code page (819 + quotes). 392 */ 393 void putchartab(void) { 394 int count, i, j; 395 ushort spwidth; 396 ushort * ctab; 397 uchar back[256]; 398 399 /* 400 * Compute the count by getting rid of non-existant chars. This 401 * is complicated by the fact that Windows encodes the .pfm file 402 * with a space metric for non-existant chars. 403 */ 404 memset(back, 0, 256); 405 count = pfm->lastchar - pfm->firstchar + 1; 406 spwidth = 0; 407 /* Compute width of space */ 408 ctab = (ushort *)(buffer+pfm->chartab); 409 if (pfm->firstchar>=' ' && pfm->lastchar<=' ') { 410 spwidth = ctab[' '-pfm->firstchar]; 411 } 412 413 if (!pfm->charset) { 414 /* 415 * Loop thru the chars, deleting those that we presume 416 * do not really exist. 417 */ 418 for (i=pfm->firstchar; i<=(int)pfm->lastchar; i++) { 419 if (Win2PSStd[i]) { 420 back[Win2PSStd[i]] = (uchar)i; 421 } else { 422 if (!allflag) { 423 if (*ctab==spwidth) { /* Default width */ 424 if (!(WinClass[i]&1)) { 425 *ctab = 0; 426 count--; 427 } 428 } else { /* Not default width */ 429 if (!WinClass[i]) { 430 *ctab = 0; 431 count--; 432 } 433 } 434 } 435 } 436 ctab++; 437 } 438 } 439 440 /* Put out the header */ 441 fputs("StartCharMetrics", outf); 442 outval(count); 443 fputc('\n', outf); 444 445 /* Put out all encoded chars */ 446 if (pfm->charset) { 447 /* 448 * If the charset is not the Windows standard, just put out 449 * unnamed entries. 450 */ 451 ctab = (ushort *)(buffer+pfm->chartab); 452 for (i=pfm->firstchar; i<=(int)pfm->lastchar; i++) { 453 if (*ctab) { 454 outchar(i, *ctab, NULL); 455 } 456 ctab++; 457 } 458 } else { 459 ctab = (ushort *)(buffer+pfm->chartab); 460 for (i=0; i<256; i++) { 461 j = back[i]; 462 if (j) { 463 outchar(i, ctab[j-pfm->firstchar], WinChars[j]); 464 ctab[j-pfm->firstchar] = 0; 465 } 466 } 467 /* Put out all non-encoded chars */ 468 ctab = (ushort *)(buffer+pfm->chartab); 469 for (i=pfm->firstchar; i<=(int)pfm->lastchar; i++) { 470 if (*ctab) { 471 outchar(-1, *ctab, WinChars[i]); 472 } 473 ctab++; 474 } 475 } 476 /* Put out the trailer */ 477 fputs("EndCharMetrics\n", outf); 478 } 479 480 /* 481 * Output a character entry 482 */ 483 void outchar(int code, ushort width, const uchar * name) { 484 fputs("C", outf); 485 outval(code); 486 fputs(" ; WX", outf); 487 outval(width); 488 if (name) { 489 fputs(" ; N ", outf); 490 fputs(name, outf); 491 } 492 fputs(" ;\n", outf); 493 } 494 495 /* 496 * Put out the kerning tables 497 */ 498 void putkerntab(KERN * kerntab, int kerncnt) { 499 int count, i; 500 KERN * kp; 501 502 /* Count non-zero kern pairs */ 503 count = kerncnt; 504 kp = kerntab; 505 for (i=0; i<kerncnt; i++) { 506 if (!kp->kern) 507 count--; 508 kp++; 509 } 510 511 /* Put out header */ 512 fputs("StartKernData\nStartKernPairs", outf); 513 outval(count); 514 fputc('\n', outf); 515 516 /* Put out each non-zero pair */ 517 kp = kerntab; 518 while (kerncnt) { 519 if (kp->kern) { 520 fputs("KPX ", outf); 521 fputs(WinChars[kp->first], outf); 522 fputc(' ', outf); 523 fputs(WinChars[kp->second], outf); 524 outval((int)kp->kern); 525 fputc('\n', outf); 526 } 527 kp++; 528 kerncnt--; 529 } 530 531 /* Put out trailer */ 532 fputs("EndKernPairs\nEndKernData\n", outf); 533 } 534 535 /* 536 * Put out the trailer of the .afm file 537 */ 538 void puttrailer(void) { 539 fputs("EndFontMetrics\n", outf); 540 } 541 542 /* 543 * Output a decimal value 544 */ 545 void outval(int v) { 546 char chx[16]; 547 #ifdef unix 548 sprintf(chx, "%d", v); /* rjl 1995-03-10 */ 549 #else 550 itoa(v, chx, 10); 551 #endif 552 fputc(' ', outf); 553 fputs(chx, outf); 554 } 555 556 /* 557 * Output a real value 558 */ 559 void outreal(float v) { 560 fprintf(outf," %g",v); 561 }
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 |