|
|
1.1 ! root 1: //-------------------------------------------------------------------------- ! 2: // ! 3: // Module Name: AFMTOPFM.C ! 4: // ! 5: // This module of the afm compiler parses the afm file and collects ! 6: // information in the PFM structure. It then passes control to the ! 7: // pfm module which outputs the pfm file. ! 8: // ! 9: // USAGE: AFM <AFM filename> <MS database filename> ! 10: // output is filename.pfm. ! 11: // ! 12: // Author: Kent Settle (kentse) ! 13: // Created: 18-Mar-1991 ! 14: // ! 15: // Copyright (c) 1988 - 1993 Microsoft Corporation ! 16: //-------------------------------------------------------------------------- ! 17: ! 18: #include <string.h> ! 19: #include "pscript.h" ! 20: #include "mapping.h" ! 21: #include "tables.h" ! 22: ! 23: int _fltused; // HEY, it shut's up the linker. That's why it's here. ! 24: ! 25: #define U_SPACE 0x20 ! 26: #define U_SYMBOL_BULLET 0x00B7 ! 27: #define U_BULLET 0x2022 ! 28: ! 29: // Alias Family Tables. ! 30: ! 31: static char *TimesAlias[] = {"Times", "Tms Rmn", "Times Roman", "TimesRoman", ! 32: "TmsRmn", "Varitimes", "Dutch", ! 33: "Times New Roman", "TimesNewRomanPS", ! 34: NULL }; ! 35: ! 36: static char *HelveticaAlias[] = {"Helvetica", "Helv", "Arial", "Swiss", NULL}; ! 37: ! 38: static char *CourierAlias[] = {"Courier", "Courier New", NULL}; ! 39: ! 40: static char *HelveticaNarrowAlias[] = {"Helvetica-Narrow", "Helvetica Narrow", ! 41: "Arial-Narrow", "Arial Narrow", NULL}; ! 42: ! 43: static char *PalatinoAlias[] = {"Palatino", "Zapf Calligraphic", ! 44: "Bookman Antiqua", "Book Antiqua", ! 45: "ZapfCalligraphic", NULL}; ! 46: ! 47: static char *BookmanAlias[] = {"ITC Bookman", "Bookman Old Style", "Bookman", ! 48: NULL}; ! 49: ! 50: static char *NewCenturySBAlias[] = {"NewCenturySchlbk", "New Century Schoolbook", ! 51: "Century Schoolbook", "NewCenturySchoolBook", ! 52: "New Century SchoolBook", "CenturySchoolBook", ! 53: NULL}; ! 54: ! 55: static char *AvantGardeAlias[] = {"AvantGarde", "ITC Avant Garde Gothic", ! 56: "Century Gothic", "ITC Avant Garde", NULL}; ! 57: ! 58: static char *ZapfChanceryAlias[] = {"ZapfChancery", "ITC Zapf Chancery", ! 59: "Monotype Corsiva", NULL}; ! 60: ! 61: static char *ZapfDingbatsAlias[] = {"ZapfDingbats", "ITC Zapf Dingbats", ! 62: "Monotype Sorts", "Zapf Dingbats", NULL}; ! 63: ! 64: static USHORT ausIFIMetrics2WinWeight[12] = ! 65: { ! 66: FW_DONTCARE, ! 67: FW_DONTCARE, ! 68: FW_LIGHT, ! 69: FW_LIGHT, ! 70: FW_NORMAL, ! 71: FW_NORMAL, ! 72: FW_NORMAL, ! 73: FW_BOLD, ! 74: FW_BOLD, ! 75: FW_BOLD, ! 76: FW_BOLD, ! 77: FW_BOLD ! 78: }; ! 79: ! 80: //#define ALL_METRICS ! 81: ! 82: // declarations of routines defined within this module. ! 83: ! 84: VOID PrintLine(char *); ! 85: VOID ParseKernPairs(PPARSEDATA); ! 86: VOID ParseKernData(PPARSEDATA); ! 87: VOID ParseFontName(PPARSEDATA); ! 88: VOID ParseFullName(PPARSEDATA); ! 89: VOID ParseFamilyName(PPARSEDATA); ! 90: VOID ParseWeight(PPARSEDATA); ! 91: BOOL ParseCharMetrics(PPARSEDATA); ! 92: int ParseCharName(PPARSEDATA); ! 93: int ParseCharWidth(PPARSEDATA); ! 94: VOID ParseBoundingBox(PPARSEDATA); ! 95: VOID InitPfm(PPARSEDATA); ! 96: VOID SetWidths(PPARSEDATA); ! 97: BOOL WritePFM(PWSTR, PPARSEDATA); ! 98: VOID ParseAfm(PPARSEDATA); ! 99: int ParseCharCode(PPARSEDATA); ! 100: int GetCharCode(char *, PPARSEDATA); ! 101: BOOL GetFirstLastChar(PPARSEDATA); ! 102: VOID BuildNTFM(PPARSEDATA, PSTR); ! 103: VOID InitIFIMETRICS(PPARSEDATA); ! 104: VOID CompleteIFIMETRICS(PPARSEDATA); ! 105: VOID ParseMSFamilyName(PPARSEDATA); ! 106: VOID ParsePitch(PPARSEDATA); ! 107: VOID GetFamilyAliases(IFIMETRICS *, PSTR); ! 108: ! 109: // external declarations. ! 110: ! 111: extern BOOL GetLine(PPARSEDATA); ! 112: extern int GetFloat(int, PPARSEDATA); ! 113: extern int GetNumber(PPARSEDATA); ! 114: extern VOID UnGetLine(PPARSEDATA); ! 115: extern VOID EatWhite(PPARSEDATA); ! 116: extern VOID GetWord(char *, int, PPARSEDATA); ! 117: extern int MapToken(char *, TABLE_ENTRY *); ! 118: extern int GetKeyword(TABLE_ENTRY *, PPARSEDATA); ! 119: ! 120: //-------------------------------------------------------------------------- ! 121: // ! 122: // VOID InitPfm(pdata) ! 123: // PPARSEDATA pdata; ! 124: // ! 125: // Initialize the NTFM structure. ! 126: // ! 127: // Returns: ! 128: // This routine returns no value. ! 129: // ! 130: // History: ! 131: // 18-Mar-1991 -by- Kent Settle (kentse) ! 132: // Brought in from PM, and cleaned up. ! 133: //-------------------------------------------------------------------------- ! 134: ! 135: VOID InitPfm(pdata) ! 136: PPARSEDATA pdata; ! 137: { ! 138: PNTFM pntfm; ! 139: ! 140: pntfm = pdata->pntfm; ! 141: ! 142: pntfm->cjThis = DWORDALIGN(sizeof(NTFM)); ! 143: pntfm->ulVersion = (ULONG)PFM_VERSION; ! 144: pntfm->fwdLowerCaseAscent = 0; ! 145: pntfm->loszFullName = 0; ! 146: pntfm->loszFontName = 0; ! 147: pntfm->loszFamilyName = 0; ! 148: pntfm->cKernPairs = 0; ! 149: pntfm->cCharacters = 0; ! 150: pntfm->cjSoftFont = 0; ! 151: pntfm->loSoftFont = 0; ! 152: pntfm->loIFIMETRICS = 0; ! 153: } ! 154: ! 155: ! 156: //-------------------------------------------------------------------------- ! 157: // VOID ParseAfm(pdata) ! 158: // PPARSEDATA pdata; ! 159: // ! 160: // Parses most of the AFM file to fill in the NTFM structure. ! 161: // ! 162: // Parameters: ! 163: // None. ! 164: // ! 165: // Returns: ! 166: // This routine returns no value. ! 167: // ! 168: // History: ! 169: // 19-Mar-1991 -by- Kent Settle (kentse) ! 170: // Ripped out of main. ! 171: //-------------------------------------------------------------------------- ! 172: ! 173: VOID ParseAfm(pdata) ! 174: PPARSEDATA pdata; ! 175: { ! 176: int iToken; ! 177: BOOL fEndOfInput; ! 178: PNTFM pntfm; ! 179: PIFIMETRICS pTmpIFI; ! 180: FLOAT eCharSlope; ! 181: ! 182: // get local pointers. ! 183: ! 184: pntfm = pdata->pntfm; ! 185: pTmpIFI = pdata->pTmpIFI; ! 186: ! 187: // fill in some default values. ! 188: ! 189: InitIFIMETRICS(pdata); ! 190: ! 191: fEndOfInput = FALSE; ! 192: while (!fEndOfInput) ! 193: { ! 194: GetLine(pdata); ! 195: iToken = GetKeyword(AFMKeywordTable, pdata); ! 196: ! 197: switch(iToken) ! 198: { ! 199: case TK_STARTFONTMETRICS: ! 200: break; ! 201: ! 202: case TK_STARTKERNDATA: ! 203: ParseKernData(pdata); ! 204: break; ! 205: ! 206: case TK_FONTNAME: ! 207: ParseFontName(pdata); ! 208: break; ! 209: ! 210: case TK_FULLNAME: ! 211: ParseFullName(pdata); ! 212: break; ! 213: ! 214: case TK_FAMILYNAME: ! 215: ParseFamilyName(pdata); ! 216: break; ! 217: ! 218: case TK_WEIGHT: ! 219: ParseWeight(pdata); ! 220: ! 221: pTmpIFI->usWinWeight = ausIFIMetrics2WinWeight[pTmpIFI->panose.bWeight]; ! 222: ! 223: if (pTmpIFI->usWinWeight > FW_NORMAL) ! 224: pTmpIFI->fsSelection |= FM_SEL_BOLD; ! 225: ! 226: break; ! 227: ! 228: case TK_ITALICANGLE: ! 229: eCharSlope = (FLOAT)(GetFloat(10, pdata) / 10); ! 230: ! 231: if ((LONG)(eCharSlope * 1000) == 0) ! 232: { ! 233: pTmpIFI->ptlCaret.x = 0; ! 234: pTmpIFI->ptlCaret.y = 1; ! 235: } ! 236: else ! 237: { ! 238: pTmpIFI->fsSelection |= FM_SEL_ITALIC; ! 239: ! 240: // lean 17.5 degrees away from the y-axis. ! 241: ! 242: pTmpIFI->ptlCaret.x = 3153; ! 243: pTmpIFI->ptlCaret.y = 10000; ! 244: } ! 245: ! 246: break; ! 247: ! 248: case TK_MSFAMILY: ! 249: ParseMSFamilyName(pdata); ! 250: break; ! 251: ! 252: case TK_ISFIXEDPITCH: ! 253: ParsePitch(pdata); ! 254: ! 255: break; ! 256: ! 257: case TK_ENCODINGSCHEME: ! 258: break; ! 259: ! 260: case TK_UNDERLINEPOSITION: ! 261: pTmpIFI->fwdUnderscorePosition = (FWORD) GetNumber(pdata); ! 262: #ifdef ALL_METRICS ! 263: DbgPrint("fwdUnderscorePosition = %d\n", ! 264: pTmpIFI->fwdUnderscorePosition); ! 265: #endif ! 266: break; ! 267: ! 268: case TK_UNDERLINETHICKNESS: ! 269: pTmpIFI->fwdUnderscoreSize = (FWORD)GetNumber(pdata); ! 270: pTmpIFI->fwdStrikeoutSize = pTmpIFI->fwdUnderscoreSize; ! 271: #ifdef ALL_METRICS ! 272: DbgPrint("fwdUnderscoreSize = %d\n", ! 273: pTmpIFI->fwdUnderscoreSize); ! 274: #endif ! 275: break; ! 276: ! 277: case TK_FONTBBOX: ! 278: ParseBoundingBox(pdata); ! 279: break; ! 280: ! 281: case TK_CAPHEIGHT: ! 282: break; ! 283: ! 284: case TK_XHEIGHT: ! 285: pTmpIFI->fwdXHeight = (FWORD)GetNumber(pdata); ! 286: #ifdef ALL_METRICS ! 287: DbgPrint("fwdXHeight = %d\n", pTmpIFI->fwdXHeight); ! 288: #endif ! 289: break; ! 290: ! 291: case TK_ASCENDER: ! 292: pntfm->fwdLowerCaseAscent = (FWORD)GetNumber(pdata); ! 293: #ifdef ALL_METRICS ! 294: DbgPrint("fwdLowerCaseAscent = %d\n", ! 295: pntfm->fwdLowerCaseAscent); ! 296: #endif ! 297: break; ! 298: ! 299: case TK_STARTCHARMETRICS: ! 300: ParseCharMetrics(pdata); ! 301: break; ! 302: ! 303: case TK_ENDFONTMETRICS: ! 304: fEndOfInput = TRUE; ! 305: break; ! 306: ! 307: } ! 308: ! 309: pdata->szLine = pdata->rgbLine; ! 310: } ! 311: } ! 312: ! 313: ! 314: //-------------------------------------------------------------------------- ! 315: // ! 316: // VOID SetWidths(); ! 317: // ! 318: // This routine computes the maximum and average character widths from the ! 319: // character metrics in the NTFM structure. ! 320: // ! 321: // Parameters: ! 322: // None. ! 323: // ! 324: // Returns: ! 325: // This routine returns no value. ! 326: // ! 327: // History: ! 328: // 01-Apr-1991 -by- Kent Settle (kentse) ! 329: // Wrote it. ! 330: //-------------------------------------------------------------------------- ! 331: ! 332: VOID SetWidths(pdata) ! 333: PPARSEDATA pdata; ! 334: { ! 335: USHORT i; ! 336: int iAvg; ! 337: int iMax; ! 338: ! 339: iAvg = 0; ! 340: iMax = 0; ! 341: ! 342: // calculate maximum and average character widths. ! 343: ! 344: for (i = 0; i < pdata->pntfm->cCharacters; i++) ! 345: { ! 346: iAvg += (int)pdata->TmpCharWidths[i]; ! 347: if (iMax < (int)pdata->TmpCharWidths[i]) ! 348: iMax = (int)pdata->TmpCharWidths[i]; ! 349: } ! 350: ! 351: pdata->pTmpIFI->fwdAveCharWidth = (FWORD)(iAvg / pdata->pntfm->cCharacters); ! 352: ! 353: pdata->pTmpIFI->fwdMaxCharInc = (FWORD)iMax; ! 354: ! 355: #ifdef ALL_METRICS ! 356: DbgPrint("fwdAveCharWidth = %d\n", pdata->pTmpIFI->fwdAveCharWidth); ! 357: DbgPrint("fwdMaxCharInc = %d\n", pdata->pTmpIFI->fwdMaxCharInc); ! 358: #endif ! 359: } ! 360: ! 361: ! 362: //-------------------------------------------------------------------------- ! 363: // ! 364: // VOID ParseKernPairs(); ! 365: // ! 366: // Parse the pairwise kerning data. ! 367: // ! 368: // Parameters: ! 369: // None. ! 370: // ! 371: // Returns: ! 372: // This routine returns no value. ! 373: // ! 374: // History: ! 375: // 13-Mar-1992 -by- Kent Settle (kentse) ! 376: // Modified to use FD_KERNINGPAIR struct instead of KP. ! 377: // 18-Mar-1991 -by- Kent Settle (kentse) ! 378: // Brought in from PM, and cleaned up. ! 379: //-------------------------------------------------------------------------- ! 380: ! 381: VOID ParseKernPairs(pdata) ! 382: PPARSEDATA pdata; ! 383: { ! 384: int i; ! 385: int iCh1; ! 386: int iCh2; ! 387: int iKernAmount; ! 388: int iToken; ! 389: int cPairs; ! 390: char szWord[80]; ! 391: WCHAR wc1, wc2; ! 392: UCMap *pmap; ! 393: UCMap *pmapReset; ! 394: BOOL bFound; ! 395: cPairs = GetNumber(pdata); ! 396: ! 397: pdata->pntfm->cKernPairs = (USHORT)cPairs; ! 398: ! 399: // point to the appropriate mapping table in mapping.h. ! 400: ! 401: if (!strcmp(pdata->szTmpFontName, "Symbol")) ! 402: pmap = SymbolMap; ! 403: else if (!strcmp(pdata->szTmpFontName, "ZapfDingbats")) ! 404: pmap = DingbatsMap; ! 405: else ! 406: pmap = LatinMap; ! 407: ! 408: pmapReset = pmap; ! 409: ! 410: for (i = 0; i < cPairs; ++i) ! 411: { ! 412: if (GetLine(pdata)) ! 413: break; ! 414: if (GetKeyword(AFMKeywordTable, pdata) != TK_KPX) ! 415: { ! 416: UnGetLine(pdata); ! 417: break; ! 418: } ! 419: ! 420: GetWord(szWord, sizeof(szWord), pdata); ! 421: #ifdef ALL_METRICS ! 422: DbgPrint("Char1 = %s ", szWord); ! 423: #endif ! 424: iCh1 = GetCharCode(szWord, pdata); ! 425: GetWord(szWord, sizeof(szWord), pdata); ! 426: #ifdef ALL_METRICS ! 427: DbgPrint("Char2 = %s ", szWord); ! 428: #endif ! 429: iCh2 = GetCharCode(szWord, pdata); ! 430: ! 431: iKernAmount = GetNumber(pdata); ! 432: ! 433: #ifdef ALL_METRICS ! 434: DbgPrint("Amount = %d\n", iKernAmount); ! 435: #endif ! 436: ! 437: iCh1 = iCh1 & 0x0FF; // 0 <= CharacerCode <= 255. ! 438: iCh2 = iCh2 & 0x0FF; ! 439: ! 440: // we now have the postscript character code for each character ! 441: // of the kerning pair. we now need to convert them to UNICODE. ! 442: ! 443: pmap = pmapReset; ! 444: ! 445: bFound = FALSE; ! 446: ! 447: while (pmap->szChar) ! 448: { ! 449: if ((USHORT)(pmap->usPSValue & 0x7FFF) == (USHORT)iCh1) ! 450: { ! 451: wc1 = pmap->usUCValue; ! 452: bFound = TRUE; ! 453: break; ! 454: } ! 455: pmap++; ! 456: } ! 457: ! 458: if (!bFound) ! 459: DbgPrint("GetPairs: Error char code %d not found.\n", iCh1); ! 460: ! 461: pmap = pmapReset; ! 462: ! 463: bFound = FALSE; ! 464: ! 465: while (pmap->szChar) ! 466: { ! 467: if ((USHORT)(pmap->usPSValue & 0x7FFF) == (USHORT)iCh2) ! 468: { ! 469: wc2 = pmap->usUCValue; ! 470: bFound = TRUE; ! 471: break; ! 472: } ! 473: pmap++; ! 474: } ! 475: ! 476: #ifdef ALL_METRICS ! 477: if (!bFound) ! 478: DbgPrint("GetPairs: Error char code %d not found.\n", iCh2); ! 479: #endif ! 480: pdata->TmpKernPairs[i].wcFirst = wc1; ! 481: pdata->TmpKernPairs[i].wcSecond = wc2; ! 482: pdata->TmpKernPairs[i].fwdKern = (FWORD)iKernAmount; ! 483: } ! 484: ! 485: GetLine(pdata); ! 486: iToken = GetKeyword(AFMKeywordTable, pdata); ! 487: ! 488: #if DBG ! 489: if (pdata->fEOF) ! 490: RIP("GetPairs: Premature end of file encountered\n"); ! 491: else if (iToken != TK_ENDKERNPAIRS) ! 492: { ! 493: DbgPrint("GetPairs: expected EndKernPairs\n"); ! 494: DbgPrint("%s\n", pdata->rgbLine); ! 495: } ! 496: #endif ! 497: ! 498: return; ! 499: } ! 500: ! 501: ! 502: //-------------------------------------------------------------------------- ! 503: // VOID ParseKernData(pdata) ! 504: // PPARSEDATA pdata; ! 505: // ! 506: // Start processing the pairwise kerning data. ! 507: // ! 508: // Parameters: ! 509: // None. ! 510: // ! 511: // Returns: ! 512: // This routine returns no value. ! 513: // ! 514: // History: ! 515: // 18-Mar-1991 -by- Kent Settle (kentse) ! 516: // Brought in from PM, and cleaned up. ! 517: //-------------------------------------------------------------------------- ! 518: ! 519: VOID ParseKernData(pdata) ! 520: PPARSEDATA pdata; ! 521: { ! 522: if (!GetLine(pdata)) ! 523: { ! 524: if (GetKeyword(AFMKeywordTable, pdata) == TK_STARTKERNPAIRS) ! 525: ParseKernPairs(pdata); ! 526: else ! 527: RIP("PSCRPTUI!ParseKernData: expected StartKernPairs\n"); ! 528: } ! 529: else ! 530: RIP("PSCRPTUI!ParseKernData: unexpected end of file\n"); ! 531: } ! 532: ! 533: ! 534: //-------------------------------------------------------------------------- ! 535: // VOID ParseFontName(pdata) ! 536: // PPARSEDATA pdata; ! 537: // ! 538: // Move the font name from the input buffer into the pfm structure. ! 539: // ! 540: // Parameters: ! 541: // None. ! 542: // ! 543: // Returns: ! 544: // This routine returns no value. ! 545: // ! 546: // History: ! 547: // 18-Mar-1991 -by- Kent Settle (kentse) ! 548: // Brought in from PM, and cleaned up. ! 549: //-------------------------------------------------------------------------- ! 550: ! 551: VOID ParseFontName(pdata) ! 552: PPARSEDATA pdata; ! 553: { ! 554: EatWhite(pdata); ! 555: ! 556: // get the length of the font name. ! 557: ! 558: pdata->cbFontName = strlen((char *)(pdata->szLine)) + 1; ! 559: ! 560: // now copy the facename to temporary storage. ! 561: ! 562: memcpy(pdata->szTmpFontName, pdata->szLine, pdata->cbFontName); ! 563: ! 564: #ifdef ALL_METRICS ! 565: DbgPrint("FontName = %s.\n", pdata->szLine); ! 566: #endif ! 567: } ! 568: ! 569: ! 570: //-------------------------------------------------------------------------- ! 571: // VOID ParseFullName(pdata) ! 572: // PPARSEDATA pdata; ! 573: // ! 574: // Move the full name from the input buffer into the pfm structure. ! 575: // ! 576: // Parameters: ! 577: // None. ! 578: // ! 579: // Returns: ! 580: // This routine returns no value. ! 581: // ! 582: // History: ! 583: // 29-Mar-1991 -by- Kent Settle (kentse) ! 584: // Wrote it. ! 585: //-------------------------------------------------------------------------- ! 586: ! 587: VOID ParseFullName(pdata) ! 588: PPARSEDATA pdata; ! 589: { ! 590: EatWhite(pdata); ! 591: ! 592: // get the length of the full name. ! 593: ! 594: pdata->cbFullName = strlen((char *)(pdata->szLine)) + 1; ! 595: ! 596: // now copy the Uniquename to temporary storage. ! 597: ! 598: memcpy(pdata->szTmpFullName, pdata->szLine, pdata->cbFullName); ! 599: ! 600: #ifdef ALL_METRICS ! 601: DbgPrint("FullName = %s.\n", pdata->szLine); ! 602: #endif ! 603: } ! 604: ! 605: ! 606: //-------------------------------------------------------------------------- ! 607: // ! 608: // VOID ParseFamilyName(); ! 609: // ! 610: // Move the family name from the input buffer into the pfm structure. ! 611: // ! 612: // Parameters: ! 613: // None. ! 614: // ! 615: // Returns: ! 616: // This routine returns no value. ! 617: // ! 618: // History: ! 619: // 29-Mar-1991 -by- Kent Settle (kentse) ! 620: // Wrote it. ! 621: //-------------------------------------------------------------------------- ! 622: ! 623: VOID ParseFamilyName(pdata) ! 624: PPARSEDATA pdata; ! 625: { ! 626: EatWhite(pdata); ! 627: ! 628: // get the length of the family name. ! 629: ! 630: pdata->cbFamilyName = strlen((char *)(pdata->szLine)) + 1; ! 631: ! 632: // now copy the familyname to temporary storage. ! 633: ! 634: memcpy(pdata->szTmpFamilyName, pdata->szLine, pdata->cbFamilyName); ! 635: ! 636: #ifdef ALL_METRICS ! 637: DbgPrint("FamilyNameName = %s.\n", pdata->szLine); ! 638: #endif ! 639: } ! 640: ! 641: ! 642: //-------------------------------------------------------------------------- ! 643: // VOID ParseMSFamilyName(pdata) ! 644: // PPARSEDATA pdata; ! 645: // ! 646: // gets the MSFamily name, and converts it to a value. ! 647: // ! 648: // Parameters: ! 649: // None. ! 650: // ! 651: // Returns: ! 652: // This routine returns no value. ! 653: // ! 654: // History: ! 655: // 18-Mar-1991 -by- Kent Settle (kentse) ! 656: // Brought in from PM, and cleaned up. ! 657: //-------------------------------------------------------------------------- ! 658: ! 659: VOID ParseMSFamilyName(pdata) ! 660: PPARSEDATA pdata; ! 661: { ! 662: char szWord[80]; ! 663: BOOL bFound = FALSE; ! 664: TABLE_ENTRY *pTable; ! 665: ! 666: // clear out the MSFamily flags. ! 667: ! 668: pdata->pTmpIFI->jWinPitchAndFamily &= ~(FF_DECORATIVE | FF_DONTCARE | ! 669: FF_MODERN | FF_ROMAN | FF_SCRIPT | ! 670: FF_SWISS); ! 671: GetWord(szWord, sizeof(szWord), pdata); ! 672: ! 673: #ifdef ALL_METRICS ! 674: DbgPrint("MSFamily = %s\n", szWord); ! 675: #endif ! 676: ! 677: pTable = MSFamilyTable; ! 678: while (pTable->szStr) ! 679: { ! 680: if (!strcmp(szWord, pTable->szStr)) ! 681: { ! 682: pdata->pTmpIFI->jWinPitchAndFamily |= pTable->iValue; ! 683: bFound = TRUE; ! 684: break; ! 685: } ! 686: ! 687: ++pTable; ! 688: } ! 689: ! 690: // set flag, if not found. ! 691: ! 692: if (!bFound) ! 693: { ! 694: #if DBG ! 695: #ifdef ALL_METRICS ! 696: DbgPrint("ParseMSFamilyName: unknown MSFamily = \"%s\"\n", szWord); ! 697: #endif ! 698: #endif ! 699: pdata->pTmpIFI->jWinPitchAndFamily |= FF_DONTCARE; ! 700: } ! 701: } ! 702: ! 703: ! 704: //-------------------------------------------------------------------------- ! 705: // VOID ParseMSFamilyName(pdata) ! 706: // PPARSEDATA pdata; ! 707: // ! 708: // gets the MSFamily name, and converts it to a value. ! 709: // ! 710: // Parameters: ! 711: // None. ! 712: // ! 713: // Returns: ! 714: // This routine returns no value. ! 715: // ! 716: // History: ! 717: // 18-Mar-1991 -by- Kent Settle (kentse) ! 718: // Brought in from PM, and cleaned up. ! 719: //-------------------------------------------------------------------------- ! 720: ! 721: VOID ParsePitch(pdata) ! 722: PPARSEDATA pdata; ! 723: { ! 724: CHAR szWord[6]; ! 725: ! 726: GetWord(szWord, sizeof(szWord), pdata); ! 727: ! 728: pdata->pTmpIFI->jWinPitchAndFamily &= ~(FIXED_PITCH | VARIABLE_PITCH); ! 729: ! 730: if ((!(strncmp(szWord, "True", 4))) || ! 731: (!(strncmp(szWord, "true", 4)))) ! 732: { ! 733: pdata->pTmpIFI->jWinPitchAndFamily |= FIXED_PITCH; ! 734: #ifdef ALL_METRICS ! 735: DbgPrint("Font is fixed pitch.\n"); ! 736: #endif ! 737: } ! 738: else ! 739: { ! 740: pdata->pTmpIFI->jWinPitchAndFamily |= VARIABLE_PITCH; ! 741: #ifdef ALL_METRICS ! 742: DbgPrint("Font is variable pitch.\n"); ! 743: #endif ! 744: } ! 745: } ! 746: ! 747: //-------------------------------------------------------------------------- ! 748: // VOID ParseWeight(pdata) ! 749: // PPARSEDATA pdata; ! 750: // ! 751: // Parse the fonts weight and set the corresponding entry in the PFM ! 752: // structure. ! 753: // ! 754: // Parameters: ! 755: // None. ! 756: // ! 757: // Returns: ! 758: // This routine returns no value. ! 759: // ! 760: // History: ! 761: // 18-Mar-1991 -by- Kent Settle (kentse) ! 762: // Brought in from PM, and cleaned up. ! 763: //-------------------------------------------------------------------------- ! 764: ! 765: VOID ParseWeight(pdata) ! 766: PPARSEDATA pdata; ! 767: { ! 768: char szWord[80]; ! 769: BOOL bFound = FALSE; ! 770: TABLE_ENTRY *pTable; ! 771: ! 772: GetWord(szWord, sizeof(szWord), pdata); ! 773: ! 774: #ifdef ALL_METRICS ! 775: DbgPrint("Weight = %s\n", szWord); ! 776: #endif ! 777: ! 778: pTable = WeightTable; ! 779: while (pTable->szStr) ! 780: { ! 781: #ifdef ALL_METRICS ! 782: DbgPrint("\tweight = %s\n", pTable->szStr); ! 783: #endif ! 784: if (!strcmp(szWord, pTable->szStr)) ! 785: { ! 786: pdata->pTmpIFI->panose.bWeight = pTable->iValue; ! 787: bFound = TRUE; ! 788: break; ! 789: } ! 790: ! 791: ++pTable; ! 792: } ! 793: ! 794: // check for and flag error conditions. ! 795: ! 796: if (!bFound) ! 797: { ! 798: #if DBG ! 799: #ifdef ALL_METRICS ! 800: DbgPrint("ParseWeight: unknown font weight = \"%s\"\n", szWord); ! 801: #endif ! 802: #endif ! 803: pdata->pTmpIFI->panose.bWeight = PAN_WEIGHT_MEDIUM; ! 804: } ! 805: } ! 806: ! 807: ! 808: //-------------------------------------------------------------------------- ! 809: // BOOL ParseCharMetrics(pdata) ! 810: // PPARSEDATA pdata; ! 811: // ! 812: // Parse the character metrics entry in the input file and set the ! 813: // width and bounding box in the PFM structure. ! 814: // ! 815: // Parameters: ! 816: // None. ! 817: // ! 818: // Returns: ! 819: // This routine returns no value. ! 820: // ! 821: // History: ! 822: // 18-Mar-1991 -by- Kent Settle (kentse) ! 823: // Brought in from PM, and cleaned up. ! 824: //-------------------------------------------------------------------------- ! 825: ! 826: BOOL ParseCharMetrics(pdata) ! 827: PPARSEDATA pdata; ! 828: { ! 829: int cChars; ! 830: USHORT usCount = 0; ! 831: int i; ! 832: int iWidth; ! 833: int iChar; ! 834: ! 835: cChars = GetNumber(pdata); ! 836: for (i = 0; i < cChars; ++i) ! 837: { ! 838: if (GetLine(pdata)) ! 839: { ! 840: RIP("PSCRPTUI!ParseCharMetrics: unexpected end of file encountered\n"); ! 841: return(FALSE); ! 842: } ! 843: ! 844: iChar = ParseCharCode(pdata); ! 845: ! 846: iWidth = ParseCharWidth(pdata); ! 847: ! 848: iChar = ParseCharName(pdata); ! 849: ! 850: if (iChar >= 0) ! 851: { ! 852: pdata->TmpCharWidths[usCount] = (USHORT)iWidth; ! 853: pdata->TmpCharCodes[usCount] = (BYTE)iChar; ! 854: ! 855: usCount++; // increment character counter. ! 856: ! 857: #ifdef ALL_METRICS ! 858: DbgPrint("iChar = %x, CharWidth = %d\n", ! 859: pdata->TmpCharCodes[usCount - 1], ! 860: pdata->TmpCharWidths[usCount - 1]); ! 861: #endif ! 862: } ! 863: } ! 864: ! 865: pdata->pntfm->cCharacters = usCount; ! 866: GetLine(pdata); ! 867: if (GetKeyword(AFMKeywordTable, pdata) != TK_ENDCHARMETRICS) ! 868: { ! 869: RIP("PSCRPTUI!ParseCharMetrics: expected EndCharMetrics\n"); ! 870: SetLastError(ERROR_INVALID_DATA); ! 871: return(FALSE); ! 872: } ! 873: ! 874: return(TRUE); ! 875: } ! 876: ! 877: ! 878: //-------------------------------------------------------------------------- ! 879: // int ParseCharName(pdata) ! 880: // PPARSEDATA pdata; ! 881: // ! 882: // Parse a character's name and return its numeric value. ! 883: // ! 884: // Parameters: ! 885: // None. ! 886: // ! 887: // Returns: ! 888: // This routine returns numeric value of given character. ! 889: // ! 890: // History: ! 891: // 18-Mar-1991 -by- Kent Settle (kentse) ! 892: // Brought in from PM, and cleaned up. ! 893: //-------------------------------------------------------------------------- ! 894: ! 895: int ParseCharName(pdata) ! 896: PPARSEDATA pdata; ! 897: { ! 898: int iChar; ! 899: char szWord[18]; ! 900: ! 901: EatWhite(pdata); ! 902: GetWord(szWord, sizeof(szWord), pdata); ! 903: ! 904: if (!strcmp("N", szWord)) ! 905: { ! 906: GetWord(szWord, sizeof(szWord), pdata); ! 907: #ifdef ALL_METRICS ! 908: DbgPrint("Char = %s ", szWord); ! 909: #endif ! 910: iChar = GetCharCode(szWord, pdata); ! 911: } ! 912: else ! 913: { ! 914: RIP("PSCRPTUI!ParseCharName: expected name field\n"); ! 915: SetLastError(ERROR_INVALID_DATA); ! 916: return(-1); ! 917: } ! 918: ! 919: return(iChar); ! 920: } ! 921: ! 922: ! 923: //-------------------------------------------------------------------------- ! 924: // int ParseCharWidth(pdata) ! 925: // PPARSEDATA pdata; ! 926: // ! 927: // Parse a character's width and return its numeric value. ! 928: // ! 929: // Parameters: ! 930: // None. ! 931: // ! 932: // Returns: ! 933: // This routine returns numeric value of given character's width. ! 934: // ! 935: // History: ! 936: // 18-Mar-1991 -by- Kent Settle (kentse) ! 937: // Brought in from PM, and cleaned up. ! 938: //-------------------------------------------------------------------------- ! 939: ! 940: int ParseCharWidth(pdata) ! 941: PPARSEDATA pdata; ! 942: { ! 943: int iWidth; ! 944: char szWord[16]; ! 945: ! 946: GetWord(szWord, sizeof(szWord), pdata); ! 947: if (!strcmp("WX", szWord)) ! 948: { ! 949: iWidth = GetNumber(pdata); ! 950: if (iWidth==0) ! 951: { ! 952: RIP("PSCRPTUI!ParseCharWidth: zero character width\n"); ! 953: SetLastError(ERROR_INVALID_DATA); ! 954: return(-1); ! 955: } ! 956: ! 957: EatWhite(pdata); ! 958: if (*(pdata->szLine++) != ';') ! 959: { ! 960: RIP("PSCRPTUI!ParseCharWidth: missing semicolon\n"); ! 961: SetLastError(ERROR_INVALID_DATA); ! 962: return(-1); ! 963: } ! 964: } ! 965: else ! 966: { ! 967: RIP("PSCRPTUI!ParseCharWidth: expected \"WX\"\n"); ! 968: SetLastError(ERROR_INVALID_DATA); ! 969: return(-1); ! 970: } ! 971: ! 972: return(iWidth); ! 973: } ! 974: ! 975: ! 976: //-------------------------------------------------------------------------- ! 977: // int ParseCharCode(pdata) ! 978: // PPARSEDATA pdata; ! 979: // ! 980: // Parse the ASCII form of a character's code point and return its ! 981: // numeric value. ! 982: // ! 983: // Parameters: ! 984: // None. ! 985: // ! 986: // Returns: ! 987: // This routine returns numeric value of given character's codepoint. ! 988: // ! 989: // History: ! 990: // 18-Mar-1991 -by- Kent Settle (kentse) ! 991: // Brought in from PM, and cleaned up. ! 992: //-------------------------------------------------------------------------- ! 993: ! 994: int ParseCharCode(pdata) ! 995: PPARSEDATA pdata; ! 996: { ! 997: int iChar; ! 998: char szWord[16]; ! 999: ! 1000: iChar = 0; ! 1001: GetWord(szWord, sizeof(szWord), pdata); ! 1002: if (!strcmp("C", szWord)) ! 1003: { ! 1004: iChar = GetNumber(pdata); ! 1005: if (iChar==0) ! 1006: { ! 1007: RIP("PSCRPTUI!ParseCharCode: invalid character code\n"); ! 1008: SetLastError(ERROR_INVALID_DATA); ! 1009: return(-1); ! 1010: } ! 1011: ! 1012: EatWhite(pdata); ! 1013: if (*(pdata->szLine++) != ';') ! 1014: { ! 1015: RIP("PSCRPTUI!ParseCharCode: missing semicolon\n"); ! 1016: SetLastError(ERROR_INVALID_DATA); ! 1017: return(-1); ! 1018: } ! 1019: } ! 1020: return(iChar); ! 1021: } ! 1022: ! 1023: ! 1024: //-------------------------------------------------------------------------- ! 1025: // VOID ParseBoundingBox(pdata) ! 1026: // PPARSEDATA pdata; ! 1027: // ! 1028: // Parses a characters's bounding box and stores its size in ! 1029: // the NTFM structure. ! 1030: // ! 1031: // Parameters: ! 1032: // None. ! 1033: // ! 1034: // Returns: ! 1035: // This routine returns no value. ! 1036: // ! 1037: // History: ! 1038: // 18-Mar-1991 -by- Kent Settle (kentse) ! 1039: // Brought in from PM, and cleaned up. ! 1040: //-------------------------------------------------------------------------- ! 1041: ! 1042: VOID ParseBoundingBox(pdata) ! 1043: PPARSEDATA pdata; ! 1044: { ! 1045: pdata->pntfm->rcBBox.left = GetNumber(pdata); ! 1046: pdata->pntfm->rcBBox.bottom = GetNumber(pdata); ! 1047: pdata->pntfm->rcBBox.right = GetNumber(pdata); ! 1048: pdata->pntfm->rcBBox.top = GetNumber(pdata); ! 1049: } ! 1050: ! 1051: ! 1052: ! 1053: //-------------------------------------------------------------------------- ! 1054: // BOOL WritePFM(pwstrPFMFile, pdata) ! 1055: // PWSTR pwstrPFMFile; ! 1056: // PPARSEDATA pdata; ! 1057: // ! 1058: // Flush the ouput buffer to the file. Note that this function is only ! 1059: // called after the entire pfm structure has been built in the output buffer. ! 1060: // ! 1061: // Parameters: ! 1062: // None. ! 1063: // ! 1064: // Returns: ! 1065: // This routine returns TRUE if success, FALSE otherwise. ! 1066: // ! 1067: // History: ! 1068: // 20-Mar-1991 -by- Kent Settle (kentse) ! 1069: // Wrote it. ! 1070: //-------------------------------------------------------------------------- ! 1071: ! 1072: BOOL WritePFM(pwstrPFMFile, pdata) ! 1073: PWSTR pwstrPFMFile; ! 1074: PPARSEDATA pdata; ! 1075: { ! 1076: HANDLE hPFMFile; ! 1077: ULONG ulCount; ! 1078: ! 1079: // create the .PFM file. ! 1080: ! 1081: hPFMFile = CreateFile(pwstrPFMFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, ! 1082: CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); ! 1083: ! 1084: if (hPFMFile == INVALID_HANDLE_VALUE) ! 1085: { ! 1086: RIP("PSCRPTUI!WritePFM: Can't open .PFM file.\n"); ! 1087: return(FALSE); ! 1088: } ! 1089: ! 1090: // write to the .PFM file, then close it. ! 1091: ! 1092: if (!WriteFile(hPFMFile, (LPVOID)pdata->pntfm, (DWORD)pdata->pntfm->cjThis, ! 1093: (LPDWORD)&ulCount, (LPOVERLAPPED)NULL)) ! 1094: { ! 1095: RIP("PSCRPTUI!WritePFM: WriteFile to .PFM file failed.\n"); ! 1096: return(FALSE); ! 1097: } ! 1098: ! 1099: if (ulCount != pdata->pntfm->cjThis) ! 1100: { ! 1101: RIP("PSCRPTUI!WritePFM: WriteFile count to .PFM file failed.\n"); ! 1102: return(FALSE); ! 1103: } ! 1104: ! 1105: if (!CloseHandle(hPFMFile)) ! 1106: RIP("PSCRPTUI!WritePFM: CloseHandle of .PFM file failed.\n"); ! 1107: ! 1108: return(TRUE); ! 1109: } ! 1110: ! 1111: ! 1112: //-------------------------------------------------------------------------- ! 1113: // ! 1114: // int GetCharCode(szWord, pdata) ! 1115: // char *szWord; ! 1116: // PPARSEDATA pdata; ! 1117: // ! 1118: // This routine is given a pointer to the character string. It returns ! 1119: // the character code, as defined in mapping.h, corresponding to this ! 1120: // character. ! 1121: // ! 1122: // Parameters: ! 1123: // szWord ! 1124: // Pointer to character name string. ! 1125: // ! 1126: // Returns: ! 1127: // This routine returns -1 if character not found, otherwise it ! 1128: // returns the character code. ! 1129: // ! 1130: // History: ! 1131: // 27-Mar-1991 -by- Kent Settle (kentse) ! 1132: // Wrote it. ! 1133: //-------------------------------------------------------------------------- ! 1134: ! 1135: int GetCharCode(szWord, pdata) ! 1136: char *szWord; ! 1137: PPARSEDATA pdata; ! 1138: { ! 1139: UCMap *pmap; ! 1140: ! 1141: //!!! maybe there is a better way to do this??? ! 1142: ! 1143: // point to the appropriate mapping table in mapping.h. ! 1144: ! 1145: if (!strcmp(pdata->szTmpFontName, "Symbol")) ! 1146: pmap = SymbolMap; ! 1147: else if (!strcmp(pdata->szTmpFontName, "ZapfDingbats")) ! 1148: pmap = DingbatsMap; ! 1149: else ! 1150: pmap = LatinMap; ! 1151: ! 1152: while (pmap->szChar) ! 1153: { ! 1154: if (!strcmp(szWord, pmap->szChar)) ! 1155: return((int)(pmap->usPSValue & 0x7FFF)); ! 1156: pmap++; ! 1157: } ! 1158: ! 1159: #ifdef ALL_METRICS ! 1160: DbgPrint("GetCharCode: Undefined Character = %s.\n", szWord); ! 1161: #endif ! 1162: return(-1); ! 1163: } ! 1164: ! 1165: ! 1166: //-------------------------------------------------------------------------- ! 1167: // ! 1168: // BOOL GetFirstLastChar() ! 1169: // ! 1170: // This routine searches through the encoding table in mapping.h to ! 1171: // determine the first and last characters in the font. The character ! 1172: // codes are stored into the NTFM structure in UNICODE value. ! 1173: // ! 1174: // Parameters: ! 1175: // None. ! 1176: // ! 1177: // Returns: ! 1178: // This routine returns TRUE for success, FALSE otherwise. ! 1179: // ! 1180: // History: ! 1181: // 18-Apr-1991 -by- Kent Settle (kentse) ! 1182: // Wrote it. ! 1183: //-------------------------------------------------------------------------- ! 1184: ! 1185: BOOL GetFirstLastChar(pdata) ! 1186: PPARSEDATA pdata; ! 1187: { ! 1188: PUCMap pmap; ! 1189: PUCMap pmapReset; ! 1190: USHORT usFirst = MAX_UNICODE_VALUE; ! 1191: USHORT usLast = MIN_UNICODE_VALUE; ! 1192: USHORT i; ! 1193: USHORT usTmp; ! 1194: ! 1195: //!!! maybe there is a better way to do this??? ! 1196: ! 1197: // point to the appropriate mapping table in mapping.h. ! 1198: ! 1199: if (!strcmp(pdata->szTmpFontName, "Symbol")) ! 1200: pmap = SymbolMap; ! 1201: else if (!strcmp(pdata->szTmpFontName, "ZapfDingbats")) ! 1202: pmap = DingbatsMap; ! 1203: else ! 1204: pmap = LatinMap; ! 1205: ! 1206: pmapReset = pmap; ! 1207: ! 1208: // for every character in the font, do a lookup in the mapping ! 1209: // table in mapping.h to find the corresponding UNICODE value. ! 1210: ! 1211: for (i = 0; i < pdata->pntfm->cCharacters; i++) ! 1212: { ! 1213: while (pmap->szChar) ! 1214: { ! 1215: if ((BYTE)pdata->TmpCharCodes[i] == (BYTE)(pmap->usPSValue & 0xFF)) ! 1216: { ! 1217: usTmp = pmap->usUCValue; ! 1218: if (usFirst > usTmp) ! 1219: usFirst = usTmp; ! 1220: if (usLast < usTmp) ! 1221: usLast = usTmp; ! 1222: break; ! 1223: } ! 1224: ! 1225: pmap++; ! 1226: } ! 1227: ! 1228: // reset pointer. ! 1229: ! 1230: pmap = pmapReset; ! 1231: } ! 1232: ! 1233: // make sure we have valid numbers. ! 1234: ! 1235: if (usFirst > usLast) ! 1236: { ! 1237: RIP("PSCRPTUI!etFirstLastChar: first char > last.\n"); ! 1238: SetLastError(ERROR_INVALID_DATA); ! 1239: return(FALSE); ! 1240: } ! 1241: ! 1242: // everything must be OK. ! 1243: ! 1244: pdata->pTmpIFI->wcFirstChar = (WCHAR)usFirst; ! 1245: pdata->pTmpIFI->wcLastChar = (WCHAR)usLast; ! 1246: ! 1247: #ifdef ALL_METRICS ! 1248: DbgPrint("FirstChar = %x, LastChar = %x.\n", usFirst, usLast); ! 1249: #endif ! 1250: ! 1251: return(TRUE); ! 1252: } ! 1253: ! 1254: ! 1255: //-------------------------------------------------------------------------- ! 1256: // ! 1257: // VOID BuildNTFM(pdata, pPFA) ! 1258: // PPARSEDATA pdata; ! 1259: // CHAR *pPFA; ! 1260: // ! 1261: // This routine builds an NTFM structure from all the temporary values ! 1262: // which have been determined by now. ! 1263: // ! 1264: // Returns: ! 1265: // This routine returns no value. ! 1266: // ! 1267: // History: ! 1268: // 18-Apr-1991 -by- Kent Settle (kentse) ! 1269: // Wrote it. ! 1270: //-------------------------------------------------------------------------- ! 1271: ! 1272: VOID BuildNTFM(pdata, pPFA) ! 1273: PPARSEDATA pdata; ! 1274: CHAR *pPFA; ! 1275: { ! 1276: PNTFM pntfm; ! 1277: int cbKernPairs, cbWidths; ! 1278: DWORD cbPFA; ! 1279: PSTR pstr; ! 1280: ! 1281: // get local pointer. ! 1282: ! 1283: pntfm = pdata->pntfm; ! 1284: ! 1285: // deal with the softfont if there is one. ! 1286: ! 1287: if (pPFA) ! 1288: { ! 1289: // the first DWORD of the .PFA file contains the length in BYTES of the ! 1290: // remainder of the .PFA file. ! 1291: ! 1292: cbPFA = *(DWORD *)pPFA; ! 1293: pntfm->cjSoftFont = DWORDALIGN(cbPFA); ! 1294: } ! 1295: ! 1296: // there are several bits of data which have now been put into temporary ! 1297: // storage, but need to be attached to the NTFM structure. ! 1298: ! 1299: cbKernPairs = (pntfm->cKernPairs * sizeof(FD_KERNINGPAIR)); ! 1300: cbWidths = DWORDALIGN(pntfm->cCharacters * sizeof(USHORT)); ! 1301: pntfm->cjThis += DWORDALIGN(pdata->cbFullName) + DWORDALIGN(pdata->cbFontName) + ! 1302: DWORDALIGN(pdata->cbFamilyName) + DWORDALIGN(cbKernPairs) + ! 1303: cbWidths + DWORDALIGN(pntfm->cCharacters) + ! 1304: DWORDALIGN(pntfm->cjSoftFont); ! 1305: ! 1306: if (pntfm->cjThis > INIT_PFM) ! 1307: { ! 1308: #if DBG ! 1309: DbgPrint("afm: PFM size greater than allocated.\n"); ! 1310: #endif ! 1311: return; ! 1312: } ! 1313: ! 1314: pntfm->loszFullName = DWORDALIGN(sizeof(NTFM)); ! 1315: pntfm->loszFontName = pntfm->loszFullName + DWORDALIGN(pdata->cbFullName); ! 1316: pntfm->loszFamilyName = pntfm->loszFontName + DWORDALIGN(pdata->cbFontName); ! 1317: pntfm->loKernPairs = pntfm->loszFamilyName + ! 1318: DWORDALIGN(pdata->cbFamilyName); ! 1319: pntfm->loCharMetrics = pntfm->loKernPairs + DWORDALIGN(cbKernPairs); ! 1320: ! 1321: if (pPFA) ! 1322: pntfm->loSoftFont = pntfm->loCharMetrics + ! 1323: DWORDALIGN(pntfm->cCharacters) + cbWidths; ! 1324: ! 1325: pntfm->loIFIMETRICS = pntfm->loCharMetrics + ! 1326: DWORDALIGN(pntfm->cCharacters) + cbWidths + ! 1327: DWORDALIGN(pntfm->cjSoftFont); ! 1328: ! 1329: pstr = (char *)pntfm + pntfm->loszFullName; ! 1330: memcpy(pstr, pdata->szTmpFullName, pdata->cbFullName); ! 1331: pstr += DWORDALIGN(pdata->cbFullName); ! 1332: memcpy(pstr, pdata->szTmpFontName, pdata->cbFontName); ! 1333: pstr += DWORDALIGN(pdata->cbFontName); ! 1334: memcpy(pstr, (char *)pdata->szTmpFamilyName, pdata->cbFamilyName); ! 1335: pstr += DWORDALIGN(pdata->cbFamilyName); ! 1336: memcpy(pstr, (char *)pdata->TmpKernPairs, cbKernPairs); ! 1337: pstr += DWORDALIGN(cbKernPairs); ! 1338: memcpy(pstr, (char *)pdata->TmpCharWidths, cbWidths); ! 1339: pstr += cbWidths; ! 1340: memcpy(pstr, (char *)pdata->TmpCharCodes, pntfm->cCharacters); ! 1341: pstr += DWORDALIGN(pntfm->cCharacters); ! 1342: ! 1343: #ifdef ALL_METRICS ! 1344: DbgPrint("FullName = %s\n", (char *)pntfm + pntfm->loszFullName); ! 1345: DbgPrint("FontName = %s\n", (char *)pntfm + pntfm->loszFontName); ! 1346: DbgPrint("FamilyName = %s\n", (char *)pntfm + pntfm->loszFamilyName); ! 1347: #endif ! 1348: ! 1349: // deal with the soft font, if there is one. ! 1350: ! 1351: if (pPFA) ! 1352: { ! 1353: // skip over the DWORD count. ! 1354: ! 1355: pPFA += sizeof(DWORD); ! 1356: memcpy(pstr, pPFA, cbPFA); ! 1357: pstr += DWORDALIGN(cbPFA); ! 1358: } ! 1359: ! 1360: // fill in the rest of the IFIMETRICS. ! 1361: ! 1362: CompleteIFIMETRICS(pdata); ! 1363: ! 1364: pntfm->cjThis += pdata->pTmpIFI->cjThis; ! 1365: ! 1366: // copy the IFIMETRICS stucture to the NTFM. ! 1367: ! 1368: memcpy(pstr, (CHAR *)pdata->pTmpIFI, pdata->pTmpIFI->cjThis); ! 1369: } ! 1370: ! 1371: ! 1372: //-------------------------------------------------------------------------- ! 1373: // ! 1374: // VOID InitIFIMETRICS(pdata) ! 1375: // PPARSEDATA pdata; ! 1376: // ! 1377: // This routine initializes the IFIMETRICS structure with default values. ! 1378: // ! 1379: // Returns: ! 1380: // This routine returns no value. ! 1381: // ! 1382: // History: ! 1383: // 25-Mar-1993 -by- Kent Settle (kentse) ! 1384: // Wrote it. ! 1385: //-------------------------------------------------------------------------- ! 1386: ! 1387: VOID InitIFIMETRICS(pdata) ! 1388: PPARSEDATA pdata; ! 1389: { ! 1390: PIFIMETRICS pTmpIFI; ! 1391: ! 1392: pTmpIFI = pdata->pTmpIFI; ! 1393: ! 1394: // initialize the size of the structure ! 1395: // we will have to add the size of added strings later ! 1396: ! 1397: pTmpIFI->cjThis = DWORDALIGN(sizeof(IFIMETRICS)); ! 1398: ! 1399: pTmpIFI->ulVersion = FM_VERSION_NUMBER; ! 1400: ! 1401: pTmpIFI->jWinCharSet = ANSI_CHARSET; // !!! i guess ! 1402: pTmpIFI->jWinPitchAndFamily = FF_DONTCARE | VARIABLE_PITCH;// !!! i Guess ! 1403: pTmpIFI->flInfo = FM_INFO_ARB_XFORMS | ! 1404: FM_INFO_NOT_CONTIGUOUS | ! 1405: FM_INFO_TECH_OUTLINE_NOT_TRUETYPE | ! 1406: FM_INFO_1BBP | ! 1407: FM_INFO_RIGHT_HANDED; ! 1408: pTmpIFI->fsType = FM_NO_EMBEDDING; ! 1409: pTmpIFI->fwdUnitsPerEm = 1000; // for PostScript fonts. ! 1410: pTmpIFI->fwdLowestPPEm = 1; // !!!I guess [kirko] ! 1411: ! 1412: pTmpIFI->fwdCapHeight = 0; //!!![kirko] Kent-can you do better? ! 1413: pTmpIFI->fwdSubscriptXSize = 300; // !!! a guess ! 1414: pTmpIFI->fwdSubscriptYSize = 300; // !!! a guess ! 1415: pTmpIFI->fwdSubscriptXOffset = 600; // !!! a guess ! 1416: pTmpIFI->fwdSubscriptYOffset = -100; // !!! a guess ! 1417: pTmpIFI->fwdSuperscriptXSize = 300; // !!! a guess ! 1418: pTmpIFI->fwdSuperscriptYSize = 300; // !!! a guess ! 1419: pTmpIFI->fwdSuperscriptXOffset = 600; // !!! a guess ! 1420: pTmpIFI->fwdSuperscriptYOffset = 300; // !!! a guess ! 1421: ! 1422: pTmpIFI->wcBreakChar = U_SPACE; ! 1423: WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&pTmpIFI->wcBreakChar, 1, ! 1424: (LPSTR)&pTmpIFI->chBreakChar, 1, NULL, NULL); ! 1425: ! 1426: pTmpIFI->ptlBaseline.x = 1; ! 1427: pTmpIFI->ptlBaseline.y = 0; ! 1428: pTmpIFI->ptlAspect.x = 1; ! 1429: pTmpIFI->ptlAspect.y = 1; ! 1430: pTmpIFI->achVendId[0] = 'U'; ! 1431: pTmpIFI->achVendId[1] = 'n'; ! 1432: pTmpIFI->achVendId[2] = 'k'; ! 1433: pTmpIFI->achVendId[3] = 'n'; ! 1434: pTmpIFI->ulPanoseCulture = FM_PANOSE_CULTURE_LATIN; ! 1435: pTmpIFI->panose.bFamilyType = PAN_ANY; ! 1436: pTmpIFI->panose.bSerifStyle = PAN_ANY; ! 1437: pTmpIFI->panose.bProportion = PAN_ANY; ! 1438: pTmpIFI->panose.bContrast = PAN_ANY; ! 1439: pTmpIFI->panose.bStrokeVariation= PAN_ANY; ! 1440: pTmpIFI->panose.bArmStyle = PAN_ANY; ! 1441: pTmpIFI->panose.bLetterform = PAN_ANY; ! 1442: pTmpIFI->panose.bMidline = PAN_ANY; ! 1443: pTmpIFI->panose.bXHeight = PAN_ANY; ! 1444: } ! 1445: ! 1446: ! 1447: ! 1448: //-------------------------------------------------------------------------- ! 1449: // ! 1450: // VOID CompleteIFIMETRICS(pdata) ! 1451: // PPARSEDATA pdata; ! 1452: // ! 1453: // This routine fill in IFIMETRICS values using NTFM values. ! 1454: // ! 1455: // Returns: ! 1456: // This routine returns no value. ! 1457: // ! 1458: // History: ! 1459: // 25-Mar-1993 -by- Kent Settle (kentse) ! 1460: // Wrote it. ! 1461: //-------------------------------------------------------------------------- ! 1462: ! 1463: VOID CompleteIFIMETRICS(pdata) ! 1464: PPARSEDATA pdata; ! 1465: { ! 1466: PIFIMETRICS pTmpIFI; ! 1467: WINFONTPAIR *pTable; ! 1468: BOOL bFound; ! 1469: PSTR pstr; ! 1470: PNTFM pntfm; ! 1471: LONG InternalLeading; ! 1472: ! 1473: // get local pointers. ! 1474: ! 1475: pntfm = pdata->pntfm; ! 1476: pTmpIFI = pdata->pTmpIFI; ! 1477: ! 1478: // for Win31 compatability - if there is a match in WinFontTable for ! 1479: // the Adobe facename, use the Windows Face Name for the IFIMETRICS ! 1480: // family name, otherwise, use the Adobe family name. ! 1481: ! 1482: //!!! use nls conversion for this. ! 1483: ! 1484: pTable = (WINFONTPAIR *)WinFontTable; ! 1485: bFound = FALSE; ! 1486: ! 1487: while(pTable->pstrAdobeFace) ! 1488: { ! 1489: if (!(strncmp(pTable->pstrAdobeFace, ! 1490: (CHAR *)pntfm + pntfm->loszFontName, MAX_FONT_NAME))) ! 1491: { ! 1492: pstr = pTable->pstrWinFace; ! 1493: bFound = TRUE; ! 1494: break; ! 1495: } ! 1496: ! 1497: pTable++; ! 1498: } ! 1499: ! 1500: if (!bFound) ! 1501: pstr = (CHAR *)pntfm + pntfm->loszFamilyName; ! 1502: ! 1503: // WIN31 COMPATABILITY! Check to see if this face name has aliases. ! 1504: // if it does, then we need to set the FM_INFO_FAMILY_EQUIV bit of ! 1505: // pTmpIFI->flInfo, and fill in an array of family aliases. ! 1506: ! 1507: GetFamilyAliases(pTmpIFI, pstr); ! 1508: ! 1509: // make the style name the same as the family name. ! 1510: ! 1511: pTmpIFI->dpwszStyleName = pTmpIFI->dpwszFamilyName; ! 1512: ! 1513: // get the face name for the font. ! 1514: ! 1515: pTmpIFI->dpwszFaceName = pTmpIFI->cjThis; ! 1516: ! 1517: strcpy2WChar((PWSZ)((char *)pTmpIFI + pTmpIFI->dpwszFaceName), ! 1518: (PSZ)((char *)pntfm + pntfm->loszFontName)); ! 1519: ! 1520: // while we have the face name, lets fill in the windows compatability ! 1521: // stuff. ! 1522: ! 1523: if (!strcmp((char *)pntfm + pntfm->loszFontName, "Symbol")) ! 1524: pTmpIFI->jWinCharSet = SYMBOL_CHARSET; ! 1525: else if (!strcmp((char *)pntfm + pntfm->loszFontName, "ZapfDingbats")) ! 1526: pTmpIFI->jWinCharSet = OEM_CHARSET; ! 1527: else ! 1528: pTmpIFI->jWinCharSet = ANSI_CHARSET; ! 1529: ! 1530: pTmpIFI->chFirstChar = (BYTE)0x20; ! 1531: pTmpIFI->chLastChar = (BYTE)0xFE; ! 1532: ! 1533: pTmpIFI->cjThis += ((wcslen((PWSZ)((char *)pTmpIFI + ! 1534: pTmpIFI->dpwszFaceName)) + 1) * sizeof(WCHAR)); ! 1535: ! 1536: // get the unique name for the font. ! 1537: ! 1538: pTmpIFI->dpwszUniqueName = pTmpIFI->cjThis; ! 1539: strcpy2WChar((PWSZ)((char *)pTmpIFI + pTmpIFI->dpwszUniqueName), ! 1540: (PSZ)((char *)pntfm + pntfm->loszFullName)); ! 1541: pTmpIFI->cjThis += ((wcslen((PWSZ)((char *)pTmpIFI + ! 1542: pTmpIFI->dpwszUniqueName)) + 1) * sizeof(WCHAR)); ! 1543: ! 1544: pTmpIFI->dpFontSim = 0; ! 1545: ! 1546: pTmpIFI->fwdWinAscender = (FWORD) pntfm->rcBBox.top; ! 1547: pTmpIFI->fwdWinDescender = -(FWORD) pntfm->rcBBox.bottom; ! 1548: pTmpIFI->fwdMacAscender = pTmpIFI->fwdWinAscender; ! 1549: pTmpIFI->fwdMacDescender = -pTmpIFI->fwdWinDescender; ! 1550: ! 1551: // as windows does, set total leading to 19.6% of EmHeight. ! 1552: // therefore, ExternalLeading = 196 - InternalLeading. ! 1553: ! 1554: InternalLeading = (pntfm->rcBBox.top - pntfm->rcBBox.bottom) - ! 1555: ADOBE_FONT_UNITS; ! 1556: ! 1557: if (InternalLeading < 0) ! 1558: InternalLeading = 0; ! 1559: ! 1560: pTmpIFI->fwdMacLineGap = 196 - InternalLeading; ! 1561: if (pTmpIFI->fwdMacLineGap < 0) ! 1562: pTmpIFI->fwdMacLineGap = 0; ! 1563: ! 1564: pTmpIFI->fwdTypoLineGap = 0; ! 1565: pTmpIFI->fwdTypoAscender = pTmpIFI->fwdWinAscender; ! 1566: pTmpIFI->fwdTypoDescender = pTmpIFI->fwdWinDescender; ! 1567: pTmpIFI->fwdStrikeoutPosition = pTmpIFI->fwdWinAscender / 2; ! 1568: ! 1569: // hardcoded from mapping.h values. ! 1570: ! 1571: if (!(strcmp((char *) pntfm + pntfm->loszFontName, "ZapfDingbats"))) ! 1572: { ! 1573: pTmpIFI->wcDefaultChar = U_SPACE; ! 1574: pTmpIFI->chDefaultChar = (BYTE)0x20; ! 1575: } ! 1576: else if (!(strcmp((char *) pntfm + pntfm->loszFontName, "Symbol"))) ! 1577: { ! 1578: pTmpIFI->wcDefaultChar = U_SYMBOL_BULLET; ! 1579: pTmpIFI->chDefaultChar = (BYTE)0xB7; ! 1580: } ! 1581: ! 1582: else ! 1583: { ! 1584: pTmpIFI->wcDefaultChar = U_BULLET; ! 1585: pTmpIFI->chDefaultChar = (BYTE)0x8C; ! 1586: } ! 1587: ! 1588: WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&pTmpIFI->wcDefaultChar, 1, ! 1589: (LPSTR)&pTmpIFI->chDefaultChar, 1, NULL, NULL); ! 1590: ! 1591: pTmpIFI->cKerningPairs = pntfm->cKernPairs; ! 1592: ! 1593: // set the average and maximum character widths for the font. ! 1594: ! 1595: SetWidths(pdata); ! 1596: ! 1597: // find the first and last characters for the given font. ! 1598: ! 1599: GetFirstLastChar(pdata); ! 1600: } ! 1601: ! 1602: ! 1603: //-------------------------------------------------------------------------- ! 1604: // ! 1605: // VOID GetFamilyAliases(pifi, pstr) ! 1606: // IFIMETRICS *pifi; ! 1607: // PSTR pstr; ! 1608: // ! 1609: // This routine fill in the family name of the IFIMETRICS structure. ! 1610: // ! 1611: // Returns: ! 1612: // This routine returns no value. ! 1613: // ! 1614: // History: ! 1615: // 25-Mar-1993 -by- Kent Settle (kentse) ! 1616: // Wrote it. ! 1617: //-------------------------------------------------------------------------- ! 1618: ! 1619: VOID GetFamilyAliases(pifi, pstr) ! 1620: IFIMETRICS *pifi; ! 1621: PSTR pstr; ! 1622: { ! 1623: PSTR *pTable; ! 1624: PWSTR pwstr; ! 1625: DWORD cb; ! 1626: ! 1627: // assume no alias table found. ! 1628: ! 1629: pTable = (PSTR *)(NULL); ! 1630: ! 1631: // this is an ugly hardcoded Win31 Hack that we need to be compatible ! 1632: // with since some stupid apps have hardcoded font names. ! 1633: ! 1634: if (!(strcmp(pstr, "Times"))) ! 1635: pTable = TimesAlias; ! 1636: ! 1637: else if (!(strcmp(pstr, "Helvetica"))) ! 1638: pTable = HelveticaAlias; ! 1639: ! 1640: else if (!(strcmp(pstr, "Courier"))) ! 1641: pTable = CourierAlias; ! 1642: ! 1643: else if (!(strcmp(pstr, "Helvetica-Narrow"))) ! 1644: pTable = HelveticaNarrowAlias; ! 1645: ! 1646: else if (!(strcmp(pstr, "Palatino"))) ! 1647: pTable = PalatinoAlias; ! 1648: ! 1649: else if (!(strcmp(pstr, "Bookman"))) ! 1650: pTable = BookmanAlias; ! 1651: ! 1652: else if (!(strcmp(pstr, "NewCenturySchlbk"))) ! 1653: pTable = NewCenturySBAlias; ! 1654: ! 1655: else if (!(strcmp(pstr, "AvantGarde"))) ! 1656: pTable = AvantGardeAlias; ! 1657: ! 1658: else if (!(strcmp(pstr, "ZapfChancery"))) ! 1659: pTable = ZapfChanceryAlias; ! 1660: ! 1661: else if (!(strcmp(pstr, "ZapfDingbats"))) ! 1662: pTable = ZapfDingbatsAlias; ! 1663: ! 1664: // get offset to family name from start of IFIMETRICS structure. ! 1665: ! 1666: pifi->dpwszFamilyName = pifi->cjThis; ! 1667: pwstr = (PWSZ)((char *)pifi + pifi->dpwszFamilyName); ! 1668: ! 1669: if (pTable) ! 1670: { ! 1671: // set the pifi->flInfo flag. ! 1672: ! 1673: pifi->flInfo |= FM_INFO_FAMILY_EQUIV; ! 1674: ! 1675: // now fill in the array of alias family names. ! 1676: ! 1677: while (*pTable) ! 1678: { ! 1679: strcpy2WChar(pwstr, (PSTR)*pTable++); ! 1680: cb = ((wcslen(pwstr) + 1) * sizeof(WCHAR)); ! 1681: pifi->cjThis += cb; ! 1682: pwstr += (cb >> 1); ! 1683: } ! 1684: ! 1685: // add the extra NULL terminator to the end of the array. ! 1686: ! 1687: *pwstr = (WCHAR)'\0'; ! 1688: pifi->cjThis += sizeof(WCHAR); ! 1689: } ! 1690: else ! 1691: { ! 1692: // fill in the single family name. ! 1693: ! 1694: strcpy2WChar(pwstr, pstr); ! 1695: pifi->cjThis += ((wcslen(pwstr) + 1) * sizeof(WCHAR)); ! 1696: } ! 1697: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.