1 /***********************************************************
3 Copyright (c) 1987 X Consortium
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
31 Permission to use, copy, modify, and distribute this software and its
32 documentation for any purpose and without fee is hereby granted,
33 provided that the above copyright notice appear in all copies and that
34 both that copyright notice and this permission notice appear in
35 supporting documentation, and that the name of Digital not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific, written prior permission.
39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47 ******************************************************************/
48 /* $XConsortium: mfbline.c,v 5.19 94/07/28 14:28:21 dpw Exp $ */
52 #include "windowstr.h"
53 #include "pixmapstr.h"
54 #include "regionstr.h"
55 #include "scrnintstr.h"
62 /* single-pixel lines on a color frame buffer
65 horizontal lines are always drawn left to right; we have to
66 move the endpoints right by one after they're swapped.
67 horizontal lines will be confined to a single band of a
68 region. the code finds that band (giving up if the lower
69 bound of the band is above the line we're drawing); then it
70 finds the first box in that band that contains part of the
71 line. we clip the line to subsequent boxes in that band.
72 vertical lines are always drawn top to bottom (y-increasing.)
73 this requires adding one to the y-coordinate of each endpoint
77 when clipping a sloped line, we bring the second point inside
78 the clipping box, rather than one beyond it, and then add 1 to
79 the length of the line before drawing it. this lets us use
80 the same box for finding the outcodes for both endpoints. since
81 the equation for clipping the second endpoint to an edge gives us
82 1 beyond the edge, we then have to move the point towards the
83 first point by one step on the major axis.
84 eventually, there will be a diagram here to explain what's going
85 on. the method uses Cohen-Sutherland outcodes to determine
86 outsideness, and a method similar to Pike's layers for doing the
93 mfbSegmentSS (pDrawable, pGC, nseg, pSeg)
94 DrawablePtr pDrawable;
97 register xSegment *pSeg;
99 mfbLineSS (pDrawable, pGC, mode, npt, pptInit)
100 DrawablePtr pDrawable;
102 int mode; /* Origin or Previous */
103 int npt; /* number of points */
110 register BoxPtr pbox;
112 register DDXPointPtr ppt; /* pointer to list of translated points */
115 unsigned int oc1; /* outcode of point 1 */
116 unsigned int oc2; /* outcode of point 2 */
118 PixelType *addrlBase; /* pointer to start of drawable */
119 PixelType *addrl; /* address of destination pixmap */
120 int nlwidth; /* width in longwords of destination pixmap */
121 int xorg, yorg; /* origin of window */
123 int adx; /* abs values of dx and dy */
125 int signdx; /* sign of dx and dy */
127 int e, e1, e2; /* bresenham error and increments */
128 int len; /* length of segment */
129 int axis; /* major axis */
131 unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
133 /* a bunch of temporaries */
139 if (!(pGC->planemask & 1))
142 cclip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip;
143 alu = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->rop;
144 pboxInit = REGION_RECTS(cclip);
145 nboxInit = REGION_NUM_RECTS(cclip);
147 mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase);
164 x1 = pSeg->x1 + xorg;
165 y1 = pSeg->y1 + yorg;
166 x2 = pSeg->x2 + xorg;
167 y2 = pSeg->y2 + yorg;
173 if (mode == CoordModePrevious)
182 if (x1 == x2) /* vertical line */
184 /* make the line go top to bottom of screen, keeping
195 if (pGC->capStyle != CapNotLast)
200 else if (pGC->capStyle != CapNotLast)
203 /* get to first band that might contain part of line */
204 while ((nbox) && (pbox->y2 <= y1))
212 /* stop when lower edge of box is beyond end of line */
213 while((nbox) && (y2 >= pbox->y1))
215 if ((x1 >= pbox->x1) && (x1 < pbox->x2))
218 /* this box has part of the line in it */
219 y1t = max(y1, pbox->y1);
220 y2t = min(y2, pbox->y2);
236 else if (y1 == y2) /* horizontal line */
238 /* force line from left to right, keeping
249 if (pGC->capStyle != CapNotLast)
254 else if (pGC->capStyle != CapNotLast)
258 /* find the correct band */
259 while( (nbox) && (pbox->y2 <= y1))
265 /* try to draw the line, if we haven't gone beyond it */
266 if ((nbox) && (pbox->y1 <= y1))
270 /* when we leave this band, we're done */
272 while((nbox) && (pbox->y1 == tmp))
278 /* skip boxes until one might contain start point */
284 /* stop if left of box is beyond right of line */
291 x1t = max(x1, pbox->x1);
292 x2t = min(x2, pbox->x2);
307 else /* sloped line */
309 CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy,
316 e2 = e1 - (adx << 1);
323 e2 = e1 - (ady << 1);
325 SetYMajorOctant(octant);
328 FIXUP_ERROR(e, octant, bias);
330 /* we have bresenham parameters and two points.
331 all we have to do now is clip and draw.
338 OUTCODES(oc1, x1, y1, pbox);
339 OUTCODES(oc2, x2, y2, pbox);
340 if ((oc1 | oc2) == 0)
347 if (pGC->capStyle != CapNotLast)
352 signdx, signdy, axis, x1, y1,
362 int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
363 int clip1 = 0, clip2 = 0;
367 if (miZeroClipLine(pbox->x1, pbox->y1, pbox->x2-1,
369 &new_x1, &new_y1, &new_x2, &new_y2,
370 adx, ady, &clip1, &clip2,
371 octant, bias, oc1, oc2) == -1)
378 len = abs(new_x2 - new_x1);
380 len = abs(new_y2 - new_y1);
382 if (clip2 != 0 || pGC->capStyle != CapNotLast)
389 /* unwind bresenham error term to first point */
392 clipdx = abs(new_x1 - x1);
393 clipdy = abs(new_y1 - y1);
395 err = e+((clipdy*e2) + ((clipdx-clipdy)*e1));
397 err = e+((clipdx*e2) + ((clipdy-clipdx)*e1));
404 signdx, signdy, axis, new_x1, new_y1,
409 } /* while (nbox--) */
411 } /* while (nline--) */
415 /* paint the last point if the end style isn't CapNotLast.
416 (Assume that a projecting, butt, or round cap that is one
417 pixel wide is the same as the single pixel of the endpoint.)
420 if ((pGC->capStyle != CapNotLast) &&
421 ((ppt->x + xorg != pptInit->x + pDrawable->x) ||
422 (ppt->y + yorg != pptInit->y + pDrawable->y) ||
423 (ppt == pptInit + 1)))
427 if (alu == RROP_BLACK)
428 _mask = rmask[x2 & PIM];
430 _mask = mask[x2 & PIM];
436 if ((x2 >= pbox->x1) &&
441 addrl = mfbScanline(addrlBase, x2, y2, nlwidth);
464 * Draw dashed 1-pixel lines.
469 mfbSegmentSD (pDrawable, pGC, nseg, pSeg)
470 DrawablePtr pDrawable;
473 register xSegment *pSeg;
475 mfbLineSD( pDrawable, pGC, mode, npt, pptInit)
476 DrawablePtr pDrawable;
478 int mode; /* Origin or Previous */
479 int npt; /* number of points */
486 register BoxPtr pbox;
488 register DDXPointPtr ppt; /* pointer to list of translated points */
491 register unsigned int oc1; /* outcode of point 1 */
492 register unsigned int oc2; /* outcode of point 2 */
494 PixelType *addrl; /* address of destination pixmap */
495 int nlwidth; /* width in longwords of destination pixmap */
496 int xorg, yorg; /* origin of window */
498 int adx; /* abs values of dx and dy */
500 int signdx; /* sign of dx and dy */
502 int e, e1, e2; /* bresenham error and increments */
503 int len; /* length of segment */
504 int axis; /* major axis */
506 unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
510 unsigned char *pDash;
515 int dashIndexTmp, dashOffsetTmp;
518 if (!(pGC->planemask & 1))
521 cclip = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip;
522 fgrop = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->rop;
523 pboxInit = REGION_RECTS(cclip);
524 nboxInit = REGION_NUM_RECTS(cclip);
526 mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrl);
528 /* compute initial dash values */
530 pDash = (unsigned char *) pGC->dash;
531 numInDashList = pGC->numInDashList;
532 isDoubleDash = (pGC->lineStyle == LineDoubleDash);
535 miStepDash ((int)pGC->dashOffset, &dashIndex, pDash,
536 numInDashList, &dashOffset);
539 bgrop = mfbReduceRop(pGC->alu, pGC->bgPixel);
556 x1 = pSeg->x1 + xorg;
557 y1 = pSeg->y1 + yorg;
558 x2 = pSeg->x2 + xorg;
559 y2 = pSeg->y2 + yorg;
565 if (mode == CoordModePrevious)
574 CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
580 e2 = e1 - (adx << 1);
588 e2 = e1 - (ady << 1);
591 SetYMajorOctant(octant);
594 FIXUP_ERROR(e, octant, bias);
596 /* we have bresenham parameters and two points.
597 all we have to do now is clip and draw.
604 OUTCODES(oc1, x1, y1, pbox);
605 OUTCODES(oc2, x2, y2, pbox);
606 if ((oc1 | oc2) == 0)
609 if (pGC->capStyle != CapNotLast)
611 dashIndexTmp = dashIndex;
612 dashOffsetTmp = dashOffset;
613 mfbBresD (fgrop, bgrop,
614 &dashIndexTmp, pDash, numInDashList,
615 &dashOffsetTmp, isDoubleDash,
617 signdx, signdy, axis, x1, y1,
618 e, e1, e2, unclippedlen);
621 mfbBresD (fgrop, bgrop,
622 &dashIndex, pDash, numInDashList,
623 &dashOffset, isDoubleDash,
625 signdx, signdy, axis, x1, y1,
626 e, e1, e2, unclippedlen);
634 else /* have to clip */
636 int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
637 int clip1 = 0, clip2 = 0;
641 if (miZeroClipLine(pbox->x1, pbox->y1, pbox->x2-1, pbox->y2-1,
642 &new_x1, &new_y1, &new_x2, &new_y2,
643 adx, ady, &clip1, &clip2,
644 octant, bias, oc1, oc2) == -1)
649 dashIndexTmp = dashIndex;
650 dashOffsetTmp = dashOffset;
656 dlen = abs(new_x1 - x1);
658 dlen = abs(new_y1 - y1);
659 miStepDash (dlen, &dashIndexTmp, pDash,
660 numInDashList, &dashOffsetTmp);
663 len = abs(new_x2 - new_x1);
665 len = abs(new_y2 - new_y1);
667 if (clip2 != 0 || pGC->capStyle != CapNotLast)
674 /* unwind bresenham error term to first point */
677 clipdx = abs(new_x1 - x1);
678 clipdy = abs(new_y1 - y1);
680 err = e+((clipdy*e2) + ((clipdx-clipdy)*e1));
682 err = e+((clipdx*e2) + ((clipdy-clipdx)*e1));
686 mfbBresD (fgrop, bgrop,
687 &dashIndexTmp, pDash, numInDashList,
688 &dashOffsetTmp, isDoubleDash,
690 signdx, signdy, axis, new_x1, new_y1,
695 } /* while (nbox--) */
698 * walk the dash list around to the next line
700 miStepDash (unclippedlen, &dashIndex, pDash,
701 numInDashList, &dashOffset);
704 } /* while (nline--) */
707 /* paint the last point if the end style isn't CapNotLast.
708 (Assume that a projecting, butt, or round cap that is one
709 pixel wide is the same as the single pixel of the endpoint.)
712 if ((pGC->capStyle != CapNotLast) &&
713 ((dashIndex & 1) == 0 || isDoubleDash) &&
714 ((ppt->x + xorg != pptInit->x + pDrawable->x) ||
715 (ppt->y + yorg != pptInit->y + pDrawable->y) ||
716 (ppt == pptInit + 1)))
722 if ((x2 >= pbox->x1) &&
733 if (rop == RROP_BLACK)
734 _mask = rmask[x2 & PIM];
736 _mask = mask[x2 & PIM];
737 addrl = mfbScanline(addrl, x2, y2, nlwidth);
738 if (rop == RROP_BLACK)
740 else if (rop == RROP_WHITE)