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
23XAAPolySegmentDashed(
24    DrawablePtr	pDrawable,
25    GCPtr	pGC,
26    int		nseg,
27    xSegment	*pSeg
28#else
29XAAPolyLinesDashed(
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    XAAGCPtr   pGCPriv = (XAAGCPtr)dixLookupPrivate(&pGC->devPrivates,
39						    XAAGetGCKey());
40    BoxPtr pboxInit = RegionRects(pGC->pCompositeClip);
41    int nboxInit = RegionNumRects(pGC->pCompositeClip);
42    unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
43    int xorg = pDrawable->x;
44    int yorg = pDrawable->y;
45    int nbox;
46    BoxPtr pbox;
47#ifndef POLYSEGMENT
48    DDXPointPtr ppt;
49#endif
50    unsigned int oc1, oc2;
51    int dmin, dmaj, e, octant;
52    int x1, x2, y1, y2, tmp, len, offset;
53    int PatternLength, PatternOffset;
54
55    if(!nboxInit)
56	return;
57
58    if (infoRec->DashedLineFlags & LINE_LIMIT_COORDS) {
59	int minValX = infoRec->DashedLineLimits.x1;
60	int maxValX = infoRec->DashedLineLimits.x2;
61	int minValY = infoRec->DashedLineLimits.y1;
62	int maxValY = infoRec->DashedLineLimits.y2;
63#ifdef POLYSEGMENT
64	int n = nseg;
65	xSegment *s = pSeg;
66
67	while (n--)
68#else
69	int n = npt;
70	int xorgtmp = xorg;
71	int yorgtmp = yorg;
72
73	ppt = pptInit;
74	x2 = ppt->x + xorgtmp;
75	y2 = ppt->y + yorgtmp;
76	while (--n)
77#endif
78	{
79#ifdef POLYSEGMENT
80	    x1 = s->x1 + xorg;
81	    y1 = s->y1 + yorg;
82	    x2 = s->x2 + xorg;
83	    y2 = s->y2 + yorg;
84	    s++;
85#else
86	    x1 = x2;
87	    y1 = y2;
88	    ++ppt;
89	    if (mode == CoordModePrevious) {
90		xorgtmp = x1;
91		yorgtmp = y1;
92	    }
93	    x2 = ppt->x + xorgtmp;
94	    y2 = ppt->y + yorgtmp;
95#endif
96	    if (x1 > maxValX || x1 < minValX ||
97		x2 > maxValX || x2 < minValX ||
98		y1 > maxValY || y1 < minValY ||
99		y2 > maxValY || y2 < minValY) {
100#ifdef POLYSEGMENT
101		XAAFallbackOps.PolySegment(pDrawable, pGC, nseg, pSeg);
102#else
103		XAAFallbackOps.Polylines(pDrawable, pGC, mode, npt, pptInit);
104#endif
105		return;
106	    }
107	}
108    }
109
110    PatternLength = pGCPriv->DashLength;
111    PatternOffset = pGC->dashOffset % PatternLength;
112
113    (*infoRec->SetupForDashedLine)(infoRec->pScrn, pGC->fgPixel,
114		(pGC->lineStyle == LineDoubleDash) ? pGC->bgPixel : -1,
115		pGC->alu, pGC->planemask, PatternLength, pGCPriv->DashPattern);
116
117
118#ifdef POLYSEGMENT
119    while (nseg--)
120#else
121    ppt = pptInit;
122    x2 = ppt->x + xorg;
123    y2 = ppt->y + yorg;
124    while(--npt)
125#endif
126    {
127	nbox = nboxInit;
128	pbox = pboxInit;
129
130#ifdef POLYSEGMENT
131	x1 = pSeg->x1 + xorg;
132	y1 = pSeg->y1 + yorg;
133	x2 = pSeg->x2 + xorg;
134	y2 = pSeg->y2 + yorg;
135	pSeg++;
136#else
137	x1 = x2;
138	y1 = y2;
139	++ppt;
140	if (mode == CoordModePrevious) {
141	    xorg = x1;
142	    yorg = y1;
143	}
144	x2 = ppt->x + xorg;
145	y2 = ppt->y + yorg;
146#endif
147
148
149	if (infoRec->SubsequentDashedBresenhamLine) {
150	    if((dmaj = x2 - x1) < 0) {
151		dmaj = -dmaj;
152		octant = XDECREASING;
153	    } else octant = 0;
154
155	    if((dmin = y2 - y1) < 0) {
156		dmin = -dmin;
157		octant |= YDECREASING;
158	    }
159
160	    if(dmin >= dmaj){
161		tmp = dmin; dmin = dmaj; dmaj = tmp;
162		octant |= YMAJOR;
163	    }
164
165	    e = -dmaj - ((bias >> octant) & 1);
166	    len = dmaj;
167	    dmin <<= 1;
168	    dmaj <<= 1;
169	} else {	/* Muffle compiler */
170	    dmin = dmaj = e = octant = len = 0;
171	}
172
173	while(nbox--) {
174	    oc1 = oc2 = 0;
175	    OUTCODES(oc1, x1, y1, pbox);
176	    OUTCODES(oc2, x2, y2, pbox);
177	    if (!(oc1 | oc2)) {   /* uncliped */
178		if(infoRec->SubsequentDashedTwoPointLine) {
179		   (*infoRec->SubsequentDashedTwoPointLine)(
180				infoRec->pScrn, x1, y1, x2, y2,
181#ifdef POLYSEGMENT
182			    	(pGC->capStyle != CapNotLast) ? 0 :
183#endif
184				OMIT_LAST, PatternOffset);
185		} else {
186		    (*infoRec->SubsequentDashedBresenhamLine)(
187				infoRec->pScrn, x1, y1, dmaj, dmin, e,
188#ifdef POLYSEGMENT
189			    	(pGC->capStyle != CapNotLast) ? (len+1) :
190#endif
191			    	len, octant, PatternOffset);
192		}
193		break;
194	    } else if (oc1 & oc2) { /* completely clipped */
195		pbox++;
196	    } else if (infoRec->ClippingFlags & HARDWARE_CLIP_DASHED_LINE) {
197		(*infoRec->SetClippingRectangle)(infoRec->pScrn,
198			pbox->x1, pbox->y1, pbox->x2 - 1, pbox->y2 - 1);
199
200		if(infoRec->SubsequentDashedBresenhamLine) {
201		    (*infoRec->SubsequentDashedBresenhamLine)(
202				infoRec->pScrn, x1, y1, dmaj, dmin, e,
203#ifdef POLYSEGMENT
204			    	(pGC->capStyle != CapNotLast) ? (len+1) :
205#endif
206			    	len, octant, PatternOffset);
207		} else {
208			(*infoRec->SubsequentDashedTwoPointLine)(
209				infoRec->pScrn, x1, y1, x2, y2,
210#ifdef POLYSEGMENT
211			    	(pGC->capStyle != CapNotLast) ? 0 :
212#endif
213				OMIT_LAST, PatternOffset
214			);
215		}
216		(*infoRec->DisableClipping)(infoRec->pScrn);
217		pbox++;
218	    } else {
219		int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
220		int clip1 = 0, clip2 = 0;
221		int err, adx, ady;
222
223		if(octant & YMAJOR) {
224		    ady = dmaj >> 1;
225		    adx = dmin >> 1;
226		} else {
227		    ady = dmin >> 1;
228		    adx = dmaj >> 1;
229		}
230
231		if (miZeroClipLine(pbox->x1, pbox->y1,
232				       pbox->x2 - 1, pbox->y2 - 1,
233				       &new_x1, &new_y1, &new_x2, &new_y2,
234				       adx, ady, &clip1, &clip2,
235				       octant, bias, oc1, oc2) == -1)
236		{
237		    pbox++;
238		    continue;
239		}
240
241		if (octant & YMAJOR)
242		    len = abs(new_y2 - new_y1);
243		else
244		    len = abs(new_x2 - new_x1);
245#ifdef POLYSEGMENT
246		if (clip2 != 0 || pGC->capStyle != CapNotLast)
247		    len++;
248#else
249		len += (clip2 != 0);
250#endif
251		if (len) {
252		    int abserr, clipdx, clipdy;
253			/* unwind bresenham error term to first point */
254		    if (clip1) {
255			clipdx = abs(new_x1 - x1);
256			clipdy = abs(new_y1 - y1);
257
258			if (octant & YMAJOR)
259			    err = e + clipdy*dmin - clipdx*dmaj;
260			else
261			    err = e + clipdx*dmin - clipdy*dmaj;
262		    } else
263			err = e;
264
265#define range infoRec->DashedBresenhamLineErrorTermBits
266		    abserr = abs(err);
267		    while((abserr & range) ||
268			  (dmaj & range) ||
269			  (dmin & range)) {
270			dmin >>= 1;
271			dmaj >>= 1;
272			abserr >>= 1;
273			err /= 2;
274		    }
275
276		    if(octant & YMAJOR)
277			offset = abs(new_y1 - y1);
278		    else
279			offset = abs(new_x1 - x1);
280
281		    offset += PatternOffset;
282		    offset %= PatternLength;
283
284		    (*infoRec->SubsequentDashedBresenhamLine)(
285				infoRec->pScrn, new_x1, new_y1,
286				dmaj, dmin, err, len, octant, offset);
287		}
288		pbox++;
289	    }
290	} /* while (nbox--) */
291#ifndef POLYSEGMENT
292	len = abs(y2 - y1);
293	tmp = abs(x2 - x1);
294	PatternOffset += (len > tmp) ? len : tmp;
295	PatternOffset %= PatternLength;
296#endif
297    } /* while (nline--) */
298
299#ifndef POLYSEGMENT
300    /* paint the last point if the end style isn't CapNotLast.
301       (Assume that a projecting, butt, or round cap that is one
302        pixel wide is the same as the single pixel of the endpoint.)
303    */
304
305    if ((pGC->capStyle != CapNotLast) &&
306	((ppt->x + xorg != pptInit->x + pDrawable->x) ||
307	 (ppt->y + yorg != pptInit->y + pDrawable->y) ||
308	 (ppt == pptInit + 1)))
309    {
310	nbox = nboxInit;
311	pbox = pboxInit;
312	while (nbox--) {
313	    if ((x2 >= pbox->x1) && (y2 >= pbox->y1) &&
314		(x2 <  pbox->x2) && (y2 <  pbox->y2))
315	    {
316		if(infoRec->SubsequentDashedTwoPointLine) {
317			(*infoRec->SubsequentDashedTwoPointLine)(
318				infoRec->pScrn, x2, y2, x2, y2, 0,
319				PatternOffset);
320		} else {
321			(*infoRec->SubsequentDashedBresenhamLine)(
322				infoRec->pScrn, x2, y2, 2, 0, -1,
323				1, 0, PatternOffset);
324		}
325		break;
326	    } else
327		pbox++;
328	}
329    }
330#endif
331
332    SET_SYNC_FLAG(infoRec);
333}
334
335