Annotation of ntddk/src/print/pscript/textout.c, revision 1.1.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.