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