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: cfbline.c,v 1.24 94/07/28 14:33:33 dpw Exp $ */
49 /* $XFree86: xc/programs/Xserver/cfb/cfbline.c,v 3.0 1996/06/29 09:05:38 dawes Exp $ */
53 #include "windowstr.h"
54 #include "pixmapstr.h"
55 #include "regionstr.h"
56 #include "scrnintstr.h"
60 #include "cfbmskbits.h"
63 /* single-pixel lines on a color frame buffer
66 horizontal lines are always drawn left to right; we have to
67 move the endpoints right by one after they're swapped.
68 horizontal lines will be confined to a single band of a
69 region. the code finds that band (giving up if the lower
70 bound of the band is above the line we're drawing); then it
71 finds the first box in that band that contains part of the
72 line. we clip the line to subsequent boxes in that band.
73 vertical lines are always drawn top to bottom (y-increasing.)
74 this requires adding one to the y-coordinate of each endpoint
78 when clipping a sloped line, we bring the second point inside
79 the clipping box, rather than one beyond it, and then add 1 to
80 the length of the line before drawing it. this lets us use
81 the same box for finding the outcodes for both endpoints. since
82 the equation for clipping the second endpoint to an edge gives us
83 1 beyond the edge, we then have to move the point towards the
84 first point by one step on the major axis.
85 eventually, there will be a diagram here to explain what's going
86 on. the method uses Cohen-Sutherland outcodes to determine
87 outsideness, and a method similar to Pike's layers for doing the
94 cfbSegmentSS (pDrawable, pGC, nseg, pSeg)
95 DrawablePtr pDrawable;
98 register xSegment *pSeg;
100 cfbLineSS (pDrawable, pGC, mode, npt, pptInit)
101 DrawablePtr pDrawable;
103 int mode; /* Origin or Previous */
104 int npt; /* number of points */
111 register BoxPtr pbox;
113 register DDXPointPtr ppt; /* pointer to list of translated points */
116 unsigned int oc1; /* outcode of point 1 */
117 unsigned int oc2; /* outcode of point 2 */
119 unsigned long *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 */
138 cfbPrivGCPtr devPriv;
139 unsigned long xor, and;
142 devPriv = cfbGetGCPrivate(pGC);
143 cclip = devPriv->pCompositeClip;
144 pboxInit = REGION_RECTS(cclip);
145 nboxInit = REGION_NUM_RECTS(cclip);
147 cfbGetLongWidthAndPointer (pDrawable, nlwidth, addrl)
167 x1 = pSeg->x1 + xorg;
168 y1 = pSeg->y1 + yorg;
169 x2 = pSeg->x2 + xorg;
170 y2 = pSeg->y2 + yorg;
176 if (mode == CoordModePrevious)
185 if (x1 == x2) /* vertical line */
187 /* make the line go top to bottom of screen, keeping
198 if (pGC->capStyle != CapNotLast)
203 else if (pGC->capStyle != CapNotLast)
206 /* get to first band that might contain part of line */
207 while ((nbox) && (pbox->y2 <= y1))
215 /* stop when lower edge of box is beyond end of line */
216 while((nbox) && (y2 >= pbox->y1))
218 if ((x1 >= pbox->x1) && (x1 < pbox->x2))
221 /* this box has part of the line in it */
222 y1t = max(y1, pbox->y1);
223 y2t = min(y2, pbox->y2);
226 cfbVertS (alu, and, xor,
239 else if (y1 == y2) /* horizontal line */
241 /* force line from left to right, keeping
252 if (pGC->capStyle != CapNotLast)
257 else if (pGC->capStyle != CapNotLast)
261 /* find the correct band */
262 while( (nbox) && (pbox->y2 <= y1))
268 /* try to draw the line, if we haven't gone beyond it */
269 if ((nbox) && (pbox->y1 <= y1))
271 /* when we leave this band, we're done */
273 while((nbox) && (pbox->y1 == tmp))
279 /* skip boxes until one might contain start point */
285 /* stop if left of box is beyond right of line */
292 x1t = max(x1, pbox->x1);
293 x2t = min(x2, pbox->x2);
296 cfbHorzS (alu, and, xor,
308 else /* sloped line */
310 CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy,
317 e2 = e1 - (adx << 1);
324 e2 = e1 - (ady << 1);
326 SetYMajorOctant(octant);
329 FIXUP_ERROR(e, octant, bias);
331 /* we have bresenham parameters and two points.
332 all we have to do now is clip and draw.
339 OUTCODES(oc1, x1, y1, pbox);
340 OUTCODES(oc2, x2, y2, pbox);
341 if ((oc1 | oc2) == 0)
348 if (pGC->capStyle != CapNotLast)
351 cfbBresS (alu, and, xor,
353 signdx, signdy, axis, x1, y1,
363 int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
364 int clip1 = 0, clip2 = 0;
368 if (miZeroClipLine(pbox->x1, pbox->y1, pbox->x2-1,
370 &new_x1, &new_y1, &new_x2, &new_y2,
371 adx, ady, &clip1, &clip2,
372 octant, bias, oc1, oc2) == -1)
379 len = abs(new_x2 - new_x1);
381 len = abs(new_y2 - new_y1);
383 if (clip2 != 0 || pGC->capStyle != CapNotLast)
390 /* unwind bresenham error term to first point */
393 clipdx = abs(new_x1 - x1);
394 clipdy = abs(new_y1 - y1);
396 err = e+((clipdy*e2) + ((clipdx-clipdy)*e1));
398 err = e+((clipdx*e2) + ((clipdy-clipdx)*e1));
402 cfbBresS(alu, and, xor,
404 signdx, signdy, axis, new_x1, new_y1,
409 } /* while (nbox--) */
411 } /* while (nline--) */
414 /* paint the last point if the end style isn't CapNotLast.
415 (Assume that a projecting, butt, or round cap that is one
416 pixel wide is the same as the single pixel of the endpoint.)
419 if ((pGC->capStyle != CapNotLast) &&
420 ((ppt->x + xorg != pptInit->x + pDrawable->x) ||
421 (ppt->y + yorg != pptInit->y + pDrawable->y) ||
422 (ppt == pptInit + 1)))
428 if ((x2 >= pbox->x1) &&
434 unsigned long scrbits;
437 mask = cfbmask[(x2 & 3)<<1];
438 addrl += (y2 * nlwidth) + ((x2*3) >> 2);
440 mask = cfbmask[x2 & PIM];
441 addrl += (y2 * nlwidth) + (x2 >> PWSH);
444 *addrl = (scrbits & ~mask) |
445 (DoRRop (scrbits, and, xor) & mask);
456 * Draw dashed 1-pixel lines.
461 cfbSegmentSD (pDrawable, pGC, nseg, pSeg)
462 DrawablePtr pDrawable;
465 register xSegment *pSeg;
467 cfbLineSD( pDrawable, pGC, mode, npt, pptInit)
468 DrawablePtr pDrawable;
470 int mode; /* Origin or Previous */
471 int npt; /* number of points */
478 register BoxPtr pbox;
480 register DDXPointPtr ppt; /* pointer to list of translated points */
483 register unsigned int oc1; /* outcode of point 1 */
484 register unsigned int oc2; /* outcode of point 2 */
486 unsigned long *addrl; /* address of destination pixmap */
487 int nlwidth; /* width in longwords of destination pixmap */
488 int xorg, yorg; /* origin of window */
490 int adx; /* abs values of dx and dy */
492 int signdx; /* sign of dx and dy */
494 int e, e1, e2; /* bresenham error and increments */
495 int len; /* length of segment */
496 int axis; /* major axis */
498 unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
502 unsigned char *pDash;
507 int dashIndexTmp, dashOffsetTmp;
509 cfbPrivGCPtr devPriv;
511 devPriv = cfbGetGCPrivate(pGC);
512 cclip = devPriv->pCompositeClip;
513 rrops[0].rop = devPriv->rop;
514 rrops[0].and = devPriv->and;
515 rrops[0].xor = devPriv->xor;
516 if (pGC->alu == GXcopy)
518 rrops[1].rop = GXcopy;
520 rrops[1].xor = PFILL (pGC->bgPixel);
524 rrops[1].rop = cfbReduceRasterOp (pGC->alu,
525 pGC->bgPixel, pGC->planemask,
526 &rrops[1].and, &rrops[1].xor);
528 pboxInit = REGION_RECTS(cclip);
529 nboxInit = REGION_NUM_RECTS(cclip);
531 cfbGetLongWidthAndPointer (pDrawable, nlwidth, addrl)
533 /* compute initial dash values */
535 pDash = (unsigned char *) pGC->dash;
536 numInDashList = pGC->numInDashList;
537 isDoubleDash = (pGC->lineStyle == LineDoubleDash);
540 miStepDash ((int)pGC->dashOffset, &dashIndex, pDash,
541 numInDashList, &dashOffset);
558 x1 = pSeg->x1 + xorg;
559 y1 = pSeg->y1 + yorg;
560 x2 = pSeg->x2 + xorg;
561 y2 = pSeg->y2 + yorg;
567 if (mode == CoordModePrevious)
576 CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
582 e2 = e1 - (adx << 1);
590 e2 = e1 - (ady << 1);
593 SetYMajorOctant(octant);
596 FIXUP_ERROR(e, octant, bias);
598 /* we have bresenham parameters and two points.
599 all we have to do now is clip and draw.
606 OUTCODES(oc1, x1, y1, pbox);
607 OUTCODES(oc2, x2, y2, pbox);
608 if ((oc1 | oc2) == 0)
611 if (pGC->capStyle != CapNotLast)
613 dashIndexTmp = dashIndex;
614 dashOffsetTmp = dashOffset;
616 &dashIndexTmp, pDash, numInDashList,
617 &dashOffsetTmp, isDoubleDash,
619 signdx, signdy, axis, x1, y1,
620 e, e1, e2, unclippedlen);
624 &dashIndex, pDash, numInDashList,
625 &dashOffset, isDoubleDash,
627 signdx, signdy, axis, x1, y1,
628 e, e1, e2, unclippedlen);
636 else /* have to clip */
638 int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
639 int clip1 = 0, clip2 = 0;
642 int dashIndexTmp, dashOffsetTmp;
644 if (miZeroClipLine(pbox->x1, pbox->y1, pbox->x2-1,
646 &new_x1, &new_y1, &new_x2, &new_y2,
647 adx, ady, &clip1, &clip2,
648 octant, bias, oc1, oc2) == -1)
654 dashIndexTmp = dashIndex;
655 dashOffsetTmp = dashOffset;
662 dlen = abs(new_x1 - x1);
664 dlen = abs(new_y1 - y1);
665 miStepDash (dlen, &dashIndexTmp, pDash,
666 numInDashList, &dashOffsetTmp);
670 len = abs(new_x2 - new_x1);
672 len = abs(new_y2 - new_y1);
674 if (clip2 != 0 || pGC->capStyle != CapNotLast)
681 /* unwind bresenham error term to first point */
684 clipdx = abs(new_x1 - x1);
685 clipdy = abs(new_y1 - y1);
687 err = e+((clipdy*e2) + ((clipdx-clipdy)*e1));
689 err = e+((clipdx*e2) + ((clipdy-clipdx)*e1));
694 &dashIndexTmp, pDash, numInDashList,
695 &dashOffsetTmp, isDoubleDash,
697 signdx, signdy, axis, new_x1, new_y1,
702 } /* while (nbox--) */
705 * walk the dash list around to the next line
707 miStepDash (unclippedlen, &dashIndex, pDash,
708 numInDashList, &dashOffset);
711 } /* while (nline--) */
714 /* paint the last point if the end style isn't CapNotLast.
715 (Assume that a projecting, butt, or round cap that is one
716 pixel wide is the same as the single pixel of the endpoint.)
719 if ((pGC->capStyle != CapNotLast) &&
720 ((dashIndex & 1) == 0 || isDoubleDash) &&
721 ((ppt->x + xorg != pptInit->x + pDrawable->x) ||
722 (ppt->y + yorg != pptInit->y + pDrawable->y) ||
723 (ppt == pptInit + 1)))
729 if ((x2 >= pbox->x1) &&
741 mask = cfbmask[(x2 & 3)<<1];
742 addrl += (y2 * nlwidth) + ((x2 *3)>> 2);
744 mask = cfbmask[x2 & PIM];
745 addrl += (y2 * nlwidth) + (x2 >> PWSH);
747 *addrl = DoMaskRRop (*addrl, rrops[pix].and, rrops[pix].xor, mask);