|
|
1.1 ! root 1: /*********************************************************** ! 2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, ! 3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts. ! 4: ! 5: All Rights Reserved ! 6: ! 7: Permission to use, copy, modify, and distribute this software and its ! 8: documentation for any purpose and without fee is hereby granted, ! 9: provided that the above copyright notice appear in all copies and that ! 10: both that copyright notice and this permission notice appear in ! 11: supporting documentation, and that the names of Digital or MIT not be ! 12: used in advertising or publicity pertaining to distribution of the ! 13: software without specific, written prior permission. ! 14: ! 15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 21: SOFTWARE. ! 22: ! 23: ******************************************************************/ ! 24: /* $Header: mfbline.c,v 1.34 87/09/11 07:21:06 toddb Exp $ */ ! 25: #include "X.h" ! 26: ! 27: #include "gcstruct.h" ! 28: #include "windowstr.h" ! 29: #include "pixmapstr.h" ! 30: #include "regionstr.h" ! 31: #include "scrnintstr.h" ! 32: #include "mistruct.h" ! 33: ! 34: #include "mfb.h" ! 35: #include "maskbits.h" ! 36: ! 37: /* single-pixel lines on a monochrome frame buffer ! 38: ! 39: NON-SLOPED LINES ! 40: horizontal lines are always drawn left to right; we have to ! 41: move the endpoints right by one after they're swapped. ! 42: horizontal lines will be confined to a single band of a ! 43: region. the code finds that band (giving up if the lower ! 44: bound of the band is above the line we're drawing); then it ! 45: finds the first box in that band that contains part of the ! 46: line. we clip the line to subsequent boxes in that band. ! 47: vertical lines are always drawn top to bottom (y-increasing.) ! 48: this requires adding one to the y-coordinate of each endpoint ! 49: after swapping. ! 50: ! 51: SLOPED LINES ! 52: when clipping a sloped line, we bring the second point inside ! 53: the clipping box, rather than one beyond it, and then add 1 to ! 54: the length of the line before drawing it. this lets us use ! 55: the same box for finding the outcodes for both endpoints. since ! 56: the equation for clipping the second endpoint to an edge gives us ! 57: 1 beyond the edge, we then have to move the point towards the ! 58: first point by one step on the major axis. ! 59: eventually, there will be a diagram here to explain what's going ! 60: on. the method uses Cohen-Sutherland outcodes to determine ! 61: outsideness, and a method similar to Pike's layers for doing the ! 62: actual clipping. ! 63: ! 64: DIVISION ! 65: When clipping the lines, we want to round the answer, rather ! 66: than truncating. We want to avoid floating point; we also ! 67: want to avoid the special code required when the dividend ! 68: and divisor have different signs. ! 69: ! 70: we work a little to make all the numbers in the division ! 71: positive. we then use the signs of the major and minor axes ! 72: decide whether to add or subtract. this takes the special-case ! 73: code out of the rounding division (making it easier for a ! 74: compiler or inline to do something clever). ! 75: ! 76: CEILING ! 77: someties, we want the ceiling. ceil(m/n) == floor((m+n-1)/n), ! 78: for n > 0. in C, integer division results in floor.] ! 79: ! 80: MULTIPLICATION ! 81: when multiplying by signdx or signdy, we KNOW that it will ! 82: be a multiplication by 1 or -1, but most compilers can't ! 83: figure this out. if your compiler/hardware combination ! 84: does better at the ?: operator and 'move negated' instructions ! 85: that it does at multiplication, you should consider using ! 86: the alternate macros. ! 87: ! 88: OPTIMIZATION ! 89: there has been no attempt to optimize this code. there ! 90: are obviously many special cases, at the cost of increased ! 91: code space. a few inline procedures (e.g. round, SignTimes, ! 92: ceiling, abs) would be very useful, since the macro expansions ! 93: are not very intelligent. ! 94: */ ! 95: ! 96: /* NOTE ! 97: maybe OUTCODES should take box (the one that includes all ! 98: edges) instead of pbox (the standard no-right-or-lower-edge one)? ! 99: */ ! 100: #define OUTCODES(result, x, y, pbox) \ ! 101: if (x < pbox->x1) \ ! 102: result |= OUT_LEFT; \ ! 103: if (y < pbox->y1) \ ! 104: result |= OUT_ABOVE; \ ! 105: if (x >= pbox->x2) \ ! 106: result |= OUT_RIGHT; \ ! 107: if (y >= pbox->y2) \ ! 108: result |= OUT_BELOW; ! 109: ! 110: #define round(dividend, divisor) \ ! 111: ( (((dividend)<<1) + (divisor)) / ((divisor)<<1) ) ! 112: ! 113: #define ceiling(m,n) ( ((m) + (n) -1)/(n) ) ! 114: ! 115: #define SignTimes(sign, n) ((sign) * (n)) ! 116: ! 117: /* ! 118: #define SignTimes(sign, n) \ ! 119: ( ((sign)<0) ? -(n) : (n) ) ! 120: */ ! 121: ! 122: #define SWAPPT(p1, p2, pttmp) \ ! 123: pttmp = p1; \ ! 124: p1 = p2; \ ! 125: p2 = pttmp; ! 126: ! 127: #define SWAPINT(i, j, t) \ ! 128: t = i; \ ! 129: i = j; \ ! 130: j = t; ! 131: ! 132: void ! 133: mfbLineSS(pDrawable, pGC, mode, npt, pptInit) ! 134: DrawablePtr pDrawable; ! 135: GCPtr pGC; ! 136: int mode; /* Origin or Previous */ ! 137: int npt; /* number of points */ ! 138: DDXPointPtr pptInit; ! 139: { ! 140: int nboxInit; ! 141: register int nbox; ! 142: BoxPtr pboxInit; ! 143: register BoxPtr pbox; ! 144: int nptTmp; ! 145: DDXPointPtr ppt; /* pointer to list of translated points */ ! 146: ! 147: DDXPointRec pt1; ! 148: DDXPointRec pt2; ! 149: ! 150: unsigned int oc1; /* outcode of point 1 */ ! 151: unsigned int oc2; /* outcode of point 2 */ ! 152: ! 153: int *addrl; /* address of longword with first point */ ! 154: int nlwidth; /* width in longwords of destination bitmap */ ! 155: int xorg, yorg; /* origin of window */ ! 156: ! 157: int adx; /* abs values of dx and dy */ ! 158: int ady; ! 159: int signdx; /* sign of dx and dy */ ! 160: int signdy; ! 161: int e, e1, e2; /* bresenham error and increments */ ! 162: int len; /* length of segment */ ! 163: int axis; /* major axis */ ! 164: ! 165: int clipDone; /* flag for clipping loop */ ! 166: DDXPointRec pt1Orig; /* unclipped start point */ ! 167: DDXPointRec pt2Orig; /* unclipped end point */ ! 168: int err; /* modified bresenham error term */ ! 169: int clip1, clip2; /* clippedness of the endpoints */ ! 170: ! 171: int clipdx, clipdy; /* difference between clipped and ! 172: unclipped start point */ ! 173: ! 174: /* a bunch of temporaries */ ! 175: int tmp; ! 176: int x1, x2, y1, y2; ! 177: ! 178: pboxInit = ((mfbPrivGC *)(pGC->devPriv))->pCompositeClip->rects; ! 179: nboxInit = ((mfbPrivGC *)(pGC->devPriv))->pCompositeClip->numRects; ! 180: ! 181: if (pDrawable->type == DRAWABLE_WINDOW) ! 182: { ! 183: xorg = ((WindowPtr)pDrawable)->absCorner.x; ! 184: yorg = ((WindowPtr)pDrawable)->absCorner.y; ! 185: addrl = (int *) ! 186: (((PixmapPtr)(pDrawable->pScreen->devPrivate))->devPrivate); ! 187: nlwidth = (int) ! 188: (((PixmapPtr)(pDrawable->pScreen->devPrivate))->devKind) >> 2; ! 189: } ! 190: else ! 191: { ! 192: xorg = 0; ! 193: yorg = 0; ! 194: addrl = (int *)(((PixmapPtr)pDrawable)->devPrivate); ! 195: nlwidth = (int)(((PixmapPtr)pDrawable)->devKind) >> 2; ! 196: } ! 197: ! 198: /* translate the point list */ ! 199: ppt = pptInit; ! 200: nptTmp = npt; ! 201: if (mode == CoordModeOrigin) ! 202: { ! 203: while(nptTmp--) ! 204: { ! 205: ppt->x += xorg; ! 206: ppt++->y += yorg; ! 207: } ! 208: } ! 209: else ! 210: { ! 211: ppt->x += xorg; ! 212: ppt->y += yorg; ! 213: nptTmp--; ! 214: while(nptTmp--) ! 215: { ! 216: ppt++; ! 217: ppt->x += (ppt-1)->x; ! 218: ppt->y += (ppt-1)->y; ! 219: } ! 220: } ! 221: ! 222: ppt = pptInit; ! 223: while(--npt) ! 224: { ! 225: nbox = nboxInit; ! 226: pbox = pboxInit; ! 227: ! 228: pt1 = *ppt++; ! 229: pt2 = *ppt; ! 230: ! 231: if (pt1.x == pt2.x) ! 232: { ! 233: /* make the line go top to bottom of screen, keeping ! 234: endpoint semantics ! 235: */ ! 236: if (pt1.y > pt2.y) ! 237: { ! 238: tmp = pt2.y; ! 239: pt2.y = pt1.y + 1; ! 240: pt1.y = tmp + 1; ! 241: } ! 242: ! 243: /* get to first band that might contain part of line */ ! 244: while ((nbox) && (pbox->y2 <= pt1.y)) ! 245: { ! 246: pbox++; ! 247: nbox--; ! 248: } ! 249: ! 250: if (nbox) ! 251: { ! 252: /* stop when lower edge of box is beyond end of line */ ! 253: while((nbox) && (pt2.y >= pbox->y1)) ! 254: { ! 255: if ((pt1.x >= pbox->x1) && (pt1.x < pbox->x2)) ! 256: { ! 257: /* this box has part of the line in it */ ! 258: y1 = max(pt1.y, pbox->y1); ! 259: y2 = min(pt2.y, pbox->y2); ! 260: if (y1 != y2) ! 261: { ! 262: mfbVertS( ((mfbPrivGC *)(pGC->devPriv))->rop, ! 263: addrl, nlwidth, ! 264: pt1.x, y1, y2-y1); ! 265: } ! 266: } ! 267: nbox--; ! 268: pbox++; ! 269: } ! 270: } ! 271: ! 272: } ! 273: else if (pt1.y == pt2.y) ! 274: { ! 275: /* force line from left to right, keeping ! 276: endpoint semantics ! 277: */ ! 278: if (pt1.x > pt2.x) ! 279: { ! 280: tmp = pt2.x; ! 281: pt2.x = pt1.x + 1; ! 282: pt1.x = tmp + 1; ! 283: } ! 284: ! 285: /* find the correct band */ ! 286: while( (nbox) && (pbox->y2 <= pt1.y)) ! 287: { ! 288: pbox++; ! 289: nbox--; ! 290: } ! 291: ! 292: /* try to draw the line, if we haven't gone beyond it */ ! 293: if ((nbox) && (pbox->y1 <= pt1.y)) ! 294: { ! 295: /* when we leave this band, we're done */ ! 296: tmp = pbox->y1; ! 297: while((nbox) && (pbox->y1 == tmp)) ! 298: { ! 299: if (pbox->x2 <= pt1.x) ! 300: { ! 301: /* skip boxes until one might contain start point */ ! 302: nbox--; ! 303: pbox++; ! 304: continue; ! 305: } ! 306: ! 307: /* stop if left of box is beyond right of line */ ! 308: if (pbox->x1 >= pt2.x) ! 309: { ! 310: nbox = 0; ! 311: continue; ! 312: } ! 313: ! 314: x1 = max(pt1.x, pbox->x1); ! 315: x2 = min(pt2.x, pbox->x2); ! 316: if (x1 != x2) ! 317: { ! 318: mfbHorzS( ((mfbPrivGC *)(pGC->devPriv))->rop, ! 319: addrl, nlwidth, ! 320: x1, pt1.y, x2-x1); ! 321: } ! 322: nbox--; ! 323: pbox++; ! 324: } ! 325: } ! 326: } ! 327: else /* sloped line */ ! 328: { ! 329: ! 330: adx = pt2.x - pt1.x; ! 331: ady = pt2.y - pt1.y; ! 332: signdx = sign(adx); ! 333: signdy = sign(ady); ! 334: adx = abs(adx); ! 335: ady = abs(ady); ! 336: ! 337: if (adx > ady) ! 338: { ! 339: axis = X_AXIS; ! 340: e1 = ady*2; ! 341: e2 = e1 - 2*adx; ! 342: e = e1 - adx; ! 343: ! 344: } ! 345: else ! 346: { ! 347: axis = Y_AXIS; ! 348: e1 = adx*2; ! 349: e2 = e1 - 2*ady; ! 350: e = e1 - ady; ! 351: } ! 352: ! 353: /* we have bresenham parameters and two points. ! 354: all we have to do now is clip and draw. ! 355: */ ! 356: ! 357: pt1Orig = pt1; ! 358: pt2Orig = pt2; ! 359: ! 360: while(nbox--) ! 361: { ! 362: ! 363: BoxRec box; ! 364: ! 365: pt1 = pt1Orig; ! 366: pt2 = pt2Orig; ! 367: clipDone = 0; ! 368: box.x1 = pbox->x1; ! 369: box.y1 = pbox->y1; ! 370: box.x2 = pbox->x2-1; ! 371: box.y2 = pbox->y2-1; ! 372: clip1 = 0; ! 373: clip2 = 0; ! 374: ! 375: oc1 = 0; ! 376: oc2 = 0; ! 377: OUTCODES(oc1, pt1.x, pt1.y, pbox); ! 378: OUTCODES(oc2, pt2.x, pt2.y, pbox); ! 379: ! 380: if (oc1 & oc2) ! 381: clipDone = -1; ! 382: else if ((oc1 | oc2) == 0) ! 383: clipDone = 1; ! 384: else /* have to clip */ ! 385: clipDone = mfbClipLine(pbox, box, ! 386: &pt1Orig, &pt1, &pt2, ! 387: adx, ady, signdx, signdy, axis, ! 388: &clip1, &clip2); ! 389: ! 390: if (clipDone == -1) ! 391: { ! 392: pbox++; ! 393: } ! 394: else ! 395: { ! 396: ! 397: if (axis == X_AXIS) ! 398: len = abs(pt2.x - pt1.x); ! 399: else ! 400: len = abs(pt2.y - pt1.y); ! 401: ! 402: len += (clip2 != 0); ! 403: if (len) ! 404: { ! 405: /* unwind bresenham error term to first point */ ! 406: if (clip1) ! 407: { ! 408: clipdx = abs(pt1.x - pt1Orig.x); ! 409: clipdy = abs(pt1.y - pt1Orig.y); ! 410: if (axis == X_AXIS) ! 411: err = e+((clipdy*e2) + ((clipdx-clipdy)*e1)); ! 412: else ! 413: err = e+((clipdx*e2) + ((clipdy-clipdx)*e1)); ! 414: } ! 415: else ! 416: err = e; ! 417: mfbBresS( ((mfbPrivGC *)(pGC->devPriv))->rop, ! 418: addrl, nlwidth, ! 419: signdx, signdy, axis, pt1.x, pt1.y, ! 420: err, e1, e2, len); ! 421: } ! 422: ! 423: /* if segment is unclipped, skip remaining rectangles */ ! 424: if (!(clip1 || clip2)) ! 425: break; ! 426: else ! 427: pbox++; ! 428: } ! 429: } /* while (nbox--) */ ! 430: } /* sloped line */ ! 431: } /* while (nline--) */ ! 432: ! 433: /* paint the last point if the end style isn't CapNotLast. ! 434: (Assume that a projecting, butt, or round cap that is one ! 435: pixel wide is the same as the single pixel of the endpoint.) ! 436: */ ! 437: ! 438: if ((pGC->capStyle != CapNotLast) && ! 439: ((ppt->x != pptInit->x) || ! 440: (ppt->y != pptInit->y))) ! 441: { ! 442: pt1 = *ppt; ! 443: ! 444: nbox = nboxInit; ! 445: pbox = pboxInit; ! 446: while (nbox--) ! 447: { ! 448: if ((pt1.x >= pbox->x1) && ! 449: (pt1.y >= pbox->y1) && ! 450: (pt1.x < pbox->x2) && ! 451: (pt1.y < pbox->y2)) ! 452: { ! 453: addrl += (pt1.y * nlwidth) + (pt1.x >> 5); ! 454: switch( ((mfbPrivGC *)(pGC->devPriv))->rop) ! 455: { ! 456: case RROP_BLACK: ! 457: *addrl &= rmask[pt1.x & 0x1f]; ! 458: break; ! 459: case RROP_WHITE: ! 460: *addrl |= mask[pt1.x & 0x1f]; ! 461: break; ! 462: case RROP_INVERT: ! 463: *addrl ^= mask[pt1.x & 0x1f]; ! 464: break; ! 465: } ! 466: break; ! 467: } ! 468: else ! 469: pbox++; ! 470: } ! 471: } ! 472: } ! 473: ! 474: ! 475: /* ! 476: this code does not pretend to be efficient, but it does recycle a ! 477: lot of the line code and use the miDashLine() code too. a better ! 478: implementation is to use the solid line code to clip and ! 479: translate, and then call mfbBresD(), to do the dashes as the ! 480: line is drawn. a Bres() procedure entry in the devPrivate ! 481: part of the GC would make this easy to do, as well as possibly speeding ! 482: up solid lines to (by avoiding the test of rrop for each segment.) ! 483: ! 484: to do double dashes we concoct a rop for the (alu, bg) pair. ! 485: ! 486: the error term at the start of each dash is computed for us by ! 487: miDashLine. if the segment we draw is not clipped, we can use this ! 488: error term; if the first point of the dash is clipped, we have to ! 489: calculate a new error term based on e at the first point of the line. ! 490: */ ! 491: ! 492: void ! 493: mfbDashLine( pDrawable, pGC, mode, npt, pptInit) ! 494: DrawablePtr pDrawable; ! 495: GCPtr pGC; ! 496: int mode; /* Origin or Previous */ ! 497: int npt; /* number of points */ ! 498: DDXPointPtr pptInit; ! 499: { ! 500: int nseg; /* number of dashed segments */ ! 501: miDashPtr pdash; /* list of dashes */ ! 502: miDashPtr pdashInit; ! 503: int fgRop; /* reduced rasterop for even dash */ ! 504: int bgRop; /* reduced rasterop for odd dash */ ! 505: int rop; ! 506: ! 507: int nboxInit; ! 508: int nbox; ! 509: BoxPtr pboxInit; ! 510: BoxPtr pbox; ! 511: int nptTmp; ! 512: DDXPointPtr ppt; /* pointer to list of translated points */ ! 513: ! 514: DDXPointRec pt1; ! 515: DDXPointRec pt2; ! 516: ! 517: unsigned int oc1; /* outcode of point 1 */ ! 518: unsigned int oc2; /* outcode of point 2 */ ! 519: ! 520: int *addrl; /* address of longword with first point */ ! 521: int nlwidth; /* width in longwords of destination bitmap */ ! 522: int xorg, yorg; /* origin of window */ ! 523: ! 524: /* these are all per original line */ ! 525: int adx; /* abs values of dx and dy */ ! 526: int ady; ! 527: int signdx; /* sign of dx and dy */ ! 528: int signdy; ! 529: int e; /* error term for first point of ! 530: original line */ ! 531: int e1, e2; /* i wonder what these are? */ ! 532: ! 533: ! 534: /* these are all per dash */ ! 535: int err; /* bres error term for first drawn point */ ! 536: int len; /* length of segment */ ! 537: int axis; /* major axis */ ! 538: ! 539: int clipDone; /* flag for clipping loop */ ! 540: DDXPointRec pt1Orig; /* unclipped start point */ ! 541: int clip1, clip2; /* clippedness of the endpoints */ ! 542: ! 543: int clipdx, clipdy; /* difference between clipped and ! 544: unclipped start point */ ! 545: ! 546: ! 547: pboxInit = ((mfbPrivGC *)(pGC->devPriv))->pCompositeClip->rects; ! 548: nboxInit = ((mfbPrivGC *)(pGC->devPriv))->pCompositeClip->numRects; ! 549: ! 550: if (pDrawable->type == DRAWABLE_WINDOW) ! 551: { ! 552: xorg = ((WindowPtr)pDrawable)->absCorner.x; ! 553: yorg = ((WindowPtr)pDrawable)->absCorner.y; ! 554: addrl = (int *) ! 555: (((PixmapPtr)(pDrawable->pScreen->devPrivate))->devPrivate); ! 556: nlwidth = (int) ! 557: (((PixmapPtr)(pDrawable->pScreen->devPrivate))->devKind) >> 2; ! 558: } ! 559: else ! 560: { ! 561: xorg = 0; ! 562: yorg = 0; ! 563: addrl = (int *)(((PixmapPtr)pDrawable)->devPrivate); ! 564: nlwidth = (int)(((PixmapPtr)pDrawable)->devKind) >> 2; ! 565: } ! 566: ! 567: /* translate the point list */ ! 568: ppt = pptInit; ! 569: nptTmp = npt; ! 570: if (mode == CoordModeOrigin) ! 571: { ! 572: while(nptTmp--) ! 573: { ! 574: ppt->x += xorg; ! 575: ppt++->y += yorg; ! 576: } ! 577: } ! 578: else ! 579: { ! 580: ppt->x += xorg; ! 581: ppt->y += yorg; ! 582: nptTmp--; ! 583: while(nptTmp--) ! 584: { ! 585: ppt++; ! 586: ppt->x += (ppt-1)->x; ! 587: ppt->y += (ppt-1)->y; ! 588: } ! 589: } ! 590: ! 591: ! 592: pdash = miDashLine(npt, pptInit, ! 593: pGC->numInDashList, pGC->dash, pGC->dashOffset, ! 594: &nseg); ! 595: pdashInit = pdash; ! 596: ! 597: if (pGC->lineStyle == LineOnOffDash) ! 598: { ! 599: rop = ((mfbPrivGC *)(pGC->devPriv))->rop; ! 600: } ! 601: else ! 602: { ! 603: fgRop = ((mfbPrivGC *)(pGC->devPriv))->rop; ! 604: bgRop = ReduceRop(pGC->alu, pGC->bgPixel); ! 605: } ! 606: ! 607: while(nseg--) ! 608: { ! 609: if (pGC->lineStyle == LineOnOffDash) ! 610: { ! 611: while ((nseg) && (pdash->which == ODD_DASH)) ! 612: { ! 613: if (pdash->newLine) ! 614: { ! 615: pt1Orig = pt1 = *pptInit++; ! 616: pt2 = *pptInit; ! 617: adx = pt2.x - pt1.x; ! 618: ady = pt2.y - pt1.y; ! 619: signdx = sign(adx); ! 620: signdy = sign(ady); ! 621: adx = abs(adx); ! 622: ady = abs(ady); ! 623: e = pdash->e; ! 624: e1 = pdash->e1; ! 625: e2 = pdash->e2; ! 626: if (adx > ady) ! 627: axis = X_AXIS; ! 628: else ! 629: axis = Y_AXIS; ! 630: } ! 631: nseg--; ! 632: pdash++; ! 633: } ! 634: /* ??? is this right ??? */ ! 635: if (!nseg) ! 636: break; ! 637: } ! 638: else if (pGC->lineStyle == LineDoubleDash) ! 639: { ! 640: /* use a different color for odd dashes */ ! 641: if (pdash->which == EVEN_DASH) ! 642: rop = fgRop; ! 643: else ! 644: rop = bgRop; ! 645: ! 646: } ! 647: ! 648: if (pdash->newLine) ! 649: { ! 650: pt1Orig = pt1 = *pptInit++; ! 651: pt2 = *pptInit; ! 652: adx = pt2.x - pt1.x; ! 653: ady = pt2.y - pt1.y; ! 654: signdx = sign(adx); ! 655: signdy = sign(ady); ! 656: adx = abs(adx); ! 657: ady = abs(ady); ! 658: e = pdash->e; ! 659: e1 = pdash->e1; ! 660: e2 = pdash->e2; ! 661: if (adx > ady) ! 662: axis = X_AXIS; ! 663: else ! 664: axis = Y_AXIS; ! 665: } ! 666: ! 667: nbox = nboxInit; ! 668: pbox = pboxInit; ! 669: while(nbox--) ! 670: { ! 671: BoxRec box; ! 672: ! 673: clipDone = 0; ! 674: pt1 = pdash->pt; ! 675: pt2 = (pdash+1)->pt; ! 676: box.x1 = pbox->x1; ! 677: box.y1 = pbox->y1; ! 678: box.x2 = pbox->x2-1; ! 679: box.y2 = pbox->y2-1; ! 680: clip1 = 0; ! 681: clip2 = 0; ! 682: ! 683: oc1 = 0; ! 684: oc2 = 0; ! 685: OUTCODES(oc1, pt1.x, pt1.y, pbox); ! 686: OUTCODES(oc2, pt2.x, pt2.y, pbox); ! 687: ! 688: if (oc1 & oc2) ! 689: clipDone = -1; ! 690: else if ((oc1 | oc2) == 0) ! 691: clipDone = 1; ! 692: else /* have to clip */ ! 693: clipDone = mfbClipLine(pbox, box, ! 694: &pt1Orig, &pt1, &pt2, ! 695: adx, ady, signdx, signdy, axis, ! 696: &clip1, &clip2); ! 697: ! 698: if (clipDone == -1) ! 699: { ! 700: pbox++; ! 701: } ! 702: else ! 703: { ! 704: if (axis == X_AXIS) ! 705: len = abs(pt2.x - pt1.x); ! 706: else ! 707: len = abs(pt2.y - pt1.y); ! 708: ! 709: len += (clip2 != 0); ! 710: if (len) ! 711: { ! 712: if (clip1) ! 713: { ! 714: /* unwind bres error term to first visible point */ ! 715: clipdx = abs(pt1.x - pt1Orig.x); ! 716: clipdy = abs(pt1.y - pt1Orig.y); ! 717: if (axis == X_AXIS) ! 718: err = e+((clipdy*e2) + ((clipdx-clipdy)*e1)); ! 719: else ! 720: err = e+((clipdx*e2) + ((clipdy-clipdx)*e1)); ! 721: } ! 722: else ! 723: { ! 724: /* use error term calculated with the dash */ ! 725: err = pdash->e; ! 726: } ! 727: ! 728: mfbBresS( rop, ! 729: addrl, nlwidth, ! 730: signdx, signdy, axis, pt1.x, pt1.y, ! 731: err, e1, e2, len); ! 732: } ! 733: ! 734: /* if segment is unclipped, skip remaining rectangles */ ! 735: if (!(clip1 || clip2)) ! 736: break; ! 737: else ! 738: pbox++; ! 739: } ! 740: } /* while (nbox--) */ ! 741: pdash++; ! 742: } /* while --nseg */ ! 743: ! 744: Xfree(pdashInit); ! 745: } ! 746: ! 747: ! 748: /* ! 749: the clipping code could be cleaned up some; most of its ! 750: mess derives from originally being inline in the line code, ! 751: then pulled out to make clipping dashes easier. ! 752: */ ! 753: ! 754: int ! 755: mfbClipLine(pbox, box, ! 756: ppt1Orig, ppt1, ppt2, ! 757: adx, ady, signdx, signdy, axis, ! 758: pclip1, pclip2) ! 759: BoxPtr pbox; /* box to clip to */ ! 760: BoxRec box; /* box to do calculations with */ ! 761: DDXPointPtr ppt1Orig, ppt1, ppt2; ! 762: register int adx, ady; ! 763: register int signdx, signdy; ! 764: int axis; ! 765: int *pclip1, *pclip2; ! 766: { ! 767: DDXPointRec pt1Orig, pt1, pt2, ptTmp; ! 768: int swapped = 0; ! 769: int clipDone = 0; ! 770: register int tmp; ! 771: int oc1, oc2; ! 772: int clip1, clip2; ! 773: ! 774: pt1Orig = *ppt1Orig; ! 775: pt1 = *ppt1; ! 776: pt2 = *ppt2; ! 777: clip1 = 0; ! 778: clip2 = 0; ! 779: ! 780: do ! 781: { ! 782: oc1 = 0; ! 783: oc2 = 0; ! 784: OUTCODES(oc1, pt1.x, pt1.y, pbox); ! 785: OUTCODES(oc2, pt2.x, pt2.y, pbox); ! 786: ! 787: if (oc1 & oc2) ! 788: clipDone = -1; ! 789: else if ((oc1 | oc2) == 0) ! 790: { ! 791: clipDone = 1; ! 792: if (swapped) ! 793: { ! 794: SWAPPT(pt1, pt2, ptTmp); ! 795: SWAPINT(oc1, oc2, tmp); ! 796: SWAPINT(clip1, clip2, tmp); ! 797: } ! 798: } ! 799: else /* have to clip */ ! 800: { ! 801: /* only clip one point at a time */ ! 802: if (!oc1) ! 803: { ! 804: SWAPPT(pt1, pt2, ptTmp); ! 805: SWAPINT(oc1, oc2, tmp); ! 806: SWAPINT(clip1, clip2, tmp); ! 807: swapped = !swapped; ! 808: } ! 809: ! 810: clip1 |= oc1; ! 811: if (oc1 & OUT_LEFT) ! 812: { ! 813: pt1.x = box.x1; ! 814: if(axis==X_AXIS) ! 815: { ! 816: pt1.y = pt1Orig.y + ! 817: SignTimes(signdy, ! 818: round(abs(box.x1-pt1Orig.x)*ady, ! 819: adx)); ! 820: } ! 821: else ! 822: { ! 823: tmp = abs(pt1Orig.x - box.x1); ! 824: tmp = 2 * tmp * ady; ! 825: if (swapped) ! 826: tmp += ady; ! 827: else ! 828: tmp -= ady; ! 829: tmp = abs(tmp); ! 830: pt1.y = pt1Orig.y + ! 831: SignTimes(signdy, ! 832: ceiling(tmp, 2*adx)); ! 833: if (swapped) ! 834: pt1.y -= signdy; ! 835: } ! 836: } ! 837: else if (oc1 & OUT_ABOVE) ! 838: { ! 839: pt1.y = box.y1; ! 840: if (axis == Y_AXIS) ! 841: { ! 842: pt1.x = pt1Orig.x + ! 843: SignTimes(signdx, ! 844: round(abs(box.y1-pt1Orig.y)*adx, ! 845: ady)); ! 846: } ! 847: else ! 848: { ! 849: tmp = abs(pt1Orig.y - box.y1); ! 850: tmp = 2 * tmp * adx; ! 851: if (swapped) ! 852: tmp += adx; ! 853: else ! 854: tmp -= adx; ! 855: tmp = abs(tmp); ! 856: pt1.x = pt1Orig.x + ! 857: SignTimes(signdx, ! 858: ceiling(tmp, 2*ady)); ! 859: if (swapped) ! 860: pt1.x -= signdx; ! 861: } ! 862: } ! 863: else if (oc1 & OUT_RIGHT) ! 864: { ! 865: pt1.x = box.x2; ! 866: if (axis == X_AXIS) ! 867: { ! 868: pt1.y = pt1Orig.y + ! 869: SignTimes(signdy, ! 870: round(abs(box.x2-pt1Orig.x)*ady, ! 871: adx)); ! 872: } ! 873: else ! 874: { ! 875: tmp = abs(pt1Orig.x - box.x2); ! 876: tmp = 2 * tmp * ady; ! 877: if (swapped) ! 878: tmp += ady; ! 879: else ! 880: tmp -= ady; ! 881: tmp = abs(tmp); ! 882: pt1.y = pt1Orig.y + ! 883: SignTimes(signdy, ! 884: ceiling(tmp, 2*adx)); ! 885: if (swapped) ! 886: pt1.y -= signdy; ! 887: } ! 888: } ! 889: else if (oc1 & OUT_BELOW) ! 890: { ! 891: pt1.y = box.y2; ! 892: if (axis == Y_AXIS) ! 893: { ! 894: pt1.x = pt1Orig.x + ! 895: SignTimes(signdx, ! 896: round(abs(box.y2-pt1Orig.y)*adx, ! 897: ady)); ! 898: } ! 899: else ! 900: { ! 901: tmp = abs(pt1Orig.y - box.y2); ! 902: tmp = 2 * tmp * adx; ! 903: if (swapped) ! 904: tmp += adx; ! 905: else ! 906: tmp -= adx; ! 907: tmp = abs(tmp); ! 908: pt1.x = pt1Orig.x + ! 909: SignTimes(signdx, ! 910: ceiling(tmp, 2*ady)); ! 911: if (swapped) ! 912: pt1.x -= signdx; ! 913: } ! 914: } ! 915: } /* else have to clip */ ! 916: } while(!clipDone); ! 917: *ppt1 = pt1; ! 918: *ppt2 = pt2; ! 919: *pclip1 = clip1; ! 920: *pclip2 = clip2; ! 921: ! 922: return clipDone; ! 923: } ! 924:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.