|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.