|
|
1.1 ! root 1: //-------------------------------------------------------------------------- ! 2: // ! 3: // Module Name: TEXTOUT.C ! 4: // ! 5: // Brief Description: This module contains the PSCRIPT driver's DrvTextOut ! 6: // function and related routines. ! 7: // ! 8: // Author: Kent Settle (kentse) ! 9: // Created: 12-Feb-1991 ! 10: // ! 11: // 26-Mar-1992 Thu 23:29:37 updated -by- Daniel Chou (danielc) ! 12: // Add another parameter to bDoClipObj() so it also return the bounding ! 13: // rectangle to the clip region for halftone purpose. ! 14: // ! 15: // Copyright (c) 1991 - 1992 Microsoft Corporation ! 16: //-------------------------------------------------------------------------- ! 17: ! 18: #include "stdlib.h" ! 19: #include <string.h> ! 20: #include "pscript.h" ! 21: #include "enable.h" ! 22: #include "mapping.h" ! 23: #include "resource.h" ! 24: ! 25: extern HMODULE ghmodDrv; // GLOBAL MODULE HANDLE. ! 26: ! 27: extern TT_FONT_MAPPING TTFamilyTable[]; // tables.h. ! 28: extern TT_FONT_MAPPING TTFontTable[]; // tables.h. ! 29: extern BOOL DrvCommonPath(PDEVDATA, PATHOBJ *); ! 30: extern VOID ps_show(PDEVDATA, STROBJ *, FLONG, TEXTDATA *); ! 31: extern DWORD PSFIXToBuffer(CHAR *, PS_FIX); ! 32: extern PS_FIX GetPointSize(PDEVDATA, FONTOBJ *, XFORM *); ! 33: ! 34: #ifdef INDEX_PAL ! 35: extern ULONG PSMonoPalette[]; ! 36: extern ULONG PSColorPalette[]; ! 37: #endif ! 38: ! 39: PSZ apszRemapCode[] = ! 40: { ! 41: "/reencode {findfont begin currentdict d length dict begin {", ! 42: "1 index /FID ne {def} {pop pop} ifelse} forall /FontName exch def", ! 43: "d length 0 ne {/Encoding Encoding 256 array copy def 0 exch {", ! 44: "d type /nametype eq {Encoding 2 index 2 index put pop 1 add", ! 45: "}{exch pop} ifelse} forall} if pop currentdict d end end", ! 46: "/FontName get exch definefont pop} bd", ! 47: NULL ! 48: } ; ! 49: ! 50: typedef struct ! 51: { ! 52: WCHAR wc; // UNICODE code point. ! 53: POINTL ptlpgp; // pointl as defined by GLYPHPOS structs. ! 54: POINTFIX ptfxorg; // pointfix as defined by original font. ! 55: } TEXTDELTA; ! 56: ! 57: #define MAX_LINE_LENGTH 70 ! 58: ! 59: // macro for scaling between TrueType and Adobe fonts. ! 60: ! 61: #define TTTOADOBE(x) (((x) * ADOBE_FONT_UNITS) / pifi->fwdUnitsPerEm) ! 62: ! 63: // declaration of routines residing in this module. ! 64: ! 65: BOOL bDoClipObj(PDEVDATA, CLIPOBJ *, RECTL *, RECTL *, BOOL *, BOOL *, DWORD); ! 66: BOOL DrawGlyphs(PDEVDATA, DWORD, GLYPHPOS *, FONTOBJ *, STROBJ *, TEXTDATA *, PWSZ); ! 67: BOOL RemapDeviceChar(PDEVDATA, PCHAR, STROBJ *, FLONG, BOOL, TEXTDATA *); ! 68: BOOL RemapUnicodeChar(PDEVDATA, PWCHAR, STROBJ *, FLONG, BOOL, TEXTDATA *); ! 69: BOOL RemapGDIChar(PDEVDATA, STROBJ *, GLYPHPOS *, DLFONT *, BOOL *, FLONG, TEXTDATA *); ! 70: BOOL SelectFont(PDEVDATA, FONTOBJ *, TEXTDATA *); ! 71: VOID RemapFont(PDEVDATA, STROBJ *, FLONG, BOOL, TEXTDATA *); ! 72: VOID CharBitmap(PDEVDATA, GLYPHPOS *); ! 73: BOOL DownloadBitmapFont(PDEVDATA, FONTOBJ *); ! 74: BOOL DownloadOutlineFont(PDEVDATA, FONTOBJ *); ! 75: BOOL SetFontRemap(PDEVDATA, DWORD); ! 76: BOOL QueryFontRemap(PDEVDATA, DWORD); ! 77: DWORD SubstituteIFace(PDEVDATA, FONTOBJ *); ! 78: LONG iHipot(LONG, LONG); ! 79: BOOL IsJustifiedText(PDEVDATA, FONTOBJ *, STROBJ *, POINTPSFX *, ! 80: POINTPSFX *, TEXTDATA *); ! 81: BOOL FillDeltaArray(PDEVDATA, FONTOBJ *, GLYPHPOS *, STROBJ *, TEXTDELTA *, ! 82: DWORD, PWSZ); ! 83: PWSTR GetUnicodeString(PDEVDATA, FONTOBJ *, STROBJ *); ! 84: VOID ConstructUCString(GLYPHPOS *, PUCMap, DWORD, PWSTR); ! 85: BOOL GetDeviceWidths(PDEVDATA, FONTOBJ *, GLYPHDATA *, HGLYPH); ! 86: ! 87: //-------------------------------------------------------------------------- ! 88: // BOOL DrvTextOut (pso, pstro, pfo, pco, prclExtra, prclOpaque, pboFore, ! 89: // pboOpaque, pptBrushOrg, mix) ! 90: // SURFOBJ *pso; ! 91: // STROBJ *pstro; ! 92: // FONTOBJ *pfo; ! 93: // CLIPOBJ *pco; ! 94: // RECTL *prclExtra; ! 95: // RECTL *prclOpaque; ! 96: // BRUSHOBJ *pboFore; ! 97: // BRUSHOBJ *pboOpaque; ! 98: // POINTL *pptlBrushOrg; ! 99: // MIX mix; ! 100: // ! 101: // The graphics engine will call this routine to render a set of glyphs at ! 102: // specified positions. In order to make things clear, we will make a short ! 103: // mathematical detour. The parameters of the function unambiguously divides ! 104: // the entire set of device space pixels into three proper subsets denoted ! 105: // foreground, background, and transparent. When the text is rendered to the ! 106: // surface, the foreground pixels are rendered with a foreground brush, the ! 107: // background pixels the background brush, and the transparent pixels are left ! 108: // untouched. The foreground pixels are defined by first forming the union of ! 109: // all the glyph pixels with the pixels of the extra rectangles, then ! 110: // intersecting the result with the pixels of the clipping region. The set ! 111: // of pixels comprising the extra rectangles are defined by (up to) three ! 112: // rectangles pointed to by prclExt. These rectangles are used to simulate ! 113: // effects like underlining and strike through glyphs. The background set of ! 114: // pixels is defined as the intersection of three sets: (1) the pixels of the ! 115: // background rectangle; (2) the complement of the foreground; (3) the ! 116: // clipping region. Any pixels that are not part of either the foreground or ! 117: // background sets are defined to be transparent. The input parameters to ! 118: // DrvTextOut define two sets of pixels foreground and opaque. The driver must ! 119: // render the surface so that the result is identical to a process where the ! 120: // opaque pixels are rendered first with the opaque brush, then the foreground ! 121: // pixels are rendered with the foreground brush. Each of these operations is ! 122: // limited by clipping. The foreground set of pixels is defined to be the ! 123: // union of the pixels of the glyphs and the pixels of the "extra" rectangles ! 124: // at prclExtra. These extra rectangles are used to simulate strike-through or ! 125: // underlines. The opaque pixels are defined by the opaque rectangle at ! 126: // prclOpaque. The foreground and opaque pixels are regarded as a screen ! 127: // through which color is brushed onto the surface. The glyphs of the font ! 128: // do not have color in themselves. The input parameters to DrvTextOut ! 129: // define the set of glyph pixels, the set of extra rectangles, the opaque ! 130: // rectangle, and the clipping region. It is the responsibility of the driver ! 131: // to calculate and then render the set of foreground and opaque pixels. ! 132: // ! 133: // Parameters: ! 134: // pso ! 135: // Pointer to a SURFOBJ. ! 136: // ! 137: // pstro ! 138: // Pointer to a STROBJ. This defines the glyphs to be rendered and the ! 139: // positions where they are to be placed. ! 140: // ! 141: // pfo ! 142: // Pointer to a FONTOBJ. This is used to retrieve information about the ! 143: // font and its glyphs. ! 144: // ! 145: // pco ! 146: // Pointer to a CLIPOBJ. This defines the clipping region through which ! 147: // all rendering must be done. No pixels can be affected outside the ! 148: // clipping region. ! 149: // ! 150: // prclExtra ! 151: // Pointer to a null terminated array of rectangles. These rectangles ! 152: // are bottom right exclusive. The pixels of the rectangles are to be ! 153: // combined with the pixels of the glyphs to produce the foreground ! 154: // pixels. The extra rectangles are used to simulate underlining or strike ! 155: // out. If prclExtra is NULL then there are no extra rectangles to be ! 156: // rendered. If the prclExtra is not NULL then the rectangles are read ! 157: // until a null rectangle is reached. A null rectangle has both coordinates ! 158: // of both points set to zero. ! 159: // ! 160: // prclOpaque ! 161: // Pointer to a single opaque rectangle. This rectangle is bottom ! 162: // right exclusive. Pixels within this rectangle (that are not foreground ! 163: // and not clipped) are to be rendered with the opaque brush. If this ! 164: // argument is NULL then no opaque pixels are to be rendered. ! 165: // ! 166: // pboFore ! 167: // Pointer to the brush object to be used for the foreground pixels. ! 168: // The fill pattern is defined by this brush. A GDI service, ! 169: // BRUSHOBJ_pvDevBrush, is provided to find the device's realization of ! 170: // the brush. ! 171: // ! 172: // pboOpaque ! 173: // Pointer to the brush object for the opaque pixels. Both the foreground ! 174: // and background mix modes for this brush are assumed to be overpaint. ! 175: // ! 176: // pptlBrushOrg ! 177: // Pointer to a POINTL defining the brush origin for both brushes. ! 178: // ! 179: // mix ! 180: // Foreground and background raster operations (mix modes) for pboFore. ! 181: // ! 182: // Returns: ! 183: // TRUE if successful. Otherwise FALSE, and an error code is logged. ! 184: // ! 185: // History: ! 186: // 12-Feb-1991 -by- Kent Settle (kentse) ! 187: // Wrote it. ! 188: //-------------------------------------------------------------------------- ! 189: ! 190: BOOL DrvTextOut( ! 191: SURFOBJ *pso, ! 192: STROBJ *pstro, ! 193: FONTOBJ *pfo, ! 194: CLIPOBJ *pco, ! 195: PRECTL prclExtra, ! 196: PRECTL prclOpaque, ! 197: BRUSHOBJ *pboFore, ! 198: BRUSHOBJ *pboOpaque, ! 199: PPOINTL pptlOrg, ! 200: MIX mix) ! 201: { ! 202: PDEVDATA pdev; ! 203: BOOL bMore; ! 204: DEVBRUSH *pBrush; ! 205: RECTL rclBounds; ! 206: FONTINFO fi; ! 207: DWORD cGlyphs; ! 208: GLYPHPOS *pgp; ! 209: BOOL bClipping; ! 210: TEXTDATA *pdata; ! 211: BOOL bFirstClipPass; ! 212: ULONG ulColor; ! 213: ULONG *pulColors; ! 214: ! 215: // make sure we have been given valid pointers. ! 216: ! 217: if ((pso == (SURFOBJ *)NULL) || (pstro == (STROBJ *)NULL) || ! 218: (pfo == (FONTOBJ *)NULL) || (pco == (CLIPOBJ *)NULL)) ! 219: { ! 220: RIP("PSCRIPT!DrvTextOut: NULL pointer passed in.\n"); ! 221: SetLastError(ERROR_INVALID_PARAMETER); ! 222: return(FALSE); ! 223: } ! 224: ! 225: // get the pointer to our DEVDATA structure and make sure it is ours. ! 226: ! 227: pdev = (PDEVDATA) pso->dhpdev; ! 228: ! 229: if (bValidatePDEV(pdev) == FALSE) ! 230: { ! 231: RIP("PSCRIPT!DrvTextOut: invalid PDEV."); ! 232: SetLastError(ERROR_INVALID_PARAMETER); ! 233: return(FALSE); ! 234: } ! 235: ! 236: // make sure we have been given a valid font. ! 237: ! 238: if ( (pfo->flFontType & DEVICE_FONTTYPE) && ! 239: (pfo->iFace > (pdev->cDeviceFonts + pdev->cSoftFonts)) ) ! 240: { ! 241: RIP("PSCRIPT!DrvTextOut: invalid iFace.\n"); ! 242: SetLastError(ERROR_INVALID_PARAMETER); ! 243: return(FALSE); ! 244: } ! 245: ! 246: // allocate and initialize a TEXTDATA structure. ! 247: ! 248: if (!(pdata = (TEXTDATA *)HeapAlloc(pdev->hheap, 0, sizeof(TEXTDATA)))) ! 249: { ! 250: RIP("PSCRIPT!DrvTextOut: HeapAlloc for TEXTDATA failed."); ! 251: return(FALSE); ! 252: } ! 253: ! 254: pdata->iFace = pfo->iFace; ! 255: pdata->bFontSubstitution = FALSE; ! 256: pdata->ptSpace.x = 0; ! 257: pdata->ptSpace.y = 0; ! 258: pdata->ptNonSpace.x = 0; ! 259: pdata->ptNonSpace.y = 0; ! 260: ! 261: if ((pfo->flFontType & TRUETYPE_FONTTYPE) && ! 262: (pdev->psdm.dwFlags & PSDEVMODE_FONTSUBST)) ! 263: { ! 264: if (pdata->iFace = SubstituteIFace(pdev, pfo)) ! 265: pdata->bFontSubstitution = TRUE; ! 266: else ! 267: pdata->iFace = pfo->iFace; ! 268: } ! 269: ! 270: pdata->bDeviceFont = (pdata->bFontSubstitution || ! 271: (pfo->flFontType & DEVICE_FONTTYPE) ); ! 272: ! 273: pdata->bJustification = IsJustifiedText(pdev, pfo, pstro, &pdata->ptSpace, ! 274: &pdata->ptNonSpace, pdata); ! 275: ! 276: // clear the font download threshold flag. ! 277: ! 278: pdev->cgs.dwFlags &= ~CGS_DLFONTTHRESHOLD; ! 279: ! 280: // select the current font in the printer from the given FONTOBJ. ! 281: ! 282: if (!SelectFont(pdev, pfo, pdata)) ! 283: { ! 284: #if DBG ! 285: DbgPrint("PSCRIPT!DrvTextOut: SelectFont failed.\n"); ! 286: #endif ! 287: HeapFree(pdev->hheap, 0, (PVOID)pdata); ! 288: return(FALSE); ! 289: } ! 290: ! 291: // handle the clip object passed in. ! 292: bFirstClipPass = TRUE; ! 293: ! 294: bClipping = bDoClipObj(pdev, pco, NULL, NULL, NULL, ! 295: &bFirstClipPass, MAX_CLIP_RECTS); ! 296: ! 297: if (bClipping) ! 298: ps_clip(pdev, TRUE); ! 299: ! 300: // output the Opaque rectangle if necessary. this is a background ! 301: // rectangle that goes behind the foreground text, therefore, send ! 302: // it to the printer before the text. ! 303: ! 304: if (prclOpaque) ! 305: { ! 306: // define the opaque rectangle in the printer. ! 307: ! 308: ps_newpath(pdev); ! 309: ps_box(pdev, prclOpaque); ! 310: ! 311: // call the driver's filling routine. this routine will do the ! 312: // right thing with the brush. ! 313: ! 314: if (!ps_patfill(pdev, pso, (FLONG)FP_WINDINGMODE, pboOpaque, pptlOrg, mix, ! 315: prclOpaque, FALSE, FALSE)) ! 316: { ! 317: HeapFree(pdev->hheap, 0, (PVOID)pdata); ! 318: return(FALSE); ! 319: } ! 320: } ! 321: ! 322: // output the text color to draw with. ! 323: ! 324: #ifdef INDEX_PAL ! 325: // just output solid color if there is one. ! 326: ! 327: if ((pdev->pntpd->flFlags & COLOR_DEVICE) && ! 328: (pdev->psdm.dm.dmColor == DMCOLOR_COLOR)) ! 329: pulColors = PSColorPalette; ! 330: else ! 331: pulColors = PSMonoPalette; ! 332: ! 333: if (pboFore->iSolidColor != NOT_SOLID_COLOR) ! 334: { ! 335: ps_setrgbcolor(pdev, (PALETTEENTRY *)pulColors + pboFore->iSolidColor); ! 336: } ! 337: else ! 338: { ! 339: // get the device brush to draw with. ! 340: ! 341: pBrush = (DEVBRUSH *)BRUSHOBJ_pvGetRbrush(pboFore); ! 342: ! 343: if (!pBrush) ! 344: { ! 345: #if DBG ! 346: DbgPrint("DrvTextOut: NULL pBrush.\n"); ! 347: #endif ! 348: // something is wrong! let's print some black text. ! 349: ! 350: ulColor = RGB_BLACK; ! 351: ps_setrgbcolor(pdev, (PALETTEENTRY *)&ulColor); ! 352: } ! 353: else ! 354: { ! 355: if (pBrush->iSolidColor == NOT_SOLID_COLOR) ! 356: { ! 357: // get the foreground color. ! 358: ! 359: ps_setrgbcolor(pdev, ((PALETTEENTRY *)pulColors + ! 360: *(ULONG *)((PBYTE)pBrush + pBrush->offsetXlate + ! 361: sizeof(ULONG)))); ! 362: } ! 363: else ! 364: { ! 365: ps_setrgbcolor(pdev, (PALETTEENTRY *)&pBrush->iSolidColor); ! 366: } ! 367: } ! 368: } ! 369: #else ! 370: if (pboFore->iSolidColor == NOT_SOLID_COLOR) ! 371: { ! 372: // this is not a solid brush, so get a pointer to the ! 373: // realized brush. ! 374: ! 375: #if DBG ! 376: DbgPrint("DrvTextOut: non-solid text brush, defaulting to black.\n"); ! 377: #endif ! 378: ulColor = RGB_BLACK; ! 379: ps_setrgbcolor(pdev, (BGR_PAL_ENTRY *)&ulColor); ! 380: } ! 381: else ! 382: { ! 383: // we have a solid brush, so simply output the line color. ! 384: ! 385: ps_setrgbcolor(pdev, (BGR_PAL_ENTRY *)&pboFore->iSolidColor); ! 386: } ! 387: #endif ! 388: ! 389: ! 390: // get some information about the font. ! 391: ! 392: FONTOBJ_vGetInfo(pfo, sizeof(FONTINFO), &fi); ! 393: ! 394: // get the GLYPHPOS's, directly or indirectly. ! 395: ! 396: if (pstro->pgp) ! 397: { ! 398: if (!DrawGlyphs(pdev, pstro->cGlyphs, pstro->pgp, pfo, pstro, pdata, pstro->pwszOrg)) ! 399: { ! 400: RIP("PSCRIPT!DrvTextOut: DrawGlyphs failed.\n"); ! 401: HeapFree(pdev->hheap, 0, (PVOID)pdata); ! 402: return(FALSE); ! 403: } ! 404: } ! 405: else ! 406: { ! 407: PWSZ pwszCur = pstro->pwszOrg; ! 408: ! 409: // prepare to enumerate the string properly. ! 410: ! 411: STROBJ_vEnumStart(pstro); ! 412: ! 413: // now draw the text. ! 414: ! 415: do ! 416: { ! 417: bMore = STROBJ_bEnum(pstro, &cGlyphs, &pgp); ! 418: ! 419: if (!DrawGlyphs(pdev, cGlyphs, pgp, pfo, pstro, pdata, pwszCur)) ! 420: { ! 421: RIP("PSCRIPT!DrvTextOut: DrawGlyphs failed.\n"); ! 422: HeapFree(pdev->hheap, 0, (PVOID)pdata); ! 423: return(FALSE); ! 424: } ! 425: ! 426: pwszCur += cGlyphs; ! 427: ! 428: } while (bMore); ! 429: } ! 430: // invalidate the current position so it will get updated next time. ! 431: ! 432: pdev->cgs.ptlCurPos.x = -1; ! 433: pdev->cgs.ptlCurPos.y = -1; ! 434: ! 435: // output the extra rectangles if necessary. These rectangles are ! 436: // bottom right exclusive. the pels of the rectangles are to be ! 437: // combined with the pixels of the glyphs to produce the foreground ! 438: // pels. the extra rectangles are used to simulate underlining or ! 439: // strikeout. ! 440: ! 441: if (prclExtra) ! 442: { ! 443: // output a newpath command to the printer. ! 444: ! 445: ps_newpath(pdev); ! 446: ! 447: // set up bounding rectangle. ! 448: ! 449: rclBounds = *prclExtra; ! 450: ! 451: // output each Extra rectangle until we find the terminating ! 452: // retangle with all NULL coordinates. ! 453: ! 454: while ((prclExtra->right != prclExtra->left) || ! 455: (prclExtra->top != prclExtra->bottom) || ! 456: (prclExtra->right != 0L) || ! 457: (prclExtra->top != 0L)) ! 458: { ! 459: ps_box(pdev, prclExtra); ! 460: ! 461: // update the bounding rectangle if necessary. ! 462: ! 463: if (prclExtra->left < rclBounds.left) ! 464: rclBounds.left = prclExtra->left; ! 465: if (prclExtra->right > rclBounds.right) ! 466: rclBounds.right = prclExtra->right; ! 467: if (prclExtra->top < rclBounds.top) ! 468: rclBounds.top = prclExtra->top; ! 469: if (prclExtra->bottom > rclBounds.bottom) ! 470: rclBounds.bottom = prclExtra->bottom; ! 471: ! 472: prclExtra++; ! 473: } ! 474: ! 475: // call the driver's filling routine. this routine will do the ! 476: // right thing with the brush. ! 477: ! 478: if (!ps_patfill(pdev, pso, (FLONG)FP_WINDINGMODE, pboFore, pptlOrg, mix, ! 479: &rclBounds, FALSE, FALSE)) ! 480: { ! 481: HeapFree(pdev->hheap, 0, (PVOID)pdata); ! 482: return(FALSE); ! 483: } ! 484: } ! 485: ! 486: if (bClipping) ! 487: ps_restore(pdev, TRUE); ! 488: ! 489: // if we have hit the downloaded font threshold, then we are doing ! 490: // a save/restore around every textout call. ! 491: ! 492: if (pdev->cgs.dwFlags & CGS_DLFONTTHRESHOLD) ! 493: ps_restore(pdev, FALSE); ! 494: ! 495: // free up memory. ! 496: ! 497: HeapFree(pdev->hheap, 0, (PVOID)pdata); ! 498: ! 499: return(TRUE); ! 500: } ! 501: ! 502: //-------------------------------------------------------------------------- ! 503: // BOOL bDoClipObj(pdev, pco, prclClipBound, pbMoreClipping, ! 504: // pbFirstPass, cRectLimit) ! 505: // PDEVDATA pdev; ! 506: // CLIPOBJ *pco; ! 507: // RECTL *prclClipBound; ! 508: // BOOL *pbMoreClipping; ! 509: // BOOL *pbFirstPass; ! 510: // DWORD cRectLimit; ! 511: // ! 512: // This routine will determine the clipping region as defined in pco, and ! 513: // send the appropriate commands to the printer to set the clip region ! 514: // in the printer. ! 515: // ! 516: // Parameters: ! 517: // pdev ! 518: // Pointer to our DEVDATA structure. ! 519: // ! 520: // pco ! 521: // Pointer to a CLIPOBJ. This defines the clipping region through which ! 522: // all rendering must be done. No pixels can be affected outside the ! 523: // clipping region. ! 524: // ! 525: // bBitblt ! 526: // True if called from bitblt function ! 527: // ! 528: // prclBound ! 529: // If not NULL then it return the bounding rectangle for the clipping ! 530: // region, the returning rclBound only valid if return value is TRUE. ! 531: // ! 532: // Returns: ! 533: // This routine returns TRUE if a clippath was sent to the printer, ! 534: // otherwise FALSE. ! 535: // ! 536: // History: ! 537: // 26-Mar-1992 Thu 23:33:58 updated -by- Daniel Chou (danielc) ! 538: // add prclBound to accumulate the bounding rectangle for the clipping ! 539: // region. ! 540: // ! 541: // 12-Feb-1991 -by- Kent Settle (kentse) ! 542: // Wrote it. ! 543: //-------------------------------------------------------------------------- ! 544: ! 545: BOOL bDoClipObj(pdev, pco, prclClipBound, prclTarget, pbMoreClipping, ! 546: pbFirstPass, cRectLimit) ! 547: PDEVDATA pdev; ! 548: CLIPOBJ *pco; ! 549: RECTL *prclClipBound; ! 550: RECTL *prclTarget; ! 551: BOOL *pbMoreClipping; ! 552: BOOL *pbFirstPass; ! 553: DWORD cRectLimit; ! 554: { ! 555: short iComplex; ! 556: ENUMRECTS buffer; ! 557: BOOL bMore; ! 558: ULONG cRects; ! 559: RECTL rclClipBound; ! 560: ! 561: // assume all clipping will be done within this one call. ! 562: ! 563: if (pbMoreClipping) ! 564: *pbMoreClipping = FALSE; ! 565: ! 566: if (pco == NULL) ! 567: return(FALSE); ! 568: ! 569: iComplex = (short)pco->iDComplexity; ! 570: ! 571: switch(iComplex) ! 572: { ! 573: case DC_TRIVIAL: ! 574: // in this case, there is no clipping. Therefore, we have ! 575: // no commands to send to the printer. ! 576: ! 577: return (FALSE); ! 578: ! 579: case DC_RECT: ! 580: // check to see if the target rectangle fits inside the clip ! 581: // rectangle. if it does, don't do clipping. ! 582: ! 583: if (prclTarget) ! 584: { ! 585: if ((pco->rclBounds.left <= prclTarget->left) && ! 586: (pco->rclBounds.top <= prclTarget->top) && ! 587: (pco->rclBounds.right >= prclTarget->right) && ! 588: (pco->rclBounds.bottom >= prclTarget->bottom)) ! 589: { ! 590: // I see no reason to clip this, do you? ! 591: ! 592: return(FALSE); ! 593: } ! 594: } ! 595: ! 596: // in this case, we are clipping to a single rectangle. ! 597: // get it from the CLIPOBJ, then send it to the printer. ! 598: ! 599: buffer.arcl[0] = pco->rclBounds; ! 600: ! 601: // send a newpath command, then the clip rectangle to ! 602: // the printer. TRUE means to do a gsave, not a save command. ! 603: ! 604: if (!ps_save(pdev, TRUE)) ! 605: return(FALSE); ! 606: ! 607: ps_newpath(pdev); ! 608: ps_box(pdev, &buffer.arcl[0]); ! 609: ! 610: if (prclClipBound) ! 611: *prclClipBound = buffer.arcl[0]; // this is the bound ! 612: ! 613: break; ! 614: ! 615: case DC_COMPLEX: ! 616: // in this case, we are clipping to a complex clip region. ! 617: // enumerate the clip region from the CLIPOBJ, and send the ! 618: // entire clip region to the printer. ! 619: ! 620: // ! 621: // 26-Mar-1992 Thu 23:49:59 updated -by- Daniel Chou (danielc) ! 622: // ! 623: // Initialize the empty bound then acculate it later, ! 624: // ! 625: // !!!! This may changed, we need to check with engine guys to ! 626: // see if you can just pick up the clip region bounding ! 627: // rectangle from pco->rclBounds, if so we need to deleted ! 628: // all accumulation codes. ! 629: // ! 630: ! 631: if (prclClipBound) ! 632: { ! 633: rclClipBound.top = ! 634: rclClipBound.left = 0x7fffffffL; ! 635: rclClipBound.right = ! 636: rclClipBound.bottom = 0; ! 637: } ! 638: ! 639: // send a newpath command to the printer. ! 640: ! 641: if (!ps_save(pdev, TRUE)) ! 642: return(FALSE); ! 643: ! 644: ps_newpath(pdev); ! 645: ! 646: // set up to enumerate the clip region, but just do this once. ! 647: ! 648: if (*pbFirstPass == TRUE) ! 649: { ! 650: cRects = CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0); ! 651: *pbFirstPass = FALSE; ! 652: } ! 653: ! 654: // now get each clipping rectangle from the engine, and ! 655: // send it down to the printer. ! 656: ! 657: bMore = TRUE; ! 658: ! 659: cRects = 0; ! 660: ! 661: while(bMore) ! 662: { ! 663: bMore = CLIPOBJ_bEnum(pco, sizeof(buffer), &buffer.c); ! 664: ! 665: if (buffer.c == 0) ! 666: { ! 667: bMore = FALSE; ! 668: break; ! 669: } ! 670: ! 671: ps_box(pdev, &buffer.arcl[0]); ! 672: ! 673: if (prclClipBound) ! 674: { ! 675: if (rclClipBound.top > buffer.arcl[0].top) ! 676: rclClipBound.top = buffer.arcl[0].top; ! 677: ! 678: if (rclClipBound.left > buffer.arcl[0].left) ! 679: rclClipBound.left = buffer.arcl[0].left; ! 680: ! 681: if (rclClipBound.right < buffer.arcl[0].right) ! 682: rclClipBound.right = buffer.arcl[0].right; ! 683: ! 684: if (rclClipBound.bottom < buffer.arcl[0].bottom) ! 685: rclClipBound.bottom = buffer.arcl[0].bottom; ! 686: } ! 687: ! 688: if (pbMoreClipping) ! 689: { ! 690: cRects++; ! 691: if (cRects >= cRectLimit) ! 692: { ! 693: *pbMoreClipping = TRUE; ! 694: break; ! 695: } ! 696: } ! 697: } ! 698: ! 699: // now intersect our new complex region with the existing ! 700: // clipping region. ! 701: ! 702: if (prclClipBound) ! 703: *prclClipBound = rclClipBound; ! 704: ! 705: break; ! 706: ! 707: default: ! 708: // if we get here, we have been passed an invalid pco->iDComplexity. ! 709: // in this case, we will RIP, then treat as trivial clipping case. ! 710: ! 711: RIP("vDoClipObj: invalid pco->iDComplexity.\n"); ! 712: } ! 713: ! 714: return(TRUE); ! 715: } ! 716: ! 717: ! 718: //-------------------------------------------------------------------------- ! 719: // BOOL DrawGlyphs(pdev, cGlyphs, pgp, pfo, pstro, pdata, pwsz) ! 720: // PDEVDATA pdev; ! 721: // DWORD cGlyphs; ! 722: // GLYPHPOS *pgp; ! 723: // FONTOBJ *pfo; ! 724: // STROBJ *pstro; ! 725: // TEXTDATA *pdata; ! 726: // PWSZ pwsz; ! 727: // ! 728: // This routine will output the given glyph at the given position. ! 729: // ! 730: // Parameters: ! 731: // pdev ! 732: // Pointer to our DEVDATA structure. ! 733: // ! 734: // Returns: ! 735: // This routine returns no value. ! 736: // ! 737: // History: ! 738: // 26-Apr-1991 -by- Kent Settle (kentse) ! 739: // Wrote it. ! 740: //-------------------------------------------------------------------------- ! 741: ! 742: BOOL DrawGlyphs(pdev, cGlyphs, pgp, pfo, pstro, pdata, pwsz) ! 743: PDEVDATA pdev; ! 744: DWORD cGlyphs; ! 745: GLYPHPOS *pgp; ! 746: FONTOBJ *pfo; ! 747: STROBJ *pstro; ! 748: TEXTDATA *pdata; ! 749: PWSZ pwsz; ! 750: { ! 751: DWORD cTmp; ! 752: PS_FIX psfxWidth, psfxHeight; ! 753: DLFONT *pDLFont; ! 754: BOOL bString; ! 755: DWORD i; ! 756: FLONG flAccel; ! 757: PWSTR pwstrString; ! 758: ! 759: // get a local copy of the accelerators to munge with. ! 760: ! 761: flAccel = pstro->flAccel; ! 762: ! 763: // if we have a TrueType font, and we are doing font substitution, ! 764: // ignore the SO_FLAG_DEFAULT_PLACEMENT flag. ie, let the engine tell ! 765: // us where to place each character. ! 766: ! 767: if (pdata->bFontSubstitution) ! 768: flAccel &= ~SO_FLAG_DEFAULT_PLACEMENT; ! 769: ! 770: if (cGlyphs != 0) ! 771: { ! 772: // position the first character of the string. ! 773: ! 774: ps_moveto(pdev, &pgp->ptl); ! 775: ! 776: // if we have non-standard spacing for the device font, ! 777: // output an array of character widths, and push the ! 778: // current point on the stack for use in the kshow command. ! 779: ! 780: if (!(flAccel & SO_FLAG_DEFAULT_PLACEMENT)) ! 781: { ! 782: cTmp = cGlyphs - 1; ! 783: ! 784: // we need to handle the different STROBJ accelerators ! 785: // here. these accelerators only affect us if the font ! 786: // is not using the default placement. ! 787: ! 788: if (flAccel & SO_HORIZONTAL) ! 789: { ! 790: if (pdata->bJustification && (cGlyphs > 1)) ! 791: { ! 792: // if we did the justification calculations and found ! 793: // that the justification widths were zero, do nothing ! 794: // here. ! 795: ! 796: if ((pdata->ptSpace.x != 0) || (pdata->ptNonSpace.x != 0)) ! 797: { ! 798: PrintPSFIX(pdev, 2, pdata->ptSpace.x, pdata->ptSpace.y); ! 799: PrintString(pdev, " 8#040 "); ! 800: PrintPSFIX(pdev, 2, pdata->ptNonSpace.x, pdata->ptNonSpace.y); ! 801: PrintString(pdev, "\n"); ! 802: } ! 803: } ! 804: else ! 805: { ! 806: // set up to output array of widths in reverse order, ! 807: // since we will get them off the stack. ! 808: ! 809: pgp += cGlyphs - 1; ! 810: ! 811: #if 0 ! 812: //!!! This is just plain wrong!!! -kentse. ! 813: // deal with fixed pitch fonts. ! 814: ! 815: if (pstro->ulCharInc) ! 816: { ! 817: // we have a fixed pitch font, and the fixed ! 818: // character increment can be found in pstro->ulCharInc. ! 819: ! 820: lCharInc = (LONG)pstro->ulCharInc; ! 821: ! 822: if (flAccel & SO_REVERSED) ! 823: lCharInc *= -1; ! 824: ! 825: // output the increment value. ! 826: ! 827: PrintDecimal(pdev, 1, lCharInc); ! 828: PrintString(pdev, " "); ! 829: } ! 830: else // must be a proportional font. ! 831: { ! 832: // output the character width for each glyph. ! 833: ! 834: i = 0; ! 835: while (cTmp--) ! 836: { ! 837: psfxWidth = X72DPI(pgp->ptl.x) - X72DPI((pgp - 1)->ptl.x); ! 838: pgp--; ! 839: PrintPSFIX(pdev, 1, psfxWidth); ! 840: PrintString(pdev, " "); ! 841: ! 842: // make it readable. ! 843: ! 844: if (i++ == 10) ! 845: { ! 846: PrintString(pdev, "\n"); ! 847: i = 0; ! 848: } ! 849: } ! 850: } ! 851: #endif ! 852: // output the character width for each glyph. ! 853: ! 854: i = 0; ! 855: while (cTmp--) ! 856: { ! 857: psfxWidth = X72DPI(pgp->ptl.x) - X72DPI((pgp - 1)->ptl.x); ! 858: pgp--; ! 859: PrintPSFIX(pdev, 1, psfxWidth); ! 860: PrintString(pdev, " "); ! 861: ! 862: // make it readable. ! 863: ! 864: if (i++ == 10) ! 865: { ! 866: PrintString(pdev, "\n"); ! 867: i = 0; ! 868: } ! 869: } ! 870: } ! 871: } ! 872: ! 873: else if (flAccel & SO_VERTICAL) ! 874: { ! 875: // set up to output array of widths in reverse order, ! 876: // since we will get them off the stack. ! 877: ! 878: pgp += cGlyphs - 1; ! 879: ! 880: #if 0 ! 881: //!!! this is just plain wrong!!! -kentse. ! 882: // deal with fixed pitch fonts. ! 883: ! 884: if (pstro->ulCharInc) ! 885: { ! 886: // we have a fixed pitch font, and the fixed ! 887: // character increment can be found in pstro->ulCharInc. ! 888: ! 889: lCharInc = (LONG)pstro->ulCharInc; ! 890: ! 891: if (flAccel & SO_REVERSED) ! 892: lCharInc *= -1; ! 893: ! 894: // output the increment value. ! 895: ! 896: PrintDecimal(pdev, 1, lCharInc); ! 897: PrintString(pdev, " "); ! 898: } ! 899: else // must be a proportional font. ! 900: { ! 901: // output the character width for each glyph. ! 902: ! 903: while (cTmp--) ! 904: { ! 905: psfxHeight = X72DPI(pgp->ptl.y) - X72DPI((pgp - 1)->ptl.y); ! 906: pgp--; ! 907: PrintPSFIX(pdev, 1, psfxHeight); ! 908: PrintString(pdev, " "); ! 909: } ! 910: } ! 911: #endif ! 912: // output the character width for each glyph. ! 913: ! 914: while (cTmp--) ! 915: { ! 916: psfxHeight = X72DPI(pgp->ptl.y) - X72DPI((pgp - 1)->ptl.y); ! 917: pgp--; ! 918: PrintPSFIX(pdev, 1, psfxHeight); ! 919: PrintString(pdev, " "); ! 920: } ! 921: } ! 922: else // the general case. ! 923: { ! 924: // in the general case, we are printing a string which ! 925: // does not use the default character spacing, and is ! 926: // not horizontal or vertical. in this case, we must ! 927: // do a moveto and a show command for every character. ! 928: ! 929: if (pdata->bDeviceFont) ! 930: { ! 931: // it should be noted that pwstrString is only used ! 932: // if substitution is on, so we do not have to worry ! 933: // about the fact that pstro->pwszOrg is not filled ! 934: // in for device fonts. we do not use the pstro->pwszOrg ! 935: // directly because the STROBJ_bEnum may be "chunking" ! 936: // the data. therefore we will use the current pos. ! 937: // string pointer passed in. it is the caller's ! 938: // responsibility to keep this current. ! 939: ! 940: pwstrString = pwsz; ! 941: ! 942: while (cGlyphs--) ! 943: { ! 944: ps_moveto(pdev, &pgp->ptl); ! 945: ! 946: // output a left paren to open the string. ! 947: ! 948: PrintString(pdev, "("); ! 949: ! 950: // output each character of the string to the printer. ! 951: // if we are doing font substitution then we are substituting ! 952: // a device font for a truetype font. it is assumed that ! 953: // the hglyphs for the truetype font are the unicode character ! 954: // codes. ! 955: ! 956: if (pdata->bFontSubstitution) ! 957: { ! 958: if (!(RemapUnicodeChar(pdev, pwstrString++, pstro, ! 959: flAccel, FALSE, pdata))) ! 960: { ! 961: RIP("PSCRIPT!DrawGlyphs: RemapUnicodeChar failed.\n"); ! 962: return(FALSE); ! 963: } ! 964: } ! 965: else ! 966: { ! 967: if (!(RemapDeviceChar(pdev, (CHAR *)&pgp->hg, pstro, ! 968: flAccel, FALSE, pdata))) ! 969: { ! 970: RIP("PSCRIPT!DrawGlyphs: RemapDeviceChar failed.\n"); ! 971: return(FALSE); ! 972: } ! 973: } ! 974: ! 975: // close the string and send out the show command, ! 976: // abreviated by 't'. ! 977: ! 978: PrintString(pdev, ")t\n"); ! 979: ! 980: // point to the next character. ! 981: ! 982: pgp++; ! 983: } ! 984: ! 985: } ! 986: else // must be a GDI font. ! 987: { ! 988: // get a pointer to our downloaded font structure for this ! 989: // font. ! 990: ! 991: pDLFont = pdev->cgs.pDLFonts; ! 992: ! 993: for (i = 0; i < pdev->iDLFonts; i++) ! 994: { ! 995: // is this entry the one we are looking for? ! 996: ! 997: if (pDLFont->iUniq == pfo->iUniq) ! 998: break; ! 999: ! 1000: pDLFont++; ! 1001: } ! 1002: ! 1003: while (cGlyphs--) ! 1004: { ! 1005: ps_moveto(pdev, &pgp->ptl); ! 1006: ! 1007: // output a left paren to open the string. ! 1008: ! 1009: PrintString(pdev, "("); ! 1010: ! 1011: // set a flag stating that we are now within a string. ! 1012: ! 1013: bString = TRUE; ! 1014: ! 1015: // output each character of the string to the printer. ! 1016: ! 1017: if (!(RemapGDIChar(pdev, pstro, pgp, pDLFont, &bString, ! 1018: flAccel, pdata))) ! 1019: { ! 1020: RIP("PSCRIPT!DrawGlyphs: RemapGDIChar failed.\n"); ! 1021: return(FALSE); ! 1022: } ! 1023: ! 1024: // close the string and send out the show command, ! 1025: // abreviated by 't'. ! 1026: ! 1027: PrintString(pdev, ")t\n"); ! 1028: ! 1029: // point to the next character. ! 1030: ! 1031: pgp++; ! 1032: } ! 1033: } ! 1034: } ! 1035: ! 1036: if ((pstro->cGlyphs != 1) && (!pdata->bJustification) && ! 1037: ((flAccel & SO_HORIZONTAL) || (flAccel & SO_VERTICAL))) ! 1038: { ! 1039: // pgp should now point back to where it did before ! 1040: // we entered this if statement. ! 1041: ! 1042: PrintString(pdev, "a\n"); // 'a' is abrev for currentpoint. ! 1043: } ! 1044: } // end of !SO_FLAG_DEFAULT_PLACEMENT. ! 1045: ! 1046: if ((flAccel & SO_FLAG_DEFAULT_PLACEMENT) || ! 1047: (flAccel & SO_HORIZONTAL) || ! 1048: (flAccel & SO_VERTICAL)) ! 1049: { ! 1050: // output a left paren to open the string. ! 1051: ! 1052: PrintString(pdev, "("); ! 1053: ! 1054: // set a flag stating that we are NOT within a string, until ! 1055: // the first character is actually output. this is necessary ! 1056: // to prevent problems in the HORIZONTAL and VERTICAL cases, ! 1057: // when remapping a font. ! 1058: ! 1059: bString = FALSE; ! 1060: ! 1061: if (pdata->bDeviceFont) ! 1062: { ! 1063: // output each character of the string to the printer. ! 1064: // if we are doing font substitution then we are substituting ! 1065: // a device font for a truetype font. it is assumed that ! 1066: // the hglyphs for the truetype font are the unicode character ! 1067: // codes. ! 1068: ! 1069: if (pdata->bFontSubstitution) ! 1070: { ! 1071: ! 1072: pwstrString = pwsz; ! 1073: ! 1074: // output the first character of the string, then ! 1075: // set the flag stating that we have actually ! 1076: // sent out a character. this prevents us from ! 1077: // setting the flag within the loop. ! 1078: ! 1079: if (!(RemapUnicodeChar(pdev, pwstrString++, pstro, ! 1080: flAccel, bString, pdata))) ! 1081: { ! 1082: RIP("PSCRIPT!DrawGlyphs: RemapUnicodeChar failed.\n"); ! 1083: return(FALSE); ! 1084: } ! 1085: ! 1086: // set the flag stating that we have actually printed ! 1087: // a character. ! 1088: ! 1089: bString = TRUE; ! 1090: cGlyphs--; ! 1091: ! 1092: while (cGlyphs--) ! 1093: { ! 1094: if (!(RemapUnicodeChar(pdev, pwstrString++, pstro, ! 1095: flAccel, bString, pdata))) ! 1096: { ! 1097: RIP("PSCRIPT!DrawGlyphs: RemapUnicodeChar failed.\n"); ! 1098: return(FALSE); ! 1099: } ! 1100: ! 1101: // point to the next character. ! 1102: ! 1103: pgp++; ! 1104: } ! 1105: } ! 1106: else ! 1107: { ! 1108: // output the first character of the string, then ! 1109: // set the flag stating that we have actually ! 1110: // sent out a character. this prevents us from ! 1111: // setting the flag within the loop. ! 1112: ! 1113: if (!(RemapDeviceChar(pdev, (CHAR *)&pgp->hg, pstro, flAccel, ! 1114: bString, pdata))) ! 1115: { ! 1116: RIP("PSCRIPT!DrawGlyphs: RemapDeviceChar failed.\n"); ! 1117: return(FALSE); ! 1118: } ! 1119: ! 1120: // set the flag stating that we have actually printed ! 1121: // a character. ! 1122: ! 1123: bString = TRUE; ! 1124: cGlyphs--; ! 1125: ! 1126: // point to the next character. ! 1127: ! 1128: pgp++; ! 1129: ! 1130: while (cGlyphs--) ! 1131: { ! 1132: if (!(RemapDeviceChar(pdev, (CHAR *)&pgp->hg, pstro, flAccel, ! 1133: bString, pdata))) ! 1134: { ! 1135: RIP("PSCRIPT!DrawGlyphs: RemapDeviceChar failed.\n"); ! 1136: return(FALSE); ! 1137: } ! 1138: ! 1139: // point to the next character. ! 1140: ! 1141: pgp++; ! 1142: } ! 1143: } ! 1144: } ! 1145: else // must be a GDI font. ! 1146: { ! 1147: // get a pointer to our downloaded font structure for this ! 1148: // font. ! 1149: ! 1150: pDLFont = pdev->cgs.pDLFonts; ! 1151: ! 1152: for (i = 0; i < pdev->iDLFonts; i++) ! 1153: { ! 1154: // is this entry the one we are looking for? ! 1155: ! 1156: ! 1157: if (pDLFont->iUniq == pfo->iUniq) ! 1158: break; ! 1159: ! 1160: pDLFont++; ! 1161: } ! 1162: ! 1163: // in the GDI font case, bString simply means we have ! 1164: // begun a string, not necessaryly output a character. ! 1165: ! 1166: bString = TRUE; ! 1167: ! 1168: while (cGlyphs--) ! 1169: { ! 1170: if (!(RemapGDIChar(pdev, pstro, pgp, pDLFont, &bString, ! 1171: flAccel, pdata))) ! 1172: { ! 1173: RIP("PSCRIPT!DrawGlyphs: RemapGDIChar failed.\n"); ! 1174: return(FALSE); ! 1175: } ! 1176: ! 1177: // point to the next character. ! 1178: ! 1179: pgp++; ! 1180: } ! 1181: } ! 1182: ! 1183: if (bString) ! 1184: ps_show(pdev, pstro, flAccel, pdata); ! 1185: } ! 1186: } ! 1187: ! 1188: return(TRUE); ! 1189: } ! 1190: ! 1191: ! 1192: //-------------------------------------------------------------------- ! 1193: // BOOL RemapDeviceChar(pdev, pChar, pstro, flAccel, bString, pdata) ! 1194: // PDEVDATA pdev; ! 1195: // PCHAR pChar; ! 1196: // STROBJ *pstro; ! 1197: // FLONG flAccel; ! 1198: // BOOL bString; ! 1199: // TEXTDATA *pdata; ! 1200: // ! 1201: // This routine is passed a pointer to a PostScript character code. ! 1202: // This routine will output the proper string to the printer, representing ! 1203: // the specified character code. '(', ')' and '\' are preceded by a ! 1204: // backslash. Characters which do not require a font remapping are ! 1205: // output directly. All other characters are output with there octal ! 1206: // representation of their character code. ! 1207: // ! 1208: // Return: ! 1209: // This routine returns TRUE for success, FALSE for failure. ! 1210: // ! 1211: // History: ! 1212: // 26-Apr-1991 -by- Kent Settle (kentse) ! 1213: // Wrote it. ! 1214: // 14-Nov-1991 -by- Kent Settle [kentse] ! 1215: // re-wrote it (got rid of text buffer). ! 1216: //-------------------------------------------------------------------- ! 1217: ! 1218: BOOL RemapDeviceChar(pdev, pChar, pstro, flAccel, bString, pdata) ! 1219: PDEVDATA pdev; ! 1220: PCHAR pChar; ! 1221: STROBJ *pstro; ! 1222: FLONG flAccel; ! 1223: BOOL bString; ! 1224: TEXTDATA *pdata; ! 1225: { ! 1226: PUCMap pmap; ! 1227: BYTE jChar; ! 1228: BOOL bFound; ! 1229: CHAR Buffer[4]; ! 1230: CHAR *pBuffer; ! 1231: ! 1232: // format each character for output to the printer. ! 1233: ! 1234: pBuffer = Buffer; ! 1235: ! 1236: switch(*pChar) ! 1237: { ! 1238: case '(': ! 1239: case ')': ! 1240: case '\\': ! 1241: // precede each of the following characters with a backslash, ! 1242: // then output to printer. ! 1243: ! 1244: *pBuffer++ = '\\'; ! 1245: *pBuffer = *pChar; ! 1246: if (!bPSWrite(pdev, Buffer, 2)) ! 1247: { ! 1248: RIP("PSCRIPT!RemapDeviceChar: bPSWrite failed.\n"); ! 1249: return(FALSE); ! 1250: } ! 1251: break; ! 1252: ! 1253: default: ! 1254: // at this point we should check to see if the high ! 1255: // bit of the usPSValue in mapping.h is set. if it ! 1256: // is, remap the font, then output character. otherwise, ! 1257: // just output character. ! 1258: ! 1259: // get local pointer to mapping table for current font. ! 1260: ! 1261: pmap = pdev->cgs.pmap; ! 1262: ! 1263: // assume character not found in font. ! 1264: ! 1265: bFound = FALSE; ! 1266: ! 1267: while (pmap->szChar) ! 1268: { ! 1269: // search for the matching code in mapping.h. remember ! 1270: // that the high bit is used to indicate the font needs ! 1271: // to be remapped. so ignore the high bit while checking ! 1272: // for a character match. ! 1273: ! 1274: if (*pChar == (CHAR)pmap->usPSValue) ! 1275: { ! 1276: bFound = TRUE; ! 1277: ! 1278: // now check the high bit of the character code in ! 1279: // mapping.h. if it is set, we need to remap the ! 1280: // font for this character. ! 1281: ! 1282: jChar = *pChar; ! 1283: ! 1284: if ((pmap->usPSValue & 0x8000) || (jChar > 0x7F)) ! 1285: { ! 1286: if (pmap->usPSValue & 0x8000) ! 1287: { ! 1288: // remap the font here. ! 1289: ! 1290: RemapFont(pdev, pstro, flAccel, bString, pdata); ! 1291: } ! 1292: ! 1293: // we have an extended character. convert the ! 1294: // non-printable ASCII to backslash octal, and ! 1295: // output to printer. ! 1296: ! 1297: *pBuffer++ = '\\'; ! 1298: *pBuffer++ = (BYTE)((jChar >> 6) + '0'); ! 1299: jChar &= 63; ! 1300: *pBuffer++ = (BYTE)((jChar >> 3) + '0'); ! 1301: *pBuffer = (BYTE)((jChar & 7) + '0'); ! 1302: ! 1303: if (!bPSWrite(pdev, Buffer, 4)) ! 1304: { ! 1305: RIP("PSCRIPT!RemapDeviceChar: bPSWrite failed.\n"); ! 1306: return(FALSE); ! 1307: } ! 1308: } ! 1309: else ! 1310: { ! 1311: // simply write out the character. ! 1312: ! 1313: *pBuffer = *pChar; ! 1314: ! 1315: if (!bPSWrite(pdev, Buffer, 1)) ! 1316: { ! 1317: RIP("PSCRIPT!RemapDeviceChar: bPSWrite failed.\n"); ! 1318: return(FALSE); ! 1319: } ! 1320: } ! 1321: ! 1322: break; ! 1323: } ! 1324: ! 1325: // point to the next character in mapping.h. ! 1326: ! 1327: pmap++; ! 1328: } // while. ! 1329: ! 1330: // if the character was not found in the font, output ! 1331: // a period. ! 1332: ! 1333: if (!bFound) ! 1334: { ! 1335: *pBuffer = '.'; ! 1336: ! 1337: if (!bPSWrite(pdev, Buffer, 1)) ! 1338: { ! 1339: RIP("PSCRIPT!RemapDeviceChar: bPSWrite failed.\n"); ! 1340: return(FALSE); ! 1341: } ! 1342: } ! 1343: ! 1344: break; ! 1345: } // switch. ! 1346: ! 1347: return(TRUE); ! 1348: } ! 1349: ! 1350: ! 1351: //-------------------------------------------------------------------- ! 1352: // BOOL RemapUnicodeChar(pdev, pWChar, pstro, flAccel, bString, pdata) ! 1353: // PDEVDATA pdev; ! 1354: // PWCHAR pWChar; ! 1355: // STROBJ *pstro; ! 1356: // FLONG flAccel; ! 1357: // BOOL bString; ! 1358: // TEXTDATA *pdata; ! 1359: // ! 1360: // This routine is passed a pointer to a UNICODE character code. ! 1361: // This routine will output the proper string to the printer, representing ! 1362: // the specified character code. '(', ')' and '\' are preceded by a ! 1363: // backslash. Characters which do not require a font remapping are ! 1364: // output directly. All other characters are output with there octal ! 1365: // representation of their character code. ! 1366: // ! 1367: // Return: ! 1368: // This routine returns TRUE for success, FALSE for failure. ! 1369: // ! 1370: // History: ! 1371: // 27-Sep-1992 -by- Kent Settle (kentse) ! 1372: // Wrote it. ! 1373: //-------------------------------------------------------------------- ! 1374: ! 1375: BOOL RemapUnicodeChar(pdev, pWChar, pstro, flAccel, bString, pdata) ! 1376: PDEVDATA pdev; ! 1377: PWCHAR pWChar; ! 1378: STROBJ *pstro; ! 1379: FLONG flAccel; ! 1380: BOOL bString; ! 1381: TEXTDATA *pdata; ! 1382: { ! 1383: PUCMap pmap; ! 1384: BYTE jChar; ! 1385: BOOL bFound; ! 1386: CHAR Buffer[4]; ! 1387: CHAR *pBuffer; ! 1388: CHAR *pChar; ! 1389: ! 1390: // begin by finding the UNICODE character code in our mapping table. ! 1391: ! 1392: pmap = pdev->cgs.pmap; ! 1393: ! 1394: // assume character is NOT found in the font. ! 1395: ! 1396: bFound = FALSE; ! 1397: ! 1398: while (pmap->szChar) ! 1399: { ! 1400: if (*pWChar == pmap->usUCValue) ! 1401: { ! 1402: bFound = TRUE; ! 1403: break; ! 1404: } ! 1405: ! 1406: // this was not the character we wanted, check the next one. ! 1407: ! 1408: pmap++; ! 1409: } ! 1410: ! 1411: // if the character was not found, output a period. ! 1412: ! 1413: pBuffer = Buffer; ! 1414: ! 1415: if (!bFound) ! 1416: { ! 1417: *pBuffer = '.'; ! 1418: ! 1419: if (!bPSWrite(pdev, Buffer, 1)) ! 1420: { ! 1421: RIP("PSCRIPT!RemapUnicodeChar: bPSWrite failed.\n"); ! 1422: return(FALSE); ! 1423: } ! 1424: ! 1425: return(TRUE); ! 1426: } ! 1427: ! 1428: // now that we have found the UNICODE character code, get the ! 1429: // corresponding PostScript character code. ! 1430: ! 1431: pChar = (CHAR *)&pmap->usPSValue; ! 1432: ! 1433: // output the character to the printer in its proper format. ! 1434: ! 1435: switch(*pChar) ! 1436: { ! 1437: case '(': ! 1438: case ')': ! 1439: case '\\': ! 1440: // precede each of the following characters with a backslash, ! 1441: // then output to printer. ! 1442: ! 1443: *pBuffer++ = '\\'; ! 1444: *pBuffer = *pChar; ! 1445: if (!bPSWrite(pdev, Buffer, 2)) ! 1446: { ! 1447: RIP("PSCRIPT!RemapUnicodeChar: bPSWrite failed.\n"); ! 1448: return(FALSE); ! 1449: } ! 1450: break; ! 1451: ! 1452: default: ! 1453: // at this point we should check to see if the high ! 1454: // bit of the usPSValue in mapping.h is set. if it ! 1455: // is, remap the font, then output character. otherwise, ! 1456: // just output character. ! 1457: ! 1458: jChar = *pChar; ! 1459: ! 1460: if ((pmap->usPSValue & 0x8000) || (jChar > 0x7F)) ! 1461: { ! 1462: if (pmap->usPSValue & 0x8000) ! 1463: { ! 1464: // remap the font here. ! 1465: ! 1466: RemapFont(pdev, pstro, flAccel, bString, pdata); ! 1467: } ! 1468: ! 1469: // we have an extended character. convert the ! 1470: // non-printable ASCII to backslash octal, and ! 1471: // output to printer. ! 1472: ! 1473: *pBuffer++ = '\\'; ! 1474: *pBuffer++ = (BYTE)((jChar >> 6) + '0'); ! 1475: jChar &= 63; ! 1476: *pBuffer++ = (BYTE)((jChar >> 3) + '0'); ! 1477: *pBuffer = (BYTE)((jChar & 7) + '0'); ! 1478: ! 1479: if (!bPSWrite(pdev, Buffer, 4)) ! 1480: { ! 1481: RIP("PSCRIPT!RemapUnicodeChar: bPSWrite failed.\n"); ! 1482: return(FALSE); ! 1483: } ! 1484: } ! 1485: else ! 1486: { ! 1487: // simply write out the character. ! 1488: ! 1489: *pBuffer = *pChar; ! 1490: ! 1491: if (!bPSWrite(pdev, Buffer, 1)) ! 1492: { ! 1493: RIP("PSCRIPT!RemapUnicodeChar: bPSWrite failed.\n"); ! 1494: return(FALSE); ! 1495: } ! 1496: } ! 1497: } // switch ! 1498: ! 1499: return(TRUE); ! 1500: } ! 1501: ! 1502: ! 1503: //-------------------------------------------------------------------- ! 1504: // BOOL RemapGDIChar(pdev, pstro, pgp, pDLFont, pbString, flAccel, pdata) ! 1505: // PDEVDATA pdev; ! 1506: // STROBJ *pstro; ! 1507: // GLYPHPOS *pgp; ! 1508: // DLFONT *pDLFont; ! 1509: // BOOL *pbString; ! 1510: // FLONG flAccel; ! 1511: // TEXTDATA *pdata; ! 1512: // ! 1513: // This routine is passed a pointer to a GLYPHPOS structure. ! 1514: // This routine will output the proper string to the printer, representing ! 1515: // the specified character code. '(', ')' and '\' are preceded by a ! 1516: // backslash. Characters which are located within the downloaded font are ! 1517: // output directly. Any other character will cause the current string ! 1518: // to be closed, and a show command to be issued. Then the current character ! 1519: // will be drawn, either by bitblt or a path. ! 1520: // ! 1521: // Return: ! 1522: // This routine returns TRUE for success, FALSE for failure. ! 1523: // ! 1524: // History: ! 1525: // 27-Mar-1992 -by- Kent Settle (kentse) ! 1526: // Wrote it. ! 1527: //-------------------------------------------------------------------- ! 1528: ! 1529: BOOL RemapGDIChar(pdev, pstro, pgp, pDLFont, pbString, flAccel, pdata) ! 1530: PDEVDATA pdev; ! 1531: STROBJ *pstro; ! 1532: GLYPHPOS *pgp; ! 1533: DLFONT *pDLFont; ! 1534: BOOL *pbString; ! 1535: FLONG flAccel; ! 1536: TEXTDATA *pdata; ! 1537: { ! 1538: BOOL bFound; ! 1539: CHAR Buffer[4]; ! 1540: CHAR *pBuffer; ! 1541: DWORD i; ! 1542: HGLYPH hglyph; ! 1543: HGLYPH *phg; ! 1544: BYTE jCurrent; ! 1545: ! 1546: // point to internal buffer to build character code into. ! 1547: ! 1548: pBuffer = Buffer; ! 1549: ! 1550: // get the handle for the current glyph. then find the corresponding ! 1551: // character code, as defined in the downloaded font. ! 1552: ! 1553: bFound = FALSE; ! 1554: hglyph = pgp->hg; ! 1555: ! 1556: #if DBG ! 1557: if (hglyph == HGLYPH_INVALID) ! 1558: { ! 1559: RIP("PSCRIPT!RemapGDIChar: hglyph is zero, we're hosed.\n"); ! 1560: return(FALSE); ! 1561: } ! 1562: #endif ! 1563: ! 1564: phg = pDLFont->phgVector; ! 1565: ! 1566: for (i = 0; i < pDLFont->cGlyphs; i++) ! 1567: { ! 1568: if (*phg == hglyph) ! 1569: { ! 1570: bFound = TRUE; ! 1571: break; ! 1572: } ! 1573: ! 1574: phg++; ! 1575: } ! 1576: ! 1577: // i contains the character code for the printer, assuming it was ! 1578: // found in the downloaded font. ! 1579: ! 1580: jCurrent = (BYTE)i; ! 1581: ! 1582: // if the character was found in the downloaded font, we will be ! 1583: // outputting it as part of a string. otherwise, we will be drawing ! 1584: // it via imagemask or as a path. ! 1585: ! 1586: if (bFound) ! 1587: { ! 1588: // the character is part of the downloaded font. so output the ! 1589: // character code as part of a string. we must, however, check ! 1590: // to see if a string already exists to add it to, or if we must ! 1591: // start a new one. ! 1592: ! 1593: if (*pbString == FALSE) ! 1594: { ! 1595: // we are not in the middle of a string, so we must begin ! 1596: // a new one. ! 1597: ! 1598: ps_moveto(pdev, &pgp->ptl); ! 1599: ! 1600: // output a left paren to open the string. ! 1601: ! 1602: PrintString(pdev, "("); ! 1603: } ! 1604: ! 1605: // we are now guaranteed to be in the middle of a string, so ! 1606: // simply output the character code. ! 1607: ! 1608: switch(jCurrent) ! 1609: { ! 1610: case '(': ! 1611: case ')': ! 1612: case '\\': ! 1613: // precede each of the following characters with a backslash, ! 1614: // then output to printer. ! 1615: ! 1616: *pBuffer++ = '\\'; ! 1617: *pBuffer = jCurrent; ! 1618: if (!bPSWrite(pdev, Buffer, 2)) ! 1619: { ! 1620: RIP("PSCRIPT!RemapGDIChar: bPSWrite failed.\n"); ! 1621: return(FALSE); ! 1622: } ! 1623: break; ! 1624: ! 1625: default: ! 1626: // if the character code is within the printable ASCII ! 1627: // range, simply write out the character. otherwise, ! 1628: // we need to output the three digit octal character code. ! 1629: ! 1630: if ((jCurrent >= 0x20) && (jCurrent <= 0x7F)) ! 1631: { ! 1632: if (!bPSWrite(pdev, &jCurrent, 1)) ! 1633: { ! 1634: RIP("PSCRIPT!RemapGDIChar: bPSWrite failed.\n"); ! 1635: return(FALSE); ! 1636: } ! 1637: } ! 1638: else ! 1639: { ! 1640: // convert the non-printable ASCII to backslash octal, ! 1641: // and output to the printer. ! 1642: ! 1643: *pBuffer++ = '\\'; ! 1644: *pBuffer++ = (BYTE)((jCurrent >> 6) + '0'); ! 1645: jCurrent &= 63; ! 1646: *pBuffer++ = (BYTE)((jCurrent >> 3) + '0'); ! 1647: *pBuffer = (BYTE)((jCurrent & 7) + '0'); ! 1648: ! 1649: if (!bPSWrite(pdev, Buffer, 4)) ! 1650: { ! 1651: RIP("PSCRIPT!RemapGDIChar: bPSWrite failed.\n"); ! 1652: return(FALSE); ! 1653: } ! 1654: } ! 1655: break; ! 1656: } // end of switch. ! 1657: ! 1658: // set the flag stating that we are now within a string. ! 1659: ! 1660: *pbString = TRUE; ! 1661: } ! 1662: else // character not found in downloaded font. ! 1663: { ! 1664: // the character is NOT part of the downloaded font. so we must ! 1665: // actually draw the character. we must, however, check to see ! 1666: // if an open string already exists in the printer, and close it ! 1667: // if it does. ! 1668: ! 1669: if (*pbString) ! 1670: { ! 1671: // we are in the middle of a string, so we must end it before ! 1672: // we can draw the current character. ! 1673: ! 1674: ps_show(pdev, pstro, flAccel, pdata); ! 1675: } ! 1676: ! 1677: // we are now ready to draw the character. ! 1678: ! 1679: //!!! for now only bitmap fonts are supported. we will support vector ! 1680: //!!! fonts whenever the engine does. -kentse. ! 1681: ! 1682: CharBitmap(pdev, pgp); ! 1683: ! 1684: // set the flag stating that we are now NOT within a string. ! 1685: ! 1686: *pbString = FALSE; ! 1687: } ! 1688: ! 1689: return(TRUE); ! 1690: } ! 1691: ! 1692: //-------------------------------------------------------------------- ! 1693: // BOOL SelectFont(pdev, pfo, pdata) ! 1694: // PDEVDATA pdev; ! 1695: // FONTOBJ *pfo; ! 1696: // TEXTDATA *pdata; ! 1697: // ! 1698: // This routine selects the font specified in the FONTOBJ, and selects ! 1699: // it as the current font in the printer. If the specified font is ! 1700: // already the current font in the printer, then this routine does ! 1701: // nothing. ! 1702: // ! 1703: // History: ! 1704: // 15-Jul-1992 -by- Kent Settle (kentse) ! 1705: // Added Font Substitution support. ! 1706: // 27-Feb-1992 -by- Kent Settle (kentse) ! 1707: // Added support for downloading, ie caching, GDI fonts. ! 1708: // 20-Feb-1992 -by- Kent Settle (kentse) ! 1709: // Added support for softfonts. ! 1710: // 26-Apr-1991 -by- Kent Settle (kentse) ! 1711: // Wrote it. ! 1712: //-------------------------------------------------------------------- ! 1713: ! 1714: BOOL SelectFont(pdev, pfo, pdata) ! 1715: PDEVDATA pdev; ! 1716: FONTOBJ *pfo; ! 1717: TEXTDATA *pdata; ! 1718: { ! 1719: PNTFM pntfm; ! 1720: BYTE *pSoftFont; ! 1721: DWORD cDownloadedFonts; ! 1722: DLFONT *pDLFont; ! 1723: PS_FIX psfxM11, psfxM12, psfxM21, psfxM22, psfxtmp; ! 1724: XFORM *pxform; ! 1725: ! 1726: // do not select the font in the printer if it is currently selected, ! 1727: // including the same point size. ! 1728: ! 1729: if (pfo->iUniq == pdev->cgs.lidFont) ! 1730: return(TRUE); ! 1731: ! 1732: // get the point size, and fill in the font xform. ! 1733: ! 1734: pdev->cgs.psfxScaleFactor = GetPointSize(pdev, pfo, &pdev->cgs.FontXform); ! 1735: ! 1736: #if DBG ! 1737: if (pdev->cgs.psfxScaleFactor == 0) ! 1738: RIP("PSCRIPT!SelectFont: Zero point size!\n"); ! 1739: #endif ! 1740: ! 1741: // do not select the font into the printer if it is a GDI font that ! 1742: // we will not be caching. according to the DDI spec, if pfo->iUniq ! 1743: // is zero, the GDI font should not be cached. ! 1744: ! 1745: if (!pdata->bDeviceFont && (pfo->iUniq == 0)) ! 1746: { ! 1747: #if DBG ! 1748: DbgPrint("A non-cached GDI font made it to SelectFont, should it have?\n"); ! 1749: #endif ! 1750: return(TRUE); ! 1751: } ! 1752: ! 1753: // select the proper font name for the new font. if this is a ! 1754: // device font, get the name from the NTFM structure. if this ! 1755: // is a GDI font that we are caching, we will create a name for ! 1756: // it at the time we download it to the printer. ! 1757: ! 1758: if (pdata->bDeviceFont) ! 1759: { ! 1760: // get the font metrics for the specified font. ! 1761: ! 1762: pntfm = pdev->pfmtable[pdata->iFace - 1].pntfm; ! 1763: ! 1764: // if the font is a softfont, and it has not yet been downloaded, ! 1765: // download it. ! 1766: ! 1767: if ((pdata->iFace > pdev->cDeviceFonts) && ! 1768: !((BYTE)pdev->cgs.pSFArray[pdata->iFace >> 3] & ! 1769: (BYTE)(1 << (pdata->iFace & 0x07)))) ! 1770: { ! 1771: pSoftFont = (BYTE *)pntfm + pntfm->loSoftFont; ! 1772: ! 1773: // if we have reached our downloaded font threshold, then ! 1774: // we will surround ever textout call with a save/restore. ! 1775: ! 1776: cDownloadedFonts = min(pdev->cgs.cDownloadedFonts, pdev->iDLFonts); ! 1777: ! 1778: if (cDownloadedFonts == pdev->iDLFonts) ! 1779: { ! 1780: ps_save(pdev, FALSE); ! 1781: pdev->cgs.dwFlags |= CGS_DLFONTTHRESHOLD; ! 1782: } ! 1783: ! 1784: if (!bPSWrite(pdev, pSoftFont, pntfm->cjSoftFont)) ! 1785: { ! 1786: RIP("PSCRIPT!SelectFont: downloading of softfont failed.\n"); ! 1787: return(FALSE); ! 1788: } ! 1789: ! 1790: // set the bit saying this font has been downloaded. ! 1791: ! 1792: (BYTE)pdev->cgs.pSFArray[pdata->iFace >> 3] |= ! 1793: (BYTE)(1 << (pdata->iFace & 0x07)); ! 1794: ! 1795: // if we have hit our limit of Fonts we can download, simply overwrite ! 1796: // the last one with the new one. this is to try to conserve on ! 1797: // memory consumption. ! 1798: ! 1799: pDLFont = pdev->cgs.pDLFonts; ! 1800: pDLFont += cDownloadedFonts; ! 1801: ! 1802: pDLFont->iFace = pdata->iFace; ! 1803: pDLFont->iUniq = pfo->iUniq; ! 1804: pDLFont->cGlyphs = 0; ! 1805: pDLFont->phgVector = NULL; ! 1806: ! 1807: pdev->cgs.cDownloadedFonts++; ! 1808: } ! 1809: ! 1810: // select the font in the printer. ! 1811: ! 1812: strcpy(pdev->cgs.szFont, (char *)pntfm + pntfm->loszFontName); ! 1813: } ! 1814: else // must be a GDI font we will be caching. ! 1815: { ! 1816: //!!! the engine is not ready for outline fonts yet!!! -kentse. ! 1817: #if 0 ! 1818: // if this font has not yet been downloaded to the printer, ! 1819: // do it now. ! 1820: ! 1821: if (pfo->flFontType & TRUETYPE_FONTTYPE) ! 1822: { ! 1823: // determine the point size. ! 1824: ! 1825: ulPointSize = (ETOL(pdev->cgs.FontXform.eM22 * 72000) / ! 1826: pdev->psdm.dm.dmPrintQuality); ! 1827: ! 1828: if (ulPointSize < 10) ! 1829: DownloadBitmapFont(pdev, pfo); ! 1830: else ! 1831: DownloadOutlineFont(pdev, pfo); ! 1832: } ! 1833: else if (pfo->flFontType & RASTER_FONTTYPE) ! 1834: DownloadBitmapFont(pdev, pfo); ! 1835: #endif ! 1836: if ( (pfo->flFontType & TRUETYPE_FONTTYPE) || ! 1837: (pfo->flFontType & RASTER_FONTTYPE) ) ! 1838: DownloadBitmapFont(pdev, pfo); ! 1839: else ! 1840: { ! 1841: RIP("PSCRIPT!SelectFont: invalid pfo->flFontType.\n"); ! 1842: return(FALSE); ! 1843: } ! 1844: } ! 1845: ! 1846: // select the proper font, depending on whether or not the ! 1847: // font in question has been reencoded. also, output a scalefont ! 1848: // command if only scaling is ocurring, otherwise output a ! 1849: // makefont command. ! 1850: ! 1851: #if 0 ! 1852: PrintPSFIX(pdev, 1, pdev->cgs.psfxScaleFactor); ! 1853: ! 1854: if (QueryFontRemap(pdev, pfo->iUniq)) ! 1855: PrintString(pdev, " /_"); ! 1856: else ! 1857: PrintString(pdev, " /"); ! 1858: ! 1859: PrintString(pdev, pdev->cgs.szFont); ! 1860: PrintString(pdev, " SF\n"); ! 1861: #endif ! 1862: ! 1863: pxform = &pdev->cgs.FontXform; ! 1864: ! 1865: if ! 1866: ( ! 1867: ((pxform->eM11 == pxform->eM22) && ! 1868: (pxform->eM12 == 0) && ! 1869: (pxform->eM21 == 0) && ! 1870: !((*((ULONG *)&pxform->eM11)) & 0x80000000)) // if positive ! 1871: || ! 1872: ((pfo->flFontType & TRUETYPE_FONTTYPE) && !pdata->bFontSubstitution) // all scaling done already by tt driver ! 1873: ) ! 1874: { ! 1875: PrintPSFIX(pdev, 1, pdev->cgs.psfxScaleFactor); ! 1876: ! 1877: if (QueryFontRemap(pdev, pfo->iUniq)) ! 1878: PrintString(pdev, " /_"); ! 1879: else ! 1880: PrintString(pdev, " /"); ! 1881: ! 1882: PrintString(pdev, pdev->cgs.szFont); ! 1883: PrintString(pdev, " SF\n"); ! 1884: } ! 1885: else ! 1886: { ! 1887: // normalize the font transform by the emheight; ! 1888: ! 1889: psfxtmp = pdev->cgs.fwdEmHeight * PS_FIX_RESOLUTION; ! 1890: ! 1891: psfxM11 = (LONG)((pdev->cgs.FontXform.eM11 * (FLOAT)psfxtmp) / ! 1892: pdev->psdm.dm.dmPrintQuality); ! 1893: psfxM12 = (LONG)((pdev->cgs.FontXform.eM12 * (FLOAT)psfxtmp) / ! 1894: pdev->psdm.dm.dmPrintQuality); ! 1895: psfxM21 = (LONG)((pdev->cgs.FontXform.eM21 * (FLOAT)psfxtmp) / ! 1896: pdev->psdm.dm.dmPrintQuality); ! 1897: psfxM22 = (LONG)((pdev->cgs.FontXform.eM22 * (FLOAT)psfxtmp) / ! 1898: pdev->psdm.dm.dmPrintQuality); ! 1899: ! 1900: PrintString(pdev, "["); ! 1901: PrintPSFIX(pdev, 6, psfxM11, -psfxM12, -psfxM21, psfxM22,0,0); ! 1902: ! 1903: if (QueryFontRemap(pdev, pfo->iUniq)) ! 1904: PrintString(pdev, "] /_"); ! 1905: else ! 1906: PrintString(pdev, "] /"); ! 1907: ! 1908: PrintString(pdev, pdev->cgs.szFont); ! 1909: PrintString(pdev, " MF\n"); ! 1910: } ! 1911: ! 1912: // update the font in our current graphics state. ! 1913: ! 1914: pdev->cgs.lidFont = pfo->iUniq; ! 1915: ! 1916: // if we have a device font, point to the appropriate mapping table ! 1917: // in mapping.h. ! 1918: ! 1919: if (pdata->bDeviceFont) ! 1920: { ! 1921: if (!strcmp((char *)pntfm + pntfm->loszFontName, "Symbol")) ! 1922: pdev->cgs.pmap = SymbolMap; ! 1923: else if (!strcmp((char *)pntfm + pntfm->loszFontName, "ZapfDingbats")) ! 1924: pdev->cgs.pmap = DingbatsMap; ! 1925: else ! 1926: pdev->cgs.pmap = LatinMap; ! 1927: } ! 1928: ! 1929: return(TRUE); ! 1930: } ! 1931: ! 1932: ! 1933: //-------------------------------------------------------------------- ! 1934: // VOID RemapFont(pdev, pstro, flAccel, bString, pdata) ! 1935: // PDEVDATA pdev; ! 1936: // STROBJ *pstro; ! 1937: // FLONG flAccel; ! 1938: // BOOL bString; ! 1939: // TEXTDATA *pdata; ! 1940: // ! 1941: // This routine is only called if we have a character which does not ! 1942: // have the standard PostScript character code. This is determined ! 1943: // by checking the high bit of the usPSValue in the proper table in ! 1944: // mapping.h. If necessary, this routine will download a new ! 1945: // encoding vector. It will then reencode the current font to the ! 1946: // new encoding vector. ! 1947: // ! 1948: // History: ! 1949: // 12-Sep-1991 -by- Kent Settle (kentse) ! 1950: // Wrote it. ! 1951: //-------------------------------------------------------------------- ! 1952: ! 1953: VOID RemapFont(pdev, pstro, flAccel, bString, pdata) ! 1954: PDEVDATA pdev; ! 1955: STROBJ *pstro; ! 1956: FLONG flAccel; ! 1957: BOOL bString; ! 1958: TEXTDATA *pdata; ! 1959: { ! 1960: int i; ! 1961: PSZ *pszEncode; ! 1962: PSZ pszVector; ! 1963: int cbLength; ! 1964: PUCMap pmap; ! 1965: BOOL bFound; ! 1966: FLONG flEncoding; ! 1967: BOOL bRemapDone = FALSE; ! 1968: XFORM *pxform; ! 1969: PS_FIX psfxM11, psfxM12, psfxM21, psfxM22, psfxtmp; ! 1970: ! 1971: //!!! All this font remapping stuff gets blown away by a gsave/grestore ! 1972: //!!! which is done from DrvTextout when clipping. Perhaps move flags from ! 1973: //!!! CGS to PDEV. ! 1974: ! 1975: // if the font remapping header has not been downloaded to the ! 1976: // printer, do it now. this header is sent at most once per job. ! 1977: ! 1978: if (!(pdev->dwFlags & PDEV_FONTREDEFINED)) ! 1979: { ! 1980: // we are in the middle of outputting a string. close ! 1981: // the current string and output a show command to the ! 1982: // printer, output the remapping, then begin a new string. ! 1983: ! 1984: ps_show(pdev, pstro, flAccel, pdata); ! 1985: bRemapDone = TRUE; ! 1986: ! 1987: pszEncode = apszRemapCode; ! 1988: while (*pszEncode) ! 1989: { ! 1990: PrintString(pdev, (PSZ)*pszEncode++); ! 1991: PrintString(pdev, "\n"); ! 1992: } ! 1993: ! 1994: pdev->dwFlags |= PDEV_FONTREDEFINED; ! 1995: } ! 1996: ! 1997: // select the proper encoding vector to download. ! 1998: ! 1999: if (pdev->cgs.pmap == SymbolMap) ! 2000: { ! 2001: pszVector = "SYMENC"; ! 2002: flEncoding = PDEV_SYMENCODED; ! 2003: } ! 2004: else if (pdev->cgs.pmap == DingbatsMap) ! 2005: { ! 2006: pszVector = "DINGENC"; ! 2007: flEncoding = PDEV_DINGENCODED; ! 2008: } ! 2009: else ! 2010: { ! 2011: pszVector = "LATENC"; ! 2012: flEncoding = PDEV_LATINENCODED; ! 2013: } ! 2014: ! 2015: // define the new font encoding if it has not already been done. ! 2016: ! 2017: if ((pdev->dwFlags & flEncoding) == 0) ! 2018: { ! 2019: if (!bRemapDone) ! 2020: { ! 2021: // we are in the middle of outputting a string. close ! 2022: // the current string and output a show command to the ! 2023: // printer, output the remapping, then begin a new string. ! 2024: ! 2025: ps_show(pdev, pstro, flAccel, pdata); ! 2026: bRemapDone = TRUE; ! 2027: } ! 2028: ! 2029: // download the new encoding vector. just to make things readable, ! 2030: // let's limit the line length. ! 2031: ! 2032: cbLength = 0; ! 2033: ! 2034: PrintString(pdev, "/"); ! 2035: PrintString(pdev, pszVector); ! 2036: PrintString(pdev, " [0\n"); ! 2037: ! 2038: // PostScript fonts containg 256 characters. for each character, ! 2039: // do a lookup in the appropriate mapping table in mapping.h to ! 2040: // get the ASCII name of the character to output in the encoding ! 2041: // vector. if the character is not found in the encoding vector, ! 2042: // output ".notdef" for that character. ! 2043: ! 2044: for (i = 0; i < 256; i++) ! 2045: { ! 2046: if (cbLength > MAX_LINE_LENGTH) ! 2047: { ! 2048: // skip to the next line. ! 2049: ! 2050: PrintString(pdev, "\n"); ! 2051: cbLength = 0; ! 2052: } ! 2053: ! 2054: // get local pointer to mapping table for current font. ! 2055: ! 2056: pmap = pdev->cgs.pmap; ! 2057: ! 2058: // assume character not found in font. ! 2059: ! 2060: bFound = FALSE; ! 2061: ! 2062: while (pmap->szChar) ! 2063: { ! 2064: // search for the matching code in mapping.h. remember ! 2065: // that the high bit is used to indicate the font needs ! 2066: // to be remapped. so ignore the high bit while checking ! 2067: // for a character match. ! 2068: ! 2069: if ((CHAR)i == (CHAR)pmap->usPSValue) ! 2070: { ! 2071: bFound = TRUE; ! 2072: ! 2073: PrintString(pdev, "/"); ! 2074: PrintString(pdev, pmap->szChar); ! 2075: ! 2076: cbLength += (strlen(pmap->szChar) + 1); ! 2077: break; ! 2078: } ! 2079: ! 2080: // point to the next character in mapping.h. ! 2081: ! 2082: pmap++; ! 2083: } // while. ! 2084: ! 2085: // if the character was not found in the font, output .notdef. ! 2086: ! 2087: if (!bFound) ! 2088: { ! 2089: PrintString(pdev, "/.notdef"); ! 2090: cbLength += 8; ! 2091: } ! 2092: } ! 2093: ! 2094: // we are done downloading the encoding vector. ! 2095: ! 2096: PrintString(pdev, "\n]def\n"); ! 2097: ! 2098: // mark that this encoding vector is now defined in the printer. ! 2099: ! 2100: pdev->dwFlags |= flEncoding; ! 2101: } ! 2102: ! 2103: // output the PostScript commands to reencode the current font ! 2104: // using the proper encoding vector, if the current font has ! 2105: // not already been reencoded. ! 2106: ! 2107: if (!QueryFontRemap(pdev, pdev->cgs.lidFont)) ! 2108: { ! 2109: if (!bRemapDone) ! 2110: { ! 2111: // we are in the middle of outputting a string. close ! 2112: // the current string and output a show command to the ! 2113: // printer, output the remapping, then begin a new string. ! 2114: ! 2115: ps_show(pdev, pstro, flAccel, pdata); ! 2116: bRemapDone = TRUE; ! 2117: } ! 2118: ! 2119: PrintString(pdev, pszVector); ! 2120: PrintString(pdev, " /_"); ! 2121: PrintString(pdev, pdev->cgs.szFont); ! 2122: PrintString(pdev, " /"); ! 2123: PrintString(pdev, pdev->cgs.szFont); ! 2124: PrintString(pdev, " reencode\n"); ! 2125: ! 2126: // select the newly reencoded font. ! 2127: ! 2128: pxform = &pdev->cgs.FontXform; ! 2129: ! 2130: if ! 2131: ( ! 2132: (pxform->eM11 == pxform->eM22) && ! 2133: (pxform->eM12 == 0) && ! 2134: (pxform->eM21 == 0) && ! 2135: !((*((ULONG *)&pxform->eM11)) & 0x80000000) // if positive ! 2136: ) ! 2137: { ! 2138: PrintPSFIX(pdev, 1, pdev->cgs.psfxScaleFactor); ! 2139: PrintString(pdev, " /_"); ! 2140: PrintString(pdev, pdev->cgs.szFont); ! 2141: PrintString(pdev, " SF\n"); ! 2142: } ! 2143: else ! 2144: { ! 2145: // normalize the font transform by the emheight; ! 2146: ! 2147: psfxtmp = pdev->cgs.fwdEmHeight * PS_FIX_RESOLUTION; ! 2148: ! 2149: psfxM11 = (LONG)((pdev->cgs.FontXform.eM11 * (FLOAT)psfxtmp) / ! 2150: pdev->psdm.dm.dmPrintQuality); ! 2151: psfxM12 = (LONG)((pdev->cgs.FontXform.eM12 * (FLOAT)psfxtmp) / ! 2152: pdev->psdm.dm.dmPrintQuality); ! 2153: psfxM21 = (LONG)((pdev->cgs.FontXform.eM21 * (FLOAT)psfxtmp) / ! 2154: pdev->psdm.dm.dmPrintQuality); ! 2155: psfxM22 = (LONG)((pdev->cgs.FontXform.eM22 * (FLOAT)psfxtmp) / ! 2156: pdev->psdm.dm.dmPrintQuality); ! 2157: ! 2158: PrintString(pdev, "["); ! 2159: PrintPSFIX(pdev, 6, psfxM11, -psfxM12, -psfxM21, psfxM22,0,0); ! 2160: ! 2161: PrintString(pdev, "] /_"); ! 2162: PrintString(pdev, pdev->cgs.szFont); ! 2163: PrintString(pdev, " MF\n"); ! 2164: } ! 2165: ! 2166: // set a flag saying that the current font has been reencoded. ! 2167: ! 2168: SetFontRemap(pdev, pdev->cgs.lidFont); ! 2169: } ! 2170: ! 2171: // if any remapping was done, start a new string. ! 2172: ! 2173: if (bRemapDone) ! 2174: { ! 2175: if ((flAccel == 0) || (flAccel & SO_FLAG_DEFAULT_PLACEMENT)) ! 2176: PrintString(pdev, "("); ! 2177: else if ((flAccel & SO_HORIZONTAL) || (flAccel & SO_VERTICAL)) ! 2178: { ! 2179: // if we have a vertical or horizontal, non default spacing, ! 2180: // case, and we have just remapped a font, and we have actuall ! 2181: // printed at least one character within the string, then we need ! 2182: // to get rid of the with between the last character printed, then ! 2183: // get the current position on the stack before we begin our ! 2184: // string. ! 2185: ! 2186: if (pdata->bJustification) ! 2187: { ! 2188: // if we did the justification calculations and found ! 2189: // that the justification widths were zero, do nothing ! 2190: // here. ! 2191: ! 2192: if ((pdata->ptSpace.x != 0) || (pdata->ptNonSpace.x != 0)) ! 2193: { ! 2194: PrintPSFIX(pdev, 2, pdata->ptSpace.x, pdata->ptSpace.y); ! 2195: PrintString(pdev, " 8#040 "); ! 2196: PrintPSFIX(pdev, 2, pdata->ptNonSpace.x, pdata->ptNonSpace.y); ! 2197: PrintString(pdev, "\n"); ! 2198: } ! 2199: ! 2200: PrintString(pdev, "("); ! 2201: } ! 2202: else if (bString) ! 2203: PrintString(pdev, "pop a ("); ! 2204: else ! 2205: { ! 2206: if(pstro->cGlyphs != 1) ! 2207: PrintString(pdev, "a ("); ! 2208: else ! 2209: PrintString(pdev, "("); ! 2210: } ! 2211: } ! 2212: } ! 2213: } ! 2214: ! 2215: ! 2216: //-------------------------------------------------------------------- ! 2217: // VOID CharBitmap(pdev, pgp) ! 2218: // PDEVDATA pdev; ! 2219: // GLYPHPOS *pgp; ! 2220: // ! 2221: // This routine downloads the bitmap for the given character to ! 2222: // the printer. ! 2223: // ! 2224: // History: ! 2225: // 26-Sep-1991 -by- Kent Settle (kentse) ! 2226: // Wrote it. ! 2227: //-------------------------------------------------------------------- ! 2228: ! 2229: VOID CharBitmap(pdev, pgp) ! 2230: PDEVDATA pdev; ! 2231: GLYPHPOS *pgp; ! 2232: { ! 2233: POINTPSFX ptpsfx; ! 2234: int cjWidth; ! 2235: int i; ! 2236: BYTE *pjBits; ! 2237: LONG cx, cy; ! 2238: ! 2239: // adjust the (x, y) coordinates to adjust for displacement of ! 2240: // character origin from bitmap origin. ! 2241: ! 2242: pgp->ptl.x += pgp->pgdf->pgb->ptlOrigin.x; ! 2243: pgp->ptl.y += pgp->pgdf->pgb->ptlOrigin.y; ! 2244: ! 2245: // position the image on the page, remembering to flip the image ! 2246: // from top to bottom. ! 2247: ! 2248: ptpsfx.x = X72DPI(pgp->ptl.x); ! 2249: ptpsfx.y = Y72DPI(pgp->ptl.y); ! 2250: ! 2251: // output PostScript user coordinates to the printer. ! 2252: ! 2253: PrintString(pdev, "save "); ! 2254: PrintPSFIX(pdev, 2, ptpsfx.x, ptpsfx.y); ! 2255: PrintString(pdev, " translate\n"); ! 2256: ! 2257: // scale the image. ! 2258: //!!! I do not know how this ever worked if it did. [Bodind] ! 2259: ! 2260: // cx = pgp->pgdf->pgb->aj[0]; ! 2261: ! 2262: // cy = pgp->pgdf->pgb->aj[1]; ! 2263: ! 2264: ! 2265: cx = pgp->pgdf->pgb->sizlBitmap.cx; ! 2266: cy = pgp->pgdf->pgb->sizlBitmap.cy; ! 2267: ! 2268: ptpsfx.x = (cx * PS_FIX_RESOLUTION) / pdev->psdm.dm.dmPrintQuality; ! 2269: ptpsfx.y = (cy * PS_FIX_RESOLUTION) / pdev->psdm.dm.dmPrintQuality; ! 2270: ! 2271: PrintPSFIX(pdev, 2, ptpsfx.x, ptpsfx.y); ! 2272: PrintString(pdev, " scale\n"); ! 2273: ! 2274: // output the image operator and the scan data. true means to ! 2275: // paint the '1' bits with the foreground color. ! 2276: ! 2277: PrintDecimal(pdev, 2, cx, cy); ! 2278: PrintString(pdev, " true ["); ! 2279: PrintDecimal(pdev, 1, cx); ! 2280: PrintString(pdev, " 0 0 "); ! 2281: PrintDecimal(pdev, 1, -cy); ! 2282: PrintString(pdev, " 0 0]\n{<"); ! 2283: ! 2284: // how wide is the destination in bytes? postscript bitmaps are padded ! 2285: // to 8bit boundaries. ! 2286: ! 2287: cjWidth = (cx + 7) >> 3; ! 2288: ! 2289: //!!! this seems to be wrong, do not know why it ever worked if it did ! 2290: //!!! [bodind] ! 2291: // pjBits = (BYTE *)&pgp->pgdf->pgb->aj[2]; ! 2292: ! 2293: ! 2294: pjBits = pgp->pgdf->pgb->aj; ! 2295: ! 2296: for (i = 0; i < cy; i++) ! 2297: { ! 2298: // output each scanline to the printer. ! 2299: ! 2300: vHexOut(pdev, pjBits, cjWidth); ! 2301: pjBits += cjWidth; ! 2302: } ! 2303: ! 2304: PrintString(pdev, ">} im restore\n"); ! 2305: } ! 2306: ! 2307: ! 2308: //-------------------------------------------------------------------- ! 2309: // BOOL DownloadBitmapFont(pdev, pfo) ! 2310: // PDEVDATA pdev; ! 2311: // FONTOBJ *pfo; ! 2312: // ! 2313: // This routine downloads the font definition for the given bitmap font, ! 2314: // if it has not already been done. The font is downloaded as an ! 2315: // Adobe Type 3 font. ! 2316: // ! 2317: // This routine return TRUE if the font is successfully, or has already ! 2318: // been, downloaded to the printer. It returns FALSE if it fails. ! 2319: // ! 2320: // History: ! 2321: // 27-Feb-1992 -by- Kent Settle (kentse) ! 2322: // Wrote it. ! 2323: //-------------------------------------------------------------------- ! 2324: ! 2325: BOOL DownloadBitmapFont(pdev, pfo) ! 2326: PDEVDATA pdev; ! 2327: FONTOBJ *pfo; ! 2328: { ! 2329: DLFONT *pDLFont; ! 2330: DWORD i, j; ! 2331: DWORD cDownloadedFonts; ! 2332: DWORD cGlyphs, cTmp; ! 2333: HGLYPH *phg; ! 2334: HGLYPH *phgSave; ! 2335: GLYPHDATA *pglyphdata; ! 2336: POINTL ptlTL, ptlBR, ptl1; ! 2337: PIFIMETRICS pifi; ! 2338: PS_FIX psfxXtrans, psfxYtrans; ! 2339: CHAR szFaceName[MAX_STRING]; ! 2340: PSZ pszFaceName; ! 2341: PWSTR pwstr; ! 2342: LONG cjWidth; ! 2343: BYTE *pjBits; ! 2344: LONG EmHeight; ! 2345: XFORMOBJ *pxo; ! 2346: POINTFIX ptfx; ! 2347: PS_FIX psfxPointSize; ! 2348: XFORM fontxform; ! 2349: ! 2350: // search through our list of downloaded GDI fonts to see if the ! 2351: // current font has already been downloaded to the printer. ! 2352: ! 2353: pDLFont = pdev->cgs.pDLFonts; ! 2354: ! 2355: cDownloadedFonts = min(pdev->cgs.cDownloadedFonts, pdev->iDLFonts); ! 2356: ! 2357: for (i = 0; i < cDownloadedFonts; i++) ! 2358: { ! 2359: // is this entry the one we are looking for? simply return if so. ! 2360: ! 2361: if (pDLFont->iUniq == pfo->iUniq) ! 2362: { ! 2363: // update the fontname and size in our current graphics state. ! 2364: ! 2365: strcpy(pdev->cgs.szFont, pDLFont->strFont); ! 2366: pdev->cgs.lidFont = pDLFont->iUniq; ! 2367: ! 2368: return(TRUE); ! 2369: } ! 2370: ! 2371: pDLFont++; ! 2372: } ! 2373: ! 2374: // we did not find that this font has been downloaded yet, so we must ! 2375: // do it now. ! 2376: ! 2377: // if we have reached our downloaded font threshold, then ! 2378: // we will surround ever textout call with a save/restore. ! 2379: ! 2380: if (cDownloadedFonts >= pdev->iDLFonts) ! 2381: { ! 2382: ps_save(pdev, FALSE); ! 2383: pdev->cgs.dwFlags |= CGS_DLFONTTHRESHOLD; ! 2384: cDownloadedFonts = pdev->iDLFonts; ! 2385: } ! 2386: ! 2387: pDLFont = pdev->cgs.pDLFonts; ! 2388: pDLFont += cDownloadedFonts; ! 2389: ! 2390: memset(pDLFont, 0, sizeof(DLFONT)); ! 2391: ! 2392: pDLFont->iFace = pfo->iFace; ! 2393: pDLFont->iUniq = pfo->iUniq; ! 2394: ! 2395: // if we have made it this far, we should simply be able to ! 2396: // download the font now. ! 2397: ! 2398: // we will be downloading an Adobe TYPE 3 font. ! 2399: ! 2400: // allocate a dictionary for the font. ! 2401: ! 2402: PrintString(pdev, "9 dict d begin\n"); ! 2403: ! 2404: // set FontType to 3 indicating user defined font. ! 2405: ! 2406: PrintString(pdev, "/FontType 3 def\n"); ! 2407: ! 2408: // allocate memory for and get the handles for each glyph of the font. ! 2409: ! 2410: if (!(cGlyphs = FONTOBJ_cGetAllGlyphHandles(pfo, NULL))) ! 2411: { ! 2412: RIP("PSCRIPT!DownloadBitmapFont: cGetAllGlyphHandles failed.\n"); ! 2413: return(FALSE); ! 2414: } ! 2415: ! 2416: if (!(phg = (HGLYPH *)HeapAlloc(pdev->hheap, 0, sizeof(HGLYPH) * cGlyphs))) ! 2417: { ! 2418: RIP("PSCRIPT!DownloadBitmapFont: HeapAlloc failed.\n"); ! 2419: return(FALSE); ! 2420: } ! 2421: ! 2422: phgSave = phg; ! 2423: ! 2424: cTmp = FONTOBJ_cGetAllGlyphHandles(pfo, phg); ! 2425: ! 2426: ASSERTPS(cTmp == cGlyphs, "PSCRIPT!DownloadBitmapFont: inconsistent cGlyphs\n"); ! 2427: ! 2428: // how many characters will we define in this font? ! 2429: // keep in mind that we can only do 256 at a time. ! 2430: // remember to leave room for the .notdef character. ! 2431: ! 2432: cGlyphs = min(255, cGlyphs); ! 2433: ! 2434: // run through the array, looking at the bounding box for each ! 2435: // glyph, in order to create the bounding box for the entire ! 2436: // font. ! 2437: ! 2438: ptlTL.x = ADOBE_FONT_UNITS; ! 2439: ptlTL.y = ADOBE_FONT_UNITS; ! 2440: ptlBR.x = 0; ! 2441: ptlBR.y = 0; ! 2442: ! 2443: for (i = 0; i < cGlyphs; i++) ! 2444: { ! 2445: // get the GLYPHDATA structure for each glyph. ! 2446: ! 2447: if (!(cTmp = FONTOBJ_cGetGlyphs(pfo, FO_GLYPHBITS, 1, phg, (PVOID *)&pglyphdata))) ! 2448: { ! 2449: RIP("PSCRIPT!DownloadBitmapFont: cGetGlyphs failed.\n"); ! 2450: HeapFree(pdev->hheap, 0, (PVOID)phgSave); ! 2451: return(FALSE); ! 2452: } ! 2453: ! 2454: ptlTL.x = min(ptlTL.x, pglyphdata->rclInk.left); ! 2455: ptlTL.y = min(ptlTL.y, pglyphdata->rclInk.top); ! 2456: ptlBR.x = max(ptlBR.x, pglyphdata->rclInk.right); ! 2457: ptlBR.y = max(ptlBR.y, pglyphdata->rclInk.bottom); ! 2458: ! 2459: // point to the next glyph handle. ! 2460: ! 2461: phg++; ! 2462: } ! 2463: ! 2464: // get the IFIMETRICS for the font. ! 2465: ! 2466: if (!(pifi = FONTOBJ_pifi(pfo))) ! 2467: { ! 2468: RIP("PSCRIPT!DownloadBitmapFont: pifi failed.\n"); ! 2469: HeapFree(pdev->hheap, 0, (PVOID)phgSave); ! 2470: return(FALSE); ! 2471: } ! 2472: ! 2473: // get the Notional to Device transform. this is needed to ! 2474: // determine the point size. ! 2475: ! 2476: pxo = FONTOBJ_pxoGetXform(pfo); ! 2477: ! 2478: if (pxo == NULL) ! 2479: { ! 2480: RIP("PSCRIPT!DownloadBitmapFont: pxo == NULL.\n"); ! 2481: return(FALSE); ! 2482: } ! 2483: ! 2484: // apply the notional to device transform. ! 2485: ! 2486: ptl1.x = 0; ! 2487: ptl1.y = pifi->fwdUnitsPerEm; ! 2488: ! 2489: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl1, &ptfx); ! 2490: ! 2491: // now get the length of the vector. ! 2492: ! 2493: EmHeight = FXTOL(iHipot(ptfx.x, ptfx.y)); ! 2494: ! 2495: // we have filled in the GLYPHPOS for each glyph in the font. ! 2496: // reset the pointer to the first glyph. ! 2497: ! 2498: phg = phgSave; ! 2499: ! 2500: PrintString(pdev, "/FontMatrix [1 "); ! 2501: PrintDecimal(pdev, 1, EmHeight); ! 2502: PrintString(pdev, " div 0 0 1 "); ! 2503: PrintDecimal(pdev, 1, EmHeight); ! 2504: PrintString(pdev, " div 0 0] def\n"); ! 2505: ! 2506: // define the bounding box for the font, defined in 1 unit ! 2507: // character space (since FontMatrix = identity). ! 2508: ! 2509: PrintString(pdev, "/FontBBox ["); ! 2510: PrintDecimal(pdev, 4, ptlTL.x, ptlTL.y, ptlBR.x, ptlBR.y); ! 2511: PrintString(pdev, " ] def\n"); ! 2512: ! 2513: // allocate array for encoding vector, then initialize ! 2514: // all characters in encoding vector with '.notdef'. ! 2515: ! 2516: PrintString(pdev, "/Encoding 256 array def\n"); ! 2517: PrintString(pdev, "0 1 255 {Encoding exch /.notdef put} for\n"); ! 2518: ! 2519: // allocate space to store the HGLYPH<==>character code mapping. ! 2520: ! 2521: if (!(pDLFont->phgVector = (HGLYPH *)HeapAlloc(pdev->hheap, 0, ! 2522: sizeof(HGLYPH) * cGlyphs))) ! 2523: { ! 2524: RIP("PSCRIPT!DownloadBitmapFont: HeapAlloc for phgVector failed.\n"); ! 2525: HeapFree(pdev->hheap, 0, (PVOID)phgSave); ! 2526: return(FALSE); ! 2527: } ! 2528: ! 2529: // fill in the HGLYPH encoding vector, and output ! 2530: // the encoding vector to the printer. ! 2531: ! 2532: pDLFont->cGlyphs = cGlyphs; ! 2533: memcpy(pDLFont->phgVector, phg, cGlyphs * sizeof(HGLYPH)); ! 2534: ! 2535: PrintString(pdev, "Encoding\n"); ! 2536: ! 2537: for (i = 0; i < cGlyphs; i++) ! 2538: { ! 2539: PrintString(pdev, "d "); ! 2540: PrintDecimal(pdev, 1, i); ! 2541: PrintString(pdev, " /c"); ! 2542: PrintDecimal(pdev, 1, i); ! 2543: PrintString(pdev, " p\n"); ! 2544: } ! 2545: ! 2546: // under level 1 of PostScript, the 'BuildChar' procedure is called ! 2547: // every time a character from the font is constructed. under ! 2548: // level 2, 'BuildGlyph' is called instead. therefore, we will ! 2549: // define a 'BuildChar' procedure, which basically calls ! 2550: // 'BuildGlyph'. this will provide us support for both level 1 ! 2551: // and level 2 of PostScript. ! 2552: ! 2553: // define the 'BuildGlyph' procedure. start by getting the ! 2554: // character name and the font dictionary from the stack. ! 2555: ! 2556: PrintString(pdev, "/BuildGlyph {0 begin /cn ed /fd ed\n"); ! 2557: ! 2558: // retrieve the character information from the CharData (CD) ! 2559: // dictionary. ! 2560: ! 2561: PrintString(pdev, "/CI fd /CD get cn get def\n"); ! 2562: ! 2563: // get the width and the bounding box from the CharData. ! 2564: // remember to divide the width by 16. ! 2565: ! 2566: PrintString(pdev, "/wx CI 0 get def /cbb CI 1 4 getinterval def\n"); ! 2567: ! 2568: // enable each character to be cached. ! 2569: ! 2570: PrintString(pdev, "wx 0 cbb aload pop setcachedevice\n"); ! 2571: ! 2572: // get the width and height of the bitmap, set invert bool to true ! 2573: // specifying reverse image. ! 2574: ! 2575: PrintString(pdev, "CI 5 get CI 6 get true\n"); ! 2576: ! 2577: // insert x and y translation components into general imagemask ! 2578: // matrix. ! 2579: ! 2580: PrintString(pdev, "[1 0 0 -1 0 0] d 4 CI 7 get p d 5 CI 8 get p\n"); ! 2581: ! 2582: // get hex string bitmap, convert into procedure, then print ! 2583: // the bitmap image. ! 2584: ! 2585: PrintString(pdev, "CI 9 1 getinterval cvx im end } def\n"); ! 2586: ! 2587: // create local storage for 'BuildGlyph' procedure. ! 2588: ! 2589: PrintString(pdev, "/BuildGlyph load 0 5 dict put\n"); ! 2590: ! 2591: // the semantics of 'BuildChar' differ from 'BuildGlyph' in the ! 2592: // following way: 'BuildChar' is called with the font dictionary ! 2593: // and character code on the stack, 'BuildGlyph' is called with ! 2594: // the font dictionary and character name on the stack. the ! 2595: // following 'BuildChar' procedure calls 'BuildGlyph', and retains ! 2596: // compatiblity with level 1 PostScript. ! 2597: ! 2598: PrintString(pdev, "/BuildChar {1 index /Encoding get exch get\n"); ! 2599: PrintString(pdev, "1 index /BuildGlyph get exec} bind def\n"); ! 2600: ! 2601: // now create a dictionary containing information on each character. ! 2602: ! 2603: PrintString(pdev, "/CD "); ! 2604: PrintDecimal(pdev, 1, cGlyphs + 1); ! 2605: PrintString(pdev, " dict def CD begin\n"); ! 2606: ! 2607: for (i = 0; i < cGlyphs; i++) ! 2608: { ! 2609: // get the GLYPHDATA structure for each glyph. ! 2610: ! 2611: if (!(cTmp = FONTOBJ_cGetGlyphs(pfo, FO_GLYPHBITS, 1, phg, (PVOID *)&pglyphdata))) ! 2612: { ! 2613: RIP("PSCRIPT!DownloadBitmapFont: cGetGlyphs failed.\n"); ! 2614: HeapFree(pdev->hheap, 0, (PVOID)phgSave); ! 2615: HeapFree(pdev->hheap, 0, (PVOID)pDLFont->phgVector); ! 2616: return(FALSE); ! 2617: } ! 2618: ! 2619: // the first number in the character description is the width ! 2620: // in 1 unit font space. the next four numbers are the bounding ! 2621: // box in 1 unit font space. the next two numbers are the width ! 2622: // and height of the bitmap. the next two numbers are the x and ! 2623: // y translation values for the matrix given to imagemask. ! 2624: // this is followed by the bitmap itself. ! 2625: ! 2626: // first, output the character name. ! 2627: ! 2628: PrintString(pdev, "/c"); ! 2629: PrintDecimal(pdev, 1, i); ! 2630: ! 2631: // output the character description array. the width and ! 2632: // bounding box need to be normalized to 1 unit font space. ! 2633: ! 2634: // the width will be sent to the printer as the actual width ! 2635: // multiplied by 16 so as not to lose any precision when ! 2636: // normalizing. ! 2637: ! 2638: PrintString(pdev, " ["); ! 2639: PrintPSFIX(pdev, 1, (pglyphdata->fxD << 4)); ! 2640: PrintString(pdev, " "); ! 2641: PrintDecimal(pdev, 4, pglyphdata->rclInk.left, ! 2642: -pglyphdata->rclInk.top, pglyphdata->rclInk.right, ! 2643: -pglyphdata->rclInk.bottom); ! 2644: PrintString(pdev, " "); ! 2645: ! 2646: // output the width and height of the bitmap itself. ! 2647: ! 2648: PrintDecimal(pdev, 2, pglyphdata->gdf.pgb->sizlBitmap.cx, ! 2649: pglyphdata->gdf.pgb->sizlBitmap.cy); ! 2650: PrintString(pdev, " "); ! 2651: ! 2652: // output the translation values for the transform matrix. ! 2653: // the x component is usually the equivalent of the left ! 2654: // sidebearing in pixels. the y component is always the height ! 2655: // of the bitmap minus any displacement factor (such as for characters ! 2656: // with descenders. ! 2657: ! 2658: psfxXtrans = -pglyphdata->gdf.pgb->ptlOrigin.x << 8; ! 2659: psfxYtrans = -pglyphdata->gdf.pgb->ptlOrigin.y << 8; ! 2660: ! 2661: PrintPSFIX(pdev, 2, psfxXtrans, psfxYtrans); ! 2662: PrintString(pdev, "\n<"); ! 2663: ! 2664: // now output the bits. calculate how many bytes each source scanline ! 2665: // contains. remember that the bitmap will be padded to 32bit bounds. ! 2666: ! 2667: // protect ourselves. ! 2668: ! 2669: if ((pglyphdata->gdf.pgb->sizlBitmap.cx < 1) || ! 2670: (pglyphdata->gdf.pgb->sizlBitmap.cy < 1)) ! 2671: { ! 2672: RIP("PSCRIPT!DownloadBitmapFont: Invalid glyphdata!!!.\n"); ! 2673: return(FALSE); ! 2674: } ! 2675: ! 2676: pjBits = pglyphdata->gdf.pgb->aj; ! 2677: ! 2678: for (j = 0; j < (DWORD)pglyphdata->gdf.pgb->sizlBitmap.cy; j++) ! 2679: { ! 2680: cjWidth = (LONG)(pglyphdata->gdf.pgb->sizlBitmap.cx + 7) >> 3; ! 2681: vHexOut(pdev, pjBits, cjWidth); ! 2682: pjBits += cjWidth; ! 2683: } ! 2684: ! 2685: PrintString(pdev, ">]def\n"); ! 2686: ! 2687: // point to the next glyph handle. ! 2688: ! 2689: phg++; ! 2690: } ! 2691: ! 2692: // don't forget the .notdef character. ! 2693: ! 2694: PrintString(pdev, "/.notdef [.24 0 0 0 1 1 0 0 <>]def end\n"); ! 2695: ! 2696: // create a unique ID for the font, then name it. ! 2697: ! 2698: pwstr = (PWSTR)((BYTE *)pifi + pifi->dpwszFaceName); ! 2699: cTmp = wcslen(pwstr); ! 2700: ! 2701: // get the font name from the UNICODE font name. ! 2702: ! 2703: memset(szFaceName, 0, sizeof(szFaceName)); ! 2704: pszFaceName = szFaceName; ! 2705: ! 2706: while (cTmp--) ! 2707: { ! 2708: *pszFaceName = (CHAR)*pwstr++; ! 2709: ! 2710: // replace any spaces in the font name with underscores. ! 2711: ! 2712: if (*pszFaceName == ' ') ! 2713: *pszFaceName = '_'; ! 2714: ! 2715: // replace any parens in the font name with asterisks. ! 2716: ! 2717: if ((*pszFaceName == '(') || (*pszFaceName == ')')) ! 2718: *pszFaceName = '*'; ! 2719: ! 2720: // point to the next character. ! 2721: ! 2722: *pszFaceName++; ! 2723: } ! 2724: ! 2725: // add the point size to the font name, so we can distinguish ! 2726: // different point sizes of the same font. ! 2727: ! 2728: // NOTE Grab a new point size here, rather than reading if from ! 2729: // the CGS. This is necessary to support DrvDownloadFace. ! 2730: ! 2731: psfxPointSize = GetPointSize(pdev, pfo, &fontxform); ! 2732: ! 2733: cTmp = PSFIXToBuffer(pszFaceName, psfxPointSize); ! 2734: ! 2735: // update the buffer pointer. ! 2736: ! 2737: pszFaceName += cTmp; ! 2738: ! 2739: // output the NULL terminator. ! 2740: ! 2741: *pszFaceName = '\0'; ! 2742: ! 2743: // output the unique id, which, in a postscript printer, can ! 2744: // be in the range from 0 to 16777215. ! 2745: ! 2746: PrintString(pdev, "/UniqueID "); ! 2747: PrintDecimal(pdev, 1, (pfo->iUniq & 0xFFFFF)); ! 2748: ! 2749: PrintString(pdev, " def end pop /"); ! 2750: PrintString(pdev, szFaceName); ! 2751: PrintString(pdev, " exch definefont pop\n"); ! 2752: ! 2753: // update the fontname in our current graphics state. ! 2754: ! 2755: strcpy(pdev->cgs.szFont, szFaceName); ! 2756: ! 2757: // update information for this downloaded font. ! 2758: ! 2759: strcpy(pDLFont->strFont, szFaceName); ! 2760: pDLFont->psfxScaleFactor = psfxPointSize; ! 2761: ! 2762: // update the downloaded font counter. ! 2763: ! 2764: pdev->cgs.cDownloadedFonts++; ! 2765: ! 2766: // free up some memory. ! 2767: ! 2768: if (phgSave) ! 2769: HeapFree(pdev->hheap, 0, (PVOID)phgSave); ! 2770: } ! 2771: ! 2772: ! 2773: //-------------------------------------------------------------------- ! 2774: // BOOL DownloadOutlineFont(pdev, pfo) ! 2775: // PDEVDATA pdev; ! 2776: // FONTOBJ *pfo; ! 2777: // ! 2778: // This routine downloads the font definition for the given bitmap font, ! 2779: // if it has not already been done. The font is downloaded as an ! 2780: // Adobe Type 3 font. ! 2781: // ! 2782: // This routine return TRUE if the font is successfully, or has already ! 2783: // been, downloaded to the printer. It returns FALSE if it fails. ! 2784: // ! 2785: // History: ! 2786: // 27-Feb-1992 -by- Kent Settle (kentse) ! 2787: // Wrote it. ! 2788: //-------------------------------------------------------------------- ! 2789: ! 2790: BOOL DownloadOutlineFont(pdev, pfo) ! 2791: PDEVDATA pdev; ! 2792: FONTOBJ *pfo; ! 2793: { ! 2794: DLFONT *pDLFont; ! 2795: DWORD i; ! 2796: DWORD cDownloadedFonts; ! 2797: DWORD cGlyphs, cTmp; ! 2798: HGLYPH *phg; ! 2799: HGLYPH *phgSave; ! 2800: GLYPHDATA *pglyphdata; ! 2801: POINTL ptlTL, ptlBR; ! 2802: PIFIMETRICS pifi; ! 2803: LONG iCharWidth; ! 2804: CHAR szFaceName[MAX_STRING]; ! 2805: PSZ pszFaceName; ! 2806: PWSTR pwstr; ! 2807: ! 2808: // search through our list of downloaded GDI fonts to see if the ! 2809: // current font has already been downloaded to the printer. ! 2810: ! 2811: pDLFont = pdev->cgs.pDLFonts; ! 2812: ! 2813: cDownloadedFonts = min(pdev->cgs.cDownloadedFonts, pdev->iDLFonts); ! 2814: ! 2815: for (i = 0; i < pdev->iDLFonts; i++) ! 2816: { ! 2817: // is this entry the one we are looking for? simply return if so. ! 2818: ! 2819: if (pDLFont->iUniq == pfo->iUniq) ! 2820: { ! 2821: // update the fontname and size in our current graphics state. ! 2822: ! 2823: strcpy(pdev->cgs.szFont, pDLFont->strFont); ! 2824: pdev->cgs.psfxScaleFactor = pDLFont->psfxScaleFactor; ! 2825: pdev->cgs.lidFont = pDLFont->iUniq; ! 2826: ! 2827: return(TRUE); ! 2828: } ! 2829: ! 2830: pDLFont++; ! 2831: } ! 2832: ! 2833: // we did not find that this font has been downloaded yet, so we must ! 2834: // do it now. ! 2835: ! 2836: // if we have reached our downloaded font threshold, then ! 2837: // we will surround ever textout call with a save/restore. ! 2838: ! 2839: if (cDownloadedFonts == pdev->iDLFonts) ! 2840: { ! 2841: ps_save(pdev, FALSE); ! 2842: pdev->cgs.dwFlags |= CGS_DLFONTTHRESHOLD; ! 2843: cDownloadedFonts--; ! 2844: } ! 2845: ! 2846: pDLFont = pdev->cgs.pDLFonts; ! 2847: pDLFont += cDownloadedFonts; ! 2848: ! 2849: // free up the memory for the hglyph array for the old font. ! 2850: ! 2851: if (pDLFont->phgVector) ! 2852: { ! 2853: HeapFree(pdev->hheap, 0, (PVOID)pDLFont->phgVector); ! 2854: pDLFont->phgVector = (HGLYPH *)NULL; ! 2855: } ! 2856: ! 2857: memset(pDLFont, 0, sizeof(DLFONT)); ! 2858: ! 2859: pDLFont->iFace = pfo->iFace; ! 2860: pDLFont->iUniq = pfo->iUniq; ! 2861: ! 2862: // if we have made it this far, we should simply be able to ! 2863: // download the font now. ! 2864: ! 2865: // we will be downloading an Adobe TYPE 3 font. ! 2866: ! 2867: // allocate a dictionary for the font. ! 2868: ! 2869: PrintString(pdev, "10 dict d begin\n"); ! 2870: ! 2871: // set FontType to 3 indicating user defined font. ! 2872: ! 2873: PrintString(pdev, "/FontType 3 def\n"); ! 2874: ! 2875: // all font coordinate systems will be defined in units of 1000. ! 2876: // specify a FontMatrix which transforms the 1000 unit font to a ! 2877: // 1 unit font. ! 2878: ! 2879: PrintString(pdev, "/FontMatrix [.001 0 0 .001 0 0] def\n"); ! 2880: ! 2881: // allocate memory for and get the handles for each glyph of the font. ! 2882: ! 2883: if (!(cGlyphs = FONTOBJ_cGetAllGlyphHandles(pfo, NULL))) ! 2884: { ! 2885: RIP("PSCRIPT!DownloadOutlineFont: cGetAllGlyphHandles failed.\n"); ! 2886: return(FALSE); ! 2887: } ! 2888: ! 2889: if (!(phg = (HGLYPH *)HeapAlloc(pdev->hheap, 0, sizeof(HGLYPH) * cGlyphs))) ! 2890: { ! 2891: RIP("PSCRIPT!DownloadOutlineFont: HeapAlloc failed.\n"); ! 2892: return(FALSE); ! 2893: } ! 2894: ! 2895: phgSave = phg; ! 2896: ! 2897: cTmp = FONTOBJ_cGetAllGlyphHandles(pfo, phg); ! 2898: ! 2899: ASSERTPS(cTmp == cGlyphs, "PSCRIPT!DownloadOutlineFont: inconsistent cGlyphs\n"); ! 2900: ! 2901: // how many characters will we define in this font? ! 2902: // keep in mind that we can only do 256 at a time. ! 2903: // remember to leave room for the .notdef character. ! 2904: ! 2905: cGlyphs = min(255, cGlyphs); ! 2906: ! 2907: // get the IFIMETRICS for the font, used in TTTOADOBE. ! 2908: ! 2909: if (!(pifi = FONTOBJ_pifi(pfo))) ! 2910: { ! 2911: RIP("PSCRIPT!DownloadOutlineFont: pifi failed.\n"); ! 2912: HeapFree(pdev->hheap, 0, (PVOID)phg); ! 2913: return(FALSE); ! 2914: } ! 2915: ! 2916: // run through the array, looking at the bounding box for each ! 2917: // glyph, in order to create the bounding box for the entire ! 2918: // font. ! 2919: ! 2920: ptlTL.x = ADOBE_FONT_UNITS; ! 2921: ptlTL.y = ADOBE_FONT_UNITS; ! 2922: ptlBR.x = 0; ! 2923: ptlBR.y = 0; ! 2924: ! 2925: for (i = 0; i < cGlyphs; i++) ! 2926: { ! 2927: // get the GLYPHDATA structure for each glyph. ! 2928: ! 2929: if (!(cTmp = FONTOBJ_cGetGlyphs(pfo, FO_PATHOBJ, 1, phg, (PVOID *)&pglyphdata))) ! 2930: { ! 2931: RIP("PSCRIPT!DownloadOutlineFont: cGetGlyphs failed.\n"); ! 2932: HeapFree(pdev->hheap, 0, (PVOID)phgSave); ! 2933: return(FALSE); ! 2934: } ! 2935: ! 2936: ptlTL.x = min(ptlTL.x, TTTOADOBE(pglyphdata->rclInk.left)); ! 2937: ptlTL.y = min(ptlTL.y, TTTOADOBE(pglyphdata->rclInk.top)); ! 2938: ptlBR.x = max(ptlBR.x, TTTOADOBE(pglyphdata->rclInk.right)); ! 2939: ptlBR.y = max(ptlBR.y, TTTOADOBE(pglyphdata->rclInk.bottom)); ! 2940: ! 2941: // point to the next glyph handle. ! 2942: ! 2943: phg++; ! 2944: } ! 2945: ! 2946: // we have filled in the GLYPHPOS for each glyph in the font. ! 2947: // reset the pointer to the first glyph. ! 2948: ! 2949: phg = phgSave; ! 2950: ! 2951: // define the bounding box for the font. ! 2952: ! 2953: PrintString(pdev, "/FontBBox ["); ! 2954: PrintDecimal(pdev, 4, ptlTL.x, ptlTL.y, ptlBR.x, ptlBR.y); ! 2955: PrintString(pdev, "] def\n"); ! 2956: ! 2957: // allocate array for encoding vector, then initialize ! 2958: // all characters in encoding vector with '.notdef'. ! 2959: ! 2960: PrintString(pdev, "/Encoding 256 array def\n"); ! 2961: PrintString(pdev, "0 1 255 {Encoding exch /.notdef p} for\n"); ! 2962: ! 2963: // allocate space to store the HGLYPH<==>character code mapping. ! 2964: ! 2965: if (!(pDLFont->phgVector = (HGLYPH *)HeapAlloc(pdev->hheap, 0, ! 2966: sizeof(HGLYPH) * cGlyphs))) ! 2967: { ! 2968: RIP("PSCRIPT!DownloadOutlineFont: HeapAlloc for phgVector failed.\n"); ! 2969: HeapFree(pdev->hheap, 0, (PVOID)phg); ! 2970: return(FALSE); ! 2971: } ! 2972: ! 2973: // initialize array. ! 2974: ! 2975: pDLFont->cGlyphs = cGlyphs; ! 2976: ! 2977: // fill in the HGLYPH encoding vector, and output ! 2978: // the encoding vector to the printer. ! 2979: ! 2980: memcpy(pDLFont->phgVector, phg, cGlyphs * sizeof(HGLYPH)); ! 2981: ! 2982: PrintString(pdev, "Encoding\n"); ! 2983: ! 2984: for (i = 0; i < cGlyphs; i++) ! 2985: { ! 2986: PrintString(pdev, "d "); ! 2987: PrintDecimal(pdev, 1, i); ! 2988: PrintString(pdev, " /c"); ! 2989: PrintDecimal(pdev, 1, i); ! 2990: PrintString(pdev, " p\n"); ! 2991: } ! 2992: ! 2993: // under level 1 of PostScript, the 'BuildChar' procedure is called ! 2994: // every time a character from the font is constructed. under ! 2995: // level 2, 'BuildGlyph' is called instead. therefore, we will ! 2996: // define a 'BuildChar' procedure, which basically calls ! 2997: // 'BuildGlyph'. this will provide us support for both level 1 ! 2998: // and level 2 of PostScript. ! 2999: ! 3000: // define the 'BuildGlyph' procedure. start by getting the ! 3001: // character name and the font dictionary from the stack. ! 3002: ! 3003: PrintString(pdev, "/BuildGlyph {0 begin /cn ed /fd ed\n"); ! 3004: ! 3005: // retrieve the character information from the CharData (CD) ! 3006: // dictionary. ! 3007: ! 3008: PrintString(pdev, "/CI fd /CD get cn get def\n"); ! 3009: ! 3010: // get the width and the bounding box from the CharData. ! 3011: ! 3012: PrintString(pdev, "/wx CI 0 get def /cbb CI 1 4 getinterval def\n"); ! 3013: ! 3014: // enable each character to be cached. ! 3015: ! 3016: PrintString(pdev, "wx 0 cbb aload pop setcachedevice\n"); ! 3017: ! 3018: // get the procedure for rendering the character and execute it. ! 3019: ! 3020: PrintString(pdev, "CI 5 get exec end } def\n"); ! 3021: ! 3022: // create local storage for 'BuildGlyph' procedure. ! 3023: ! 3024: PrintString(pdev, "/BuildGlyph load 0 5 dict p\n"); ! 3025: ! 3026: // the semantics of 'BuildChar' differ from 'BuildGlyph' in the ! 3027: // following way: 'BuildChar' is called with the font dictionary ! 3028: // and character code on the stack, 'BuildGlyph' is called with ! 3029: // the font dictionary and character name on the stack. the ! 3030: // following 'BuildChar' procedure calls 'BuildGlyph', and retains ! 3031: // compatiblity with level 1 PostScript. ! 3032: ! 3033: PrintString(pdev, "/BuildChar {1 index /Encoding get exch get\n"); ! 3034: PrintString(pdev, "1 index /BuildGlyph get exec} bd\n"); ! 3035: ! 3036: // now create a dictionary containing information on each character. ! 3037: ! 3038: PrintString(pdev, "/CD "); ! 3039: PrintDecimal(pdev, 1, cGlyphs + 1); ! 3040: PrintString(pdev, " dict def CD begin\n"); ! 3041: ! 3042: for (i = 0; i < cGlyphs; i++) ! 3043: { ! 3044: // get the GLYPHDATA structure for each glyph. ! 3045: ! 3046: DbgPrint("calling cGetGlyphs.\n"); ! 3047: DbgBreakPoint(); ! 3048: ! 3049: if (!(cTmp = FONTOBJ_cGetGlyphs(pfo, FO_PATHOBJ, 1, phg, (PVOID *)&pglyphdata))) ! 3050: { ! 3051: RIP("PSCRIPT!DownloadOutlineFont: cGetGlyphs failed.\n"); ! 3052: HeapFree(pdev->hheap, 0, (PVOID)phgSave); ! 3053: return(FALSE); ! 3054: } ! 3055: ! 3056: // the first number in the character description is the width ! 3057: // in 1000 unit font space. the next four numbers are the bounding ! 3058: // box in 1000 unit font space. these are followed by the ! 3059: // procedure used to draw the character itself. ! 3060: ! 3061: // first, output the character name. ! 3062: ! 3063: PrintString(pdev, "/c"); ! 3064: PrintDecimal(pdev, 1, i); ! 3065: ! 3066: // output the character description array. ! 3067: ! 3068: // the width will be sent to the printer as the actual width ! 3069: // multiplied by 16 so as not to lose any percision when ! 3070: // normalizing. ! 3071: ! 3072: iCharWidth = TTTOADOBE((LONG)pglyphdata->fxD); ! 3073: ! 3074: ptlTL.x = TTTOADOBE(pglyphdata->rclInk.left); ! 3075: ptlTL.y = TTTOADOBE(pglyphdata->rclInk.top); ! 3076: ptlBR.x = TTTOADOBE(pglyphdata->rclInk.right); ! 3077: ptlBR.y = TTTOADOBE(pglyphdata->rclInk.bottom); ! 3078: ! 3079: // remember to flip over the y coordinates. ! 3080: ! 3081: PrintString(pdev, " ["); ! 3082: PrintDecimal(pdev, 5, iCharWidth, ptlTL.x, -ptlTL.y, ptlBR.x, -ptlBR.y); ! 3083: ! 3084: // output the procedure to draw the character itself. ! 3085: ! 3086: PrintString (pdev, " {"); ! 3087: DrvCommonPath(pdev, pglyphdata->gdf.ppo); ! 3088: PrintString(pdev, "fill }]def\n"); ! 3089: ! 3090: // point to the next glyph handle. ! 3091: ! 3092: phg++; ! 3093: } ! 3094: ! 3095: // don't forget the .notdef character. ! 3096: ! 3097: PrintString(pdev, "/.notdef [0 0 0 0 0 {}]def end\n"); ! 3098: ! 3099: // create a unique ID for the font, then name it. ! 3100: ! 3101: pwstr = (PWSTR)((BYTE *)pifi + pifi->dpwszFaceName); ! 3102: cTmp = wcslen(pwstr); ! 3103: ! 3104: // get the font name from the UNICODE font name. ! 3105: ! 3106: pszFaceName = szFaceName; ! 3107: ! 3108: while (cTmp--) ! 3109: { ! 3110: *pszFaceName = (CHAR)*pwstr++; ! 3111: ! 3112: // replace any spaces in the font name with underscores. ! 3113: ! 3114: if (*pszFaceName == ' ') ! 3115: *pszFaceName = '_'; ! 3116: ! 3117: // replace any parens in the font name with asterisks. ! 3118: ! 3119: if ((*pszFaceName == '(') || (*pszFaceName == ')')) ! 3120: *pszFaceName = '*'; ! 3121: ! 3122: // point to the next character. ! 3123: ! 3124: *pszFaceName++; ! 3125: } ! 3126: ! 3127: // NULL terminate the font name. ! 3128: ! 3129: *pszFaceName = '\0'; ! 3130: ! 3131: // output the unique id, which, in a postscript printer, can ! 3132: // be in the range from 0 to 16777215. ! 3133: ! 3134: PrintString(pdev, "/UniqueID "); ! 3135: PrintDecimal(pdev, 1, (pfo->iUniq & 0xFFFFF)); ! 3136: ! 3137: PrintString(pdev, " def end pop /"); ! 3138: PrintString(pdev, szFaceName); ! 3139: PrintString(pdev, " exch definefont pop\n"); ! 3140: ! 3141: // update the fontname in our current graphics state. ! 3142: ! 3143: strcpy(pdev->cgs.szFont, szFaceName); ! 3144: ! 3145: // update the downloaded font counter. ! 3146: ! 3147: pdev->cgs.cDownloadedFonts++; ! 3148: ! 3149: // free up some memory. ! 3150: ! 3151: if (phgSave) ! 3152: HeapFree(pdev->hheap, 0, (PVOID)phgSave); ! 3153: } ! 3154: ! 3155: ! 3156: //-------------------------------------------------------------------- ! 3157: // BOOL SetFontRemap(pdev, iFontID) ! 3158: // PDEVDATA pdev; ! 3159: // DWORD iFontID; ! 3160: // ! 3161: // This routine adds the specified font to the list of remapped fonts. ! 3162: // ! 3163: // This routine return TRUE for success, FALSE otherwise. ! 3164: // ! 3165: // History: ! 3166: // 11-Jun-1992 -by- Kent Settle (kentse) ! 3167: // Wrote it. ! 3168: //-------------------------------------------------------------------- ! 3169: ! 3170: BOOL SetFontRemap(pdev, iFontID) ! 3171: PDEVDATA pdev; ! 3172: DWORD iFontID; ! 3173: { ! 3174: FREMAP *pfremap; ! 3175: ! 3176: // add the specified font id to the list of remapped fonts. ! 3177: ! 3178: pfremap = &pdev->cgs.FontRemap; ! 3179: ! 3180: // find the end of the list. ! 3181: ! 3182: if (pfremap->pNext) ! 3183: { ! 3184: while (pfremap->pNext) ! 3185: pfremap = (PFREMAP)pfremap->pNext; ! 3186: ! 3187: // allocate the next entry in the list. ! 3188: ! 3189: if (!(pfremap->pNext = (struct _FREMAP *)HeapAlloc(pdev->hheap, 0, sizeof(FREMAP)))) ! 3190: { ! 3191: RIP("PSCRIPT!SetFontRemap: HeapAlloc failed.\n"); ! 3192: return(FALSE); ! 3193: } ! 3194: ! 3195: pfremap = (PFREMAP)pfremap->pNext; ! 3196: } ! 3197: ! 3198: // now that we have found the last entry in the list, fill it in. ! 3199: ! 3200: pfremap->iFontID = iFontID; ! 3201: pfremap->pNext = NULL; ! 3202: ! 3203: return(TRUE); ! 3204: } ! 3205: ! 3206: ! 3207: //-------------------------------------------------------------------- ! 3208: // BOOL QueryFontRemap(pdev, iFontID) ! 3209: // PDEVDATA pdev; ! 3210: // DWORD iFontID; ! 3211: // ! 3212: // This routine scans the list of remapped fonts. ! 3213: // ! 3214: // This routine return TRUE if iFontID is found, FALSE otherwise. ! 3215: // ! 3216: // History: ! 3217: // 11-Jun-1992 -by- Kent Settle (kentse) ! 3218: // Wrote it. ! 3219: //-------------------------------------------------------------------- ! 3220: ! 3221: BOOL QueryFontRemap(pdev, iFontID) ! 3222: PDEVDATA pdev; ! 3223: DWORD iFontID; ! 3224: { ! 3225: FREMAP *pfremap; ! 3226: ! 3227: // add the specified font id to the list of remapped fonts. ! 3228: ! 3229: pfremap = &pdev->cgs.FontRemap; ! 3230: ! 3231: // search the list for iFontID. ! 3232: ! 3233: do ! 3234: { ! 3235: // return TRUE if we have found the font. ! 3236: ! 3237: if (pfremap->iFontID == iFontID) ! 3238: return(TRUE); ! 3239: ! 3240: // we have not found the font, point to the next entry. ! 3241: ! 3242: pfremap = (PFREMAP)pfremap->pNext; ! 3243: ! 3244: } while (pfremap); ! 3245: ! 3246: // we did not find the font. ! 3247: ! 3248: return(FALSE); ! 3249: } ! 3250: ! 3251: ! 3252: //-------------------------------------------------------------------- ! 3253: // DWORD SubstituteIFace(pdev, pfo) ! 3254: // PDEVDATA pdev; ! 3255: // FONTOBJ *pfo; ! 3256: // ! 3257: // This routine takes the TrueType font specified by pfo, and returns ! 3258: // the iFace of the device font to substitute. This routine returns ! 3259: // zero if no font is found for substitution. ! 3260: // ! 3261: // History: ! 3262: // 14-Jul-1992 -by- Kent Settle (kentse) ! 3263: // Wrote it. ! 3264: //-------------------------------------------------------------------- ! 3265: ! 3266: DWORD SubstituteIFace(pdev, pfo) ! 3267: PDEVDATA pdev; ! 3268: FONTOBJ *pfo; ! 3269: { ! 3270: DWORD iFace = 0; ! 3271: DWORD iTmp; ! 3272: CHAR strDevFont[MAX_FONT_NAME]; ! 3273: WCHAR wstrDevFont[MAX_FONT_NAME]; ! 3274: PSTR pstrDevFont; ! 3275: PWSTR pwstrDevFont; ! 3276: IFIMETRICS *pifiTT; ! 3277: DWORD cTmp; ! 3278: PWSTR pwstr, pwstrTT; ! 3279: PNTFM pntfm; ! 3280: BOOL bFound; ! 3281: ! 3282: #if DBG ! 3283: // make sure we have a TrueType font. ! 3284: ! 3285: if (!(pfo->flFontType & TRUETYPE_FONTTYPE)) ! 3286: { ! 3287: DbgPrint("PSCRIPT!SubstituteIFace: Trying to substitute for non-TT font.\n"); ! 3288: return(0); ! 3289: } ! 3290: ! 3291: // make sure we are supposed to be doing font substitution. ! 3292: ! 3293: if (!(pdev->psdm.dwFlags & PSDEVMODE_FONTSUBST)) ! 3294: { ! 3295: DbgPrint("PSCRIPT!SubstituteIFace: not supposed to font substitute.\n"); ! 3296: return(0); ! 3297: } ! 3298: #endif ! 3299: ! 3300: // get the TrueType font name from the IFIMETRICS structure. ! 3301: ! 3302: if (!(pifiTT = FONTOBJ_pifi(pfo))) ! 3303: { ! 3304: RIP("PSCRIPT!SubstituteIFace: FONTOBJ_pifiTT failed.\n"); ! 3305: return(0); ! 3306: } ! 3307: ! 3308: pwstrTT = (PWSTR)((BYTE *)pifiTT + pifiTT->dpwszFaceName); ! 3309: ! 3310: // now search the font substitution table for a matching TrueType font. ! 3311: // the substitution table is in the following format: a NULL terminated ! 3312: // UNICODE TrueType font name followed by the matching NULL terminated ! 3313: // device font name. this sequence is repeated until a double NULL ! 3314: // terminator ends the table. ! 3315: ! 3316: pwstr = pdev->pTTSubstTable; ! 3317: bFound = FALSE; ! 3318: ! 3319: while (*pwstr) ! 3320: { ! 3321: if (!(wcscmp(pwstr, pwstrTT))) ! 3322: { ! 3323: // we found the TrueType font, now get the matching device font. ! 3324: ! 3325: pwstr += (wcslen(pwstr) + 1); ! 3326: wcsncpy(wstrDevFont, pwstr, ! 3327: (sizeof(wstrDevFont) / sizeof(wstrDevFont[0]))); ! 3328: bFound = TRUE; ! 3329: break; ! 3330: } ! 3331: else ! 3332: { ! 3333: // this was not the font in question. skip over both font names. ! 3334: ! 3335: pwstr += (wcslen(pwstr) + 1); ! 3336: pwstr += (wcslen(pwstr) + 1); ! 3337: } ! 3338: } ! 3339: ! 3340: // if we could not get a corresponding device font for any reason, ! 3341: // simply return zero for the iFace. ! 3342: ! 3343: if (!bFound) ! 3344: return(0); ! 3345: ! 3346: // get an ANSI version of the font name. ! 3347: ! 3348: cTmp = wcslen(wstrDevFont); ! 3349: cTmp++; ! 3350: ! 3351: pwstrDevFont = wstrDevFont; ! 3352: pstrDevFont = strDevFont; ! 3353: ! 3354: while (cTmp--) ! 3355: *pstrDevFont++ = (CHAR)*pwstrDevFont++; ! 3356: ! 3357: *pstrDevFont = '\0'; ! 3358: ! 3359: // at this point we have a mapping between a TrueType font name, ! 3360: // and a device font name. we need to determine the iFace of ! 3361: // the font name. ! 3362: ! 3363: for (iTmp = 1; iTmp <= (pdev->cDeviceFonts + pdev->cSoftFonts); iTmp++) ! 3364: { ! 3365: // get the font metrics for the specified font. ! 3366: ! 3367: pntfm = pdev->pfmtable[iTmp - 1].pntfm; ! 3368: ! 3369: // see if it is the font family we are looking for. if it is, ! 3370: // select it into the current graphics state, and return its iFace. ! 3371: ! 3372: if (!strcmp(strDevFont, ((char *)pntfm + pntfm->loszFontName))) ! 3373: { ! 3374: // select the device font in the current graphics state. ! 3375: ! 3376: strcpy(pdev->cgs.szFont, strDevFont); ! 3377: iFace = iTmp; ! 3378: break; ! 3379: } ! 3380: } ! 3381: ! 3382: // return the iFace of the device font to the caller. ! 3383: ! 3384: return(iFace); ! 3385: } ! 3386: ! 3387: ! 3388: ! 3389: //-------------------------------------------------------------------- ! 3390: // ULONG DrvGetGlyphMode(dhpdev, pfo, iMode) ! 3391: // DHPDEV dhpdev; ! 3392: // FONTOBJ *pfo; ! 3393: // ULONG iMode; ! 3394: // ! 3395: // This routine returns to the engine, the type of font caching the ! 3396: // engine should do. ! 3397: // ! 3398: // History: ! 3399: // 22-Jul-1992 -by- Kent Settle (kentse) ! 3400: // Wrote it. ! 3401: //-------------------------------------------------------------------- ! 3402: ! 3403: ULONG DrvGetGlyphMode(dhpdev, pfo) ! 3404: DHPDEV dhpdev; ! 3405: FONTOBJ *pfo; ! 3406: { ! 3407: return(SO_MONOBITMAP); ! 3408: // return(SO_GLYPHHANDLES); ! 3409: } ! 3410: ! 3411: ! 3412: ! 3413: //-------------------------------------------------------------------- ! 3414: // LONG iHipot(x, y) ! 3415: // LONG x; ! 3416: // LONG y; ! 3417: // ! 3418: // This routine returns the hypoteneous of a right triangle. ! 3419: // ! 3420: // FORMULA: ! 3421: // use sq(x) + sq(y) = sq(hypo); ! 3422: // start with MAX(x, y), ! 3423: // use sq(x + 1) = sq(x) + 2x + 1 to incrementally get to the ! 3424: // target hypotenouse. ! 3425: // ! 3426: // History: ! 3427: // 10-Feb-1993 -by- Kent Settle (kentse) ! 3428: // Stole from RASDD. ! 3429: // 21-Aug-1991 -by- Lindsay Harris (lindsayh) ! 3430: // Cleaned up UniDrive version, added comments etc. ! 3431: //-------------------------------------------------------------------- ! 3432: ! 3433: LONG iHipot(x, y) ! 3434: LONG x; ! 3435: LONG y; ! 3436: { ! 3437: register int hypo; /* Value to calculate */ ! 3438: register int delta; /* Used in the calculation loop */ ! 3439: ! 3440: int target; /* Loop limit factor */ ! 3441: ! 3442: // quick exit for frequent trivial cases [bodind] ! 3443: ! 3444: if (x == 0) ! 3445: { ! 3446: return ((y > 0) ? y : -y); ! 3447: } ! 3448: ! 3449: if (y == 0) ! 3450: { ! 3451: return ((x > 0) ? x : -x); ! 3452: } ! 3453: ! 3454: if (x < 0) ! 3455: x = -x; ! 3456: ! 3457: if (y < 0) ! 3458: y = -y; ! 3459: ! 3460: if(x > y) ! 3461: { ! 3462: hypo = x; ! 3463: target = y * y; ! 3464: } ! 3465: else ! 3466: { ! 3467: hypo = y; ! 3468: target = x * x; ! 3469: } ! 3470: ! 3471: for (delta = 0; delta < target; hypo++) ! 3472: delta += hypo << 1 + 1; ! 3473: ! 3474: return hypo; ! 3475: } ! 3476: ! 3477: ! 3478: //-------------------------------------------------------------------------- ! 3479: // BOOL IsJustifiedText(pdev, pfo, pstro, pptSpace, pptNonSpace, pdata) ! 3480: // PDEVDATA pdev; ! 3481: // FONTOBJ *pfo; ! 3482: // STROBJ *pstro; ! 3483: // POINTPSFX *pptSpace; ! 3484: // POINTPSFX *pptNonSpace; ! 3485: // TEXTDATA *pdata; ! 3486: // ! 3487: // This routine analyzes the string defined in pstro. If the spacing after ! 3488: // each non-space character is the same (with in 1), and the spacing after ! 3489: // each space character is the same, this routine will fill in the ! 3490: // POINTPSFX for each value, and return TRUE, otherwise it returns FALSE. ! 3491: // ! 3492: // History: ! 3493: // 31-Mar-1993 -by- Kent Settle (kentse) ! 3494: // Wrote it. ! 3495: //-------------------------------------------------------------------------- ! 3496: ! 3497: ! 3498: BOOL IsJustifiedText(pdev, pfo, pstro, pptSpace, pptNonSpace, pdata) ! 3499: PDEVDATA pdev; ! 3500: FONTOBJ *pfo; ! 3501: STROBJ *pstro; ! 3502: POINTPSFX *pptSpace; ! 3503: POINTPSFX *pptNonSpace; ! 3504: TEXTDATA *pdata; ! 3505: { ! 3506: DWORD i; ! 3507: TEXTDELTA *pdelta; ! 3508: TEXTDELTA *pdeltaSave; ! 3509: POINTFIX ptfxSpace, ptfxNonSpace, ptfxTmp; ! 3510: POINTFIX ptfxSExtra, ptfxNSExtra; ! 3511: GLYPHPOS *pgp; ! 3512: WCHAR wcSpace; ! 3513: FLONG flAccel; ! 3514: LONG cSpace, cNonSpace, denom; ! 3515: DWORD cGlyphs; ! 3516: BOOL bMore; ! 3517: PWSZ pwszOrg; ! 3518: ! 3519: flAccel = pstro->flAccel; ! 3520: ! 3521: // currently, just handle horizontal text. justification for a string ! 3522: // with one character makes no sense. and, justification is ! 3523: // obviously not happening, if we are using default placement. ! 3524: // finally, we must individually place the characters if substitution ! 3525: // is in effect, because it is the only way we have of getting the ! 3526: // true character widths. ! 3527: ! 3528: if ((!(flAccel & SO_HORIZONTAL)) || (pstro->cGlyphs <= 1) || ! 3529: (flAccel & SO_FLAG_DEFAULT_PLACEMENT) || pdata->bFontSubstitution) ! 3530: return(FALSE); ! 3531: ! 3532: // now the ugly part. we must go through the string a character at a ! 3533: // time, comparing the widths given in the pstro with the actual font ! 3534: // character widths. if the difference is the same for each space ! 3535: // character, and the same for each non-space character, then ! 3536: // justification, as we know it, is in effect. ! 3537: ! 3538: // first start off by allocating an array of TEXTDELTAs, so we can fill ! 3539: // them in with the deltas between each character. ! 3540: ! 3541: if (!(pdelta = (TEXTDELTA *)HeapAlloc(pdev->hheap, 0, ! 3542: (sizeof(TEXTDELTA) * (pstro->cGlyphs - 1))))) ! 3543: { ! 3544: #if DBG ! 3545: DbgPrint("PSCRIPT!IsJustifiedText: HeapAlloc for pdelta failed.\n"); ! 3546: #endif ! 3547: return(FALSE); ! 3548: } ! 3549: ! 3550: pdeltaSave = pdelta; ! 3551: ! 3552: // get the original UNICODE string. ! 3553: ! 3554: if (pfo->flFontType & DEVICE_FONTTYPE) ! 3555: pwszOrg = GetUnicodeString(pdev, pfo, pstro); ! 3556: else ! 3557: pwszOrg = pstro->pwszOrg; ! 3558: ! 3559: // fill in the TEXTDELTA structures. ! 3560: ! 3561: if (pstro->pgp) ! 3562: { ! 3563: if (!FillDeltaArray(pdev, pfo, pstro->pgp, pstro, pdelta, pstro->cGlyphs, pwszOrg)) ! 3564: { ! 3565: RIP("PSCRIPT!IsJustifiedText: FillDeltaArray failed.\n"); ! 3566: HeapFree(pdev->hheap, 0, (PVOID)pdeltaSave); ! 3567: return(FALSE); ! 3568: } ! 3569: } ! 3570: else ! 3571: { ! 3572: // prepare to enumerate the string properly. ! 3573: ! 3574: STROBJ_vEnumStart(pstro); ! 3575: ! 3576: // now draw the text. ! 3577: ! 3578: do ! 3579: { ! 3580: bMore = STROBJ_bEnum(pstro, &cGlyphs, &pgp); ! 3581: ! 3582: if (!FillDeltaArray(pdev, pfo, pgp, pstro, pdelta, cGlyphs, pwszOrg)) ! 3583: { ! 3584: RIP("PSCRIPT!IsJustifiedText: FillDeltaArray failed.\n"); ! 3585: HeapFree(pdev->hheap, 0, (PVOID)pdeltaSave); ! 3586: return(FALSE); ! 3587: } ! 3588: ! 3589: pdelta += cGlyphs; ! 3590: pwszOrg += cGlyphs; ! 3591: ! 3592: } while (bMore); ! 3593: } ! 3594: ! 3595: // reset pointer to first structure. ! 3596: ! 3597: pdelta = pdeltaSave; ! 3598: ! 3599: // get the unicode value for the space character. ! 3600: ! 3601: MultiByteToWideChar(CP_ACP, 0, (LPCSTR)" ", 1, (LPWSTR)&wcSpace, 1); ! 3602: ! 3603: // now get the widths of the characters themselves. ! 3604: ! 3605: ptfxSpace.x = -1; ! 3606: ptfxNonSpace.x = -1; ! 3607: ptfxSExtra.x = 0; ! 3608: ptfxSExtra.y = 0; ! 3609: ptfxNSExtra.x = 0; ! 3610: ptfxNSExtra.y = 0; ! 3611: cSpace = 0; ! 3612: cNonSpace = 0; ! 3613: ! 3614: for (i = 0; i < (pstro->cGlyphs - 1); i++) ! 3615: { ! 3616: ptfxTmp.x = abs(pdelta->ptfxorg.x - LTOFX(pdelta->ptlpgp.x)); ! 3617: ptfxTmp.y = abs(pdelta->ptfxorg.y - LTOFX(pdelta->ptlpgp.y)); ! 3618: ! 3619: if (pdelta->wc == wcSpace) ! 3620: { ! 3621: if (ptfxSpace.x == -1) ! 3622: { ! 3623: ptfxSpace = ptfxTmp; ! 3624: ptfxSExtra.x = LTOFX(pdelta->ptlpgp.x) - pdelta->ptfxorg.x; ! 3625: ptfxSExtra.y = LTOFX(pdelta->ptlpgp.y) - pdelta->ptfxorg.y; ! 3626: } ! 3627: else ! 3628: { ! 3629: if ((abs(ptfxSpace.x - ptfxTmp.x) > LTOFX(1)) || ! 3630: (abs(ptfxSpace.y - ptfxTmp.y) > LTOFX(1))) ! 3631: { ! 3632: HeapFree(pdev->hheap, 0, (PVOID)pdeltaSave); ! 3633: return(FALSE); ! 3634: } ! 3635: ! 3636: ptfxSExtra.x += (LTOFX(pdelta->ptlpgp.x) - pdelta->ptfxorg.x); ! 3637: ptfxSExtra.y += (LTOFX(pdelta->ptlpgp.y) - pdelta->ptfxorg.y); ! 3638: } ! 3639: ! 3640: cSpace++; ! 3641: } ! 3642: else // non spacing character. ! 3643: { ! 3644: if (ptfxNonSpace.x == -1) ! 3645: { ! 3646: ptfxNonSpace = ptfxTmp; ! 3647: ptfxNSExtra.x = LTOFX(pdelta->ptlpgp.x) - pdelta->ptfxorg.x; ! 3648: ptfxNSExtra.y = LTOFX(pdelta->ptlpgp.y) - pdelta->ptfxorg.y; ! 3649: } ! 3650: else ! 3651: { ! 3652: if ((abs(ptfxNonSpace.x - ptfxTmp.x) > LTOFX(1)) || ! 3653: (abs(ptfxNonSpace.y - ptfxTmp.y) > LTOFX(1))) ! 3654: { ! 3655: HeapFree(pdev->hheap, 0, (PVOID)pdeltaSave); ! 3656: return(FALSE); ! 3657: } ! 3658: ! 3659: ptfxNSExtra.x += (LTOFX(pdelta->ptlpgp.x) - pdelta->ptfxorg.x); ! 3660: ptfxNSExtra.y += (LTOFX(pdelta->ptlpgp.y) - pdelta->ptfxorg.y); ! 3661: } ! 3662: ! 3663: cNonSpace++; ! 3664: } ! 3665: ! 3666: pdelta++; ! 3667: } ! 3668: ! 3669: // fill in the justification amounts. ! 3670: ! 3671: if (cSpace == 0) ! 3672: { ! 3673: pptSpace->x = 0; ! 3674: pptSpace->y = 0; ! 3675: } ! 3676: else ! 3677: { ! 3678: denom = pdev->psdm.dm.dmPrintQuality * cSpace; ! 3679: ! 3680: pptSpace->x = ((ptfxSExtra.x << 4) * PS_RESOLUTION) / denom; ! 3681: pptSpace->y = ((ptfxSExtra.y << 4) * PS_RESOLUTION) / denom; ! 3682: } ! 3683: ! 3684: if (cNonSpace == 0) ! 3685: { ! 3686: pptNonSpace->x = 0; ! 3687: pptNonSpace->y = 0; ! 3688: } ! 3689: else ! 3690: { ! 3691: denom = pdev->psdm.dm.dmPrintQuality * cNonSpace; ! 3692: ! 3693: pptNonSpace->x = ((ptfxNSExtra.x << 4) * PS_RESOLUTION) / denom; ! 3694: pptNonSpace->y = ((ptfxNSExtra.y << 4) * PS_RESOLUTION) / denom; ! 3695: } ! 3696: ! 3697: // free some memory. ! 3698: ! 3699: HeapFree(pdev->hheap, 0, (PVOID)pdeltaSave); ! 3700: ! 3701: return(TRUE); ! 3702: } ! 3703: ! 3704: ! 3705: //-------------------------------------------------------------------------- ! 3706: // BOOL FillDeltaArray(pdev, pfo, pgp, pstro, pdelta, cGlyphs, pwsz) ! 3707: // PDEVDATA pdev; ! 3708: // FONTOBJ *pfo; ! 3709: // GLYPHPOS *pgp; ! 3710: // STROBJ *pstro; ! 3711: // TEXTDELTA *pdelta; ! 3712: // DWORD cGlyphs; ! 3713: // PWSZ pwsz; ! 3714: // ! 3715: // This routine fills in the given TEXTDELTA array from the given STROBJ. ! 3716: // ! 3717: // History: ! 3718: // 31-Mar-1993 -by- Kent Settle (kentse) ! 3719: // Wrote it. ! 3720: //-------------------------------------------------------------------------- ! 3721: ! 3722: BOOL FillDeltaArray(pdev, pfo, pgp, pstro, pdelta, cGlyphs, pwsz) ! 3723: PDEVDATA pdev; ! 3724: FONTOBJ *pfo; ! 3725: GLYPHPOS *pgp; ! 3726: STROBJ *pstro; ! 3727: TEXTDELTA *pdelta; ! 3728: DWORD cGlyphs; ! 3729: PWSZ pwsz; ! 3730: { ! 3731: DWORD i; ! 3732: GLYPHDATA *pglyphdata; ! 3733: DWORD cReturned; ! 3734: GLYPHDATA glyphdata; ! 3735: ! 3736: if (!pwsz) ! 3737: { ! 3738: #if DBG ! 3739: DbgPrint("PSCRIPT!FillDeltaArray: NULL pwsz.\n"); ! 3740: #endif ! 3741: return(FALSE); ! 3742: } ! 3743: ! 3744: // initialize pglyphdata for device font case. ! 3745: ! 3746: pglyphdata = &glyphdata; ! 3747: ! 3748: // fill in the TEXTDELTA structures. ! 3749: ! 3750: for (i = 0; i < (cGlyphs - 1); i++) ! 3751: { ! 3752: // get the UNICODE code point. ! 3753: ! 3754: pdelta->wc = *pwsz++; ! 3755: ! 3756: // get the delta vector as defined by the GLYPHPOS. ! 3757: ! 3758: pdelta->ptlpgp.x = (pgp + 1)->ptl.x - pgp->ptl.x; ! 3759: pdelta->ptlpgp.y = (pgp + 1)->ptl.y - pgp->ptl.y; ! 3760: ! 3761: if (pfo->flFontType & DEVICE_FONTTYPE) ! 3762: { ! 3763: if (!GetDeviceWidths(pdev, pfo, &glyphdata, pgp->hg)) ! 3764: { ! 3765: RIP("PSCRIPT!FillDeltaArray: GetDeviceWidth failed.\n"); ! 3766: return(FALSE); ! 3767: } ! 3768: } ! 3769: else ! 3770: { ! 3771: // now get the delta vector for the glyph itself. ! 3772: ! 3773: if (!(cReturned = FONTOBJ_cGetGlyphs(pfo, FO_GLYPHBITS, 1, ! 3774: &pgp->hg, ! 3775: (PVOID *)&pglyphdata))) ! 3776: { ! 3777: RIP("PSCRIPT!FillDeltaArray: cGetGlyphs failed.\n"); ! 3778: return(FALSE); ! 3779: } ! 3780: } ! 3781: ! 3782: pdelta->ptfxorg.x = pglyphdata->ptqD.x.HighPart; ! 3783: pdelta->ptfxorg.y = pglyphdata->ptqD.y.HighPart; ! 3784: ! 3785: pgp++; ! 3786: pdelta++; ! 3787: } ! 3788: ! 3789: return(TRUE); ! 3790: } ! 3791: ! 3792: ! 3793: //-------------------------------------------------------------------------- ! 3794: // PWSTR GetUnicodeString(pdev, pfo, pstro) ! 3795: // PDEVDATA pdev; ! 3796: // FONTOBJ *pfo; ! 3797: // STROBJ *pstro; ! 3798: // ! 3799: // This routine allocates a UNICODE string, and fills it is from the pstro. ! 3800: // This routine is ONLY called for device fonts. ! 3801: // ! 3802: // History: ! 3803: // 10-May-1993 -by- Kent Settle (kentse) ! 3804: // Wrote it. ! 3805: //-------------------------------------------------------------------------- ! 3806: ! 3807: PWSTR GetUnicodeString(pdev, pfo, pstro) ! 3808: PDEVDATA pdev; ! 3809: FONTOBJ *pfo; ! 3810: STROBJ *pstro; ! 3811: { ! 3812: PWSTR pwstr, pwstrSave; ! 3813: BOOL bMore; ! 3814: PUCMap pmap; ! 3815: PNTFM pntfm; ! 3816: DWORD cGlyphs; ! 3817: GLYPHPOS *pgp; ! 3818: ! 3819: // allocate the UNICODE string, leaving room for NULL terminator. ! 3820: ! 3821: if (!(pwstr = (PWSTR)HeapAlloc(pdev->hheap, 0, ! 3822: ((pstro->cGlyphs + 1) * sizeof(WCHAR))))) ! 3823: { ! 3824: RIP("PSCRIPT!GetUnicodeString: HeapAlloc for pwstr failed.\n"); ! 3825: return((PWSTR)NULL); ! 3826: } ! 3827: ! 3828: pwstrSave = pwstr; ! 3829: ! 3830: // prepare to enumerate the string. ! 3831: ! 3832: STROBJ_vEnumStart(pstro); ! 3833: ! 3834: // get the GLYPHPOS structure for each glyph. from that, get the ! 3835: // HGLYPH. from that, get the UNICODE codepoint, and jam that into ! 3836: // our allocate UNICODE string. ! 3837: ! 3838: // get the font metrics for the specified font. ! 3839: ! 3840: pntfm = pdev->pfmtable[pfo->iFace - 1].pntfm; ! 3841: ! 3842: // get local pointer to mapping table for current font. ! 3843: ! 3844: if (!strcmp((char *)pntfm + pntfm->loszFontName, "Symbol")) ! 3845: pmap = SymbolMap; ! 3846: else if (!strcmp((char *)pntfm + pntfm->loszFontName, "ZapfDingbats")) ! 3847: pmap = DingbatsMap; ! 3848: else ! 3849: pmap = LatinMap; ! 3850: ! 3851: if (pstro->pgp) ! 3852: ConstructUCString(pstro->pgp, pmap, pstro->cGlyphs, pwstr); ! 3853: else ! 3854: { ! 3855: do ! 3856: { ! 3857: bMore = STROBJ_bEnum(pstro, &cGlyphs, &pgp); ! 3858: ! 3859: ConstructUCString(pgp, pmap, cGlyphs, pwstr); ! 3860: ! 3861: pwstr += cGlyphs; ! 3862: ! 3863: } while (bMore); ! 3864: } ! 3865: ! 3866: return(pwstrSave); ! 3867: } ! 3868: ! 3869: ! 3870: //-------------------------------------------------------------------------- ! 3871: // VOID ConstructUCString(pgp, pmap, cGlyphs, pwstr) ! 3872: // GLYPHPOS *pgp; ! 3873: // PUCMap pmap; ! 3874: // DWORD cGlyphs; ! 3875: // PWSTR pwstr; ! 3876: // ! 3877: // This routine constructs a UNICODE string from the pstro. ! 3878: // This routine is ONLY called for device fonts. ! 3879: // ! 3880: // History: ! 3881: // 10-May-1993 -by- Kent Settle (kentse) ! 3882: // Wrote it. ! 3883: //-------------------------------------------------------------------------- ! 3884: ! 3885: VOID ConstructUCString(pgp, pmap, cGlyphs, pwstr) ! 3886: GLYPHPOS *pgp; ! 3887: PUCMap pmap; ! 3888: DWORD cGlyphs; ! 3889: PWSTR pwstr; ! 3890: { ! 3891: BOOL bFound; ! 3892: DWORD i; ! 3893: PUCMap pmapReset; ! 3894: WCHAR *pwc; ! 3895: CHAR jChar; ! 3896: ! 3897: // assume character not found in font. ! 3898: ! 3899: bFound = FALSE; ! 3900: ! 3901: pwc = pwstr; ! 3902: pmapReset = pmap; ! 3903: ! 3904: for (i = 0; i < cGlyphs; i++) ! 3905: { ! 3906: pmap = pmapReset; ! 3907: ! 3908: jChar = (CHAR)pgp->hg; ! 3909: ! 3910: while (pmap->szChar) ! 3911: { ! 3912: // search for the matching code in mapping.h. remember ! 3913: // that the high bit is used to indicate the font needs ! 3914: // to be remapped. so ignore the high bit while checking ! 3915: // for a character match. ! 3916: ! 3917: if (jChar == (CHAR)pmap->usPSValue) ! 3918: { ! 3919: bFound = TRUE; ! 3920: ! 3921: *pwc = (WCHAR)pmap->usUCValue; ! 3922: break; ! 3923: } ! 3924: ! 3925: // point to the next character in mapping.h. ! 3926: ! 3927: pmap++; ! 3928: } // while. ! 3929: ! 3930: // if the character in question was not found, replace it with ! 3931: // our default character. ! 3932: ! 3933: if (!bFound) ! 3934: { ! 3935: // get the unicode value for the period character. ! 3936: ! 3937: MultiByteToWideChar(CP_ACP, 0, (LPCSTR)".", 1, (LPWSTR)pwc, 1); ! 3938: } ! 3939: ! 3940: // point to the next glyph to fill in. ! 3941: ! 3942: pwc++; ! 3943: ! 3944: // point to the next GLYPHPOS structure. ! 3945: ! 3946: pgp++; ! 3947: } ! 3948: ! 3949: // add the NULL terminator. ! 3950: ! 3951: *pwc = (WCHAR)'\0'; ! 3952: } ! 3953: ! 3954: ! 3955: //-------------------------------------------------------------------------- ! 3956: // BOOL GetDeviceWidths(pdev, pfo, pgd, hg) ! 3957: // PDEVDATA pdev; ! 3958: // FONTOBJ *pfo; ! 3959: // GLYPHDATA *pgd; ! 3960: // HGLYPH hg; ! 3961: // ! 3962: // This routine fills in the width parameters of a GLYPHDATA ! 3963: // structure for the given HGLYPH. This is currently needed since ! 3964: // the journaling code does not allow us to do engine callbacks ! 3965: // such as FONTOBJ_cGetGlyphs with a device font. ! 3966: // ! 3967: // History: ! 3968: // 24-May-1993 -by- Kent Settle (kentse) ! 3969: // Wrote it. ! 3970: //-------------------------------------------------------------------------- ! 3971: ! 3972: BOOL GetDeviceWidths(pdev, pfo, pgd, hg) ! 3973: PDEVDATA pdev; ! 3974: FONTOBJ *pfo; ! 3975: GLYPHDATA *pgd; ! 3976: HGLYPH hg; ! 3977: { ! 3978: PNTFM pntfm; ! 3979: XFORMOBJ *pxo; ! 3980: PBYTE pCharCode; ! 3981: PBYTE pCode; ! 3982: PUSHORT pCharWidth; ! 3983: int i; ! 3984: POINTL ptl; ! 3985: POINTFIX ptfx; ! 3986: LONG lWidth; ! 3987: ! 3988: // make sure we have been given a valid font. ! 3989: ! 3990: if ((pfo->iFace == 0) || (pfo->iFace > (pdev->cDeviceFonts + pdev->cSoftFonts))) ! 3991: { ! 3992: RIP("PSCRIPT!GetDeviceWidths: invalid iFace.\n"); ! 3993: SetLastError(ERROR_INVALID_PARAMETER); ! 3994: return(FALSE); ! 3995: } ! 3996: ! 3997: // get the metrics for the given font. ! 3998: ! 3999: pntfm = pdev->pfmtable[pfo->iFace - 1].pntfm; ! 4000: ! 4001: // get the Notional to Device transform. ! 4002: ! 4003: if(!(pxo = FONTOBJ_pxoGetXform(pfo))) ! 4004: { ! 4005: RIP("PSCRIPT!DrvQueryFontData: pxo == NULL.\n"); ! 4006: return(-1); ! 4007: } ! 4008: ! 4009: // get the font transform information. ! 4010: ! 4011: XFORMOBJ_iGetXform(pxo, &pdev->cgs.FontXform); ! 4012: ! 4013: // fill in the glyph widths portions of the GLYPHDATA structure. ! 4014: ! 4015: // We don't actually return bitmaps, but we give them ! 4016: // metrics via this call. ! 4017: ! 4018: // get a pointer to the character codes. ! 4019: ! 4020: pCharCode = ((PBYTE)pntfm + pntfm->loCharMetrics + ! 4021: DWORDALIGN(pntfm->cCharacters * sizeof(USHORT))); ! 4022: ! 4023: // get a pointer to the character widths. ! 4024: ! 4025: pCharWidth = (PUSHORT)((PBYTE)pntfm + pntfm->loCharMetrics); ! 4026: ! 4027: // now get the character width for the given GLYPH. ! 4028: // we set our HGLYPHs to be equal to the PostScript ! 4029: // character code for that given glyph. this allows ! 4030: // us to quickly search through our font metrics and ! 4031: // find the width for the given character. ! 4032: ! 4033: // first get a pointer to the character codes. once ! 4034: // the character has been found, we know how much to ! 4035: // index into the character widths and find the width ! 4036: // in question. ! 4037: ! 4038: pCode = pCharCode; ! 4039: ! 4040: for (i = 0; (USHORT)i < pntfm->cCharacters; i++) ! 4041: { ! 4042: if (*pCharCode++ == (BYTE)hg) ! 4043: break; ! 4044: } ! 4045: ! 4046: // now get the width in question. ! 4047: ! 4048: lWidth = (LONG)pCharWidth[i]; ! 4049: ! 4050: #if 0 ! 4051: // now fill in the GLYPHDATA structure. ! 4052: // remember under NT 0,0 is top left, while under ! 4053: // PostScript 0,0 is bottom left. return device coords. ! 4054: ! 4055: ptl.x = pntfm->rcBBox.left; ! 4056: ptl.y = 0; ! 4057: ! 4058: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx); ! 4059: ! 4060: pgd->rclInk.left = FXTOL(iHipot(ptfx.x, ptfx.y)); ! 4061: ! 4062: ptl.x = pntfm->rcBBox.bottom; ! 4063: ptl.y = 0; ! 4064: ! 4065: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx); ! 4066: ! 4067: pgd->rclInk.top = FXTOL(iHipot(ptfx.x, ptfx.y)); ! 4068: ! 4069: ptl.x = pntfm->rcBBox.right; ! 4070: ptl.y = 0; ! 4071: ! 4072: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx); ! 4073: ! 4074: pgd->rclInk.right = FXTOL(iHipot(ptfx.x, ptfx.y)); ! 4075: ! 4076: ptl.x = pntfm->rcBBox.top; ! 4077: ptl.y = 0; ! 4078: ! 4079: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx); ! 4080: ! 4081: pgd->rclInk.bottom = FXTOL(iHipot(ptfx.x, ptfx.y)); ! 4082: #endif ! 4083: ! 4084: ptl.x = lWidth; ! 4085: ptl.y = 0; ! 4086: ! 4087: XFORMOBJ_bApplyXform(pxo, XF_LTOFX, 1, &ptl, &ptfx); ! 4088: ! 4089: pgd->fxD = iHipot(ptfx.x, ptfx.y); ! 4090: ! 4091: pgd->ptqD.x.HighPart = ptfx.x; ! 4092: pgd->ptqD.x.LowPart = 0; ! 4093: pgd->ptqD.y.HighPart = ptfx.y; ! 4094: pgd->ptqD.y.LowPart = 0; ! 4095: ! 4096: #if 0 ! 4097: pgd->fxA = 0; ! 4098: pgd->fxAB = pgd->fxD; ! 4099: ! 4100: pgd->fxInkTop = - LTOFX(pgd->rclInk.top); ! 4101: pgd->fxInkBottom = - LTOFX(pgd->rclInk.bottom); ! 4102: #endif ! 4103: ! 4104: pgd->hg = hg; ! 4105: ! 4106: return(TRUE); ! 4107: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.