|
|
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.