1
/* $XFree86: xc/programs/Xserver/mfb/mfbline.c,v 1.6 2001/01/17 22:37:03 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: mfbline.c,v 1.4 2001/02/09 02:05:19 xorgcvs Exp $ */
49
#ifdef HAVE_DIX_CONFIG_H
50
#include <dix-config.h>
56
#include "windowstr.h"
57
#include "pixmapstr.h"
58
#include "regionstr.h"
59
#include "scrnintstr.h"
66
/* single-pixel lines on a color frame buffer
69
horizontal lines are always drawn left to right; we have to
70
move the endpoints right by one after they're swapped.
71
horizontal lines will be confined to a single band of a
72
region. the code finds that band (giving up if the lower
73
bound of the band is above the line we're drawing); then it
74
finds the first box in that band that contains part of the
75
line. we clip the line to subsequent boxes in that band.
76
vertical lines are always drawn top to bottom (y-increasing.)
77
this requires adding one to the y-coordinate of each endpoint
81
when clipping a sloped line, we bring the second point inside
82
the clipping box, rather than one beyond it, and then add 1 to
83
the length of the line before drawing it. this lets us use
84
the same box for finding the outcodes for both endpoints. since
85
the equation for clipping the second endpoint to an edge gives us
86
1 beyond the edge, we then have to move the point towards the
87
first point by one step on the major axis.
88
eventually, there will be a diagram here to explain what's going
89
on. the method uses Cohen-Sutherland outcodes to determine
90
outsideness, and a method similar to Pike's layers for doing the
97
mfbSegmentSS (pDrawable, pGC, nseg, pSeg)
98
DrawablePtr pDrawable;
101
register xSegment *pSeg;
103
mfbLineSS (pDrawable, pGC, mode, npt, pptInit)
104
DrawablePtr pDrawable;
106
int mode; /* Origin or Previous */
107
int npt; /* number of points */
114
register BoxPtr pbox;
116
register DDXPointPtr ppt; /* pointer to list of translated points */
119
unsigned int oc1; /* outcode of point 1 */
120
unsigned int oc2; /* outcode of point 2 */
122
PixelType *addrlBase; /* pointer to start of drawable */
124
PixelType *addrl; /* address of destination pixmap */
126
int nlwidth; /* width in longwords of destination pixmap */
127
int xorg, yorg; /* origin of window */
129
int adx; /* abs values of dx and dy */
131
int signdx; /* sign of dx and dy */
133
int e, e1, e2; /* bresenham error and increments */
134
int len; /* length of segment */
135
int axis; /* major axis */
137
unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
139
/* a bunch of temporaries */
145
if (!(pGC->planemask & 1))
148
cclip = pGC->pCompositeClip;
149
alu = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->rop;
150
pboxInit = REGION_RECTS(cclip);
151
nboxInit = REGION_NUM_RECTS(cclip);
153
mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrlBase);
170
x1 = pSeg->x1 + xorg;
171
y1 = pSeg->y1 + yorg;
172
x2 = pSeg->x2 + xorg;
173
y2 = pSeg->y2 + yorg;
179
if (mode == CoordModePrevious)
188
if (x1 == x2) /* vertical line */
190
/* make the line go top to bottom of screen, keeping
201
if (pGC->capStyle != CapNotLast)
206
else if (pGC->capStyle != CapNotLast)
209
/* get to first band that might contain part of line */
210
while ((nbox) && (pbox->y2 <= y1))
218
/* stop when lower edge of box is beyond end of line */
219
while((nbox) && (y2 >= pbox->y1))
221
if ((x1 >= pbox->x1) && (x1 < pbox->x2))
224
/* this box has part of the line in it */
225
y1t = max(y1, pbox->y1);
226
y2t = min(y2, pbox->y2);
242
else if (y1 == y2) /* horizontal line */
244
/* force line from left to right, keeping
255
if (pGC->capStyle != CapNotLast)
260
else if (pGC->capStyle != CapNotLast)
264
/* find the correct band */
265
while( (nbox) && (pbox->y2 <= y1))
271
/* try to draw the line, if we haven't gone beyond it */
272
if ((nbox) && (pbox->y1 <= y1))
276
/* when we leave this band, we're done */
278
while((nbox) && (pbox->y1 == tmp))
284
/* skip boxes until one might contain start point */
290
/* stop if left of box is beyond right of line */
297
x1t = max(x1, pbox->x1);
298
x2t = min(x2, pbox->x2);
313
else /* sloped line */
315
CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy,
322
e2 = e1 - (adx << 1);
329
e2 = e1 - (ady << 1);
331
SetYMajorOctant(octant);
334
FIXUP_ERROR(e, octant, bias);
336
/* we have bresenham parameters and two points.
337
all we have to do now is clip and draw.
344
OUTCODES(oc1, x1, y1, pbox);
345
OUTCODES(oc2, x2, y2, pbox);
346
if ((oc1 | oc2) == 0)
353
if (pGC->capStyle != CapNotLast)
358
signdx, signdy, axis, x1, y1,
368
int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
369
int clip1 = 0, clip2 = 0;
373
if (miZeroClipLine(pbox->x1, pbox->y1, pbox->x2-1,
375
&new_x1, &new_y1, &new_x2, &new_y2,
376
adx, ady, &clip1, &clip2,
377
octant, bias, oc1, oc2) == -1)
384
len = abs(new_x2 - new_x1);
386
len = abs(new_y2 - new_y1);
388
if (clip2 != 0 || pGC->capStyle != CapNotLast)
395
/* unwind bresenham error term to first point */
398
clipdx = abs(new_x1 - x1);
399
clipdy = abs(new_y1 - y1);
401
err = e+((clipdy*e2) + ((clipdx-clipdy)*e1));
403
err = e+((clipdx*e2) + ((clipdy-clipdx)*e1));
410
signdx, signdy, axis, new_x1, new_y1,
415
} /* while (nbox--) */
417
} /* while (nline--) */
421
/* paint the last point if the end style isn't CapNotLast.
422
(Assume that a projecting, butt, or round cap that is one
423
pixel wide is the same as the single pixel of the endpoint.)
426
if ((pGC->capStyle != CapNotLast) &&
427
((ppt->x + xorg != pptInit->x + pDrawable->x) ||
428
(ppt->y + yorg != pptInit->y + pDrawable->y) ||
429
(ppt == pptInit + 1)))
433
if (alu == RROP_BLACK)
434
_mask = rmask[x2 & PIM];
436
_mask = mask[x2 & PIM];
442
if ((x2 >= pbox->x1) &&
447
addrl = mfbScanline(addrlBase, x2, y2, nlwidth);
470
* Draw dashed 1-pixel lines.
475
mfbSegmentSD (pDrawable, pGC, nseg, pSeg)
476
DrawablePtr pDrawable;
479
register xSegment *pSeg;
481
mfbLineSD( pDrawable, pGC, mode, npt, pptInit)
482
DrawablePtr pDrawable;
484
int mode; /* Origin or Previous */
485
int npt; /* number of points */
492
register BoxPtr pbox;
494
register DDXPointPtr ppt; /* pointer to list of translated points */
497
register unsigned int oc1; /* outcode of point 1 */
498
register unsigned int oc2; /* outcode of point 2 */
500
PixelType *addrl; /* address of destination pixmap */
501
int nlwidth; /* width in longwords of destination pixmap */
502
int xorg, yorg; /* origin of window */
504
int adx; /* abs values of dx and dy */
506
int signdx; /* sign of dx and dy */
508
int e, e1, e2; /* bresenham error and increments */
509
int len; /* length of segment */
510
int axis; /* major axis */
512
unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
515
int fgrop = 0, bgrop = 0;
516
unsigned char *pDash;
521
int dashIndexTmp, dashOffsetTmp;
524
if (!(pGC->planemask & 1))
527
cclip = pGC->pCompositeClip;
528
fgrop = ((mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr))->rop;
529
pboxInit = REGION_RECTS(cclip);
530
nboxInit = REGION_NUM_RECTS(cclip);
532
mfbGetPixelWidthAndPointer(pDrawable, nlwidth, addrl);
534
/* compute initial dash values */
536
pDash = (unsigned char *) pGC->dash;
537
numInDashList = pGC->numInDashList;
538
isDoubleDash = (pGC->lineStyle == LineDoubleDash);
541
miStepDash ((int)pGC->dashOffset, &dashIndex, pDash,
542
numInDashList, &dashOffset);
545
bgrop = mfbReduceRop(pGC->alu, pGC->bgPixel);
562
x1 = pSeg->x1 + xorg;
563
y1 = pSeg->y1 + yorg;
564
x2 = pSeg->x2 + xorg;
565
y2 = pSeg->y2 + yorg;
571
if (mode == CoordModePrevious)
580
CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
586
e2 = e1 - (adx << 1);
594
e2 = e1 - (ady << 1);
597
SetYMajorOctant(octant);
600
FIXUP_ERROR(e, octant, bias);
602
/* we have bresenham parameters and two points.
603
all we have to do now is clip and draw.
610
OUTCODES(oc1, x1, y1, pbox);
611
OUTCODES(oc2, x2, y2, pbox);
612
if ((oc1 | oc2) == 0)
615
if (pGC->capStyle != CapNotLast)
617
dashIndexTmp = dashIndex;
618
dashOffsetTmp = dashOffset;
619
mfbBresD (fgrop, bgrop,
620
&dashIndexTmp, pDash, numInDashList,
621
&dashOffsetTmp, isDoubleDash,
623
signdx, signdy, axis, x1, y1,
624
e, e1, e2, unclippedlen);
627
mfbBresD (fgrop, bgrop,
628
&dashIndex, pDash, numInDashList,
629
&dashOffset, isDoubleDash,
631
signdx, signdy, axis, x1, y1,
632
e, e1, e2, unclippedlen);
640
else /* have to clip */
642
int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
643
int clip1 = 0, clip2 = 0;
647
if (miZeroClipLine(pbox->x1, pbox->y1, pbox->x2-1, pbox->y2-1,
648
&new_x1, &new_y1, &new_x2, &new_y2,
649
adx, ady, &clip1, &clip2,
650
octant, bias, oc1, oc2) == -1)
655
dashIndexTmp = dashIndex;
656
dashOffsetTmp = dashOffset;
662
dlen = abs(new_x1 - x1);
664
dlen = abs(new_y1 - y1);
665
miStepDash (dlen, &dashIndexTmp, pDash,
666
numInDashList, &dashOffsetTmp);
669
len = abs(new_x2 - new_x1);
671
len = abs(new_y2 - new_y1);
673
if (clip2 != 0 || pGC->capStyle != CapNotLast)
680
/* unwind bresenham error term to first point */
683
clipdx = abs(new_x1 - x1);
684
clipdy = abs(new_y1 - y1);
686
err = e+((clipdy*e2) + ((clipdx-clipdy)*e1));
688
err = e+((clipdx*e2) + ((clipdy-clipdx)*e1));
692
mfbBresD (fgrop, bgrop,
693
&dashIndexTmp, pDash, numInDashList,
694
&dashOffsetTmp, isDoubleDash,
696
signdx, signdy, axis, new_x1, new_y1,
701
} /* while (nbox--) */
704
* walk the dash list around to the next line
706
miStepDash (unclippedlen, &dashIndex, pDash,
707
numInDashList, &dashOffset);
710
} /* while (nline--) */
713
/* paint the last point if the end style isn't CapNotLast.
714
(Assume that a projecting, butt, or round cap that is one
715
pixel wide is the same as the single pixel of the endpoint.)
718
if ((pGC->capStyle != CapNotLast) &&
719
((dashIndex & 1) == 0 || isDoubleDash) &&
720
((ppt->x + xorg != pptInit->x + pDrawable->x) ||
721
(ppt->y + yorg != pptInit->y + pDrawable->y) ||
722
(ppt == pptInit + 1)))
728
if ((x2 >= pbox->x1) &&
739
if (rop == RROP_BLACK)
740
_mask = rmask[x2 & PIM];
742
_mask = mask[x2 & PIM];
743
addrl = mfbScanline(addrl, x2, y2, nlwidth);
744
if (rop == RROP_BLACK)
746
else if (rop == RROP_WHITE)