1706f2543Smrg
2706f2543Smrg#ifdef HAVE_XORG_CONFIG_H
3706f2543Smrg#include <xorg-config.h>
4706f2543Smrg#endif
5706f2543Smrg
6706f2543Smrg#include <stdlib.h>
7706f2543Smrg
8706f2543Smrg#include <X11/X.h>
9706f2543Smrg#include "misc.h"
10706f2543Smrg#include "xf86.h"
11706f2543Smrg#include "xf86_OSproc.h"
12706f2543Smrg
13706f2543Smrg#include "scrnintstr.h"
14706f2543Smrg#include "pixmapstr.h"
15706f2543Smrg#include "miline.h"
16706f2543Smrg#include "xf86str.h"
17706f2543Smrg#include "xaa.h"
18706f2543Smrg#include "xaalocal.h"
19706f2543Smrg
20706f2543Smrg
21706f2543Smrgvoid
22706f2543Smrg#ifdef POLYSEGMENT
23706f2543SmrgXAAPolySegment(
24706f2543Smrg    DrawablePtr	pDrawable,
25706f2543Smrg    GCPtr	pGC,
26706f2543Smrg    int		nseg,
27706f2543Smrg    xSegment	*pSeg
28706f2543Smrg#else
29706f2543SmrgXAAPolyLines(
30706f2543Smrg    DrawablePtr pDrawable,
31706f2543Smrg    GCPtr	pGC,
32706f2543Smrg    int		mode,		/* Origin or Previous */
33706f2543Smrg    int		npt,		/* number of points */
34706f2543Smrg    DDXPointPtr pptInit
35706f2543Smrg#endif
36706f2543Smrg){
37706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
38706f2543Smrg    BoxPtr pboxInit = RegionRects(pGC->pCompositeClip);
39706f2543Smrg    int nboxInit = RegionNumRects(pGC->pCompositeClip);
40706f2543Smrg    unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
41706f2543Smrg    int xorg = pDrawable->x;
42706f2543Smrg    int yorg = pDrawable->y;
43706f2543Smrg    int nbox;
44706f2543Smrg    BoxPtr pbox;
45706f2543Smrg#ifndef POLYSEGMENT
46706f2543Smrg    DDXPointPtr ppt;
47706f2543Smrg#endif
48706f2543Smrg    int x1, x2, y1, y2, tmp, len;
49706f2543Smrg
50706f2543Smrg    if(!nboxInit)
51706f2543Smrg	return;
52706f2543Smrg
53706f2543Smrg    if (infoRec->SolidLineFlags & LINE_LIMIT_COORDS) {
54706f2543Smrg	int minValX = infoRec->SolidLineLimits.x1;
55706f2543Smrg	int maxValX = infoRec->SolidLineLimits.x2;
56706f2543Smrg	int minValY = infoRec->SolidLineLimits.y1;
57706f2543Smrg	int maxValY = infoRec->SolidLineLimits.y2;
58706f2543Smrg#ifdef POLYSEGMENT
59706f2543Smrg	int n = nseg;
60706f2543Smrg	xSegment *s = pSeg;
61706f2543Smrg
62706f2543Smrg	while (n--)
63706f2543Smrg#else
64706f2543Smrg	int n = npt;
65706f2543Smrg	int xorgtmp = xorg;
66706f2543Smrg	int yorgtmp = yorg;
67706f2543Smrg
68706f2543Smrg	ppt = pptInit;
69706f2543Smrg	x2 = ppt->x + xorgtmp;
70706f2543Smrg	y2 = ppt->y + yorgtmp;
71706f2543Smrg	while (--n)
72706f2543Smrg#endif
73706f2543Smrg	{
74706f2543Smrg#ifdef POLYSEGMENT
75706f2543Smrg	    x1 = s->x1 + xorg;
76706f2543Smrg	    y1 = s->y1 + yorg;
77706f2543Smrg	    x2 = s->x2 + xorg;
78706f2543Smrg	    y2 = s->y2 + yorg;
79706f2543Smrg	    s++;
80706f2543Smrg#else
81706f2543Smrg	    x1 = x2;
82706f2543Smrg	    y1 = y2;
83706f2543Smrg	    ++ppt;
84706f2543Smrg	    if (mode == CoordModePrevious) {
85706f2543Smrg		xorgtmp = x1;
86706f2543Smrg		yorgtmp = y1;
87706f2543Smrg	    }
88706f2543Smrg	    x2 = ppt->x + xorgtmp;
89706f2543Smrg	    y2 = ppt->y + yorgtmp;
90706f2543Smrg#endif
91706f2543Smrg	    if (x1 > maxValX || x1 < minValX ||
92706f2543Smrg		x2 > maxValX || x2 < minValX ||
93706f2543Smrg		y1 > maxValY || y1 < minValY ||
94706f2543Smrg		y2 > maxValY || y2 < minValY) {
95706f2543Smrg#ifdef POLYSEGMENT
96706f2543Smrg		XAAFallbackOps.PolySegment(pDrawable, pGC, nseg, pSeg);
97706f2543Smrg#else
98706f2543Smrg		XAAFallbackOps.Polylines(pDrawable, pGC, mode, npt, pptInit);
99706f2543Smrg#endif
100706f2543Smrg		return;
101706f2543Smrg	    }
102706f2543Smrg	}
103706f2543Smrg    }
104706f2543Smrg
105706f2543Smrg    (*infoRec->SetupForSolidLine)(infoRec->pScrn, pGC->fgPixel,
106706f2543Smrg					pGC->alu, pGC->planemask);
107706f2543Smrg
108706f2543Smrg#ifdef POLYSEGMENT
109706f2543Smrg    while (nseg--)
110706f2543Smrg#else
111706f2543Smrg    ppt = pptInit;
112706f2543Smrg    x2 = ppt->x + xorg;
113706f2543Smrg    y2 = ppt->y + yorg;
114706f2543Smrg    while(--npt)
115706f2543Smrg#endif
116706f2543Smrg    {
117706f2543Smrg	nbox = nboxInit;
118706f2543Smrg	pbox = pboxInit;
119706f2543Smrg
120706f2543Smrg#ifdef POLYSEGMENT
121706f2543Smrg	x1 = pSeg->x1 + xorg;
122706f2543Smrg	y1 = pSeg->y1 + yorg;
123706f2543Smrg	x2 = pSeg->x2 + xorg;
124706f2543Smrg	y2 = pSeg->y2 + yorg;
125706f2543Smrg	pSeg++;
126706f2543Smrg#else
127706f2543Smrg	x1 = x2;
128706f2543Smrg	y1 = y2;
129706f2543Smrg	++ppt;
130706f2543Smrg	if (mode == CoordModePrevious) {
131706f2543Smrg	    xorg = x1;
132706f2543Smrg	    yorg = y1;
133706f2543Smrg	}
134706f2543Smrg	x2 = ppt->x + xorg;
135706f2543Smrg	y2 = ppt->y + yorg;
136706f2543Smrg#endif
137706f2543Smrg
138706f2543Smrg	if (x1 == x2) { /* vertical line */
139706f2543Smrg	    /* make the line go top to bottom of screen, keeping
140706f2543Smrg	       endpoint semantics
141706f2543Smrg	    */
142706f2543Smrg	    if (y1 > y2) {
143706f2543Smrg		tmp = y2;
144706f2543Smrg		y2 = y1 + 1;
145706f2543Smrg		y1 = tmp + 1;
146706f2543Smrg#ifdef POLYSEGMENT
147706f2543Smrg		if (pGC->capStyle != CapNotLast) y1--;
148706f2543Smrg#endif
149706f2543Smrg	    }
150706f2543Smrg#ifdef POLYSEGMENT
151706f2543Smrg	    else if (pGC->capStyle != CapNotLast) y2++;
152706f2543Smrg#endif
153706f2543Smrg	    /* get to first band that might contain part of line */
154706f2543Smrg	    while(nbox && (pbox->y2 <= y1)) {
155706f2543Smrg		pbox++;
156706f2543Smrg		nbox--;
157706f2543Smrg	    }
158706f2543Smrg
159706f2543Smrg	   /* stop when lower edge of box is beyond end of line */
160706f2543Smrg	    while(nbox && (y2 >= pbox->y1)) {
161706f2543Smrg		if ((x1 >= pbox->x1) && (x1 < pbox->x2)) {
162706f2543Smrg		    tmp = max(y1, pbox->y1);
163706f2543Smrg		    len = min(y2, pbox->y2) - tmp;
164706f2543Smrg		    if (len) (*infoRec->SubsequentSolidHorVertLine)(
165706f2543Smrg				infoRec->pScrn, x1, tmp, len, DEGREES_270);
166706f2543Smrg		}
167706f2543Smrg		nbox--;
168706f2543Smrg		pbox++;
169706f2543Smrg	    }
170706f2543Smrg#ifndef POLYSEGMENT
171706f2543Smrg	    y2 = ppt->y + yorg;
172706f2543Smrg#endif
173706f2543Smrg	} else if (y1 == y2) { /* horizontal line */
174706f2543Smrg	/* force line from left to right, keeping endpoint semantics */
175706f2543Smrg	    if (x1 > x2) {
176706f2543Smrg		tmp = x2;
177706f2543Smrg		x2 = x1 + 1;
178706f2543Smrg		x1 = tmp + 1;
179706f2543Smrg#ifdef POLYSEGMENT
180706f2543Smrg		if (pGC->capStyle != CapNotLast)  x1--;
181706f2543Smrg#endif
182706f2543Smrg	    }
183706f2543Smrg#ifdef POLYSEGMENT
184706f2543Smrg	    else if (pGC->capStyle != CapNotLast) x2++;
185706f2543Smrg#endif
186706f2543Smrg
187706f2543Smrg	    /* find the correct band */
188706f2543Smrg	    while(nbox && (pbox->y2 <= y1)) {
189706f2543Smrg		pbox++;
190706f2543Smrg		nbox--;
191706f2543Smrg	    }
192706f2543Smrg
193706f2543Smrg	    /* try to draw the line, if we haven't gone beyond it */
194706f2543Smrg	    if (nbox && (pbox->y1 <= y1)) {
195706f2543Smrg		int orig_y = pbox->y1;
196706f2543Smrg		/* when we leave this band, we're done */
197706f2543Smrg		while(nbox && (orig_y == pbox->y1)) {
198706f2543Smrg		    if (pbox->x2 <= x1) {
199706f2543Smrg			/* skip boxes until one might contain start point */
200706f2543Smrg			nbox--;
201706f2543Smrg			pbox++;
202706f2543Smrg			continue;
203706f2543Smrg		    }
204706f2543Smrg
205706f2543Smrg		    /* stop if left of box is beyond right of line */
206706f2543Smrg		    if (pbox->x1 >= x2) {
207706f2543Smrg			nbox = 0;
208706f2543Smrg			break;
209706f2543Smrg		    }
210706f2543Smrg
211706f2543Smrg		    tmp = max(x1, pbox->x1);
212706f2543Smrg		    len = min(x2, pbox->x2) - tmp;
213706f2543Smrg		    if (len) (*infoRec->SubsequentSolidHorVertLine)(
214706f2543Smrg				infoRec->pScrn, tmp, y1, len, DEGREES_0);
215706f2543Smrg		    nbox--;
216706f2543Smrg		    pbox++;
217706f2543Smrg		}
218706f2543Smrg	    }
219706f2543Smrg#ifndef POLYSEGMENT
220706f2543Smrg	    x2 = ppt->x + xorg;
221706f2543Smrg#endif
222706f2543Smrg	} else{ /* sloped line */
223706f2543Smrg	    unsigned int oc1, oc2;
224706f2543Smrg	    int dmin, dmaj, e, octant;
225706f2543Smrg
226706f2543Smrg	    if (infoRec->SubsequentSolidBresenhamLine) {
227706f2543Smrg	        if((dmaj = x2 - x1) < 0) {
228706f2543Smrg		   dmaj = -dmaj;
229706f2543Smrg		   octant = XDECREASING;
230706f2543Smrg		} else octant = 0;
231706f2543Smrg
232706f2543Smrg	        if((dmin = y2 - y1) < 0) {
233706f2543Smrg		   dmin = -dmin;
234706f2543Smrg		   octant |= YDECREASING;
235706f2543Smrg		}
236706f2543Smrg
237706f2543Smrg		if(dmin >= dmaj){
238706f2543Smrg		    tmp = dmin; dmin = dmaj; dmaj = tmp;
239706f2543Smrg		    octant |= YMAJOR;
240706f2543Smrg		}
241706f2543Smrg
242706f2543Smrg		e = -dmaj - ((bias >> octant) & 1);
243706f2543Smrg		len = dmaj;
244706f2543Smrg		dmin <<= 1;
245706f2543Smrg		dmaj <<= 1;
246706f2543Smrg	    } else {	/* Muffle compiler */
247706f2543Smrg		dmin = dmaj = e = octant = len = 0;
248706f2543Smrg	    }
249706f2543Smrg
250706f2543Smrg	    while(nbox--) {
251706f2543Smrg		oc1 = oc2 = 0;
252706f2543Smrg		OUTCODES(oc1, x1, y1, pbox);
253706f2543Smrg		OUTCODES(oc2, x2, y2, pbox);
254706f2543Smrg		if (!(oc1 | oc2)) {   /* unclipped */
255706f2543Smrg		    if(infoRec->SubsequentSolidTwoPointLine) {
256706f2543Smrg			(*infoRec->SubsequentSolidTwoPointLine)(
257706f2543Smrg				infoRec->pScrn, x1, y1, x2, y2,
258706f2543Smrg#ifdef POLYSEGMENT
259706f2543Smrg			    	(pGC->capStyle != CapNotLast) ? 0 :
260706f2543Smrg#endif
261706f2543Smrg				OMIT_LAST
262706f2543Smrg			);
263706f2543Smrg		    } else {
264706f2543Smrg			(*infoRec->SubsequentSolidBresenhamLine)(
265706f2543Smrg				infoRec->pScrn, x1, y1, dmaj, dmin, e,
266706f2543Smrg#ifdef POLYSEGMENT
267706f2543Smrg			    	(pGC->capStyle != CapNotLast) ? (len+1) :
268706f2543Smrg#endif
269706f2543Smrg			    	len, octant);
270706f2543Smrg		    }
271706f2543Smrg		    break;
272706f2543Smrg		} else if (oc1 & oc2) { /* completely clipped */
273706f2543Smrg		    pbox++;
274706f2543Smrg		} else if (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_LINE) {
275706f2543Smrg		    (*infoRec->SetClippingRectangle)(infoRec->pScrn,
276706f2543Smrg			pbox->x1, pbox->y1, pbox->x2 - 1, pbox->y2 - 1);
277706f2543Smrg
278706f2543Smrg		    if(infoRec->SubsequentSolidBresenhamLine) {
279706f2543Smrg			(*infoRec->SubsequentSolidBresenhamLine)(
280706f2543Smrg				infoRec->pScrn, x1, y1, dmaj, dmin, e,
281706f2543Smrg#ifdef POLYSEGMENT
282706f2543Smrg			    	(pGC->capStyle != CapNotLast) ? (len+1) :
283706f2543Smrg#endif
284706f2543Smrg			    	len, octant);
285706f2543Smrg		    } else {
286706f2543Smrg			(*infoRec->SubsequentSolidTwoPointLine)(
287706f2543Smrg				infoRec->pScrn, x1, y1, x2, y2,
288706f2543Smrg#ifdef POLYSEGMENT
289706f2543Smrg			    	(pGC->capStyle != CapNotLast) ? 0 :
290706f2543Smrg#endif
291706f2543Smrg				OMIT_LAST
292706f2543Smrg			);
293706f2543Smrg		    }
294706f2543Smrg		    (*infoRec->DisableClipping)(infoRec->pScrn);
295706f2543Smrg		    pbox++;
296706f2543Smrg		} else {
297706f2543Smrg		    int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
298706f2543Smrg		    int clip1 = 0, clip2 = 0;
299706f2543Smrg		    int err, adx, ady;
300706f2543Smrg
301706f2543Smrg		    if(octant & YMAJOR) {
302706f2543Smrg			ady = dmaj >> 1;
303706f2543Smrg			adx = dmin >> 1;
304706f2543Smrg		    } else {
305706f2543Smrg			ady = dmin >> 1;
306706f2543Smrg			adx = dmaj >> 1;
307706f2543Smrg		    }
308706f2543Smrg
309706f2543Smrg		    if (miZeroClipLine(pbox->x1, pbox->y1,
310706f2543Smrg				       pbox->x2 - 1, pbox->y2 - 1,
311706f2543Smrg				       &new_x1, &new_y1, &new_x2, &new_y2,
312706f2543Smrg				       adx, ady, &clip1, &clip2,
313706f2543Smrg				       octant, bias, oc1, oc2) == -1)
314706f2543Smrg		    {
315706f2543Smrg			pbox++;
316706f2543Smrg			continue;
317706f2543Smrg		    }
318706f2543Smrg
319706f2543Smrg		    if (octant & YMAJOR)
320706f2543Smrg			len = abs(new_y2 - new_y1);
321706f2543Smrg		    else
322706f2543Smrg			len = abs(new_x2 - new_x1);
323706f2543Smrg#ifdef POLYSEGMENT
324706f2543Smrg		    if (clip2 != 0 || pGC->capStyle != CapNotLast)
325706f2543Smrg			len++;
326706f2543Smrg#else
327706f2543Smrg		    len += (clip2 != 0);
328706f2543Smrg#endif
329706f2543Smrg		    if (len) {
330706f2543Smrg		    	int abserr, clipdx, clipdy;
331706f2543Smrg			/* unwind bresenham error term to first point */
332706f2543Smrg			if (clip1) {
333706f2543Smrg			    clipdx = abs(new_x1 - x1);
334706f2543Smrg			    clipdy = abs(new_y1 - y1);
335706f2543Smrg
336706f2543Smrg			    if (octant & YMAJOR)
337706f2543Smrg				err = e + clipdy*dmin - clipdx*dmaj;
338706f2543Smrg			    else
339706f2543Smrg				err = e + clipdx*dmin - clipdy*dmaj;
340706f2543Smrg			} else
341706f2543Smrg			    err = e;
342706f2543Smrg
343706f2543Smrg#define range infoRec->SolidBresenhamLineErrorTermBits
344706f2543Smrg			abserr = abs(err);
345706f2543Smrg			while((abserr & range) ||
346706f2543Smrg			      (dmaj & range) ||
347706f2543Smrg			      (dmin & range)) {
348706f2543Smrg				dmin >>= 1;
349706f2543Smrg				dmaj >>= 1;
350706f2543Smrg				abserr >>= 1;
351706f2543Smrg				err /= 2;
352706f2543Smrg			}
353706f2543Smrg
354706f2543Smrg			(*infoRec->SubsequentSolidBresenhamLine)(
355706f2543Smrg				infoRec->pScrn, new_x1, new_y1,
356706f2543Smrg				dmaj, dmin, err, len, octant);
357706f2543Smrg		    }
358706f2543Smrg		    pbox++;
359706f2543Smrg		}
360706f2543Smrg	    } /* while (nbox--) */
361706f2543Smrg	} /* sloped line */
362706f2543Smrg    } /* while (nline--) */
363706f2543Smrg
364706f2543Smrg#ifndef POLYSEGMENT
365706f2543Smrg    /* paint the last point if the end style isn't CapNotLast.
366706f2543Smrg       (Assume that a projecting, butt, or round cap that is one
367706f2543Smrg        pixel wide is the same as the single pixel of the endpoint.)
368706f2543Smrg    */
369706f2543Smrg
370706f2543Smrg    if ((pGC->capStyle != CapNotLast) &&
371706f2543Smrg	((ppt->x + xorg != pptInit->x + pDrawable->x) ||
372706f2543Smrg	 (ppt->y + yorg != pptInit->y + pDrawable->y) ||
373706f2543Smrg	 (ppt == pptInit + 1)))
374706f2543Smrg    {
375706f2543Smrg	nbox = nboxInit;
376706f2543Smrg	pbox = pboxInit;
377706f2543Smrg	while (nbox--)
378706f2543Smrg	{
379706f2543Smrg	    if ((x2 >= pbox->x1) && (y2 >= pbox->y1) &&
380706f2543Smrg		(x2 <  pbox->x2) && (y2 <  pbox->y2))
381706f2543Smrg	    {
382706f2543Smrg		(*infoRec->SubsequentSolidHorVertLine)(
383706f2543Smrg			infoRec->pScrn, x2, y2, 1, DEGREES_0);
384706f2543Smrg		break;
385706f2543Smrg	    }
386706f2543Smrg	    else
387706f2543Smrg		pbox++;
388706f2543Smrg	}
389706f2543Smrg    }
390706f2543Smrg#endif
391706f2543Smrg
392706f2543Smrg    SET_SYNC_FLAG(infoRec);
393706f2543Smrg}
394706f2543Smrg
395