1
/* $XFree86: xc/programs/Xserver/cfb/cfbline.c,v 3.6 2001/12/14 19:59:23 dawes Exp $ */
2
/***********************************************************
4
Copyright 1987, 1998 The Open Group
6
Permission to use, copy, modify, distribute, and sell this software and its
7
documentation for any purpose is hereby granted without fee, provided that
8
the above copyright notice appear in all copies and that both that
9
copyright notice and this permission notice appear in supporting
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
OPEN GROUP 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 Open Group 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 Open Group.
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
/* $Xorg: cfbline.c,v 1.4 2001/02/09 02:04:38 xorgcvs Exp $ */
52
#include "windowstr.h"
53
#include "pixmapstr.h"
54
#include "regionstr.h"
55
#include "scrnintstr.h"
59
#include "cfbmskbits.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
cfbSegmentSS (pDrawable, pGC, nseg, pSeg)
94
DrawablePtr pDrawable;
97
register xSegment *pSeg;
99
cfbLineSS (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
CfbBits *addrl; /* address of destination pixmap */
119
int nlwidth; /* width in longwords of destination pixmap */
120
int xorg, yorg; /* origin of window */
122
int adx; /* abs values of dx and dy */
124
int signdx; /* sign of dx and dy */
126
int e, e1, e2; /* bresenham error and increments */
127
int len; /* length of segment */
128
int axis; /* major axis */
130
unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
132
/* a bunch of temporaries */
137
cfbPrivGCPtr devPriv;
141
devPriv = cfbGetGCPrivate(pGC);
142
cclip = pGC->pCompositeClip;
143
pboxInit = REGION_RECTS(cclip);
144
nboxInit = REGION_NUM_RECTS(cclip);
146
cfbGetLongWidthAndPointer (pDrawable, nlwidth, addrl)
166
x1 = pSeg->x1 + xorg;
167
y1 = pSeg->y1 + yorg;
168
x2 = pSeg->x2 + xorg;
169
y2 = pSeg->y2 + yorg;
175
if (mode == CoordModePrevious)
184
if (x1 == x2) /* vertical line */
186
/* make the line go top to bottom of screen, keeping
197
if (pGC->capStyle != CapNotLast)
202
else if (pGC->capStyle != CapNotLast)
205
/* get to first band that might contain part of line */
206
while ((nbox) && (pbox->y2 <= y1))
214
/* stop when lower edge of box is beyond end of line */
215
while((nbox) && (y2 >= pbox->y1))
217
if ((x1 >= pbox->x1) && (x1 < pbox->x2))
220
/* this box has part of the line in it */
221
y1t = max(y1, pbox->y1);
222
y2t = min(y2, pbox->y2);
225
cfbVertS (alu, and, xor,
238
else if (y1 == y2) /* horizontal line */
240
/* force line from left to right, keeping
251
if (pGC->capStyle != CapNotLast)
256
else if (pGC->capStyle != CapNotLast)
260
/* find the correct band */
261
while( (nbox) && (pbox->y2 <= y1))
267
/* try to draw the line, if we haven't gone beyond it */
268
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);
295
cfbHorzS (alu, and, xor,
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)
350
cfbBresS (alu, and, xor,
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));
401
cfbBresS(alu, and, xor,
403
signdx, signdy, axis, new_x1, new_y1,
408
} /* while (nbox--) */
410
} /* while (nline--) */
413
/* paint the last point if the end style isn't CapNotLast.
414
(Assume that a projecting, butt, or round cap that is one
415
pixel wide is the same as the single pixel of the endpoint.)
418
if ((pGC->capStyle != CapNotLast) &&
419
((ppt->x + xorg != pptInit->x + pDrawable->x) ||
420
(ppt->y + yorg != pptInit->y + pDrawable->y) ||
421
(ppt == pptInit + 1)))
427
if ((x2 >= pbox->x1) &&
436
mask = cfbmask[(x2 & 3)<<1];
437
addrl += (y2 * nlwidth) + ((x2*3) >> 2);
439
mask = cfbmask[x2 & PIM];
440
addrl += (y2 * nlwidth) + (x2 >> PWSH);
443
*addrl = (scrbits & ~mask) |
444
(DoRRop (scrbits, and, xor) & mask);
455
* Draw dashed 1-pixel lines.
460
cfbSegmentSD (pDrawable, pGC, nseg, pSeg)
461
DrawablePtr pDrawable;
464
register xSegment *pSeg;
466
cfbLineSD( pDrawable, pGC, mode, npt, pptInit)
467
DrawablePtr pDrawable;
469
int mode; /* Origin or Previous */
470
int npt; /* number of points */
477
register BoxPtr pbox;
479
register DDXPointPtr ppt; /* pointer to list of translated points */
482
register unsigned int oc1; /* outcode of point 1 */
483
register unsigned int oc2; /* outcode of point 2 */
485
CfbBits *addrl; /* address of destination pixmap */
486
int nlwidth; /* width in longwords of destination pixmap */
487
int xorg, yorg; /* origin of window */
489
int adx; /* abs values of dx and dy */
491
int signdx; /* sign of dx and dy */
493
int e, e1, e2; /* bresenham error and increments */
494
int len; /* length of segment */
495
int axis; /* major axis */
497
unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
501
unsigned char *pDash;
506
int dashIndexTmp, dashOffsetTmp;
508
cfbPrivGCPtr devPriv;
510
devPriv = cfbGetGCPrivate(pGC);
511
cclip = pGC->pCompositeClip;
512
rrops[0].rop = devPriv->rop;
513
rrops[0].and = devPriv->and;
514
rrops[0].xor = devPriv->xor;
515
if (pGC->alu == GXcopy)
517
rrops[1].rop = GXcopy;
519
rrops[1].xor = PFILL (pGC->bgPixel);
523
rrops[1].rop = cfbReduceRasterOp (pGC->alu,
524
pGC->bgPixel, pGC->planemask,
525
&rrops[1].and, &rrops[1].xor);
527
pboxInit = REGION_RECTS(cclip);
528
nboxInit = REGION_NUM_RECTS(cclip);
530
cfbGetLongWidthAndPointer (pDrawable, nlwidth, addrl)
532
/* compute initial dash values */
534
pDash = (unsigned char *) pGC->dash;
535
numInDashList = pGC->numInDashList;
536
isDoubleDash = (pGC->lineStyle == LineDoubleDash);
539
miStepDash ((int)pGC->dashOffset, &dashIndex, pDash,
540
numInDashList, &dashOffset);
557
x1 = pSeg->x1 + xorg;
558
y1 = pSeg->y1 + yorg;
559
x2 = pSeg->x2 + xorg;
560
y2 = pSeg->y2 + yorg;
566
if (mode == CoordModePrevious)
575
CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
581
e2 = e1 - (adx << 1);
589
e2 = e1 - (ady << 1);
592
SetYMajorOctant(octant);
595
FIXUP_ERROR(e, octant, bias);
597
/* we have bresenham parameters and two points.
598
all we have to do now is clip and draw.
605
OUTCODES(oc1, x1, y1, pbox);
606
OUTCODES(oc2, x2, y2, pbox);
607
if ((oc1 | oc2) == 0)
610
if (pGC->capStyle != CapNotLast)
612
dashIndexTmp = dashIndex;
613
dashOffsetTmp = dashOffset;
615
&dashIndexTmp, pDash, numInDashList,
616
&dashOffsetTmp, isDoubleDash,
618
signdx, signdy, axis, x1, y1,
619
e, e1, e2, unclippedlen);
623
&dashIndex, pDash, numInDashList,
624
&dashOffset, isDoubleDash,
626
signdx, signdy, axis, x1, y1,
627
e, e1, e2, unclippedlen);
635
else /* have to clip */
637
int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
638
int clip1 = 0, clip2 = 0;
642
if (miZeroClipLine(pbox->x1, pbox->y1, pbox->x2-1,
644
&new_x1, &new_y1, &new_x2, &new_y2,
645
adx, ady, &clip1, &clip2,
646
octant, bias, oc1, oc2) == -1)
652
dashIndexTmp = dashIndex;
653
dashOffsetTmp = dashOffset;
660
dlen = abs(new_x1 - x1);
662
dlen = abs(new_y1 - y1);
663
miStepDash (dlen, &dashIndexTmp, pDash,
664
numInDashList, &dashOffsetTmp);
668
len = abs(new_x2 - new_x1);
670
len = abs(new_y2 - new_y1);
672
if (clip2 != 0 || pGC->capStyle != CapNotLast)
679
/* unwind bresenham error term to first point */
682
clipdx = abs(new_x1 - x1);
683
clipdy = abs(new_y1 - y1);
685
err = e+((clipdy*e2) + ((clipdx-clipdy)*e1));
687
err = e+((clipdx*e2) + ((clipdy-clipdx)*e1));
692
&dashIndexTmp, pDash, numInDashList,
693
&dashOffsetTmp, isDoubleDash,
695
signdx, signdy, axis, new_x1, new_y1,
700
} /* while (nbox--) */
703
* walk the dash list around to the next line
705
miStepDash (unclippedlen, &dashIndex, pDash,
706
numInDashList, &dashOffset);
709
} /* while (nline--) */
712
/* paint the last point if the end style isn't CapNotLast.
713
(Assume that a projecting, butt, or round cap that is one
714
pixel wide is the same as the single pixel of the endpoint.)
717
if ((pGC->capStyle != CapNotLast) &&
718
((dashIndex & 1) == 0 || isDoubleDash) &&
719
((ppt->x + xorg != pptInit->x + pDrawable->x) ||
720
(ppt->y + yorg != pptInit->y + pDrawable->y) ||
721
(ppt == pptInit + 1)))
727
if ((x2 >= pbox->x1) &&
739
mask = cfbmask[(x2 & 3)<<1];
740
addrl += (y2 * nlwidth) + ((x2 *3)>> 2);
742
mask = cfbmask[x2 & PIM];
743
addrl += (y2 * nlwidth) + (x2 >> PWSH);
745
*addrl = DoMaskRRop (*addrl, rrops[pix].and, rrops[pix].xor, mask);