1
2#ifdef HAVE_XORG_CONFIG_H
3#include <xorg-config.h>
4#endif
5
6#include <stdlib.h>
7
8#include <X11/X.h>
9#include "misc.h"
10#include "xf86.h"
11#include "xf86_OSproc.h"
12
13#include "scrnintstr.h"
14#include "pixmapstr.h"
15#include "miline.h"
16#include "xf86str.h"
17#include "xaa.h"
18#include "xaalocal.h"
19
20
21void
22#ifdef POLYSEGMENT
23XAAPolySegment(
24    DrawablePtr	pDrawable,
25    GCPtr	pGC,
26    int		nseg,
27    xSegment	*pSeg
28#else
29XAAPolyLines(
30    DrawablePtr pDrawable,
31    GCPtr	pGC,
32    int		mode,		/* Origin or Previous */
33    int		npt,		/* number of points */
34    DDXPointPtr pptInit
35#endif
36){
37    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
38    BoxPtr pboxInit = RegionRects(pGC->pCompositeClip);
39    int nboxInit = RegionNumRects(pGC->pCompositeClip);
40    unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
41    int xorg = pDrawable->x;
42    int yorg = pDrawable->y;
43    int nbox;
44    BoxPtr pbox;
45#ifndef POLYSEGMENT
46    DDXPointPtr ppt;
47#endif
48    int x1, x2, y1, y2, tmp, len;
49
50    if(!nboxInit)
51	return;
52
53    if (infoRec->SolidLineFlags & LINE_LIMIT_COORDS) {
54	int minValX = infoRec->SolidLineLimits.x1;
55	int maxValX = infoRec->SolidLineLimits.x2;
56	int minValY = infoRec->SolidLineLimits.y1;
57	int maxValY = infoRec->SolidLineLimits.y2;
58#ifdef POLYSEGMENT
59	int n = nseg;
60	xSegment *s = pSeg;
61
62	while (n--)
63#else
64	int n = npt;
65	int xorgtmp = xorg;
66	int yorgtmp = yorg;
67
68	ppt = pptInit;
69	x2 = ppt->x + xorgtmp;
70	y2 = ppt->y + yorgtmp;
71	while (--n)
72#endif
73	{
74#ifdef POLYSEGMENT
75	    x1 = s->x1 + xorg;
76	    y1 = s->y1 + yorg;
77	    x2 = s->x2 + xorg;
78	    y2 = s->y2 + yorg;
79	    s++;
80#else
81	    x1 = x2;
82	    y1 = y2;
83	    ++ppt;
84	    if (mode == CoordModePrevious) {
85		xorgtmp = x1;
86		yorgtmp = y1;
87	    }
88	    x2 = ppt->x + xorgtmp;
89	    y2 = ppt->y + yorgtmp;
90#endif
91	    if (x1 > maxValX || x1 < minValX ||
92		x2 > maxValX || x2 < minValX ||
93		y1 > maxValY || y1 < minValY ||
94		y2 > maxValY || y2 < minValY) {
95#ifdef POLYSEGMENT
96		XAAFallbackOps.PolySegment(pDrawable, pGC, nseg, pSeg);
97#else
98		XAAFallbackOps.Polylines(pDrawable, pGC, mode, npt, pptInit);
99#endif
100		return;
101	    }
102	}
103    }
104
105    (*infoRec->SetupForSolidLine)(infoRec->pScrn, pGC->fgPixel,
106					pGC->alu, pGC->planemask);
107
108#ifdef POLYSEGMENT
109    while (nseg--)
110#else
111    ppt = pptInit;
112    x2 = ppt->x + xorg;
113    y2 = ppt->y + yorg;
114    while(--npt)
115#endif
116    {
117	nbox = nboxInit;
118	pbox = pboxInit;
119
120#ifdef POLYSEGMENT
121	x1 = pSeg->x1 + xorg;
122	y1 = pSeg->y1 + yorg;
123	x2 = pSeg->x2 + xorg;
124	y2 = pSeg->y2 + yorg;
125	pSeg++;
126#else
127	x1 = x2;
128	y1 = y2;
129	++ppt;
130	if (mode == CoordModePrevious) {
131	    xorg = x1;
132	    yorg = y1;
133	}
134	x2 = ppt->x + xorg;
135	y2 = ppt->y + yorg;
136#endif
137
138	if (x1 == x2) { /* vertical line */
139	    /* make the line go top to bottom of screen, keeping
140	       endpoint semantics
141	    */
142	    if (y1 > y2) {
143		tmp = y2;
144		y2 = y1 + 1;
145		y1 = tmp + 1;
146#ifdef POLYSEGMENT
147		if (pGC->capStyle != CapNotLast) y1--;
148#endif
149	    }
150#ifdef POLYSEGMENT
151	    else if (pGC->capStyle != CapNotLast) y2++;
152#endif
153	    /* get to first band that might contain part of line */
154	    while(nbox && (pbox->y2 <= y1)) {
155		pbox++;
156		nbox--;
157	    }
158
159	   /* stop when lower edge of box is beyond end of line */
160	    while(nbox && (y2 >= pbox->y1)) {
161		if ((x1 >= pbox->x1) && (x1 < pbox->x2)) {
162		    tmp = max(y1, pbox->y1);
163		    len = min(y2, pbox->y2) - tmp;
164		    if (len) (*infoRec->SubsequentSolidHorVertLine)(
165				infoRec->pScrn, x1, tmp, len, DEGREES_270);
166		}
167		nbox--;
168		pbox++;
169	    }
170#ifndef POLYSEGMENT
171	    y2 = ppt->y + yorg;
172#endif
173	} else if (y1 == y2) { /* horizontal line */
174	/* force line from left to right, keeping endpoint semantics */
175	    if (x1 > x2) {
176		tmp = x2;
177		x2 = x1 + 1;
178		x1 = tmp + 1;
179#ifdef POLYSEGMENT
180		if (pGC->capStyle != CapNotLast)  x1--;
181#endif
182	    }
183#ifdef POLYSEGMENT
184	    else if (pGC->capStyle != CapNotLast) x2++;
185#endif
186
187	    /* find the correct band */
188	    while(nbox && (pbox->y2 <= y1)) {
189		pbox++;
190		nbox--;
191	    }
192
193	    /* try to draw the line, if we haven't gone beyond it */
194	    if (nbox && (pbox->y1 <= y1)) {
195		int orig_y = pbox->y1;
196		/* when we leave this band, we're done */
197		while(nbox && (orig_y == pbox->y1)) {
198		    if (pbox->x2 <= x1) {
199			/* skip boxes until one might contain start point */
200			nbox--;
201			pbox++;
202			continue;
203		    }
204
205		    /* stop if left of box is beyond right of line */
206		    if (pbox->x1 >= x2) {
207			nbox = 0;
208			break;
209		    }
210
211		    tmp = max(x1, pbox->x1);
212		    len = min(x2, pbox->x2) - tmp;
213		    if (len) (*infoRec->SubsequentSolidHorVertLine)(
214				infoRec->pScrn, tmp, y1, len, DEGREES_0);
215		    nbox--;
216		    pbox++;
217		}
218	    }
219#ifndef POLYSEGMENT
220	    x2 = ppt->x + xorg;
221#endif
222	} else{ /* sloped line */
223	    unsigned int oc1, oc2;
224	    int dmin, dmaj, e, octant;
225
226	    if (infoRec->SubsequentSolidBresenhamLine) {
227	        if((dmaj = x2 - x1) < 0) {
228		   dmaj = -dmaj;
229		   octant = XDECREASING;
230		} else octant = 0;
231
232	        if((dmin = y2 - y1) < 0) {
233		   dmin = -dmin;
234		   octant |= YDECREASING;
235		}
236
237		if(dmin >= dmaj){
238		    tmp = dmin; dmin = dmaj; dmaj = tmp;
239		    octant |= YMAJOR;
240		}
241
242		e = -dmaj - ((bias >> octant) & 1);
243		len = dmaj;
244		dmin <<= 1;
245		dmaj <<= 1;
246	    } else {	/* Muffle compiler */
247		dmin = dmaj = e = octant = len = 0;
248	    }
249
250	    while(nbox--) {
251		oc1 = oc2 = 0;
252		OUTCODES(oc1, x1, y1, pbox);
253		OUTCODES(oc2, x2, y2, pbox);
254		if (!(oc1 | oc2)) {   /* unclipped */
255		    if(infoRec->SubsequentSolidTwoPointLine) {
256			(*infoRec->SubsequentSolidTwoPointLine)(
257				infoRec->pScrn, x1, y1, x2, y2,
258#ifdef POLYSEGMENT
259			    	(pGC->capStyle != CapNotLast) ? 0 :
260#endif
261				OMIT_LAST
262			);
263		    } else {
264			(*infoRec->SubsequentSolidBresenhamLine)(
265				infoRec->pScrn, x1, y1, dmaj, dmin, e,
266#ifdef POLYSEGMENT
267			    	(pGC->capStyle != CapNotLast) ? (len+1) :
268#endif
269			    	len, octant);
270		    }
271		    break;
272		} else if (oc1 & oc2) { /* completely clipped */
273		    pbox++;
274		} else if (infoRec->ClippingFlags & HARDWARE_CLIP_SOLID_LINE) {
275		    (*infoRec->SetClippingRectangle)(infoRec->pScrn,
276			pbox->x1, pbox->y1, pbox->x2 - 1, pbox->y2 - 1);
277
278		    if(infoRec->SubsequentSolidBresenhamLine) {
279			(*infoRec->SubsequentSolidBresenhamLine)(
280				infoRec->pScrn, x1, y1, dmaj, dmin, e,
281#ifdef POLYSEGMENT
282			    	(pGC->capStyle != CapNotLast) ? (len+1) :
283#endif
284			    	len, octant);
285		    } else {
286			(*infoRec->SubsequentSolidTwoPointLine)(
287				infoRec->pScrn, x1, y1, x2, y2,
288#ifdef POLYSEGMENT
289			    	(pGC->capStyle != CapNotLast) ? 0 :
290#endif
291				OMIT_LAST
292			);
293		    }
294		    (*infoRec->DisableClipping)(infoRec->pScrn);
295		    pbox++;
296		} else {
297		    int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
298		    int clip1 = 0, clip2 = 0;
299		    int err, adx, ady;
300
301		    if(octant & YMAJOR) {
302			ady = dmaj >> 1;
303			adx = dmin >> 1;
304		    } else {
305			ady = dmin >> 1;
306			adx = dmaj >> 1;
307		    }
308
309		    if (miZeroClipLine(pbox->x1, pbox->y1,
310				       pbox->x2 - 1, pbox->y2 - 1,
311				       &new_x1, &new_y1, &new_x2, &new_y2,
312				       adx, ady, &clip1, &clip2,
313				       octant, bias, oc1, oc2) == -1)
314		    {
315			pbox++;
316			continue;
317		    }
318
319		    if (octant & YMAJOR)
320			len = abs(new_y2 - new_y1);
321		    else
322			len = abs(new_x2 - new_x1);
323#ifdef POLYSEGMENT
324		    if (clip2 != 0 || pGC->capStyle != CapNotLast)
325			len++;
326#else
327		    len += (clip2 != 0);
328#endif
329		    if (len) {
330		    	int abserr, clipdx, clipdy;
331			/* unwind bresenham error term to first point */
332			if (clip1) {
333			    clipdx = abs(new_x1 - x1);
334			    clipdy = abs(new_y1 - y1);
335
336			    if (octant & YMAJOR)
337				err = e + clipdy*dmin - clipdx*dmaj;
338			    else
339				err = e + clipdx*dmin - clipdy*dmaj;
340			} else
341			    err = e;
342
343#define range infoRec->SolidBresenhamLineErrorTermBits
344			abserr = abs(err);
345			while((abserr & range) ||
346			      (dmaj & range) ||
347			      (dmin & range)) {
348				dmin >>= 1;
349				dmaj >>= 1;
350				abserr >>= 1;
351				err /= 2;
352			}
353
354			(*infoRec->SubsequentSolidBresenhamLine)(
355				infoRec->pScrn, new_x1, new_y1,
356				dmaj, dmin, err, len, octant);
357		    }
358		    pbox++;
359		}
360	    } /* while (nbox--) */
361	} /* sloped line */
362    } /* while (nline--) */
363
364#ifndef POLYSEGMENT
365    /* paint the last point if the end style isn't CapNotLast.
366       (Assume that a projecting, butt, or round cap that is one
367        pixel wide is the same as the single pixel of the endpoint.)
368    */
369
370    if ((pGC->capStyle != CapNotLast) &&
371	((ppt->x + xorg != pptInit->x + pDrawable->x) ||
372	 (ppt->y + yorg != pptInit->y + pDrawable->y) ||
373	 (ppt == pptInit + 1)))
374    {
375	nbox = nboxInit;
376	pbox = pboxInit;
377	while (nbox--)
378	{
379	    if ((x2 >= pbox->x1) && (y2 >= pbox->y1) &&
380		(x2 <  pbox->x2) && (y2 <  pbox->y2))
381	    {
382		(*infoRec->SubsequentSolidHorVertLine)(
383			infoRec->pScrn, x2, y2, 1, DEGREES_0);
384		break;
385	    }
386	    else
387		pbox++;
388	}
389    }
390#endif
391
392    SET_SYNC_FLAG(infoRec);
393}
394
395