|
|
1.1 root 1: //--------------------------------------------------------------------------
2: //
3: // Module Name: PATHS.C
4: //
5: // Brief Description: This module contains the PSCRIPT driver's path
6: // rendering functions and related routines.
7: //
8: // Author: Kent Settle (kentse)
9: // Created: 02-May-1991
10: //
11: // 26-Mar-1992 Thu 23:53:12 updated -by- Daniel Chou (danielc)
12: // add the prclBound parameter to the bDoClipObj()
13: //
14: // Copyright (c) 1991 - 1992 Microsoft Corporation
15: //
16: // This Module contains the following functions:
17: // DrvStrokePath
18: // DrvFillPath
19: // DrvStrokeAndFillPath
20: //--------------------------------------------------------------------------
21:
22: #include "pscript.h"
23: #include "enable.h"
24:
25: extern ULONG PSMonoPalette[];
26: extern ULONG PSColorPalette[];
27:
28: extern BOOL bDoClipObj(PDEVDATA, CLIPOBJ *, RECTL *, RECTL *, BOOL *, BOOL *, DWORD);
29:
30: BOOL DrvCommonPath(PDEVDATA, PATHOBJ *);
31:
32: //--------------------------------------------------------------------------
33: // BOOL DrvStrokePath(pso, ppo, pco, pxo, pbo, pptlBrushOrg, plineattrs, mix)
34: // SURFOBJ *pso;
35: // PATHOBJ *ppo;
36: // CLIPOBJ *pco;
37: // XFORMOBJ *pxo;
38: // BRUSHOBJ *pbo;
39: // PPOINTL pptlBrushOrg;
40: // PLINEATTRS plineattrs;
41: // MIX mix;
42: //
43: //
44: // Parameters:
45: //
46: // Returns:
47: // This function returns TRUE.
48: //
49: // History:
50: // 02-May-1991 -by- Kent Settle [kentse]
51: // Wrote it.
52: //--------------------------------------------------------------------------
53:
54: BOOL DrvStrokePath(pso, ppo, pco, pxo, pbo, pptlBrushOrg, plineattrs, mix)
55: SURFOBJ *pso;
56: PATHOBJ *ppo;
57: CLIPOBJ *pco;
58: XFORMOBJ *pxo;
59: BRUSHOBJ *pbo;
60: PPOINTL pptlBrushOrg;
61: PLINEATTRS plineattrs;
62: MIX mix;
63: {
64: PDEVDATA pdev;
65: BOOL bClipping; // TRUE if there is a clip region.
66: ULONG ulColor;
67: BOOL bMoreClipping; // TRUE if there is more clipping to handle.
68: BOOL bFirstClipPass;
69: #ifdef INDEX_PAL
70: DEVBRUSH *pBrush;
71: ULONG *pulColors;
72: #endif
73: RECTFX rcfxBound;
74: RECTL rclBound;
75:
76: UNREFERENCED_PARAMETER(mix);
77:
78: // get the pointer to our DEVDATA structure and make sure it is ours.
79:
80: pdev = (PDEVDATA) pso->dhpdev;
81:
82: if (bValidatePDEV(pdev) == FALSE)
83: {
84: RIP("PSCRIPT!DrvStrokePath: invalid pdev.\n");
85: SetLastError(ERROR_INVALID_PARAMETER);
86: return(FALSE);
87: }
88:
89: // deal with LINEATTRS.
90:
91: if (!(ps_setlineattrs(pdev, plineattrs, pxo)))
92: return(FALSE);
93:
94: // output the line color to stroke with. do this before we handle
95: // clipping, so the line color will remain beyond the gsave/grestore.
96:
97: #ifdef INDEX_PAL
98: // just output the solid color if there is one.
99:
100: if ((pdev->pntpd->flFlags & COLOR_DEVICE) &&
101: (pdev->psdm.dm.dmColor == DMCOLOR_COLOR))
102: pulColors = PSColorPalette;
103: else
104: pulColors = PSMonoPalette;
105:
106: if (pbo->iSolidColor != NOT_SOLID_COLOR)
107: {
108: ps_setrgbcolor(pdev, (PALETTEENTRY *)pulColors + pbo->iSolidColor);
109: }
110: else
111: {
112: // get the device brush to draw with.
113:
114: pBrush = (DEVBRUSH *)BRUSHOBJ_pvGetRbrush(pbo);
115:
116: if (!pBrush)
117: {
118: #if DBG
119: DbgPrint("DrvStrokePath: NULL pBrush.\n");
120: #endif
121: // something is wrong! just output black path.
122:
123: ulColor = RGB_BLACK;
124: ps_setrgbcolor(pdev, (PALETTEENTRY *)&ulColor);
125: }
126: else
127: {
128: if (pBrush->iSolidColor == NOT_SOLID_COLOR)
129: {
130: // get the foreground color.
131:
132: ps_setrgbcolor(pdev, ((PALETTEENTRY *)pulColors +
133: *(ULONG *)((PBYTE)pBrush + pBrush->offsetXlate +
134: sizeof(ULONG))));
135: }
136: else
137: {
138: ps_setrgbcolor(pdev, (PALETTEENTRY *)&pBrush->iSolidColor);
139: }
140: }
141: }
142: #else
143: if (pbo->iSolidColor == NOT_SOLID_COLOR)
144: {
145: //!!! this needs to be fixed!!! -kentse.
146: ulColor = RGB_GRAY;
147:
148: ps_setrgbcolor(pdev, (BGR_PAL_ENTRY *)&ulColor);
149: }
150: else
151: {
152: // we have a solid brush, so simply output the line color.
153:
154: ps_setrgbcolor(pdev, (BGR_PAL_ENTRY *)&pbo->iSolidColor);
155: }
156: #endif
157:
158: // get the bounding rectangle for the path. this is used to checked
159: // against the clipping for optimization.
160:
161: PATHOBJ_vGetBounds(ppo, &rcfxBound);
162:
163: // get a RECTL which is guaranteed to bound the path.
164:
165: rclBound.left = FXTOL(rcfxBound.xLeft);
166: rclBound.top = FXTOL(rcfxBound.yTop);
167: rclBound.right = FXTOL(rcfxBound.xRight + FIX_ONE);
168: rclBound.bottom = FXTOL(rcfxBound.yBottom + FIX_ONE);
169:
170: bMoreClipping = TRUE;
171: bFirstClipPass = TRUE;
172:
173: while (bMoreClipping)
174: {
175: // handle the clipping.
176:
177: if (bClipping = bDoClipObj(pdev, pco, NULL, &rclBound, &bMoreClipping,
178: &bFirstClipPass, MAX_CLIP_RECTS))
179: ps_clip(pdev, TRUE);
180:
181: if (!(DrvCommonPath(pdev, ppo)))
182: return(FALSE);
183:
184: // now transform for geometric lines if necessary.
185:
186: if (plineattrs->fl & LA_GEOMETRIC)
187: ps_geolinexform(pdev, plineattrs, pxo);
188:
189: // now stroke the path.
190:
191: ps_stroke(pdev, pbo, pptlBrushOrg);
192:
193: // restore the CTM if a transform for a geometric line was in effect.
194:
195: if (pdev->cgs.dwFlags & CGS_GEOLINEXFORM)
196: {
197: PrintString(pdev, "SM\n");
198: pdev->cgs.dwFlags &= ~CGS_GEOLINEXFORM;
199: }
200:
201: // restore the clip path to what it was before this call.
202:
203: if (bClipping)
204: ps_restore(pdev, TRUE);
205: }
206:
207: return(TRUE);
208: }
209:
210:
211: //--------------------------------------------------------------------------
212: // BOOL DrvFillPath(pso, ppo, pco, pbo, pptlBrushOrg, mix, flOptions)
213: // SURFOBJ *pso;
214: // PATHOBJ *ppo;
215: // CLIPOBJ *pco;
216: // BRUSHOBJ *pbo;
217: // PPOINTL pptlBrushOrg;
218: // MIX mix;
219: // FLONG flOptions;
220: //
221: // Parameters:
222: //
223: // Returns:
224: // This function returns TRUE.
225: //
226: // History:
227: // 03-May-1991 -by- Kent Settle [kentse]
228: // Wrote it.
229: //--------------------------------------------------------------------------
230:
231: BOOL DrvFillPath(pso, ppo, pco, pbo, pptlBrushOrg, mix, flOptions)
232: SURFOBJ *pso;
233: PATHOBJ *ppo;
234: CLIPOBJ *pco;
235: BRUSHOBJ *pbo;
236: PPOINTL pptlBrushOrg;
237: MIX mix;
238: FLONG flOptions;
239: {
240: PDEVDATA pdev;
241: RECTL rclBounds;
242: RECTFX rcfxBounds;
243: BOOL bClipping;
244: BOOL bMoreClipping;
245: BOOL bFirstClipPass;
246:
247: // get the pointer to our DEVDATA structure and make sure it is ours.
248:
249: pdev = (PDEVDATA) pso->dhpdev;
250:
251: if (bValidatePDEV(pdev) == FALSE)
252: return(FALSE);
253:
254: bMoreClipping = TRUE;
255: bFirstClipPass = TRUE;
256:
257: while (bMoreClipping)
258: {
259: // get the bounding rectangle of the path to pass to ps_patfill.
260:
261: PATHOBJ_vGetBounds(ppo, &rcfxBounds);
262:
263: rclBounds.left = FXTOL(rcfxBounds.xLeft);
264: rclBounds.right = FXTOL(rcfxBounds.xRight) + 1;
265: rclBounds.top = FXTOL(rcfxBounds.yTop);
266: rclBounds.bottom = FXTOL(rcfxBounds.yBottom) + 1;
267:
268: // if there is a clip region, clip to it. we want to keep this
269: // separate from the clip path.
270:
271: if (bClipping = bDoClipObj(pdev, pco, NULL, &rclBounds, &bMoreClipping,
272: &bFirstClipPass, MAX_CLIP_RECTS))
273: {
274: if (flOptions & FP_WINDINGMODE)
275: ps_clip(pdev, TRUE);
276: else
277: ps_clip(pdev, FALSE);
278: }
279:
280: // if there was no clip region, we need to output a gsave before we
281: // send the clip path, so we can blow it away when we are done.
282:
283: if (!bClipping)
284: ps_save(pdev, TRUE);
285:
286: if (!(DrvCommonPath(pdev, ppo)))
287: {
288: RIP("PSCRIPT!DrvFillPath: invalid pdev.\n");
289: SetLastError(ERROR_INVALID_PARAMETER);
290: return(FALSE);
291: }
292:
293: // now fill the path.
294:
295: if (!ps_patfill(pdev, pso, flOptions, pbo, pptlBrushOrg, mix, &rclBounds,
296: FALSE, TRUE))
297: return(FALSE);
298:
299: ps_restore(pdev, TRUE);
300: }
301:
302: return(TRUE);
303: }
304:
305:
306: //--------------------------------------------------------------------------
307: // BOOL DrvStrokeAndFillPath(pso, ppo, pco, pxo, pboStroke, plineattrs,
308: // pboFill, pptlBrushOrg, mixFill, flOptions)
309: // SURFOBJ *pso;
310: // PATHOBJ *ppo;
311: // CLIPOBJ *pco;
312: // XFORMOBJ *pxo;
313: // BRUSHOBJ *pboStroke;
314: // PLINEATTRS plineattrs;
315: // BRUSHOBJ *pboFill;
316: // PPOINTL pptlBrushOrg;
317: // MIX mixFill;
318: // FLONG flOptions;
319: //
320: // Parameters:
321: //
322: // Returns:
323: // This function returns TRUE.
324: //
325: // History:
326: // 03-May-1991 -by- Kent Settle [kentse]
327: // Wrote it.
328: //--------------------------------------------------------------------------
329:
330: BOOL DrvStrokeAndFillPath(pso, ppo, pco, pxo, pboStroke, plineattrs,
331: pboFill, pptlBrushOrg, mixFill, flOptions)
332: SURFOBJ *pso;
333: PATHOBJ *ppo;
334: CLIPOBJ *pco;
335: XFORMOBJ *pxo;
336: BRUSHOBJ *pboStroke;
337: PLINEATTRS plineattrs;
338: BRUSHOBJ *pboFill;
339: PPOINTL pptlBrushOrg;
340: MIX mixFill;
341: FLONG flOptions;
342: {
343: PDEVDATA pdev;
344: RECTL rclBounds;
345: RECTFX rcfxBounds;
346: BOOL bClipping;
347: ULONG ulColor;
348: BOOL bMoreClipping;
349: BOOL bFirstClipPass;
350: #ifdef INDEX_PAL
351: DEVBRUSH *pBrush;
352: ULONG *pulColors;
353: #endif
354:
355: // get the pointer to our DEVDATA structure and make sure it is ours.
356:
357: pdev = (PDEVDATA) pso->dhpdev;
358:
359: if (bValidatePDEV(pdev) == FALSE)
360: return(FALSE);
361:
362: // deal with LINEATTRS.
363:
364: if (!(ps_setlineattrs(pdev, plineattrs, pxo)))
365: return(FALSE);
366:
367: // output the line color to stroke with. do this before we handle
368: // clipping, so the line color will remain beyond the gsave/grestore.
369:
370: #ifdef INDEX_PAL
371: // just output solid color if there is one.
372:
373: if ((pdev->pntpd->flFlags & COLOR_DEVICE) &&
374: (pdev->psdm.dm.dmColor == DMCOLOR_COLOR))
375: pulColors = PSColorPalette;
376: else
377: pulColors = PSMonoPalette;
378:
379: if (pboStroke->iSolidColor != NOT_SOLID_COLOR)
380: {
381: ps_setrgbcolor(pdev, (PALETTEENTRY *)pulColors + pboStroke->iSolidColor);
382: }
383: else
384: {
385: // get the device brush to draw with.
386:
387: pBrush = (DEVBRUSH *)BRUSHOBJ_pvGetRbrush(pboStroke);
388:
389: if (!pBrush)
390: {
391: #if DBG
392: DbgPrint("DrvStrokeAndFillPath: NULL pBrush.\n");
393: #endif
394: // something is wrong! stroke with black.
395:
396: ulColor = RGB_BLACK;
397: ps_setrgbcolor(pdev, (PALETTEENTRY *)&ulColor);
398: }
399: else
400: {
401: if (pBrush->iSolidColor == NOT_SOLID_COLOR)
402: {
403: // get the foreground color.
404:
405: ps_setrgbcolor(pdev, ((PALETTEENTRY *)pulColors +
406: *(ULONG *)((PBYTE)pBrush + pBrush->offsetXlate +
407: sizeof(ULONG))));
408: }
409: else
410: {
411: ps_setrgbcolor(pdev, (PALETTEENTRY *)&pBrush->iSolidColor);
412: }
413: }
414: }
415: #else
416: if (pboStroke->iSolidColor == NOT_SOLID_COLOR)
417: {
418: //!!! this needs to be fixed!!! -kentse.
419: ulColor = RGB_GRAY;
420:
421: ps_setrgbcolor(pdev, (BGR_PAL_ENTRY *)&ulColor);
422: }
423: else
424: {
425: // we have a solid brush, so simply output the line color.
426:
427: ps_setrgbcolor(pdev, (BGR_PAL_ENTRY *)&pboStroke->iSolidColor);
428: }
429: #endif
430:
431: bMoreClipping = TRUE;
432: bFirstClipPass = TRUE;
433:
434: while (bMoreClipping)
435: {
436: // get the bounding rectangle of the path to pass to ps_patfill.
437:
438: PATHOBJ_vGetBounds(ppo, &rcfxBounds);
439:
440: rclBounds.left = FXTOL(rcfxBounds.xLeft);
441: rclBounds.right = FXTOL(rcfxBounds.xRight) + 1;
442: rclBounds.top = FXTOL(rcfxBounds.yTop);
443: rclBounds.bottom = FXTOL(rcfxBounds.yBottom) + 1;
444:
445: // if there is a clip region, clip to it. we want to keep this
446: // separate from the clip path.
447:
448: if (bClipping = bDoClipObj(pdev, pco, NULL, &rclBounds, &bMoreClipping,
449: &bFirstClipPass, MAX_CLIP_RECTS))
450: {
451: if (flOptions & FP_WINDINGMODE)
452: ps_clip(pdev, TRUE);
453: else
454: ps_clip(pdev, FALSE);
455: }
456:
457: // if there was no clip region, we need to output a gsave before we
458: // send the clip path, so we can blow it away when we are done.
459:
460: if (!bClipping)
461: ps_save(pdev, TRUE);
462:
463: if (!(DrvCommonPath(pdev, ppo)))
464: {
465: RIP("PSCRIPT!DrvStrokeAndFillPath: invalid pdev.\n");
466: SetLastError(ERROR_INVALID_PARAMETER);
467: return(FALSE);
468: }
469:
470: // save the path. then fill it. then restore the path which
471: // was wiped out when it was filled so we can stroke it. TRUE
472: // means to do a gsave, not a save command.
473:
474: if (!ps_save(pdev, TRUE))
475: return(FALSE);
476:
477: if (!ps_patfill(pdev, pso, flOptions, pboFill, pptlBrushOrg, mixFill,
478: &rclBounds, FALSE, TRUE))
479: return(FALSE);
480:
481: if (!ps_restore(pdev, TRUE))
482: return(FALSE);
483:
484: // now transform for geometric lines if necessary.
485:
486: if (plineattrs->fl & LA_GEOMETRIC)
487: ps_geolinexform(pdev, plineattrs, pxo);
488:
489: // now stroke the path. remember that ps_patfill will have marked that
490: // the path no longer exists. since we surrounded it with gsave -
491: // grestore, we know otherwise.
492:
493: pdev->cgs.dwFlags |= CGS_PATHEXISTS;
494: ps_stroke(pdev, pboStroke, pptlBrushOrg);
495:
496: // restore the CTM if a transform for a geometric line was in effect.
497:
498: if (pdev->cgs.dwFlags & CGS_GEOLINEXFORM)
499: {
500: PrintString(pdev, "SM\n");
501: pdev->cgs.dwFlags &= ~CGS_GEOLINEXFORM;
502: }
503:
504: ps_restore(pdev, TRUE);
505: }
506:
507: return(TRUE);
508: }
509:
510:
511: //--------------------------------------------------------------------------
512: // BOOL DrvCommonPath(pdev, ppo)
513: // PDEVDATA pdev;
514: // PATHOBJ *ppo;
515: //
516: //
517: // Parameters:
518: //
519: // Returns:
520: // This function returns TRUE.
521: //
522: // History:
523: // 02-May-1991 -by- Kent Settle [kentse]
524: // Wrote it.
525: //--------------------------------------------------------------------------
526:
527: BOOL DrvCommonPath(pdev, ppo)
528: PDEVDATA pdev;
529: PATHOBJ *ppo;
530: {
531: PATHDATA pathdata;
532: POINTL ptl, ptl1, ptl2;
533: POINTFIX *pptfx;
534: LONG cPoints;
535: BOOL bMore;
536:
537: // before we enumerate the path, let's make sure we have a clean start.
538:
539: ps_newpath(pdev);
540:
541: // enumerate the path, doing what needs to be done along the way.
542:
543: PATHOBJ_vEnumStart(ppo);
544:
545: do
546: {
547: bMore = PATHOBJ_bEnum(ppo, &pathdata);
548:
549: // get a local pointer to the array of POINTFIX's.
550:
551: pptfx = pathdata.pptfx;
552: cPoints = (LONG)pathdata.count;
553:
554: if (pathdata.flags & PD_BEGINSUBPATH)
555: {
556: // the first path begins a new subpath. it is not connected
557: // to the previous subpath. note that if this flag is not
558: // set, then the starting point for the first curve to be
559: // drawn from this data is the last point returned in the
560: // previous call.
561:
562: #if 0
563: if (pathdata.flags & PD_RESETSTYLE)
564: {
565: // this bit is defined only if this record begins a new
566: // subpath. if set, it indicates that the style state
567: // should be reset to zero at the beginning of the subpath.
568: // if not set, the style state is defined by the
569: // LINEATTRS, or continues from the previous path.
570:
571: #if DBG
572: DbgPrint("DrvCommonPath: PD_RESETSTYLE flag set.\n");
573: #endif
574: //!!! fill in here - kentse
575: }
576: #endif
577:
578: // begin the subpath within the printer by issuing a moveto
579: // command.
580:
581: ptl.x = FXTOL(pptfx->x);
582: ptl.y = FXTOL(pptfx->y);
583: pptfx++;
584: cPoints--;
585:
586: ps_moveto(pdev, &ptl);
587: }
588:
589: if (pathdata.flags & PD_BEZIERS)
590: {
591: // if set, then each set of three control points returned for
592: // this call describe a Bezier curve. if clear then each
593: // control point describes a line segment. a starting point
594: // for either type is either explicit at the beginning of the
595: // subpath, or implicit as the endpoint of the previous curve.
596:
597: // there had better be the correct number of points if we are
598: // going to draw curves.
599:
600: if ((cPoints % 3) != 0)
601: {
602: RIP("PSCRIPT!DrvCommonPath: incompatible number of points.\n");
603: SetLastError(ERROR_INVALID_PARAMETER);
604: return(FALSE);
605: }
606:
607: // now draw the bezier for each set of points.
608:
609: while (cPoints > 0)
610: {
611: ptl.x = FXTOL(pptfx->x);
612: ptl.y = FXTOL(pptfx->y);
613: pptfx++;
614: ptl1.x = FXTOL(pptfx->x);
615: ptl1.y = FXTOL(pptfx->y);
616: pptfx++;
617: ptl2.x = FXTOL(pptfx->x);
618: ptl2.y = FXTOL(pptfx->y);
619: pptfx++;
620:
621: ps_curveto(pdev, &ptl, &ptl1, &ptl2);
622: cPoints -= 3;
623: }
624: }
625: else
626: {
627: // draw the line segment for each point.
628:
629: while (cPoints-- > 0)
630: {
631: ptl.x = FXTOL(pptfx->x);
632: ptl.y = FXTOL(pptfx->y);
633: pptfx++;
634:
635: ps_lineto(pdev, &ptl);
636: }
637: }
638: } while(bMore);
639:
640: if (pathdata.flags & PD_ENDSUBPATH)
641: {
642: // the last point in the array ends the subpath. this subpath
643: // may be open or closed depending on the PD_CLOSEFIGURE flag.
644: // if there is more data to be returned in the path, then the
645: // next record will begin a new subpath. note that a single
646: // record might begin and end a subpath.
647:
648: if (pathdata.flags & PD_CLOSEFIGURE)
649: {
650: // this bit is only defined if the record ends a subpath. if
651: // set, then there is an implicit line segment connecting
652: // the last point of the subpath with the first point. if
653: // such a closed subpath is being stroked, then joins are used
654: // all around the path, and there are no end caps. if this
655: // flag is not set then the subpath is considered open, even
656: // if the first and last points happen to be coincident. in
657: // that case, end caps should be drawn. this flag is not
658: // relevant for filling, since all subpaths are assumed closed
659: // when a path is filled.
660:
661: ps_closepath(pdev);
662: }
663: }
664:
665: return(TRUE);
666: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.