Annotation of ntddk/src/print/pscript/textout.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.