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

1.1     ! root        1: //--------------------------------------------------------------------------
        !             2: //
        !             3: // Module Name:  PSLAYER.C
        !             4: //
        !             5: // Brief Description:  This module contains the PSCRIPT driver's layer
        !             6: // of PostScript translation routines.
        !             7: //
        !             8: // Author:  Kent Settle (kentse)
        !             9: // Created: 17-Dec-1990
        !            10: //
        !            11: // Copyright (c) 1990 - 1992 Microsoft Corporation
        !            12: //
        !            13: // This module contains routines to handle the outputting of the PostScript
        !            14: // language commands to the output channel.  One of the main functions of
        !            15: // this pslayer is to help provide device independence, by shielding the
        !            16: // output of the actual device resolution.  The NT PostScript driver will
        !            17: // output all PostScript commands in POINTS space; that is 72 dots per inch.
        !            18: // This is the default user coordinates for ALL PostScript printers, so we
        !            19: // will use it.  As far as the DDI is concerned, it only knows of the actual
        !            20: // device resolution.  This pslayer will convert between device coordinates
        !            21: // and the PostScript user coordinates.
        !            22: //
        !            23: // Coordinates will be output to the device using PS_FIX (24.8) numbers.
        !            24: // It may be useful, therefore to note the following relations using
        !            25: // PS_FIX numbers.  PS_FIX / LONG = PS_FIX.  LONG * PS_FIX = PS_FIX.
        !            26: // (PS_FIX * PS_FIX) >> 8 = PS_FIX.
        !            27: //--------------------------------------------------------------------------
        !            28: 
        !            29: #include "pscript.h"
        !            30: #include <memory.h>
        !            31: #include "enable.h"
        !            32: 
        !            33: extern LONG iHipot(LONG, LONG);
        !            34: 
        !            35: //--------------------------------------------------------------------------
        !            36: // VOID ps_setrgbcolor(pdev, pbgr)
        !            37: // PDEVDATA        pdev;
        !            38: // BGR_PAL_ENTRY  *pbgr;
        !            39: //
        !            40: // This routine is called by the driver to set the current color.  PostScript
        !            41: // printers only know about the current color.    For example, if you are
        !            42: // printing text in red and lines in blue, and you alternate printing text
        !            43: // and a line, you also have to set the current color each time.
        !            44: //
        !            45: // For black and white devices the RGB color is converted to a gray scale
        !            46: // between 0.0 (black) and 1.0 (white).
        !            47: //
        !            48: // Parameters:
        !            49: //   pdev:
        !            50: //     pointer to DEVDATA structure.
        !            51: //
        !            52: //   lColor:
        !            53: //     RGB value of new color.
        !            54: //
        !            55: // Returns:
        !            56: //   This function returns no value.
        !            57: //
        !            58: // History:
        !            59: //   17-Dec-1990     -by-     Kent Settle     (kentse)
        !            60: //  Wrote it.
        !            61: //--------------------------------------------------------------------------
        !            62: 
        !            63: 
        !            64: VOID ps_setrgbcolor(pdev, pbgr)
        !            65: PDEVDATA        pdev;
        !            66: BGR_PAL_ENTRY  *pbgr;
        !            67: {
        !            68:     PS_FIX psfxRed, psfxGreen, psfxBlue;
        !            69:     PS_FIX psfxGray;
        !            70: 
        !            71:     // if the all colors to black flag is set, set all colors, except
        !            72:     // white to black.
        !            73: 
        !            74:     if (pdev->psdm.dwFlags & PSDEVMODE_BLACK)
        !            75:     {
        !            76:         // if the last color was non-white and the new color is non-white,
        !            77:         // or the last color was white and the new color is white, then
        !            78:         // we want to leave the color alone.
        !            79: 
        !            80:         if (((pdev->cgs.ulColor != RGB_WHITE) && (*(ULONG *)pbgr != RGB_WHITE)) ||
        !            81:             ((pdev->cgs.ulColor == RGB_WHITE) && (*(ULONG *)pbgr == RGB_WHITE)))
        !            82:             return;
        !            83: 
        !            84:         // the color must be updated in the printer.
        !            85: 
        !            86:         if (*(ULONG *)pbgr == RGB_WHITE)
        !            87:             PrintString(pdev, "1 g\n");
        !            88:         else
        !            89:             PrintString(pdev, "0 g\n");
        !            90:     }
        !            91:     else if (pdev->cgs.ulColor != *(ULONG *)pbgr)
        !            92:     {
        !            93:         // save the new color in the current graphics state structure.
        !            94: 
        !            95:         pdev->cgs.ulColor = *(ULONG *)pbgr;
        !            96: 
        !            97:         if (pdev->psdm.dm.dmColor == DMCOLOR_COLOR)
        !            98:         {
        !            99:             // each color component must be output to the printer
        !           100:             // in the range from 0.0 to 1.0, so normalize to this
        !           101:             // range by dividing by 255.
        !           102: 
        !           103:             psfxRed = LTOPSFX((ULONG)pbgr->bgrRed) / 255;
        !           104:             psfxGreen = LTOPSFX((ULONG)pbgr->bgrGreen) / 255;
        !           105:             psfxBlue = LTOPSFX((ULONG)pbgr->bgrBlue) / 255;
        !           106: 
        !           107:             // if each of the color components is equal, just output a
        !           108:             // gray scale.  otherwise, output the RGB value.
        !           109: 
        !           110:            if ((psfxRed == psfxGreen) && (psfxRed == psfxBlue))
        !           111:            {
        !           112:                PrintPSFIX(pdev, 1, psfxRed);
        !           113:                 PrintString(pdev, " g\n");
        !           114:            }
        !           115:            else
        !           116:            {
        !           117:                PrintPSFIX(pdev, 3, psfxRed, psfxGreen, psfxBlue);;
        !           118:                 PrintString(pdev, " r\n");
        !           119:            }
        !           120:         }
        !           121:         else
        !           122:         {
        !           123:             // convert the RGB color to a gray scale and output to the
        !           124:             // printer.
        !           125: 
        !           126:             psfxGray = psfxRGBtoGray(pbgr);
        !           127:            PrintPSFIX(pdev, 1, psfxGray);
        !           128:             PrintString(pdev, " g\n");
        !           129:         }
        !           130:     }
        !           131: }
        !           132: 
        !           133: 
        !           134: //--------------------------------------------------------------------------
        !           135: // VOID ps_newpath(pdev)
        !           136: // PDEVDATA    pdev;
        !           137: //
        !           138: // This routine is called by the driver to issue a newpath command to
        !           139: // the printer.
        !           140: //
        !           141: // Parameters:
        !           142: //   pdev:
        !           143: //     pointer to DEVDATA structure.
        !           144: //
        !           145: // Returns:
        !           146: //   This function returns no value.
        !           147: //
        !           148: // History:
        !           149: //   18-Dec-1990     -by-     Kent Settle     (kentse)
        !           150: //  Wrote it.
        !           151: //--------------------------------------------------------------------------
        !           152: 
        !           153: VOID ps_newpath(pdev)
        !           154: PDEVDATA    pdev;
        !           155: {
        !           156:     if (pdev->cgs.dwFlags & CGS_PATHEXISTS)
        !           157:     {
        !           158:        PrintString(pdev, "n\n");
        !           159: 
        !           160:         // indicate that no path exists in the printer.
        !           161: 
        !           162:         pdev->cgs.dwFlags &= ~CGS_PATHEXISTS;
        !           163:     }
        !           164: }
        !           165: 
        !           166: 
        !           167: //--------------------------------------------------------------------------
        !           168: // BOOL ps_save(pdev, bgsave)
        !           169: // PDEVDATA    pdev;
        !           170: // BOOL        bgsave;
        !           171: //
        !           172: // This routine is called by the driver to save the current graphics state.
        !           173: //
        !           174: // Parameters:
        !           175: //   pdev:
        !           176: //     pointer to DEVDATA structure.
        !           177: //
        !           178: //   bgsave:
        !           179: //     TRUE if to perform gsave instead of save.
        !           180: //
        !           181: // Returns:
        !           182: //   This function returns no value.
        !           183: //
        !           184: // History:
        !           185: //   18-Dec-1990     -by-     Kent Settle     (kentse)
        !           186: //  Wrote it.
        !           187: //   06-Nov-1991    -by-    Kent Settle     [kentse]
        !           188: //  Rewrote it using linked list.
        !           189: //--------------------------------------------------------------------------
        !           190: 
        !           191: BOOL ps_save(pdev, bgsave)
        !           192: PDEVDATA       pdev;
        !           193: BOOL   bgsave;
        !           194: {
        !           195:     CGS    *pcgs;
        !           196:     CGS    *pNew;
        !           197:     DLFONT *pDLFont;
        !           198: 
        !           199:     // save the current graphics state in a linked list.
        !           200: 
        !           201:     // get pointer to beginning of gsave linked list.
        !           202: 
        !           203:     pcgs = pdev->pcgsSave;
        !           204: 
        !           205:     // move to the last entry in the list.
        !           206: 
        !           207:     if (pcgs)
        !           208:     {
        !           209:        while(pcgs->pcgsNext)
        !           210:            pcgs = pcgs->pcgsNext;
        !           211:     }
        !           212: 
        !           213:     // allocate the new element of the linked list.
        !           214: 
        !           215:     if (!(pNew = (PCGS)HeapAlloc(pdev->hheap, 0, sizeof(CGS))))
        !           216:     {
        !           217:         RIP("PSCRIPT!ps_save: HeapAlloc for pNew failed.\n");
        !           218:        return(FALSE);
        !           219:     }
        !           220: 
        !           221:     // save the current graphics state in our new element.
        !           222: 
        !           223:     memcpy(pNew, &pdev->cgs, sizeof(CGS));
        !           224: 
        !           225:     // allocate a new set of DLFONT structures, then copy the existing ones
        !           226:     // to the new ones.
        !           227: 
        !           228:     if (!(pNew->pDLFonts = (DLFONT *)HeapAlloc(pdev->hheap, 0,
        !           229:                                               sizeof(DLFONT) * (pdev->iDLFonts + 1))))
        !           230:     {
        !           231:         RIP("PSCRIPT!ps_save: HeapAlloc for pDLFonts failed.\n");
        !           232:         HeapFree(pdev->hheap, 0, (PVOID)pNew);
        !           233:         return(FALSE);
        !           234:     }
        !           235: 
        !           236:     pDLFont = pNew->pDLFonts;
        !           237: 
        !           238:     memcpy(pDLFont, pdev->cgs.pDLFonts, sizeof(DLFONT) * (pdev->iDLFonts));
        !           239: 
        !           240:     // clear out the last entry.
        !           241: 
        !           242:     pDLFont += pdev->iDLFonts;
        !           243:     memset(pDLFont, 0, sizeof(DLFONT));
        !           244: 
        !           245:     // if this is first element in the list, set the pointer in our
        !           246:     // pdev, else update list to point to new element.
        !           247: 
        !           248:     if (!pcgs)
        !           249:        pdev->pcgsSave = pNew;
        !           250:     else
        !           251:        pcgs->pcgsNext = pNew;
        !           252: 
        !           253:     // initialize pointers in new element.
        !           254: 
        !           255:     pNew->pcgsPrev = pcgs;  // NULL if first gsave.
        !           256:     pNew->pcgsNext = NULL;
        !           257: 
        !           258:     // output save command to printer.
        !           259: 
        !           260:     if (bgsave)
        !           261:        PrintString(pdev, "gs\n");
        !           262:     else
        !           263:        PrintString(pdev, "save\n");
        !           264: 
        !           265:     return(TRUE);
        !           266: }
        !           267: 
        !           268: 
        !           269: //--------------------------------------------------------------------------
        !           270: // BOOL ps_restore(pdev, bgrestore)
        !           271: // PDEVDATA    pdev;
        !           272: // BOOL        bgrestore;
        !           273: //
        !           274: // This routine is called by the driver to restore a previously saved
        !           275: // graphics state.
        !           276: //
        !           277: // Parameters:
        !           278: //   pdev:
        !           279: //     pointer to DEVDATA structure.
        !           280: //
        !           281: // Returns:
        !           282: //   This function returns no value.
        !           283: //
        !           284: // History:
        !           285: //   18-Dec-1990     -by-     Kent Settle     (kentse)
        !           286: //  Wrote it.
        !           287: //   06-Nov-1991    -by-    Kent Settle     [kentse]
        !           288: //  Rewrote it using linked list.
        !           289: //   15-Feb-1993    -by-    Rob Kiesler
        !           290: //  If a restore is being performed, reset pdev flags indicating that
        !           291: //  the Adobe PS utility, pattern, and image procsets have been downloaded.
        !           292: //--------------------------------------------------------------------------
        !           293: 
        !           294: BOOL ps_restore(pdev, bgrestore)
        !           295: PDEVDATA       pdev;
        !           296: BOOL   bgrestore;
        !           297: {
        !           298:     CGS    *pcgs;
        !           299:     CGS    *pcgsTmp;
        !           300:     DLFONT *pDLFont;
        !           301: 
        !           302:     // restore the current graphics state from the last element
        !           303:     // of the graphics state save linked list.
        !           304: 
        !           305:     // get pointer to the linked list.
        !           306: 
        !           307:     pcgs = pdev->pcgsSave;
        !           308: 
        !           309:     // find the last element of the list.
        !           310: 
        !           311:     while (pcgs->pcgsNext)
        !           312:        pcgs = pcgs->pcgsNext;
        !           313: 
        !           314:     // we are about to copy the last saved CGS from the linked list into the
        !           315:     // current CGS.  therefore, we must free up memory used in the CGS before
        !           316:     // we clobber the pointers.
        !           317: 
        !           318:     if  (pdev->cgs.pDLFonts)
        !           319:     {
        !           320:         // point to the last DLFONT structure.  this will have been filled
        !           321:         // in iff we have hit our downloaded font threshold.  if it is filled
        !           322:         // in, free up the hglyph vector.
        !           323: 
        !           324:         pDLFont = pdev->cgs.pDLFonts;
        !           325:         pDLFont += pdev->iDLFonts;
        !           326: 
        !           327:         if (pDLFont->phgVector)
        !           328:             HeapFree(pdev->hheap, 0, (PVOID)pDLFont->phgVector);
        !           329: 
        !           330:         HeapFree(pdev->hheap, 0, (PVOID)pdev->cgs.pDLFonts);
        !           331:     }
        !           332: 
        !           333:     // restore the current graphics state.
        !           334: 
        !           335:     memcpy(&pdev->cgs, pcgs, sizeof(CGS));
        !           336: 
        !           337:     // back up one element, and free up the last element of the list.
        !           338: 
        !           339:     if (!(pcgsTmp = pcgs->pcgsPrev))
        !           340:     {
        !           341:        // restored back to original state.  clear out pointer to
        !           342:        // linked list.
        !           343: 
        !           344:        pdev->pcgsSave = (CGS *)NULL;
        !           345:     }
        !           346:     else
        !           347:     {
        !           348:        // mark the current element as the last in the list.
        !           349: 
        !           350:        pcgsTmp->pcgsNext = (PCGS)NULL;
        !           351:     }
        !           352: 
        !           353:     // free up the save CGS.
        !           354: 
        !           355:     HeapFree(pdev->hheap, 0, (PVOID)pcgs);
        !           356: 
        !           357:     if (bgrestore)
        !           358:        PrintString(pdev, "gr\n");
        !           359:     else
        !           360:     {
        !           361:       //
        !           362:       // If the Adobe PS Utilites were downloaded, clean up after
        !           363:       // them before blowing them away with the restore.
        !           364:       //
        !           365:       if (pdev->dwFlags & PDEV_UTILSSENT)
        !           366:       {
        !           367:          PrintString(pdev, "Adobe_WinNT_Driver_Gfx dup /terminate get exec\n");
        !           368:          pdev->dwFlags &= ~(PDEV_UTILSSENT | PDEV_BMPPATSENT | PDEV_IMAGESENT);
        !           369:       }
        !           370:       PrintString(pdev, "restore\n");
        !           371: 
        !           372:     }
        !           373: 
        !           374:     return(TRUE);
        !           375: }
        !           376: 
        !           377: 
        !           378: //--------------------------------------------------------------------------
        !           379: // VOID ps_clip(pdev, bWinding)
        !           380: // PDEVDATA    pdev;
        !           381: // BOOL        bWinding;
        !           382: //
        !           383: // This routine is called by the driver to intersect the current path with
        !           384: // the clipping path and make this the nwe clipping path.  The winding
        !           385: // number rule is used to determine the area clipped, if bWinding is TRUE.
        !           386: //
        !           387: // Parameters:
        !           388: //   pdev:
        !           389: //     pointer to DEVDATA structure.
        !           390: //
        !           391: // Returns:
        !           392: //   This function returns no value.
        !           393: //
        !           394: // History:
        !           395: //   13-Feb-1991     -by-     Kent Settle     (kentse)
        !           396: //  Wrote it.
        !           397: //--------------------------------------------------------------------------
        !           398: 
        !           399: VOID ps_clip(pdev, bWinding)
        !           400: PDEVDATA    pdev;
        !           401: BOOL       bWinding;
        !           402: {
        !           403:     // output the clip command to the printer, then output a newpath
        !           404:     // command, since the clip command does not destroy the path in the
        !           405:     // printer.
        !           406: 
        !           407:     if (bWinding)
        !           408:        PrintString(pdev, "clip n\n");
        !           409:     else
        !           410:        PrintString(pdev, "eoclip n\n");
        !           411: 
        !           412:     // indicate that the path no longer exists.
        !           413: 
        !           414:     pdev->cgs.dwFlags &= ~CGS_PATHEXISTS;
        !           415: }
        !           416: 
        !           417: 
        !           418: //--------------------------------------------------------------------------
        !           419: // VOID ps_show(pdev, pstro, flAccel, pdata)
        !           420: // PDEVDATA    pdev;
        !           421: // STROBJ     *pstro;
        !           422: // FLONG       flAccel;
        !           423: // TEXTDATA   *pdata;
        !           424: //
        !           425: // This routine is called by the driver to intersect the current path with
        !           426: // the clipping path and make this the nwe clipping path.  The winding
        !           427: // number rule is used to determine the area clipped, if bWinding is TRUE.
        !           428: //
        !           429: // Parameters:
        !           430: //   pdev:
        !           431: //     pointer to DEVDATA structure.
        !           432: //
        !           433: // Returns:
        !           434: //   This function returns no value.
        !           435: //
        !           436: // History:
        !           437: //   13-Feb-1991     -by-     Kent Settle     (kentse)
        !           438: //  Wrote it.
        !           439: //--------------------------------------------------------------------------
        !           440: 
        !           441: VOID ps_show(pdev, pstro, flAccel, pdata)
        !           442: PDEVDATA    pdev;
        !           443: STROBJ     *pstro;
        !           444: FLONG       flAccel;
        !           445: TEXTDATA   *pdata;
        !           446: {
        !           447:     // close the string and send out the show command, abreviated
        !           448:     // by 't', or our version of the fixed pitched horizontal
        !           449:     // show command 'H', or the proportional horizontal show
        !           450:     // command 'h', or the fixed pitched vertical show command 'V',
        !           451:     // or the proportional vertical show command 'v'.
        !           452: 
        !           453:     if ((flAccel == 0) || (flAccel & SO_FLAG_DEFAULT_PLACEMENT) ||
        !           454:         (pstro->cGlyphs == 1))
        !           455:         PrintString(pdev, ")t\n");
        !           456:     else if (flAccel & SO_HORIZONTAL)
        !           457:     {
        !           458:         if (pstro->ulCharInc)
        !           459:             PrintString(pdev, ")H\n");
        !           460:         else
        !           461:         {
        !           462:             if (pdata->bJustification)
        !           463:             {
        !           464:                 // if we calculated the text justification, and it turns
        !           465:                 // out the the justification widths are zero, just to
        !           466:                 // a reguluar show command, otherwise it is time for
        !           467:                 // awidthshow.
        !           468: 
        !           469:                 if ((pdata->ptSpace.x == 0) && (pdata->ptNonSpace.x == 0))
        !           470:                     PrintString(pdev, ")t\n");
        !           471:                 else
        !           472:                     PrintString(pdev, ")aw\n");
        !           473:             }
        !           474:             else
        !           475:                 PrintString(pdev, ")h\n");
        !           476:         }
        !           477:     }
        !           478:     else
        !           479:     {
        !           480:         if (pstro->ulCharInc)
        !           481:             PrintString(pdev, ")V\n");
        !           482:         else
        !           483:             PrintString(pdev, ")v\n");
        !           484:     }
        !           485: }
        !           486: 
        !           487: 
        !           488: //--------------------------------------------------------------------------
        !           489: // VOID ps_box(pdev, prectl)
        !           490: // PDEVDATA    pdev;
        !           491: // PRECTL    prectl;
        !           492: //
        !           493: // This routine is called by the driver to send box drawing commands to
        !           494: // the printer.
        !           495: //
        !           496: // Parameters:
        !           497: //   pdev:
        !           498: //     Pointer to DEVDATA structure.
        !           499: //
        !           500: //   prectl:
        !           501: //     Pointer to RECTL defining the box.
        !           502: //
        !           503: // Returns:
        !           504: //   This function returns no value.
        !           505: //
        !           506: // History:
        !           507: //   13-Feb-1991     -by-     Kent Settle     (kentse)
        !           508: //  Wrote it.
        !           509: //--------------------------------------------------------------------------
        !           510: 
        !           511: VOID ps_box(pdev, prectl)
        !           512: PDEVDATA pdev;
        !           513: PRECTL     prectl;
        !           514: {
        !           515:     RECTPSFX   rectpsfx;
        !           516: 
        !           517:     // output the box command to the printer.  remember to convert
        !           518:     // between device resolution and PostScript user coordinates.
        !           519: 
        !           520:     // get a local copy of the rectangle, turn it into FIX numbers,
        !           521:     // flip over the y coordinates since 0,0 is upper left under NT, and
        !           522:     // 0,0 is lower left under PostScript.
        !           523: 
        !           524:     rectpsfx.xLeft = X72DPI(prectl->left);
        !           525:     rectpsfx.yBottom = Y72DPI(prectl->bottom);
        !           526:     rectpsfx.xRight = X72DPI(prectl->right);
        !           527:     rectpsfx.yTop = Y72DPI(prectl->top);
        !           528: 
        !           529:     PrintPSFIX(pdev, 4, rectpsfx.xLeft, rectpsfx.yTop,
        !           530:               rectpsfx.xRight, rectpsfx.yBottom);
        !           531:     PrintString(pdev, " box\n");
        !           532: 
        !           533:     // indicate that a path now exists.
        !           534: 
        !           535:     pdev->cgs.dwFlags |= CGS_PATHEXISTS;
        !           536: }
        !           537: 
        !           538: 
        !           539: //--------------------------------------------------------------------------
        !           540: // VOID ps_moveto(pdev, pptl)
        !           541: // PDEVDATA    pdev;
        !           542: // PPOINTL    pptl;
        !           543: //
        !           544: // This routine is called by the driver to update the current position
        !           545: // in the printer.
        !           546: //
        !           547: // Parameters:
        !           548: //   pdev:
        !           549: //     Pointer to DEVDATA structure.
        !           550: //
        !           551: //   pptl:
        !           552: //     Pointer to PPOINTL defining new current position.
        !           553: //
        !           554: // Returns:
        !           555: //   This function returns no value.
        !           556: //
        !           557: // History:
        !           558: //   26-Apr-1991     -by-     Kent Settle     (kentse)
        !           559: //  Wrote it.
        !           560: //--------------------------------------------------------------------------
        !           561: 
        !           562: VOID ps_moveto(pdev, pptl)
        !           563: PDEVDATA     pdev;
        !           564: PPOINTL      pptl;
        !           565: {
        !           566:     POINTPSFX  ptpsfx;
        !           567: 
        !           568:     // output the moveto command if new position is different from
        !           569:     // the old position.  remember to flip from top to bottom, since
        !           570:     // under NT 0,0 is top left, and under PostScript 0,0 is bottom left.
        !           571:     // also, we should output a moveto command even if we are at the
        !           572:     // current location, if a path does not exist.
        !           573: 
        !           574:     if ((pptl->x != pdev->cgs.ptlCurPos.x) ||
        !           575:         (pptl->y != pdev->cgs.ptlCurPos.y) ||
        !           576:         (!(pdev->cgs.dwFlags & CGS_PATHEXISTS)))
        !           577:     {
        !           578:        ptpsfx.x = X72DPI(pptl->x);
        !           579:        ptpsfx.y = Y72DPI(pptl->y);
        !           580: 
        !           581:         // output PostScript user coordinates to the printer.
        !           582: 
        !           583:        PrintPSFIX(pdev, 2, ptpsfx.x, ptpsfx.y);
        !           584:         PrintString(pdev, " M\n");
        !           585: 
        !           586:         // save the new current position in device coordinates.
        !           587: 
        !           588:         pdev->cgs.ptlCurPos = *pptl;
        !           589: 
        !           590:         // state that a path now exists in the printer.
        !           591: 
        !           592:         pdev->cgs.dwFlags |= CGS_PATHEXISTS;
        !           593:     }
        !           594: }
        !           595: 
        !           596: 
        !           597: //--------------------------------------------------------------------------
        !           598: // VOID ps_showpage(pdev)
        !           599: // PDEVDATA    pdev;
        !           600: //
        !           601: // This routine issues a showpage command to the printer, and resets
        !           602: // the current graphics state (which is done in the printer by the
        !           603: // showpage command).
        !           604: //
        !           605: // Parameters:
        !           606: //   pdev:
        !           607: //     Pointer to DEVDATA structure.
        !           608: //
        !           609: // Returns:
        !           610: //   This function returns no value.
        !           611: //
        !           612: // History:
        !           613: //   01-May-1991     -by-     Kent Settle     (kentse)
        !           614: //  Wrote it.
        !           615: //--------------------------------------------------------------------------
        !           616: 
        !           617: VOID ps_showpage(pdev)
        !           618: PDEVDATA    pdev;
        !           619: {
        !           620:     // output the eject command to the printer.
        !           621: 
        !           622:     PrintString(pdev, "showpage\n");
        !           623: 
        !           624:     init_cgs(pdev);
        !           625: }
        !           626: 
        !           627: 
        !           628: //--------------------------------------------------------------------------
        !           629: // VOID init_cgs(pdev)
        !           630: // PDEVDATA    pdev;
        !           631: //
        !           632: // This routine is called to reset the current graphics state.
        !           633: //
        !           634: // Parameters:
        !           635: //   pdev:
        !           636: //     Pointer to DEVDATA structure.
        !           637: //
        !           638: // Returns:
        !           639: //   This function returns no value.
        !           640: //
        !           641: // History:
        !           642: //   01-May-1991     -by-     Kent Settle     (kentse)
        !           643: //  Wrote it.
        !           644: //--------------------------------------------------------------------------
        !           645: 
        !           646: VOID init_cgs(pdev)
        !           647: PDEVDATA    pdev;
        !           648: {
        !           649:     PCGS    pcgs;
        !           650:     DWORD   i;
        !           651:     DLFONT *pDLFont, *pDLFontSave;
        !           652: 
        !           653:     pcgs = &pdev->cgs;
        !           654: 
        !           655:     // save pointer to DLFONT structures.
        !           656: 
        !           657:     pDLFont = pdev->cgs.pDLFonts;
        !           658:     pDLFontSave = pDLFont;
        !           659: 
        !           660:     // if any downloaded fonts currently exist, free up their memory.
        !           661: 
        !           662:     if (pDLFont)
        !           663:     {
        !           664:         for (i = 0; i < pcgs->cDownloadedFonts; i++)
        !           665:         {
        !           666:             if (pDLFont->phgVector)
        !           667:                 HeapFree(pdev->hheap, 0, (PVOID)pDLFont->phgVector);
        !           668: 
        !           669:             pDLFont++;
        !           670:         }
        !           671:     }
        !           672: 
        !           673:     // clear all the softfont downloading bits, if any softfonts.
        !           674: 
        !           675:     if (pcgs->pSFArray)
        !           676:        memset(pcgs->pSFArray, 0, ((pdev->cSoftFonts + 7) / 8));
        !           677: 
        !           678:     // initialize the entire structure to zero, then fill in the
        !           679:     // elements we care about.
        !           680: 
        !           681:     memset(pcgs, 0, sizeof(CGS));
        !           682: 
        !           683:     pcgs->lineattrs.fl = LA_GEOMETRIC;
        !           684:     pcgs->lineattrs.iJoin = JOIN_MITER;
        !           685:     pcgs->lineattrs.iEndCap = ENDCAP_BUTT;
        !           686:     pcgs->psfxLineWidth = 0;
        !           687:     pcgs->lineattrs.eMiterLimit = (FLOAT)10.0;
        !           688:     pcgs->ulColor = RGB_BLACK;
        !           689:     pcgs->FontXform.eM11 = (float)1.0;
        !           690:     pcgs->FontXform.eM22 = (float)1.0;
        !           691:     pcgs->GeoLineXform.eM11 = (float)1.0;
        !           692:     pcgs->GeoLineXform.eM22 = (float)1.0;
        !           693:     pcgs->psfxScaleFactor = LTOPSFX(10L);
        !           694: 
        !           695:     // restore pointer to DLFONT structures.
        !           696: 
        !           697:     pcgs->pDLFonts = pDLFontSave;
        !           698: }
        !           699: 
        !           700: 
        !           701: //--------------------------------------------------------------------------
        !           702: // VOID ps_stroke(pdev, pbo, pptl)
        !           703: // PDEVDATA    pdev;
        !           704: // BRUSHOBJ   *pbo;
        !           705: // PPOINTL     pptl;
        !           706: //
        !           707: // This routine is called to stroke the current path.
        !           708: //
        !           709: // Parameters:
        !           710: //   pdev:
        !           711: //     Pointer to DEVDATA structure.
        !           712: //
        !           713: //   pbo:
        !           714: //     Pointer to BRUSHOBJ to use for stroking.
        !           715: //
        !           716: //   pptl:
        !           717: //     Pointer to POINTL to use for brush origin.
        !           718: //
        !           719: // Returns:
        !           720: //   This function returns no value.
        !           721: //
        !           722: // History:
        !           723: //   03-May-1991     -by-     Kent Settle     (kentse)
        !           724: //  Wrote it.
        !           725: //--------------------------------------------------------------------------
        !           726: 
        !           727: VOID ps_stroke(pdev, pbo, pptl)
        !           728: PDEVDATA    pdev;
        !           729: BRUSHOBJ   *pbo;
        !           730: PPOINTL     pptl;
        !           731: {
        !           732:     UNREFERENCED_PARAMETER(pptl);
        !           733: 
        !           734:     // stroke the path if it exists.
        !           735: 
        !           736:     if (pdev->cgs.dwFlags & CGS_PATHEXISTS)
        !           737:     {
        !           738:         //!!! check into a path buffer.  - kentse.
        !           739: 
        !           740:        PrintString(pdev, "s\n");
        !           741:     }
        !           742: #if DBG
        !           743:     else
        !           744:         DbgPrint("PSCRIPT!ps_stroke: stroking a non-existent path.\n");
        !           745: #endif
        !           746: 
        !           747:     // the path gets destroyed in the printer, when it is stroked, so
        !           748:     // mark it as such.
        !           749: 
        !           750:     pdev->cgs.dwFlags &= ~CGS_PATHEXISTS;
        !           751: }
        !           752: 
        !           753: 
        !           754: //--------------------------------------------------------------------------
        !           755: // VOID ps_lineto(pdev, pptl)
        !           756: // PDEVDATA    pdev;
        !           757: // PPOINTL    pptl;
        !           758: //
        !           759: // This routine is called by the driver to output a lineto command, as
        !           760: // well as update the current position.
        !           761: //
        !           762: // Parameters:
        !           763: //   pdev:
        !           764: //     Pointer to DEVDATA structure.
        !           765: //
        !           766: //   pptl:
        !           767: //     Pointer to PPOINTL defining new current position.
        !           768: //
        !           769: // Returns:
        !           770: //   This function returns no value.
        !           771: //
        !           772: // History:
        !           773: //   03-May-1991     -by-     Kent Settle     (kentse)
        !           774: //  Wrote it.
        !           775: //--------------------------------------------------------------------------
        !           776: 
        !           777: VOID ps_lineto(pdev, pptl)
        !           778: PDEVDATA     pdev;
        !           779: PPOINTL      pptl;
        !           780: {
        !           781:     POINTPSFX   ptpsfx;
        !           782: 
        !           783:     // output the lineto command and set the new current position in
        !           784:     // the printer.  remember to flip from top to bottom, since
        !           785:     // under NT 0,0 is top left, and under PostScript 0,0 is bottom left.
        !           786: 
        !           787:     if ((pptl->x != pdev->cgs.ptlCurPos.x) ||
        !           788:         (pptl->y != pdev->cgs.ptlCurPos.y))
        !           789:     {
        !           790:        ptpsfx.x = X72DPI(pptl->x);
        !           791:        ptpsfx.y = Y72DPI(pptl->y);
        !           792: 
        !           793:         // output the lineto command using PostScript user coordinates,
        !           794:         // then update the current position.
        !           795: 
        !           796:        PrintPSFIX(pdev, 2, ptpsfx.x, ptpsfx.y);
        !           797:         PrintString(pdev, " L\n");
        !           798: 
        !           799:         // save the new current position in device coordinates.
        !           800: 
        !           801:         pdev->cgs.ptlCurPos = *pptl;
        !           802: 
        !           803:         // mark that we do indeed have a path.
        !           804: 
        !           805:         pdev->cgs.dwFlags |= CGS_PATHEXISTS;
        !           806:     }
        !           807: }
        !           808: 
        !           809: 
        !           810: //--------------------------------------------------------------------------
        !           811: // VOID ps_curveto(pdev, pptl, pptl1, pptl2)
        !           812: // PDEVDATA  pdev;
        !           813: // PPOINTL   pptl;
        !           814: // PPOINTL   pptl1;
        !           815: // PPOINTL   pptl2;
        !           816: //
        !           817: // This routine is called by the driver to output a curveto command as well
        !           818: // as update the current position.
        !           819: //
        !           820: // Parameters:
        !           821: //   pdev:
        !           822: //     Pointer to DEVDATA structure.
        !           823: //
        !           824: //   pptl, pptl1, pptl2:
        !           825: //     Pointer to PPOINTLs defining the bezier curve to output.
        !           826: //
        !           827: // Returns:
        !           828: //   This function returns no value.
        !           829: //
        !           830: // History:
        !           831: //   03-May-1991     -by-     Kent Settle     (kentse)
        !           832: //  Wrote it.
        !           833: //--------------------------------------------------------------------------
        !           834: 
        !           835: VOID ps_curveto(pdev, pptl, pptl1, pptl2)
        !           836: PDEVDATA     pdev;
        !           837: PPOINTL      pptl;
        !           838: PPOINTL      pptl1;
        !           839: PPOINTL      pptl2;
        !           840: {
        !           841:     POINTPSFX   ptpsfx;
        !           842:     POINTPSFX   ptpsfx1;
        !           843:     POINTPSFX   ptpsfx2;
        !           844: 
        !           845:     // output the curveto command and set the new current position in
        !           846:     // the printer.  remember to flip from top to bottom, since
        !           847:     // under NT 0,0 is top left, and under PostScript 0,0 is bottom left.
        !           848: 
        !           849:     ptpsfx.x = X72DPI(pptl->x);
        !           850:     ptpsfx.y = Y72DPI(pptl->y);
        !           851:     ptpsfx1.x = X72DPI(pptl1->x);
        !           852:     ptpsfx1.y = Y72DPI(pptl1->y);
        !           853:     ptpsfx2.x = X72DPI(pptl2->x);
        !           854:     ptpsfx2.y = Y72DPI(pptl2->y);
        !           855: 
        !           856:     // output the curveto command using PostScript user coordinates,
        !           857:     // then update the current position to be the last point on the curve.
        !           858: 
        !           859:     PrintPSFIX(pdev, 6, ptpsfx.x, ptpsfx.y, ptpsfx1.x, ptpsfx1.y,
        !           860:               ptpsfx2.x, ptpsfx2.y);
        !           861:     PrintString(pdev, " c\n");
        !           862: 
        !           863:     // save the new current position in device coordinates.
        !           864: 
        !           865:     pdev->cgs.ptlCurPos = *pptl2;
        !           866: 
        !           867:     // mark that we do indeed have a path.
        !           868: 
        !           869:     pdev->cgs.dwFlags |= CGS_PATHEXISTS;
        !           870: 
        !           871:     return;
        !           872: }
        !           873: 
        !           874: 
        !           875: //--------------------------------------------------------------------------
        !           876: // VOID ps_fill(pdev, flFillMode)
        !           877: // PDEVDATA  pdev;
        !           878: // FLONG     flFillMode;
        !           879: //
        !           880: // This routine is called by the driver to output a fill command to
        !           881: // the printer.
        !           882: //
        !           883: // Parameters:
        !           884: //   pdev:
        !           885: //     Pointer to DEVDATA structure.
        !           886: //
        !           887: // Returns:
        !           888: //   This function returns no value.
        !           889: //
        !           890: // History:
        !           891: //   03-May-1991     -by-     Kent Settle     (kentse)
        !           892: //  Wrote it.
        !           893: //--------------------------------------------------------------------------
        !           894: 
        !           895: VOID ps_fill(pdev, flFillMode)
        !           896: PDEVDATA pdev;
        !           897: FLONG    flFillMode;
        !           898: {
        !           899:     // output the fill command if we have an existing path.
        !           900: 
        !           901:     if (pdev->cgs.dwFlags & CGS_PATHEXISTS)
        !           902:     {
        !           903:         //!!! check into path buffer.  - kentse.
        !           904: 
        !           905:         if (flFillMode & FP_WINDINGMODE)
        !           906:         {
        !           907:             // output the PostScript fill command to do a winding mode fill.
        !           908: 
        !           909:            PrintString(pdev, "f\n");
        !           910:         }
        !           911:         else
        !           912:         {
        !           913:             // output the PostScript eofill command to do an even odd, or
        !           914:             // alternate fill.
        !           915: 
        !           916:            PrintString(pdev, "e\n");
        !           917:         }
        !           918: 
        !           919:         // the fill operator deletes the path, so mark it as such.
        !           920: 
        !           921:         pdev->cgs.dwFlags &= ~CGS_PATHEXISTS;
        !           922:     }
        !           923: #if DBG
        !           924:     else
        !           925:         DbgPrint("PSCRIPT!ps_fill: filling non-existent path.\n");
        !           926: #endif
        !           927: }
        !           928: 
        !           929: 
        !           930: //--------------------------------------------------------------------------
        !           931: // VOID ps_closepath(pdev)
        !           932: // PDEVDATA    pdev;
        !           933: //
        !           934: // This routine is called to close the current path.
        !           935: //
        !           936: // Parameters:
        !           937: //   pdev:
        !           938: //     Pointer to DEVDATA structure.
        !           939: //
        !           940: // Returns:
        !           941: //   This function returns no value.
        !           942: //
        !           943: // History:
        !           944: //   03-May-1991     -by-     Kent Settle     (kentse)
        !           945: //  Wrote it.
        !           946: //--------------------------------------------------------------------------
        !           947: 
        !           948: VOID ps_closepath(pdev)
        !           949: PDEVDATA    pdev;
        !           950: {
        !           951:     // if a path exists, close it.
        !           952: 
        !           953:     if (pdev->cgs.dwFlags & CGS_PATHEXISTS)
        !           954:        PrintString(pdev, "cp\n");
        !           955: }
        !           956: 
        !           957: 
        !           958: //--------------------------------------------------------------------------
        !           959: // PS_FIX psfxRGBtoGray(pbgr)
        !           960: // BGR_PAL_ENTRY  *pbgr;
        !           961: //
        !           962: // This routine is called to convert an RGB value to a gray scale.
        !           963: //
        !           964: // Parameters:
        !           965: //   ppe:
        !           966: //     pointer to PALETTEENTRY color to convert.
        !           967: //
        !           968: // Returns:
        !           969: //   This function returns PS_FIX gray scale value.
        !           970: //
        !           971: // History:
        !           972: //   21-May-1991     -by-     Kent Settle     (kentse)
        !           973: //  Wrote it.
        !           974: //--------------------------------------------------------------------------
        !           975: 
        !           976: 
        !           977: PS_FIX psfxRGBtoGray(pbgr)
        !           978: BGR_PAL_ENTRY  *pbgr;
        !           979: {
        !           980:     PS_FIX  psfxRed, psfxGreen, psfxBlue, psfxGray;
        !           981: 
        !           982:     // The gray value is computed as a normalized average of the
        !           983:     // three color components.  The resultant gray level should
        !           984:     // range from 0.0 to 1.0
        !           985: 
        !           986:     psfxRed = (ULONG)pbgr->bgrRed * PSFXPERCENT_RED;
        !           987:     psfxGreen = (ULONG)pbgr->bgrGreen * PSFXPERCENT_GREEN;
        !           988:     psfxBlue = (ULONG)pbgr->bgrBlue * PSFXPERCENT_BLUE;
        !           989: 
        !           990:     psfxGray = (PS_FIX)((psfxRed + psfxGreen + psfxBlue) / 255);
        !           991: 
        !           992:     return (psfxGray);
        !           993: }
        !           994: 
        !           995: 
        !           996: //--------------------------------------------------------------------------
        !           997: // VOID ps_setlinewidth(pdev, psfxLineWidth)
        !           998: // PDEVDATA     pdev;
        !           999: // PS_FIX       psfxLineWidth;
        !          1000: //
        !          1001: // This routine is called by the driver to set the current geometric linewidth.
        !          1002: // The line width is specified in USER coordinates (1/72 inch).
        !          1003: //
        !          1004: // Parameters:
        !          1005: //   pdev:
        !          1006: //     pointer to DEVDATA structure.
        !          1007: //
        !          1008: //   psfxLineWidth:
        !          1009: //     linewidth to set.
        !          1010: //
        !          1011: // Returns:
        !          1012: //   This function returns no value.
        !          1013: //
        !          1014: // History:
        !          1015: //   05-July-1991       -by-     Kent Settle     (kentse)
        !          1016: //  Wrote it.
        !          1017: //--------------------------------------------------------------------------
        !          1018: 
        !          1019: VOID ps_setlinewidth(pdev, psfxLineWidth)
        !          1020: PDEVDATA        pdev;
        !          1021: PS_FIX          psfxLineWidth;
        !          1022: {
        !          1023:     // only update the linewidth if the new value differs from the old.
        !          1024: 
        !          1025:     if (pdev->cgs.psfxLineWidth != psfxLineWidth)
        !          1026:     {
        !          1027:         // update the linewidth in our current graphics state.
        !          1028: 
        !          1029:         pdev->cgs.psfxLineWidth = psfxLineWidth;
        !          1030: 
        !          1031:         // update the printer's linewidth.
        !          1032: 
        !          1033:        PrintPSFIX(pdev, 1, psfxLineWidth);
        !          1034:         PrintString(pdev, " sl\n");
        !          1035:     }
        !          1036: 
        !          1037:     return;
        !          1038: }
        !          1039: 
        !          1040: 
        !          1041: //--------------------------------------------------------------------------
        !          1042: // BOOL ps_setlineattrs(pdev, plineattrs, pxo)
        !          1043: // PDEVDATA    pdev;
        !          1044: // PLINEATTRS  plineattrs;
        !          1045: // XFORMOBJ   *pxo;
        !          1046: //
        !          1047: // This routine is called by the driver to set the current line attributes.
        !          1048: //
        !          1049: // Parameters:
        !          1050: //   pdev:
        !          1051: //     pointer to DEVDATA structure.
        !          1052: //
        !          1053: //   plineattrs:
        !          1054: //     line attributes to set.
        !          1055: //
        !          1056: // Returns:
        !          1057: //   This function returns no value.
        !          1058: //
        !          1059: // History:
        !          1060: //   19-Mar-1992        -by-    Kent Settle     (kentse)
        !          1061: //  Wrote it.
        !          1062: //--------------------------------------------------------------------------
        !          1063: 
        !          1064: BOOL ps_setlineattrs(pdev, plineattrs, pxo)
        !          1065: PDEVDATA    pdev;
        !          1066: PLINEATTRS  plineattrs;
        !          1067: XFORMOBJ   *pxo;
        !          1068: {
        !          1069:     ULONG   iJoin;
        !          1070:     ULONG   iEndCap;
        !          1071:     PS_FIX  psfxMiterLimit;
        !          1072:     PS_FIX  psfxStyle, psfxScale;
        !          1073:     PS_FIX  psfxWidth;
        !          1074:     BOOL    bDiffer;
        !          1075:     DWORD   i;
        !          1076:     FLOAT  *pfloat1;
        !          1077:     FLOAT  *pfloat2;
        !          1078:     LONG   *plong1;
        !          1079:     LONG   *plong2;
        !          1080: 
        !          1081:     // there are several line attributes which have meaning for a
        !          1082:     // geometric line, but not for a cosmetic.  set each of them, if
        !          1083:     // necessary.
        !          1084: 
        !          1085:     if (plineattrs->fl & LA_GEOMETRIC)
        !          1086:     {
        !          1087:         // update the line join value, if it differs from the old one.
        !          1088: 
        !          1089:         if (plineattrs->iJoin != pdev->cgs.lineattrs.iJoin)
        !          1090:         {
        !          1091:             // update the line join value in our current graphics state.
        !          1092: 
        !          1093:             pdev->cgs.lineattrs.iJoin = plineattrs->iJoin;
        !          1094: 
        !          1095:             // update the printer's line join.
        !          1096: 
        !          1097:             switch (plineattrs->iJoin)
        !          1098:             {
        !          1099:                 case JOIN_BEVEL:
        !          1100:                     iJoin = PSCRIPT_JOIN_BEVEL;
        !          1101:                     break;
        !          1102: 
        !          1103:                 case JOIN_ROUND:
        !          1104:                     iJoin = PSCRIPT_JOIN_ROUND;
        !          1105:                     break;
        !          1106: 
        !          1107:                 default:
        !          1108:                     iJoin = PSCRIPT_JOIN_MITER;
        !          1109:                     break;
        !          1110:             }
        !          1111: 
        !          1112:             PrintDecimal(pdev, 1, iJoin);
        !          1113:             PrintString(pdev, " j\n");
        !          1114:         }
        !          1115: 
        !          1116:         // update the end cap value, if it differs from the old one.
        !          1117: 
        !          1118:         if (plineattrs->iEndCap != pdev->cgs.lineattrs.iEndCap)
        !          1119:         {
        !          1120:             // update the end cap value in our current graphics state.
        !          1121: 
        !          1122:             pdev->cgs.lineattrs.iEndCap = plineattrs->iEndCap;
        !          1123: 
        !          1124:             // update the printer's end cap value.
        !          1125: 
        !          1126:             switch (plineattrs->iEndCap)
        !          1127:             {
        !          1128:                 case ENDCAP_SQUARE:
        !          1129:                     iEndCap = PSCRIPT_ENDCAP_SQUARE;
        !          1130:                     break;
        !          1131: 
        !          1132:                 case ENDCAP_ROUND:
        !          1133:                     iEndCap = PSCRIPT_ENDCAP_ROUND;
        !          1134:                     break;
        !          1135: 
        !          1136:                 default:
        !          1137:                     iEndCap = PSCRIPT_ENDCAP_BUTT;
        !          1138:                     break;
        !          1139:             }
        !          1140: 
        !          1141:             PrintDecimal(pdev, 1, iEndCap);
        !          1142:             PrintString(pdev, " setlinecap\n");
        !          1143:         }
        !          1144: 
        !          1145:         // a miter limit less than one does not make sense.  rather than
        !          1146:         // returning an error in this case, just default to one.
        !          1147: 
        !          1148:         plineattrs->eMiterLimit = max(plineattrs->eMiterLimit, (FLOAT)1.0);
        !          1149: 
        !          1150:         // update the miter limit value, if it differs from the old one.
        !          1151: 
        !          1152:         if (plineattrs->eMiterLimit != pdev->cgs.lineattrs.eMiterLimit)
        !          1153:         {
        !          1154:             // update the miter limit value in our current graphics state.
        !          1155: 
        !          1156:             pdev->cgs.lineattrs.eMiterLimit = plineattrs->eMiterLimit;
        !          1157: 
        !          1158:             // update the printer's miter limit value.
        !          1159: 
        !          1160:             psfxMiterLimit = ETOPSFX(plineattrs->eMiterLimit);
        !          1161:             PrintPSFIX(pdev, 1, psfxMiterLimit);
        !          1162:             PrintString(pdev, " setmiterlimit\n");
        !          1163:         }
        !          1164: 
        !          1165:         // update the geometric line width, if it differs from the old one.
        !          1166:         // we use pdev->cgs.psfxLineWidth to check against rather than
        !          1167:         // pdev->cgs.lineattrs.elWidth.e since we need to set the line width
        !          1168:         // at times in the driver when we do not have access to the
        !          1169:         // current transform to go from WORLD to DEVICE coordinates.
        !          1170: 
        !          1171:         psfxWidth = (ETOPSFX(plineattrs->elWidth.e) * PS_RESOLUTION) /
        !          1172:                     pdev->psdm.dm.dmPrintQuality;
        !          1173: 
        !          1174:         if (psfxWidth != pdev->cgs.psfxLineWidth)
        !          1175:         {
        !          1176:             // update the line width value in our current graphics state.
        !          1177: 
        !          1178:             pdev->cgs.psfxLineWidth = psfxWidth;
        !          1179: 
        !          1180:             // update the printer's linewidth.  the linewidth is specified
        !          1181:             // in user coordinates.
        !          1182: 
        !          1183:             PrintPSFIX(pdev, 1, psfxWidth);
        !          1184:             PrintString(pdev, " sl\n");
        !          1185:         }
        !          1186: 
        !          1187:         // time to deal with the line style.  note:  we don't want to output
        !          1188:         // the style code unless something about the style has actually
        !          1189:         // changed.  specifically, only if the cStyle, elStyleState, or any element
        !          1190:         // of the array has changed will we output the code to change the
        !          1191:         // style.
        !          1192: 
        !          1193:         bDiffer = FALSE;    // assume style the same.
        !          1194: 
        !          1195:         if ((plineattrs->cstyle != pdev->cgs.lineattrs.cstyle) ||
        !          1196:             (plineattrs->elStyleState.e != pdev->cgs.lineattrs.elStyleState.e))
        !          1197:             bDiffer = TRUE;
        !          1198: 
        !          1199:         if (!bDiffer)
        !          1200:         {
        !          1201:             pfloat1 = (FLOAT *)plineattrs->pstyle;
        !          1202:             pfloat2 = (FLOAT *)pdev->cgs.lineattrs.pstyle;
        !          1203: 
        !          1204: #if DBG
        !          1205:             if ((plineattrs->cstyle == 0) && (plineattrs->pstyle != NULL))
        !          1206:             {
        !          1207:                 RIP("PSCRIPT!ps_setlineattrs: cstyle == 0, but pstyle != NULL.\n");
        !          1208:                 return(FALSE);
        !          1209:             }
        !          1210: #endif
        !          1211: 
        !          1212:             for (i = 0; i < plineattrs->cstyle; i++)
        !          1213:             {
        !          1214:                 if (*pfloat1++ != *pfloat2++)
        !          1215:                 {
        !          1216:                     bDiffer = TRUE;
        !          1217:                     break;
        !          1218:                 }
        !          1219:             }
        !          1220:         }
        !          1221: 
        !          1222:         // now change the line style in the printer, if something about
        !          1223:         // it has changed.
        !          1224: 
        !          1225:         if (bDiffer)
        !          1226:         {
        !          1227:             // handle the solid line case.
        !          1228: 
        !          1229:             if ((plineattrs->pstyle == NULL) || (plineattrs->cstyle == 0))
        !          1230:                 PrintString(pdev, "[]0 sd\n");
        !          1231:             else    // not a solid line.
        !          1232:             {
        !          1233:                 PrintString(pdev, "[");
        !          1234: 
        !          1235:                 pfloat1 = (FLOAT *)plineattrs->pstyle;
        !          1236: 
        !          1237:                 for (i = 0; i < plineattrs->cstyle; i++)
        !          1238:                 {
        !          1239:                     psfxStyle = LTOPSFX((ETOL(*pfloat1++)) * PS_RESOLUTION) /
        !          1240:                                pdev->psdm.dm.dmPrintQuality;
        !          1241: 
        !          1242:                     PrintPSFIX(pdev, 1, psfxStyle);
        !          1243:                     PrintString(pdev, " ");
        !          1244:                 }
        !          1245: 
        !          1246:                 PrintString(pdev, "]");
        !          1247: 
        !          1248:                 // output the style state in user coordinates.
        !          1249: 
        !          1250:                 psfxStyle = LTOPSFX((ETOL(plineattrs->elStyleState.e)) * PS_RESOLUTION) /
        !          1251:                                    pdev->psdm.dm.dmPrintQuality;
        !          1252: 
        !          1253:                 PrintPSFIX(pdev, 1, psfxStyle);
        !          1254:                 PrintString(pdev, " sd\n");
        !          1255:             }
        !          1256: 
        !          1257:             // something in the lineattrs may have changed, update the cgs.
        !          1258: 
        !          1259:             if (pdev->cgs.lineattrs.pstyle)
        !          1260:                 HeapFree(pdev->hheap, 0, (PVOID)pdev->cgs.lineattrs.pstyle);
        !          1261: 
        !          1262:             pdev->cgs.lineattrs = *plineattrs;
        !          1263: 
        !          1264:             // allocate space to copy the style array to.
        !          1265: 
        !          1266:             if (!(pfloat1 = (FLOAT *)HeapAlloc(pdev->hheap, 0,
        !          1267:                                      sizeof(FLOAT) * plineattrs->cstyle)))
        !          1268:             {
        !          1269:                 RIP("PSCRIPT!ps_setlineattrs: HeapAlloc for pfloat1 failed.\n");
        !          1270:                 return(FALSE);
        !          1271:             }
        !          1272: 
        !          1273:             // copy the style array itself.
        !          1274: 
        !          1275:             pfloat2 = (FLOAT *)plineattrs->pstyle;
        !          1276:             pdev->cgs.lineattrs.pstyle = (PFLOAT_LONG)pfloat1;
        !          1277: 
        !          1278:             for (i = 0; i < plineattrs->cstyle; i++)
        !          1279:                 *pfloat1++ = *pfloat2++;
        !          1280:         }
        !          1281:     }
        !          1282:     else    // cosmetic lines.
        !          1283:     {
        !          1284:         // now handle cosmetic lines.  iJoin, iEndCap and eMiterLimit make
        !          1285:         // no sense for cosmetic lines, so we won't worry about them.
        !          1286: 
        !          1287:         psfxWidth = LTOPSFX(plineattrs->elWidth.l * PS_RESOLUTION) /
        !          1288:                            pdev->psdm.dm.dmPrintQuality;
        !          1289: 
        !          1290:         // update the cosmetic line width, if it differs from the old one.
        !          1291:         // we use pdev->cgs.psfxLineWidth to check against rather than
        !          1292:         // pdev->cgs.lineattrs.elWidth.e since we need to set the line width
        !          1293:         // at times in the driver when we do not have access to the
        !          1294:         // current transform to go from WORLD to DEVICE coordinates.
        !          1295: 
        !          1296:         if (psfxWidth != pdev->cgs.psfxLineWidth)
        !          1297:         {
        !          1298:             // update the line width value in our current graphics state.
        !          1299: 
        !          1300:             pdev->cgs.psfxLineWidth = psfxWidth;
        !          1301: 
        !          1302:             // update the printer's linewidth.  the linewidth is specified
        !          1303:             // in user coordinates.
        !          1304: 
        !          1305:             PrintPSFIX(pdev, 1, psfxWidth);
        !          1306:             PrintString(pdev, " sl\n");
        !          1307:         }
        !          1308: 
        !          1309:         // the LA_ALTERNATE linestyle is a special cosmetic line style, where
        !          1310:         // every other pel is on.  well, if we have a printer with 2500 dpi,
        !          1311:         // do we really want every other pel on?  i don't think so.  so,
        !          1312:         // for now at least, we will simply turn on every other user coordinate
        !          1313:         // pel.
        !          1314: 
        !          1315:         if (plineattrs->fl & LA_ALTERNATE)
        !          1316:         {
        !          1317: //!!! perhaps we really want to do a .5 setgray.  what about color.  -kentse.
        !          1318: 
        !          1319:             PrintString(pdev, "[1] ");
        !          1320:             psfxStyle = LTOPSFX(plineattrs->elStyleState.l * PS_RESOLUTION) /
        !          1321:                                 pdev->psdm.dm.dmPrintQuality;
        !          1322: 
        !          1323:             PrintPSFIX(pdev, 1, psfxStyle);
        !          1324:             PrintString(pdev, " sd\n");
        !          1325:         }
        !          1326:         else
        !          1327:         {
        !          1328:             // time to deal with the line style.  note:  we don't want to output
        !          1329:             // the style code unless something about the style has actually
        !          1330:             // changed.  specifically, only if the cStyle, elStyleState, or any element
        !          1331:             // of the array has changed will we output the code to change the
        !          1332:             // style.
        !          1333: 
        !          1334:             bDiffer = FALSE;    // assume style the same.
        !          1335: 
        !          1336:             if ((plineattrs->cstyle != pdev->cgs.lineattrs.cstyle) ||
        !          1337:                 (plineattrs->elStyleState.l != pdev->cgs.lineattrs.elStyleState.l))
        !          1338:                 bDiffer = TRUE;
        !          1339: 
        !          1340:             if (!bDiffer)
        !          1341:             {
        !          1342:                 plong1 = (LONG *)plineattrs->pstyle;
        !          1343:                 plong2 = (LONG *)pdev->cgs.lineattrs.pstyle;
        !          1344: 
        !          1345: #if DBG
        !          1346:                 if ((plineattrs->cstyle == 0) && (plineattrs->pstyle != NULL))
        !          1347:                 {
        !          1348:                     RIP("PSCRIPT!ps_setlineattrs: cstyle == 0, but pstyle != NULL.\n");
        !          1349:                     return(FALSE);
        !          1350:                 }
        !          1351: #endif
        !          1352: 
        !          1353:                 for (i = 0; i < plineattrs->cstyle; i++)
        !          1354:                 {
        !          1355:                     if (*plong1++ != *plong2++)
        !          1356:                     {
        !          1357:                         bDiffer = TRUE;
        !          1358:                         break;
        !          1359:                     }
        !          1360:                 }
        !          1361:             }
        !          1362: 
        !          1363:             // now change the line style in the printer, if something about
        !          1364:             // it has changed.
        !          1365: 
        !          1366:             if (bDiffer)
        !          1367:             {
        !          1368:                 // handle the solid line case.
        !          1369: 
        !          1370:                 if ((plineattrs->pstyle == NULL) || (plineattrs->cstyle == 0))
        !          1371:                     PrintString(pdev, "[]0 sd\n");
        !          1372:                 else    // not a solid line.
        !          1373:                 {
        !          1374:                     PrintString(pdev, "[");
        !          1375: 
        !          1376:                     plong1 = (LONG *)plineattrs->pstyle;
        !          1377: 
        !          1378:                     // get style scaling factor.
        !          1379: 
        !          1380:                     psfxScale = LTOPSFX(pdev->psdm.dm.dmPrintQuality / 25);
        !          1381:                     psfxScale = (psfxScale * PS_RESOLUTION) /
        !          1382:                                 pdev->psdm.dm.dmPrintQuality;
        !          1383: 
        !          1384:                     for (i = 0; i < plineattrs->cstyle; i++)
        !          1385:                     {
        !          1386:                         psfxStyle = (*plong1++) * psfxScale;
        !          1387: 
        !          1388:                         PrintPSFIX(pdev, 1, psfxStyle);
        !          1389:                         PrintString(pdev, " ");
        !          1390:                     }
        !          1391: 
        !          1392:                     PrintString(pdev, "]");
        !          1393:                     psfxStyle = plineattrs->elStyleState.l * psfxScale;
        !          1394: 
        !          1395:                     PrintPSFIX(pdev, 1, psfxStyle);
        !          1396:                     PrintString(pdev, " sd\n");
        !          1397:                 }
        !          1398: 
        !          1399:                 // something in the lineattrs may have changed, update the cgs.
        !          1400: 
        !          1401:                 if (pdev->cgs.lineattrs.pstyle)
        !          1402:                     HeapFree(pdev->hheap, 0, (PVOID)pdev->cgs.lineattrs.pstyle);
        !          1403: 
        !          1404:                 pdev->cgs.lineattrs = *plineattrs;
        !          1405: 
        !          1406:                 // allocate space to copy the style array to.
        !          1407: 
        !          1408:                 if (!(plong1 = (LONG *)HeapAlloc(pdev->hheap, 0,
        !          1409:                                          sizeof(LONG) * plineattrs->cstyle)))
        !          1410:                 {
        !          1411:                     RIP("PSCRIPT!ps_setlineattrs: HeapAlloc for plong1 failed.\n");
        !          1412:                     return(FALSE);
        !          1413:                 }
        !          1414: 
        !          1415:                 // copy the style array itself.
        !          1416: 
        !          1417:                 plong2 = (LONG *)plineattrs->pstyle;
        !          1418:                 pdev->cgs.lineattrs.pstyle = (PFLOAT_LONG)plong1;
        !          1419: 
        !          1420:                 for (i = 0; i < plineattrs->cstyle; i++)
        !          1421:                     *plong1++ = *plong2++;
        !          1422:             }
        !          1423:         }
        !          1424: 
        !          1425:     }
        !          1426: 
        !          1427:     return(TRUE);
        !          1428: }
        !          1429: 
        !          1430: 
        !          1431: //--------------------------------------------------------------------------
        !          1432: // VOID ps_geolinexform(pdev, plineattrs, pxo)
        !          1433: // PDEVDATA    pdev;
        !          1434: // PLINEATTRS  plineattrs;
        !          1435: // XFORMOBJ   *pxo;
        !          1436: //
        !          1437: // This routine is called by the driver to set the current line attributes.
        !          1438: //
        !          1439: // Parameters:
        !          1440: //   pdev:
        !          1441: //     pointer to DEVDATA structure.
        !          1442: //
        !          1443: //   plineattrs:
        !          1444: //     line attributes to set.
        !          1445: //
        !          1446: // Returns:
        !          1447: //   This function returns no value.
        !          1448: //
        !          1449: // History:
        !          1450: //   12-Mar-1993        -by-    Kent Settle     (kentse)
        !          1451: //  Wrote it.
        !          1452: //--------------------------------------------------------------------------
        !          1453: 
        !          1454: VOID ps_geolinexform(pdev, plineattrs, pxo)
        !          1455: PDEVDATA    pdev;
        !          1456: PLINEATTRS  plineattrs;
        !          1457: XFORMOBJ   *pxo;
        !          1458: {
        !          1459:     ULONG   ulComplexity;
        !          1460:     PS_FIX  psfxM11, psfxM12, psfxM21, psfxM22, psfxdx, psfxdy;
        !          1461: 
        !          1462:     // update the printer's geometric line width.  the line width
        !          1463:     // is given in WORLD coordinates for a geometric line.  it needs
        !          1464:     // to be transformed into DEVICE space.
        !          1465: 
        !          1466:     ulComplexity = XFORMOBJ_iGetXform(pxo, &pdev->cgs.GeoLineXform);
        !          1467: 
        !          1468:     // assume no transform will be done.
        !          1469: 
        !          1470:     pdev->cgs.dwFlags &= ~CGS_GEOLINEXFORM;
        !          1471: 
        !          1472:     switch(ulComplexity)
        !          1473:     {
        !          1474:         case GX_IDENTITY:
        !          1475:             // there will be nothing to do in this case.
        !          1476: 
        !          1477:             break;
        !          1478: 
        !          1479:         case GX_SCALE:
        !          1480:             // output scale command, rather than entire transform.
        !          1481: 
        !          1482:             psfxM11 = ETOPSFX(pdev->cgs.GeoLineXform.eM11);
        !          1483: 
        !          1484:             psfxM22 = ETOPSFX(pdev->cgs.GeoLineXform.eM22);
        !          1485: 
        !          1486:             // save the current CTM, then output the scale command.
        !          1487:             // DrvStrokePath and DrvStrokeAndFillPath are
        !          1488:             // responsible for restoring the CTM.
        !          1489: 
        !          1490:             PrintString(pdev, "CM ");
        !          1491:             PrintPSFIX(pdev, 2, psfxM11, psfxM22);
        !          1492:             PrintString(pdev, " scale\n");
        !          1493: 
        !          1494:             pdev->cgs.dwFlags |= CGS_GEOLINEXFORM;
        !          1495: 
        !          1496:             break;
        !          1497: 
        !          1498:         default:
        !          1499:             // output a general transform.
        !          1500: 
        !          1501:             psfxM11 = ETOPSFX(pdev->cgs.GeoLineXform.eM11);
        !          1502: 
        !          1503:             psfxM12 = ETOPSFX(pdev->cgs.GeoLineXform.eM12);
        !          1504: 
        !          1505:             psfxM21 = ETOPSFX(pdev->cgs.GeoLineXform.eM21);
        !          1506: 
        !          1507:             psfxM22 = ETOPSFX(pdev->cgs.GeoLineXform.eM22);
        !          1508: 
        !          1509:             psfxdx = ETOPSFX(pdev->cgs.GeoLineXform.eDx);
        !          1510: 
        !          1511:             psfxdy = ETOPSFX(pdev->cgs.GeoLineXform.eDy);
        !          1512: 
        !          1513:             // save the current CTM, then output the concat command.
        !          1514:             // DrvStrokePath and DrvStrokeAndFillPath are
        !          1515:             // responsible for restoring the CTM.
        !          1516: 
        !          1517:             PrintString(pdev, "CM ");
        !          1518:             PrintString(pdev, "[");
        !          1519:             PrintPSFIX(pdev, 6, psfxM11, psfxM12, psfxM21, psfxM22,
        !          1520:                        psfxdx, psfxdy);
        !          1521:             PrintString(pdev, "] concat\n");
        !          1522: 
        !          1523:             pdev->cgs.dwFlags |= CGS_GEOLINEXFORM;
        !          1524: 
        !          1525:             break;
        !          1526:     }
        !          1527: }
        !          1528: 
        !          1529: //--------------------------------------------------------------------------
        !          1530: // VOID ps_begin_eps(pdev)
        !          1531: // VOID ps_end_eps(pdev)
        !          1532: //
        !          1533: // These routines are called by the driver to issue commands to bracket EPS
        !          1534: // files to the printer.  They conform to the Guidelines for Importing EPS
        !          1535: // Files version 3.0 by Adobe.
        !          1536: //
        !          1537: // Parameters:
        !          1538: //   pdev:
        !          1539: //     pointer to DEVDATA structure.
        !          1540: //
        !          1541: // Returns:
        !          1542: //   None.
        !          1543: //
        !          1544: // History:
        !          1545: //   Sat May 08 15:15:01 1993          -by-    Hock San Lee    [hockl]
        !          1546: //  Wrote it.
        !          1547: //--------------------------------------------------------------------------
        !          1548: 
        !          1549: PSZ apszEPSProc[] =
        !          1550:     {
        !          1551:     "/BeginEPSF {/b4_Inc_state save def /dict_count countdictstack def",
        !          1552:     "/op_count count 1 sub def userdict begin /showpage {} def",
        !          1553:     "0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin",
        !          1554:     "10 setmiterlimit [] 0 setdash newpath",
        !          1555:     "/languagelevel where {pop languagelevel 1 ne",
        !          1556:     "{false setstrokeadjust false setoverprint} if } if } bind def",
        !          1557:     "/EndEPSF {count op_count sub {pop} repeat",
        !          1558:     "countdictstack dict_count sub {end} repeat b4_Inc_state restore} bind def",
        !          1559:     NULL
        !          1560:     };
        !          1561: 
        !          1562: VOID ps_begin_eps(pdev)
        !          1563: PDEVDATA    pdev;
        !          1564: {
        !          1565:     PSZ        *ppsz;
        !          1566: 
        !          1567:     // emit the EPS procedures if necessary.
        !          1568: 
        !          1569:     if (!(pdev->cgs.dwFlags & CGS_EPS_PROC))
        !          1570:     {
        !          1571:         ppsz = apszEPSProc;
        !          1572:         while (*ppsz)
        !          1573:         {
        !          1574:             PrintString(pdev, *ppsz++);
        !          1575:             PrintString(pdev, "\n");
        !          1576:         }
        !          1577: 
        !          1578:         pdev->cgs.dwFlags |= CGS_EPS_PROC;
        !          1579:     }
        !          1580: 
        !          1581:     PrintString(pdev, "BeginEPSF\n");
        !          1582: }
        !          1583: 
        !          1584: VOID ps_end_eps(pdev)
        !          1585: PDEVDATA    pdev;
        !          1586: {
        !          1587:     if (!(pdev->cgs.dwFlags & CGS_EPS_PROC))
        !          1588:     {
        !          1589:         RIP("PSCRIPT!ps_end_eps: EndEPSF not defined.\n");
        !          1590:     }
        !          1591: 
        !          1592:     PrintString(pdev, "EndEPSF\n");
        !          1593: }

unix.superglobalmegacorp.com

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