|
|
1.1 ! root 1: //-------------------------------------------------------------------------- ! 2: // ! 3: // Module Name: FNTMANAG.C ! 4: // ! 5: // Brief Description: This module contains the PSCRIPT driver's ! 6: // DrvFontManagement function and related routines. ! 7: // ! 8: // Author: Kent Settle (kentse) ! 9: // Created: 07-May-1993 ! 10: // ! 11: // Copyright (c) 1993 Microsoft Corporation ! 12: //-------------------------------------------------------------------------- ! 13: ! 14: #include "stdlib.h" ! 15: #include <string.h> ! 16: #include "pscript.h" ! 17: #include "enable.h" ! 18: #include "winbase.h" ! 19: ! 20: // declarations of external routines. ! 21: ! 22: extern LONG iHipot(LONG, LONG); ! 23: extern DWORD PSFIXToBuffer(CHAR *, PS_FIX); ! 24: ! 25: // declarations of routines residing within this module. ! 26: ! 27: BOOL ForceLoadFont(PDEVDATA, FONTOBJ *, DWORD, HGLYPH *); ! 28: BOOL GrabFaceName(PDEVDATA, FONTOBJ *, CHAR *, DWORD); ! 29: PS_FIX GetPointSize(PDEVDATA, FONTOBJ *, XFORM *); ! 30: BOOL DownloadANSIBitmapFont(PDEVDATA, FONTOBJ *, HGLYPH *); ! 31: BOOL SendCharBitmap(PDEVDATA, FONTOBJ *, HGLYPH, DWORD, BOOL); ! 32: ! 33: //-------------------------------------------------------------------------- ! 34: // BOOL DrvFontManagement(pfo, iType, pvIn, cjIn, pvOut, cjOut) ! 35: // FONTOBJ *pfo; ! 36: // DWORD iType; ! 37: // PVOID pvIn; ! 38: // DWORD cjIn; ! 39: // PVOID pvOut; ! 40: // DWORD cjOut; ! 41: // ! 42: // This routine handles multiple font management related functions, ! 43: // depending on iType. ! 44: // ! 45: // Parameters: ! 46: // pdev ! 47: // Pointer to our DEVDATA structure. ! 48: // ! 49: // Returns: ! 50: // This routine returns no value. ! 51: // ! 52: // History: ! 53: // 26-Apr-1991 -by- Kent Settle (kentse) ! 54: // Wrote it. ! 55: //-------------------------------------------------------------------------- ! 56: ! 57: ULONG DrvFontManagement(pso, pfo, iType, cjIn, pvIn, cjOut, pvOut) ! 58: SURFOBJ *pso; ! 59: FONTOBJ *pfo; ! 60: DWORD iType; ! 61: DWORD cjIn; ! 62: PVOID pvIn; ! 63: DWORD cjOut; ! 64: PVOID pvOut; ! 65: { ! 66: PDEVDATA pdev; ! 67: ! 68: // pso may be NULL if QUERYESCSUPPORT. ! 69: ! 70: if (iType != QUERYESCSUPPORT) ! 71: { ! 72: // get the pointer to our DEVDATA structure and make sure it is ours. ! 73: ! 74: pdev = (PDEVDATA) pso->dhpdev; ! 75: ! 76: if (bValidatePDEV(pdev) == FALSE) ! 77: { ! 78: RIP("PSCRIPT!DrvFontManagement: invalid pdev.\n"); ! 79: SetLastError(ERROR_INVALID_PARAMETER); ! 80: return(FALSE); ! 81: } ! 82: } ! 83: ! 84: // handle the different cases. ! 85: ! 86: switch (iType) ! 87: { ! 88: case QUERYESCSUPPORT: ! 89: // when querying escape support, the function in question is ! 90: // passed in the ULONG passed in pvIn. ! 91: ! 92: switch (*(PULONG)pvIn) ! 93: { ! 94: case QUERYESCSUPPORT: ! 95: case DOWNLOADFACE: ! 96: case GETFACENAME: ! 97: return(1); ! 98: ! 99: default: ! 100: // return 0 if the escape in question is not supported. ! 101: ! 102: return(0); ! 103: } ! 104: ! 105: case DOWNLOADFACE: ! 106: // call ForceLoadFont to do the work. ! 107: ! 108: return(ForceLoadFont(pdev, pfo, cjIn, (PHGLYPH)pvIn)); ! 109: ! 110: case GETFACENAME: ! 111: // call GrabFaceName to do the work. ! 112: ! 113: return(GrabFaceName(pdev, pfo, (CHAR *)pvOut, cjOut)); ! 114: ! 115: default: ! 116: return(FALSE); ! 117: } ! 118: return(TRUE); ! 119: } ! 120: ! 121: ! 122: //-------------------------------------------------------------------- ! 123: // BOOL ForceLoadFont(pdev, pfo) ! 124: // PDEVDATA pdev; ! 125: // FONTOBJ *pfo; ! 126: // ! 127: // This routine downloads the specified font to the printer, no ! 128: // questions asked. ! 129: // ! 130: // History: ! 131: // 07-May-1993 -by- Kent Settle (kentse) ! 132: // Wrote it. ! 133: //-------------------------------------------------------------------- ! 134: ! 135: BOOL ForceLoadFont(pdev, pfo, cjIn, phglyphs) ! 136: PDEVDATA pdev; ! 137: FONTOBJ *pfo; ! 138: DWORD cjIn; ! 139: HGLYPH *phglyphs; ! 140: { ! 141: PNTFM pntfm; ! 142: BYTE *pSoftFont; ! 143: BOOL bDeviceFont; ! 144: XFORM fontxform; ! 145: PS_FIX psfxScaleFactor; ! 146: BOOL bProcSet; ! 147: ! 148: // make sure we have our hglyph => ANSI translation table. ! 149: // the table consists of 256 HGLYPHS, plus two WORDS at the ! 150: // beginning. The first WORD states whether to always download ! 151: // the font, or just if it has not yet been done. The second ! 152: // WORD is simply padding for alignment. ! 153: ! 154: if (cjIn < (sizeof(HGLYPH) * 257)) ! 155: { ! 156: RIP("PSCRIPT!ForceLoadFont: invalid cjIn.\n"); ! 157: SetLastError(ERROR_INVALID_PARAMETER); ! 158: return(FALSE); ! 159: } ! 160: // get the point size, and fill in the font xform. ! 161: ! 162: psfxScaleFactor = GetPointSize(pdev, pfo, &fontxform); ! 163: ! 164: // is this a device font? ! 165: ! 166: bDeviceFont = (pfo->flFontType & DEVICE_FONTTYPE); ! 167: ! 168: // select the proper font name for the new font. if this is a ! 169: // device font, get the name from the NTFM structure. if this ! 170: // is a GDI font that we are caching, we will create a name for ! 171: // it at the time we download it to the printer. ! 172: ! 173: if (bDeviceFont) ! 174: { ! 175: // get the font metrics for the specified font. ! 176: ! 177: pntfm = pdev->pfmtable[pfo->iFace - 1].pntfm; ! 178: ! 179: // !!! NOTE NOTE the following assumption is invalid. I need to look at the ! 180: // !!! first word of phglyph to decide whether to always download the font or ! 181: // !!! only download it if it has not yet been downloaded. ! 182: ! 183: //!!! I am writing this with the assumption, that the application will worry ! 184: //!!! about printer memory. In other words, I will just blindly download ! 185: //!!! a font when I am told to, and not worry about killing the printer. ! 186: //!!! Is this a valid assumption??? ! 187: ! 188: //!!! I am also assuming that I do not have to keep track of which fonts ! 189: //!!! have been downloaded. ! 190: ! 191: // if the font is a softfont, download it. ! 192: ! 193: if (pfo->iFace > pdev->cDeviceFonts) ! 194: { ! 195: pSoftFont = (BYTE *)pntfm + pntfm->loSoftFont; ! 196: ! 197: // we need to make sure that our header does not get downloaded ! 198: // by bPSWrite ! 199: ! 200: // note whether or not the procset has already been sent. ! 201: ! 202: if (pdev->dwFlags & PDEV_PROCSET) ! 203: bProcSet = TRUE; ! 204: else ! 205: { ! 206: pdev->dwFlags |= PDEV_PROCSET; ! 207: bProcSet = FALSE; ! 208: } ! 209: ! 210: ! 211: if (!bPSWrite(pdev, pSoftFont, pntfm->cjSoftFont)) ! 212: { ! 213: RIP("PSCRIPT!SelectFont: downloading of softfont failed.\n"); ! 214: return(FALSE); ! 215: } ! 216: ! 217: // if the procset was not sent, then clear the flag. ! 218: ! 219: if (!bProcSet) ! 220: pdev->dwFlags &= ~PDEV_PROCSET; ! 221: } ! 222: } ! 223: else // must be a GDI font we will be caching. ! 224: { ! 225: // we need to make sure that our header does not get downloaded ! 226: // by DownloadANSIBitmapFont. ! 227: ! 228: // note whether or not the procset has already been sent. ! 229: ! 230: if (pdev->dwFlags & PDEV_PROCSET) ! 231: bProcSet = TRUE; ! 232: else ! 233: { ! 234: pdev->dwFlags |= PDEV_PROCSET; ! 235: bProcSet = FALSE; ! 236: } ! 237: ! 238: //!!! the engine is not ready for outline fonts yet!!! -kentse. ! 239: #if 0 ! 240: // if this font has not yet been downloaded to the printer, ! 241: // do it now. ! 242: ! 243: if (pfo->flFontType & TRUETYPE_FONTTYPE) ! 244: { ! 245: // determine the point size. ! 246: ! 247: ulPointSize = (ETOL(fontxform.eM22 * 72000) / ! 248: pdev->psdm.dm.dmPrintQuality); ! 249: ! 250: if (ulPointSize < 10) ! 251: DownloadANSIBitmapFont(pdev, pfo, phglyphs); ! 252: else ! 253: DownloadOutlineFont(pdev, pfo); ! 254: } ! 255: else if (pfo->flFontType & RASTER_FONTTYPE) ! 256: DownloadANSIBitmapFont(pdev, pfo, phglyphs); ! 257: #endif ! 258: if ( (pfo->flFontType & TRUETYPE_FONTTYPE) || ! 259: (pfo->flFontType & RASTER_FONTTYPE) ) ! 260: DownloadANSIBitmapFont(pdev, pfo, phglyphs); ! 261: else ! 262: { ! 263: RIP("PSCRIPT!SelectFont: invalid pfo->flFontType.\n"); ! 264: return(FALSE); ! 265: } ! 266: ! 267: // if the procset was not sent, then clear the flag. ! 268: ! 269: if (!bProcSet) ! 270: pdev->dwFlags &= ~PDEV_PROCSET; ! 271: } ! 272: ! 273: return(TRUE); ! 274: } ! 275: ! 276: ! 277: //-------------------------------------------------------------------- ! 278: // BOOL GrabFaceName(pdev, pfo, pbuffer, cb) ! 279: // PDEVDATA pdev; ! 280: // FONTOBJ *pfo; ! 281: // CHAR *pbuffer; ! 282: // DWORD cb; ! 283: // ! 284: // This routine returns the driver's internal facename (ie the name ! 285: // which is sent to the printer) to the caller. pbuffer, is filled ! 286: // in with the face name, being sure to not write more than cb bytes ! 287: // to the buffer. ! 288: // ! 289: // History: ! 290: // 07-May-1993 -by- Kent Settle (kentse) ! 291: // Wrote it. ! 292: //-------------------------------------------------------------------- ! 293: ! 294: BOOL GrabFaceName(pdev, pfo, pbuffer, cb) ! 295: PDEVDATA pdev; ! 296: FONTOBJ *pfo; ! 297: CHAR *pbuffer; ! 298: DWORD cb; ! 299: { ! 300: PNTFM pntfm; ! 301: BOOL bDeviceFont; ! 302: PIFIMETRICS pifi; ! 303: XFORM fontxform; ! 304: PS_FIX psfxScaleFactor; ! 305: PWSTR pwstr; ! 306: DWORD cTmp; ! 307: CHAR szFaceName[MAX_STRING]; ! 308: PSZ pszFaceName; ! 309: ! 310: // get the point size, and fill in the font xform. ! 311: ! 312: psfxScaleFactor = GetPointSize(pdev, pfo, &fontxform); ! 313: ! 314: // is this a device font? ! 315: ! 316: bDeviceFont = (pfo->flFontType & DEVICE_FONTTYPE); ! 317: ! 318: // select the proper font name for the new font. if this is a ! 319: // device font, get the name from the NTFM structure. if this ! 320: // is a GDI font that we are caching, we will create a name for ! 321: // it at the time we download it to the printer. ! 322: ! 323: if (bDeviceFont) ! 324: { ! 325: // get the font metrics for the specified font. ! 326: ! 327: pntfm = pdev->pfmtable[pfo->iFace - 1].pntfm; ! 328: ! 329: // copy the font name to the buffer. ! 330: ! 331: strncpy(pbuffer, (char *)pntfm + pntfm->loszFontName, cb); ! 332: } ! 333: else // must be a GDI font we will be caching. ! 334: { ! 335: if ( (pfo->flFontType & TRUETYPE_FONTTYPE) || ! 336: (pfo->flFontType & RASTER_FONTTYPE) ) ! 337: { ! 338: // create the ASCII name for this font which will get used ! 339: // to select this font in the printer. ! 340: ! 341: if (!(pifi = FONTOBJ_pifi(pfo))) ! 342: { ! 343: RIP("PSCRIPT!SelectFont: pifi failed.\n"); ! 344: return(FALSE); ! 345: } ! 346: ! 347: pwstr = (PWSTR)((BYTE *)pifi + pifi->dpwszFaceName); ! 348: cTmp = wcslen(pwstr); ! 349: ! 350: // get the font name from the UNICODE font name. ! 351: ! 352: memset(szFaceName, 0, sizeof(szFaceName)); ! 353: pszFaceName = szFaceName; ! 354: ! 355: while (cTmp--) ! 356: { ! 357: *pszFaceName = (CHAR)*pwstr++; ! 358: ! 359: // replace any spaces in the font name with underscores. ! 360: ! 361: if (*pszFaceName == ' ') ! 362: *pszFaceName = '_'; ! 363: ! 364: // replace any parens in the font name with asterisks. ! 365: ! 366: if ((*pszFaceName == '(') || (*pszFaceName == ')')) ! 367: *pszFaceName = '*'; ! 368: ! 369: // point to the next character. ! 370: ! 371: *pszFaceName++; ! 372: } ! 373: ! 374: // add the point size to the font name, so we can distinguish ! 375: // different point sizes of the same font. ! 376: ! 377: cTmp = PSFIXToBuffer(pszFaceName, psfxScaleFactor); ! 378: ! 379: // update the buffer pointer. ! 380: ! 381: pszFaceName += cTmp; ! 382: ! 383: // output the NULL terminator. ! 384: ! 385: *pszFaceName = '\0'; ! 386: ! 387: // copy to the output buffer. ! 388: ! 389: strncpy(pbuffer, szFaceName, cb); ! 390: } ! 391: else ! 392: { ! 393: RIP("PSCRIPT!GrabFaceName: invalid pfo->flFontType.\n"); ! 394: return(FALSE); ! 395: } ! 396: } ! 397: } ! 398: ! 399: ! 400: //-------------------------------------------------------------------- ! 401: // PS_FIX GetPointSize(pdev, pfo, pxform) ! 402: // PDEVDATA pdev; ! 403: // FONTOBJ *pfo; ! 404: // XFORM *pxform; ! 405: // ! 406: // This routine returns the point size for the specified font. ! 407: // ! 408: // History: ! 409: // 11-May-1993 -by- Kent Settle (kentse) ! 410: // Broke out into a separate routine. ! 411: //-------------------------------------------------------------------- ! 412: ! 413: PS_FIX GetPointSize(pdev, pfo, pxform) ! 414: PDEVDATA pdev; ! 415: FONTOBJ *pfo; ! 416: XFORM *pxform; ! 417: { ! 418: XFORMOBJ *pxo; ! 419: ULONG ulComplex; ! 420: BOOL bDeviceFont; ! 421: POINTFIX ptfx; ! 422: POINTL ptl; ! 423: FIX fxVector; ! 424: IFIMETRICS *pifi; ! 425: PS_FIX psfxPointSize; ! 426: ! 427: // get the Notional to Device transform. this is needed to ! 428: // determine the point size. ! 429: ! 430: pxo = FONTOBJ_pxoGetXform(pfo); ! 431: ! 432: if (pxo == NULL) ! 433: { ! 434: RIP("PSCRIPT!GrabFaceName: pxo == NULL.\n"); ! 435: return((PS_FIX)-1); ! 436: } ! 437: ! 438: ulComplex = XFORMOBJ_iGetXform(pxo, pxform); ! 439: ! 440: bDeviceFont = (pfo->flFontType & DEVICE_FONTTYPE); ! 441: ! 442: // determine the notional space point size of the new font. ! 443: ! 444: if (bDeviceFont) ! 445: { ! 446: // PSCRIPT font's em height is hardcoded to be 1000 (see quryfont.c). ! 447: ! 448: pdev->cgs.fwdEmHeight = ADOBE_FONT_UNITS; ! 449: } ! 450: else ! 451: { ! 452: // If its not a device font, we'll have to call back and ask. ! 453: ! 454: if (!(pifi = FONTOBJ_pifi(pfo))) ! 455: { ! 456: RIP("PSCRIPT!SelectFont: pifi failed.\n"); ! 457: return((PS_FIX)-1); ! 458: } ! 459: ! 460: pdev->cgs.fwdEmHeight = pifi->fwdUnitsPerEm; ! 461: } ! 462: ! 463: // apply the notional to device transform. ! 464: ! 465: ptl.x = 0; ! 466: ptl.y = pdev->cgs.fwdEmHeight; ! 467: ! 468: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx); ! 469: ! 470: // now get the length of the vector. ! 471: ! 472: fxVector = iHipot(ptfx.x, ptfx.y); ! 473: ! 474: // make it a PS_FIX 24.8 number. ! 475: ! 476: fxVector <<= 4; ! 477: ! 478: psfxPointSize = (PS_FIX)(MulDiv(fxVector, PS_RESOLUTION, ! 479: pdev->psdm.dm.dmPrintQuality)); ! 480: ! 481: return(psfxPointSize); ! 482: } ! 483: ! 484: //-------------------------------------------------------------------- ! 485: // BOOL DownloadANSIBitmapFont(pdev, pfo, phglyphs) ! 486: // PDEVDATA pdev; ! 487: // FONTOBJ *pfo; ! 488: // HGLYPH *phglyphs; ! 489: // ! 490: // This routine downloads the font definition for the given bitmap font, ! 491: // if it has not already been done. The font is downloaded as an ! 492: // Adobe Type 3 font. ! 493: // ! 494: // This routine return TRUE if the font is successfully, or has already ! 495: // been, downloaded to the printer. It returns FALSE if it fails. ! 496: // ! 497: // History: ! 498: // 13-May-1993 -by- Kent Settle (kentse) ! 499: // Wrote it. ! 500: //-------------------------------------------------------------------- ! 501: ! 502: BOOL DownloadANSIBitmapFont(pdev, pfo, phglyphs) ! 503: PDEVDATA pdev; ! 504: FONTOBJ *pfo; ! 505: HGLYPH *phglyphs; ! 506: { ! 507: DLFONT *pDLFont; ! 508: DWORD i; ! 509: DWORD cDownloadedFonts; ! 510: DWORD cTmp; ! 511: HGLYPH *phg; ! 512: GLYPHDATA *pglyphdata; ! 513: POINTL ptlTL, ptlBR, ptl1; ! 514: PIFIMETRICS pifi; ! 515: CHAR szFaceName[MAX_STRING]; ! 516: PSZ pszFaceName; ! 517: PWSTR pwstr; ! 518: LONG EmHeight; ! 519: XFORMOBJ *pxo; ! 520: POINTFIX ptfx; ! 521: PS_FIX psfxPointSize; ! 522: XFORM fontxform; ! 523: HGLYPH hgDefault; ! 524: ! 525: // search through our list of downloaded GDI fonts to see if the ! 526: // current font has already been downloaded to the printer. ! 527: ! 528: pDLFont = pdev->cgs.pDLFonts; ! 529: ! 530: cDownloadedFonts = min(pdev->cgs.cDownloadedFonts, pdev->iDLFonts); ! 531: ! 532: for (i = 0; i < cDownloadedFonts; i++) ! 533: { ! 534: // is this entry the one we are looking for? simply return if so. ! 535: ! 536: if (pDLFont->iUniq == pfo->iUniq) ! 537: { ! 538: // update the fontname and size in our current graphics state. ! 539: ! 540: strcpy(pdev->cgs.szFont, pDLFont->strFont); ! 541: pdev->cgs.lidFont = pDLFont->iUniq; ! 542: ! 543: return(TRUE); ! 544: } ! 545: ! 546: pDLFont++; ! 547: } ! 548: ! 549: // we did not find that this font has been downloaded yet, so we must ! 550: // do it now. ! 551: ! 552: // if we have reached our downloaded font threshold, then ! 553: // we will surround ever textout call with a save/restore. ! 554: ! 555: if (cDownloadedFonts >= pdev->iDLFonts) ! 556: { ! 557: ps_save(pdev, FALSE); ! 558: pdev->cgs.dwFlags |= CGS_DLFONTTHRESHOLD; ! 559: cDownloadedFonts = pdev->iDLFonts; ! 560: } ! 561: ! 562: pDLFont = pdev->cgs.pDLFonts; ! 563: pDLFont += cDownloadedFonts; ! 564: ! 565: memset(pDLFont, 0, sizeof(DLFONT)); ! 566: ! 567: pDLFont->iFace = pfo->iFace; ! 568: pDLFont->iUniq = pfo->iUniq; ! 569: ! 570: // if we have made it this far, we should simply be able to ! 571: // download the font now. ! 572: ! 573: // we will be downloading an Adobe TYPE 3 font. ! 574: ! 575: // allocate a dictionary for the font. ! 576: ! 577: PrintString(pdev, "9 dict dup begin\n"); ! 578: ! 579: // set FontType to 3 indicating user defined font. ! 580: ! 581: PrintString(pdev, "/FontType 3 def\n"); ! 582: ! 583: // get a pointer to our array of HGLYPHS. remember to skip over the ! 584: // first two WORDS. ! 585: ! 586: phg = phglyphs + 1; ! 587: ! 588: //!!! for now - assuming first hglyph is the default one. ! 589: ! 590: hgDefault = *phg; ! 591: ! 592: // run through the array, looking at the bounding box for each ! 593: // glyph, in order to create the bounding box for the entire ! 594: // font. ! 595: ! 596: ptlTL.x = ADOBE_FONT_UNITS; ! 597: ptlTL.y = ADOBE_FONT_UNITS; ! 598: ptlBR.x = 0; ! 599: ptlBR.y = 0; ! 600: ! 601: for (i = 0; i < 256; i++) ! 602: { ! 603: // get the GLYPHDATA structure for each glyph. ! 604: ! 605: if (!(cTmp = FONTOBJ_cGetGlyphs(pfo, FO_GLYPHBITS, 1, phg, (PVOID *)&pglyphdata))) ! 606: { ! 607: RIP("PSCRIPT!DownloadANSIBitmapFont: cGetGlyphs failed.\n"); ! 608: return(FALSE); ! 609: } ! 610: ! 611: ptlTL.x = min(ptlTL.x, pglyphdata->rclInk.left); ! 612: ptlTL.y = min(ptlTL.y, pglyphdata->rclInk.top); ! 613: ptlBR.x = max(ptlBR.x, pglyphdata->rclInk.right); ! 614: ptlBR.y = max(ptlBR.y, pglyphdata->rclInk.bottom); ! 615: ! 616: // point to the next glyph handle. ! 617: ! 618: phg++; ! 619: } ! 620: ! 621: // get the IFIMETRICS for the font. ! 622: ! 623: if (!(pifi = FONTOBJ_pifi(pfo))) ! 624: { ! 625: RIP("PSCRIPT!DownloadANSIBitmapFont: pifi failed.\n"); ! 626: return(FALSE); ! 627: } ! 628: ! 629: // get the Notional to Device transform. this is needed to ! 630: // determine the point size. ! 631: ! 632: pxo = FONTOBJ_pxoGetXform(pfo); ! 633: ! 634: if (pxo == NULL) ! 635: { ! 636: RIP("PSCRIPT!DownloadANSIBitmapFont: pxo == NULL.\n"); ! 637: return(FALSE); ! 638: } ! 639: ! 640: // apply the notional to device transform. ! 641: ! 642: ptl1.x = 0; ! 643: ptl1.y = pifi->fwdUnitsPerEm; ! 644: ! 645: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx); ! 646: ! 647: // now get the length of the vector. ! 648: ! 649: EmHeight = FXTOL(iHipot(ptfx.x, ptfx.y)); ! 650: ! 651: // we have filled in the GLYPHPOS for each glyph in the font. ! 652: // reset the pointer to the first glyph. ! 653: ! 654: PrintString(pdev, "/FontMatrix [1 "); ! 655: PrintDecimal(pdev, 1, EmHeight); ! 656: PrintString(pdev, " div 0 0 1 "); ! 657: PrintDecimal(pdev, 1, EmHeight); ! 658: PrintString(pdev, " div 0 0] def\n"); ! 659: ! 660: // define the bounding box for the font, defined in 1 unit ! 661: // character space (since FontMatrix = identity). ! 662: ! 663: PrintString(pdev, "/FontBBox ["); ! 664: PrintDecimal(pdev, 4, ptlTL.x, ptlTL.y, ptlBR.x, ptlBR.y); ! 665: PrintString(pdev, " ] def\n"); ! 666: ! 667: // allocate array for encoding vector, then initialize ! 668: // all characters in encoding vector with '.notdef'. ! 669: ! 670: PrintString(pdev, "/Encoding 256 array def\n"); ! 671: PrintString(pdev, "0 1 255 {Encoding exch /.notdef put} for\n"); ! 672: ! 673: // allocate space to store the HGLYPH<==>character code mapping. ! 674: ! 675: if (!(pDLFont->phgVector = (HGLYPH *)HeapAlloc(pdev->hheap, 0, ! 676: sizeof(HGLYPH) * 256))) ! 677: { ! 678: RIP("PSCRIPT!DownloadANSIBitmapFont: HeapAlloc for phgVector failed.\n"); ! 679: return(FALSE); ! 680: } ! 681: ! 682: // reset pointer to our array of HGLYPHS. remember to skip over the ! 683: // first two WORDS. ! 684: ! 685: phg = phglyphs + 1; ! 686: ! 687: // fill in the HGLYPH encoding vector, and output ! 688: // the encoding vector to the printer. leave the first position for ! 689: // the .notdef character. ! 690: ! 691: pDLFont->cGlyphs = 256; ! 692: memcpy(pDLFont->phgVector, phg, 256 * sizeof(HGLYPH)); ! 693: ! 694: PrintString(pdev, "Encoding\n"); ! 695: ! 696: for (i = 1; i < 256; i++) ! 697: { ! 698: PrintString(pdev, "dup "); ! 699: PrintDecimal(pdev, 1, i); ! 700: PrintString(pdev, " /c"); ! 701: PrintDecimal(pdev, 1, i); ! 702: PrintString(pdev, " put\n"); ! 703: } ! 704: ! 705: // under level 1 of PostScript, the 'BuildChar' procedure is called ! 706: // every time a character from the font is constructed. under ! 707: // level 2, 'BuildGlyph' is called instead. therefore, we will ! 708: // define a 'BuildChar' procedure, which basically calls ! 709: // 'BuildGlyph'. this will provide us support for both level 1 ! 710: // and level 2 of PostScript. ! 711: ! 712: // define the 'BuildGlyph' procedure. start by getting the ! 713: // character name and the font dictionary from the stack. ! 714: ! 715: PrintString(pdev, "/BuildGlyph {0 begin /cn exch def /fd exch def\n"); ! 716: ! 717: // retrieve the character information from the CharData (CD) ! 718: // dictionary. ! 719: ! 720: PrintString(pdev, "/CI fd /CD get cn get def\n"); ! 721: ! 722: // get the width and the bounding box from the CharData. ! 723: // remember to divide the width by 16. ! 724: ! 725: PrintString(pdev, "/wx CI 0 get def /cbb CI 1 4 getinterval def\n"); ! 726: ! 727: // enable each character to be cached. ! 728: ! 729: PrintString(pdev, "wx 0 cbb aload pop setcachedevice\n"); ! 730: ! 731: // get the width and height of the bitmap, set invert bool to true ! 732: // specifying reverse image. ! 733: ! 734: PrintString(pdev, "CI 5 get CI 6 get true\n"); ! 735: ! 736: // insert x and y translation components into general imagemask ! 737: // matrix. ! 738: ! 739: PrintString(pdev, "[1 0 0 -1 0 0] dup 4 CI 7 get put dup 5 CI 8 get put\n"); ! 740: ! 741: // get hex string bitmap, convert into procedure, then print ! 742: // the bitmap image. ! 743: ! 744: PrintString(pdev, "CI 9 1 getinterval cvx imagemask end } def\n"); ! 745: ! 746: // create local storage for 'BuildGlyph' procedure. ! 747: ! 748: PrintString(pdev, "/BuildGlyph load 0 5 dict put\n"); ! 749: ! 750: // the semantics of 'BuildChar' differ from 'BuildGlyph' in the ! 751: // following way: 'BuildChar' is called with the font dictionary ! 752: // and character code on the stack, 'BuildGlyph' is called with ! 753: // the font dictionary and character name on the stack. the ! 754: // following 'BuildChar' procedure calls 'BuildGlyph', and retains ! 755: // compatiblity with level 1 PostScript. ! 756: ! 757: PrintString(pdev, "/BuildChar {1 index /Encoding get exch get\n"); ! 758: PrintString(pdev, "1 index /BuildGlyph get exec} bind def\n"); ! 759: ! 760: // now create a dictionary containing information on each character. ! 761: ! 762: PrintString(pdev, "/CD 256 dict def CD begin\n"); ! 763: ! 764: // send out the definition of the default (.notdef) character. ! 765: ! 766: if (!SendCharBitmap(pdev, pfo, *phg++, 0, TRUE)) ! 767: { ! 768: RIP("PSCRIPT!DownloadANSIBitmapFont: SendCharBitmap failed.\n"); ! 769: HeapFree(pdev->hheap, 0, (PVOID)pDLFont->phgVector); ! 770: return(FALSE); ! 771: } ! 772: ! 773: for (i = 1; i < 256; i++) ! 774: { ! 775: // don't send out duplicates of the .notdef definition. ! 776: ! 777: if (*phg != hgDefault) ! 778: { ! 779: if (!SendCharBitmap(pdev, pfo, *phg, i, FALSE)) ! 780: { ! 781: RIP("PSCRIPT!DownloadANSIBitmapFont: SendCharBitmap failed.\n"); ! 782: HeapFree(pdev->hheap, 0, (PVOID)pDLFont->phgVector); ! 783: return(FALSE); ! 784: } ! 785: } ! 786: ! 787: // point to the next HGLYPH. ! 788: ! 789: phg++; ! 790: } ! 791: ! 792: // close the definition of the font. ! 793: ! 794: PrintString(pdev, "end\n"); ! 795: ! 796: // create a unique ID for the font, then name it. ! 797: ! 798: pwstr = (PWSTR)((BYTE *)pifi + pifi->dpwszFaceName); ! 799: cTmp = wcslen(pwstr); ! 800: ! 801: // get the font name from the UNICODE font name. ! 802: ! 803: memset(szFaceName, 0, sizeof(szFaceName)); ! 804: pszFaceName = szFaceName; ! 805: ! 806: while (cTmp--) ! 807: { ! 808: *pszFaceName = (CHAR)*pwstr++; ! 809: ! 810: // replace any spaces in the font name with underscores. ! 811: ! 812: if (*pszFaceName == ' ') ! 813: *pszFaceName = '_'; ! 814: ! 815: // replace any parens in the font name with asterisks. ! 816: ! 817: if ((*pszFaceName == '(') || (*pszFaceName == ')')) ! 818: *pszFaceName = '*'; ! 819: ! 820: // point to the next character. ! 821: ! 822: *pszFaceName++; ! 823: } ! 824: ! 825: // add the point size to the font name, so we can distinguish ! 826: // different point sizes of the same font. ! 827: ! 828: // NOTE Grab a new point size here, rather than reading if from ! 829: // the CGS. This is necessary to support DrvDownloadFace. ! 830: ! 831: psfxPointSize = GetPointSize(pdev, pfo, &fontxform); ! 832: ! 833: cTmp = PSFIXToBuffer(pszFaceName, psfxPointSize); ! 834: ! 835: // update the buffer pointer. ! 836: ! 837: pszFaceName += cTmp; ! 838: ! 839: // output the NULL terminator. ! 840: ! 841: *pszFaceName = '\0'; ! 842: ! 843: // output the unique id, which, in a postscript printer, can ! 844: // be in the range from 0 to 16777215. ! 845: ! 846: PrintString(pdev, "/UniqueID "); ! 847: PrintDecimal(pdev, 1, (pfo->iUniq & 0xFFFFF)); ! 848: ! 849: PrintString(pdev, " def end pop /"); ! 850: PrintString(pdev, szFaceName); ! 851: PrintString(pdev, " exch definefont pop\n"); ! 852: ! 853: // update the fontname in our current graphics state. ! 854: ! 855: strcpy(pdev->cgs.szFont, szFaceName); ! 856: ! 857: // update information for this downloaded font. ! 858: ! 859: strcpy(pDLFont->strFont, szFaceName); ! 860: pDLFont->psfxScaleFactor = psfxPointSize; ! 861: ! 862: // update the downloaded font counter. ! 863: ! 864: pdev->cgs.cDownloadedFonts++; ! 865: } ! 866: ! 867: ! 868: //-------------------------------------------------------------------- ! 869: // BOOL SendCharBitmap(pdev, pfo, hglyph, index, bnotdef); ! 870: // PDEVDATA pdev; ! 871: // FONTOBJ *pfo; ! 872: // HGLYPH hglyph; ! 873: // DWORD index; ! 874: // BOOL bnotdef; ! 875: // ! 876: // This routine downloads the character bitmap definition to the printer. ! 877: // ! 878: // This routine return TRUE for success, FALSE otherwise. ! 879: // ! 880: // History: ! 881: // 13-May-1993 -by- Kent Settle (kentse) ! 882: // Broke out of DownloadANSIBitmapFont. ! 883: //-------------------------------------------------------------------- ! 884: ! 885: BOOL SendCharBitmap(pdev, pfo, hglyph, index, bnotdef) ! 886: PDEVDATA pdev; ! 887: FONTOBJ *pfo; ! 888: HGLYPH hglyph; ! 889: DWORD index; ! 890: BOOL bnotdef; ! 891: { ! 892: DWORD cTmp; ! 893: GLYPHDATA *pglyphdata; ! 894: PS_FIX psfxXtrans, psfxYtrans; ! 895: BYTE *pjBits; ! 896: DWORD j; ! 897: LONG cjWidth; ! 898: ! 899: // get the GLYPHDATA structure for each glyph. ! 900: ! 901: if (!(cTmp = FONTOBJ_cGetGlyphs(pfo, FO_GLYPHBITS, 1, &hglyph, ! 902: (PVOID *)&pglyphdata))) ! 903: { ! 904: RIP("PSCRIPT!SendCharBitmap: cGetGlyphs failed.\n"); ! 905: return(FALSE); ! 906: } ! 907: ! 908: // the first number in the character description is the width ! 909: // in 1 unit font space. the next four numbers are the bounding ! 910: // box in 1 unit font space. the next two numbers are the width ! 911: // and height of the bitmap. the next two numbers are the x and ! 912: // y translation values for the matrix given to imagemask. ! 913: // this is followed by the bitmap itself. ! 914: ! 915: // first, output the character name. ! 916: ! 917: if (bnotdef) ! 918: PrintString(pdev, "/.notdef"); ! 919: else ! 920: { ! 921: PrintString(pdev, "/c"); ! 922: PrintDecimal(pdev, 1, index); ! 923: } ! 924: ! 925: // output the character description array. the width and ! 926: // bounding box need to be normalized to 1 unit font space. ! 927: ! 928: // the width will be sent to the printer as the actual width ! 929: // multiplied by 16 so as not to lose any precision when ! 930: // normalizing. ! 931: ! 932: PrintString(pdev, " ["); ! 933: PrintPSFIX(pdev, 1, (pglyphdata->fxD << 4)); ! 934: PrintString(pdev, " "); ! 935: PrintDecimal(pdev, 4, pglyphdata->rclInk.left, ! 936: -pglyphdata->rclInk.top, pglyphdata->rclInk.right, ! 937: -pglyphdata->rclInk.bottom); ! 938: PrintString(pdev, " "); ! 939: ! 940: // output the width and height of the bitmap itself. ! 941: ! 942: PrintDecimal(pdev, 2, pglyphdata->gdf.pgb->sizlBitmap.cx, ! 943: pglyphdata->gdf.pgb->sizlBitmap.cy); ! 944: PrintString(pdev, " "); ! 945: ! 946: // output the translation values for the transform matrix. ! 947: // the x component is usually the equivalent of the left ! 948: // sidebearing in pixels. the y component is always the height ! 949: // of the bitmap minus any displacement factor (such as for characters ! 950: // with descenders. both components have .5 subtracted from the original ! 951: // values to avoid roundoff errors. ! 952: ! 953: psfxXtrans = ETOPSFX((FLOAT)FXTOLROUND(-pglyphdata->fxA) - 0.5); ! 954: psfxYtrans = ETOPSFX(-(FLOAT)pglyphdata->gdf.pgb->ptlOrigin.y - 0.5); ! 955: ! 956: PrintPSFIX(pdev, 2, psfxXtrans, psfxYtrans); ! 957: PrintString(pdev, "\n<"); ! 958: ! 959: // now output the bits. calculate how many bytes each source scanline ! 960: // contains. remember that the bitmap will be padded to 32bit bounds. ! 961: ! 962: // protect ourselves. ! 963: ! 964: if ((pglyphdata->gdf.pgb->sizlBitmap.cx < 1) || ! 965: (pglyphdata->gdf.pgb->sizlBitmap.cy < 1)) ! 966: { ! 967: RIP("PSCRIPT!SendCharBitmap: Invalid glyphdata!!!.\n"); ! 968: return(FALSE); ! 969: } ! 970: ! 971: pjBits = pglyphdata->gdf.pgb->aj; ! 972: ! 973: for (j = 0; j < (DWORD)pglyphdata->gdf.pgb->sizlBitmap.cy; j++) ! 974: { ! 975: cjWidth = (LONG)(pglyphdata->gdf.pgb->sizlBitmap.cx + 7) >> 3; ! 976: vHexOut(pdev, pjBits, cjWidth); ! 977: pjBits += cjWidth; ! 978: } ! 979: ! 980: PrintString(pdev, ">]def\n"); ! 981: ! 982: return(TRUE); ! 983: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.