1 /***********************************************************
3 Copyright 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
26 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46 ******************************************************************/
47 #ifdef HAVE_DIX_CONFIG_H
48 #include <dix-config.h>
55 #include "windowstr.h"
56 #include "pixmapstr.h"
57 #include "regionstr.h"
58 #include "scrnintstr.h"
62 #include "cfbmskbits.h"
65 /* single-pixel lines on a color frame buffer
68 horizontal lines are always drawn left to right; we have to
69 move the endpoints right by one after they're swapped.
70 horizontal lines will be confined to a single band of a
71 region. the code finds that band (giving up if the lower
72 bound of the band is above the line we're drawing); then it
73 finds the first box in that band that contains part of the
74 line. we clip the line to subsequent boxes in that band.
75 vertical lines are always drawn top to bottom (y-increasing.)
76 this requires adding one to the y-coordinate of each endpoint
80 when clipping a sloped line, we bring the second point inside
81 the clipping box, rather than one beyond it, and then add 1 to
82 the length of the line before drawing it. this lets us use
83 the same box for finding the outcodes for both endpoints. since
84 the equation for clipping the second endpoint to an edge gives us
85 1 beyond the edge, we then have to move the point towards the
86 first point by one step on the major axis.
87 eventually, there will be a diagram here to explain what's going
88 on. the method uses Cohen-Sutherland outcodes to determine
89 outsideness, and a method similar to Pike's layers for doing the
96 cfbSegmentSS (pDrawable
, pGC
, nseg
, pSeg
)
97 DrawablePtr pDrawable
;
100 register xSegment
*pSeg
;
102 cfbLineSS (pDrawable
, pGC
, mode
, npt
, pptInit
)
103 DrawablePtr pDrawable
;
105 int mode
; /* Origin or Previous */
106 int npt
; /* number of points */
113 register BoxPtr pbox
;
115 register DDXPointPtr ppt
; /* pointer to list of translated points */
118 unsigned int oc1
; /* outcode of point 1 */
119 unsigned int oc2
; /* outcode of point 2 */
121 CfbBits
*addrl
; /* address of destination pixmap */
122 int nlwidth
; /* width in longwords of destination pixmap */
123 int xorg
, yorg
; /* origin of window */
125 int adx
; /* abs values of dx and dy */
127 int signdx
; /* sign of dx and dy */
129 int e
, e1
, e2
; /* bresenham error and increments */
130 int len
; /* length of segment */
131 int axis
; /* major axis */
133 unsigned int bias
= miGetZeroLineBias(pDrawable
->pScreen
);
135 /* a bunch of temporaries */
140 cfbPrivGCPtr devPriv
;
144 devPriv
= cfbGetGCPrivate(pGC
);
145 cclip
= pGC
->pCompositeClip
;
146 pboxInit
= REGION_RECTS(cclip
);
147 nboxInit
= REGION_NUM_RECTS(cclip
);
149 cfbGetLongWidthAndPointer (pDrawable
, nlwidth
, addrl
)
169 x1
= pSeg
->x1
+ xorg
;
170 y1
= pSeg
->y1
+ yorg
;
171 x2
= pSeg
->x2
+ xorg
;
172 y2
= pSeg
->y2
+ yorg
;
178 if (mode
== CoordModePrevious
)
187 if (x1
== x2
) /* vertical line */
189 /* make the line go top to bottom of screen, keeping
200 if (pGC
->capStyle
!= CapNotLast
)
205 else if (pGC
->capStyle
!= CapNotLast
)
208 /* get to first band that might contain part of line */
209 while ((nbox
) && (pbox
->y2
<= y1
))
217 /* stop when lower edge of box is beyond end of line */
218 while((nbox
) && (y2
>= pbox
->y1
))
220 if ((x1
>= pbox
->x1
) && (x1
< pbox
->x2
))
223 /* this box has part of the line in it */
224 y1t
= max(y1
, pbox
->y1
);
225 y2t
= min(y2
, pbox
->y2
);
228 cfbVertS (alu
, and, xor,
241 else if (y1
== y2
) /* horizontal line */
243 /* force line from left to right, keeping
254 if (pGC
->capStyle
!= CapNotLast
)
259 else if (pGC
->capStyle
!= CapNotLast
)
263 /* find the correct band */
264 while( (nbox
) && (pbox
->y2
<= y1
))
270 /* try to draw the line, if we haven't gone beyond it */
271 if ((nbox
) && (pbox
->y1
<= y1
))
273 /* when we leave this band, we're done */
275 while((nbox
) && (pbox
->y1
== tmp
))
281 /* skip boxes until one might contain start point */
287 /* stop if left of box is beyond right of line */
294 x1t
= max(x1
, pbox
->x1
);
295 x2t
= min(x2
, pbox
->x2
);
298 cfbHorzS (alu
, and, xor,
310 else /* sloped line */
312 CalcLineDeltas(x1
, y1
, x2
, y2
, adx
, ady
, signdx
, signdy
,
319 e2
= e1
- (adx
<< 1);
326 e2
= e1
- (ady
<< 1);
328 SetYMajorOctant(octant
);
331 FIXUP_ERROR(e
, octant
, bias
);
333 /* we have bresenham parameters and two points.
334 all we have to do now is clip and draw.
341 OUTCODES(oc1
, x1
, y1
, pbox
);
342 OUTCODES(oc2
, x2
, y2
, pbox
);
343 if ((oc1
| oc2
) == 0)
350 if (pGC
->capStyle
!= CapNotLast
)
353 cfbBresS (alu
, and, xor,
355 signdx
, signdy
, axis
, x1
, y1
,
365 int new_x1
= x1
, new_y1
= y1
, new_x2
= x2
, new_y2
= y2
;
366 int clip1
= 0, clip2
= 0;
370 if (miZeroClipLine(pbox
->x1
, pbox
->y1
, pbox
->x2
-1,
372 &new_x1
, &new_y1
, &new_x2
, &new_y2
,
373 adx
, ady
, &clip1
, &clip2
,
374 octant
, bias
, oc1
, oc2
) == -1)
381 len
= abs(new_x2
- new_x1
);
383 len
= abs(new_y2
- new_y1
);
385 if (clip2
!= 0 || pGC
->capStyle
!= CapNotLast
)
392 /* unwind bresenham error term to first point */
395 clipdx
= abs(new_x1
- x1
);
396 clipdy
= abs(new_y1
- y1
);
398 err
= e
+((clipdy
*e2
) + ((clipdx
-clipdy
)*e1
));
400 err
= e
+((clipdx
*e2
) + ((clipdy
-clipdx
)*e1
));
404 cfbBresS(alu
, and, xor,
406 signdx
, signdy
, axis
, new_x1
, new_y1
,
411 } /* while (nbox--) */
413 } /* while (nline--) */
416 /* paint the last point if the end style isn't CapNotLast.
417 (Assume that a projecting, butt, or round cap that is one
418 pixel wide is the same as the single pixel of the endpoint.)
421 if ((pGC
->capStyle
!= CapNotLast
) &&
422 ((ppt
->x
+ xorg
!= pptInit
->x
+ pDrawable
->x
) ||
423 (ppt
->y
+ yorg
!= pptInit
->y
+ pDrawable
->y
) ||
424 (ppt
== pptInit
+ 1)))
430 if ((x2
>= pbox
->x1
) &&
439 mask
= cfbmask
[(x2
& 3)<<1];
440 addrl
+= (y2
* nlwidth
) + ((x2
*3) >> 2);
442 mask
= cfbmask
[x2
& PIM
];
443 addrl
+= (y2
* nlwidth
) + (x2
>> PWSH
);
446 *addrl
= (scrbits
& ~mask
) |
447 (DoRRop (scrbits
, and, xor) & mask
);
458 * Draw dashed 1-pixel lines.
463 cfbSegmentSD (pDrawable
, pGC
, nseg
, pSeg
)
464 DrawablePtr pDrawable
;
467 register xSegment
*pSeg
;
469 cfbLineSD( pDrawable
, pGC
, mode
, npt
, pptInit
)
470 DrawablePtr pDrawable
;
472 int mode
; /* Origin or Previous */
473 int npt
; /* number of points */
480 register BoxPtr pbox
;
482 register DDXPointPtr ppt
; /* pointer to list of translated points */
485 register unsigned int oc1
; /* outcode of point 1 */
486 register unsigned int oc2
; /* outcode of point 2 */
488 CfbBits
*addrl
; /* address of destination pixmap */
489 int nlwidth
; /* width in longwords of destination pixmap */
490 int xorg
, yorg
; /* origin of window */
492 int adx
; /* abs values of dx and dy */
494 int signdx
; /* sign of dx and dy */
496 int e
, e1
, e2
; /* bresenham error and increments */
497 int len
; /* length of segment */
498 int axis
; /* major axis */
500 unsigned int bias
= miGetZeroLineBias(pDrawable
->pScreen
);
504 unsigned char *pDash
;
509 int dashIndexTmp
, dashOffsetTmp
;
511 cfbPrivGCPtr devPriv
;
513 devPriv
= cfbGetGCPrivate(pGC
);
514 cclip
= pGC
->pCompositeClip
;
515 rrops
[0].rop
= devPriv
->rop
;
516 rrops
[0].and = devPriv
->and;
517 rrops
[0].xor = devPriv
->xor;
518 if (pGC
->alu
== GXcopy
)
520 rrops
[1].rop
= GXcopy
;
522 rrops
[1].xor = PFILL (pGC
->bgPixel
);
526 rrops
[1].rop
= cfbReduceRasterOp (pGC
->alu
,
527 pGC
->bgPixel
, pGC
->planemask
,
528 &rrops
[1].and, &rrops
[1].xor);
530 pboxInit
= REGION_RECTS(cclip
);
531 nboxInit
= REGION_NUM_RECTS(cclip
);
533 cfbGetLongWidthAndPointer (pDrawable
, nlwidth
, addrl
)
535 /* compute initial dash values */
537 pDash
= (unsigned char *) pGC
->dash
;
538 numInDashList
= pGC
->numInDashList
;
539 isDoubleDash
= (pGC
->lineStyle
== LineDoubleDash
);
542 miStepDash ((int)pGC
->dashOffset
, &dashIndex
, pDash
,
543 numInDashList
, &dashOffset
);
560 x1
= pSeg
->x1
+ xorg
;
561 y1
= pSeg
->y1
+ yorg
;
562 x2
= pSeg
->x2
+ xorg
;
563 y2
= pSeg
->y2
+ yorg
;
569 if (mode
== CoordModePrevious
)
578 CalcLineDeltas(x1
, y1
, x2
, y2
, adx
, ady
, signdx
, signdy
, 1, 1, octant
);
584 e2
= e1
- (adx
<< 1);
592 e2
= e1
- (ady
<< 1);
595 SetYMajorOctant(octant
);
598 FIXUP_ERROR(e
, octant
, bias
);
600 /* we have bresenham parameters and two points.
601 all we have to do now is clip and draw.
608 OUTCODES(oc1
, x1
, y1
, pbox
);
609 OUTCODES(oc2
, x2
, y2
, pbox
);
610 if ((oc1
| oc2
) == 0)
613 if (pGC
->capStyle
!= CapNotLast
)
615 dashIndexTmp
= dashIndex
;
616 dashOffsetTmp
= dashOffset
;
618 &dashIndexTmp
, pDash
, numInDashList
,
619 &dashOffsetTmp
, isDoubleDash
,
621 signdx
, signdy
, axis
, x1
, y1
,
622 e
, e1
, e2
, unclippedlen
);
626 &dashIndex
, pDash
, numInDashList
,
627 &dashOffset
, isDoubleDash
,
629 signdx
, signdy
, axis
, x1
, y1
,
630 e
, e1
, e2
, unclippedlen
);
638 else /* have to clip */
640 int new_x1
= x1
, new_y1
= y1
, new_x2
= x2
, new_y2
= y2
;
641 int clip1
= 0, clip2
= 0;
645 if (miZeroClipLine(pbox
->x1
, pbox
->y1
, pbox
->x2
-1,
647 &new_x1
, &new_y1
, &new_x2
, &new_y2
,
648 adx
, ady
, &clip1
, &clip2
,
649 octant
, bias
, oc1
, oc2
) == -1)
655 dashIndexTmp
= dashIndex
;
656 dashOffsetTmp
= dashOffset
;
663 dlen
= abs(new_x1
- x1
);
665 dlen
= abs(new_y1
- y1
);
666 miStepDash (dlen
, &dashIndexTmp
, pDash
,
667 numInDashList
, &dashOffsetTmp
);
671 len
= abs(new_x2
- new_x1
);
673 len
= abs(new_y2
- new_y1
);
675 if (clip2
!= 0 || pGC
->capStyle
!= CapNotLast
)
682 /* unwind bresenham error term to first point */
685 clipdx
= abs(new_x1
- x1
);
686 clipdy
= abs(new_y1
- y1
);
688 err
= e
+((clipdy
*e2
) + ((clipdx
-clipdy
)*e1
));
690 err
= e
+((clipdx
*e2
) + ((clipdy
-clipdx
)*e1
));
695 &dashIndexTmp
, pDash
, numInDashList
,
696 &dashOffsetTmp
, isDoubleDash
,
698 signdx
, signdy
, axis
, new_x1
, new_y1
,
703 } /* while (nbox--) */
706 * walk the dash list around to the next line
708 miStepDash (unclippedlen
, &dashIndex
, pDash
,
709 numInDashList
, &dashOffset
);
712 } /* while (nline--) */
715 /* paint the last point if the end style isn't CapNotLast.
716 (Assume that a projecting, butt, or round cap that is one
717 pixel wide is the same as the single pixel of the endpoint.)
720 if ((pGC
->capStyle
!= CapNotLast
) &&
721 ((dashIndex
& 1) == 0 || isDoubleDash
) &&
722 ((ppt
->x
+ xorg
!= pptInit
->x
+ pDrawable
->x
) ||
723 (ppt
->y
+ yorg
!= pptInit
->y
+ pDrawable
->y
) ||
724 (ppt
== pptInit
+ 1)))
730 if ((x2
>= pbox
->x1
) &&
742 mask
= cfbmask
[(x2
& 3)<<1];
743 addrl
+= (y2
* nlwidth
) + ((x2
*3)>> 2);
745 mask
= cfbmask
[x2
& PIM
];
746 addrl
+= (y2
* nlwidth
) + (x2
>> PWSH
);
748 *addrl
= DoMaskRRop (*addrl
, rrops
[pix
].and, rrops
[pix
].xor, mask
);