1 /*
2  * $XConsortium: cfbply1rct.c /main/16 1996/08/12 22:07:31 dpw $
3  * $XFree86: xc/programs/Xserver/cfb/cfbply1rct.c,v 3.3 1996/12/23 06:29:21 dawes Exp $
4  *
5 Copyright (c) 1990  X Consortium
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
20 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 
24 Except as contained in this notice, the name of the X Consortium shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from the X Consortium.
27  *
28  * Author:  Keith Packard, MIT X Consortium
29  */
30 
31 #include "X.h"
32 
33 #include "gcstruct.h"
34 #include "windowstr.h"
35 #include "pixmapstr.h"
36 #include "regionstr.h"
37 #include "scrnintstr.h"
38 #include "mistruct.h"
39 
40 #include "cfb.h"
41 #include "cfbmskbits.h"
42 #include "cfbrrop.h"
43 
44 void
45 RROP_NAME(cfbFillPoly1Rect) (pDrawable, pGC, shape, mode, count, ptsIn)
46     DrawablePtr	pDrawable;
47     GCPtr	pGC;
48     int		shape;
49     int		mode;
50     int		count;
51     DDXPointPtr	ptsIn;
52 {
53     cfbPrivGCPtr    devPriv;
54     int		    nwidth;
55     unsigned long   *addrl, *addr;
56 #if PSZ == 24
57     unsigned long startmask, endmask;
58     register int pidx;
59 #endif
60     int		    maxy;
61     int		    origin;
62     register int    vertex1, vertex2;
63     int		    c;
64     BoxPtr	    extents;
65     int		    clip;
66     int		    y;
67     int		    *vertex1p, *vertex2p;
68     int		    *endp;
69     int		    x1, x2;
70     int		    dx1, dx2;
71     int		    dy1, dy2;
72     int		    e1, e2;
73     int		    step1, step2;
74     int		    sign1, sign2;
75     int		    h;
76     int		    l, r;
77     unsigned long   mask, bits = ~((unsigned long)0);
78     int		    nmiddle;
79     RROP_DECLARE
80 
81     if (mode == CoordModePrevious)
82     {
83 	miFillPolygon (pDrawable, pGC, shape, mode, count, ptsIn);
84 	return;
85     }
86 
87     devPriv = cfbGetGCPrivate(pGC);
88 #ifdef NO_ONE_RECT
89     if (REGION_NUM_RECTS(devPriv->pCompositeClip) != 1)
90     {
91 	miFillPolygon (pDrawable, pGC, shape, mode, count, ptsIn);
92 	return;
93     }
94 #endif
95     origin = *((int *) &pDrawable->x);
96     vertex2 = origin - ((origin & 0x8000) << 1);
97     extents = &devPriv->pCompositeClip->extents;
98     RROP_FETCH_GCPRIV(devPriv);
99     vertex1 = *((int *) &extents->x1) - vertex2;
100     vertex2 = *((int *) &extents->x2) - vertex2 - 0x00010001;
101     clip = 0;
102     y = 32767;
103     maxy = 0;
104     vertex2p = (int *) ptsIn;
105     endp = vertex2p + count;
106     if (shape == Convex)
107     {
108     	while (count--)
109     	{
110 	    c = *vertex2p;
111 	    clip |= (c - vertex1) | (vertex2 - c);
112 	    c = intToY(c);
113 	    if (c < y)
114 	    {
115 	    	y = c;
116 	    	vertex1p = vertex2p;
117 	    }
118 	    vertex2p++;
119 	    if (c > maxy)
120 	    	maxy = c;
121     	}
122     }
123     else
124     {
125 	int yFlip = 0;
126 	dx1 = 1;
127 	x2 = -1;
128 	x1 = -1;
129     	while (count--)
130     	{
131 	    c = *vertex2p;
132 	    clip |= (c - vertex1) | (vertex2 - c);
133 	    c = intToY(c);
134 	    if (c < y)
135 	    {
136 	    	y = c;
137 	    	vertex1p = vertex2p;
138 	    }
139 	    vertex2p++;
140 	    if (c > maxy)
141 	    	maxy = c;
142 	    if (c == x1)
143 		continue;
144 	    if (dx1 > 0)
145 	    {
146 		if (x2 < 0)
147 		    x2 = c;
148 		else
149 		    dx2 = dx1 = (c - x1) >> 31;
150 	    }
151 	    else
152 		if ((c - x1) >> 31 != dx1)
153 		{
154 		    dx1 = ~dx1;
155 		    yFlip++;
156 		}
157 	    x1 = c;
158        	}
159 	x1 = (x2 - c) >> 31;
160 	if (x1 != dx1)
161 	    yFlip++;
162 	if (x1 != dx2)
163 	    yFlip++;
164 	if (yFlip != 2)
165 	    clip = 0x8000;
166     }
167     if (y == maxy)
168 	return;
169 
170     if (clip & 0x80008000)
171     {
172 	miFillPolygon (pDrawable, pGC, shape, mode, vertex2p - (int *) ptsIn, ptsIn);
173 	return;
174     }
175 
176 #define AddrYPlus(a,y)  (unsigned long *) (((unsigned char *) (a)) + (y) * nwidth)
177 
178     cfbGetTypedWidthAndPointer(pDrawable, nwidth, addrl, unsigned char, unsigned long);
179     addrl = AddrYPlus(addrl,y + pDrawable->y);
180     origin = intToX(origin);
181     vertex2p = vertex1p;
182     vertex2 = vertex1 = *vertex2p++;
183     if (vertex2p == endp)
184 	vertex2p = (int *) ptsIn;
185 #define Setup(c,x,vertex,dx,dy,e,sign,step) {\
186     x = intToX(vertex); \
187     if (dy = intToY(c) - y) { \
188     	dx = intToX(c) - x; \
189 	step = 0; \
190     	if (dx >= 0) \
191     	{ \
192 	    e = 0; \
193 	    sign = 1; \
194 	    if (dx >= dy) {\
195 	    	step = dx / dy; \
196 	    	dx = dx % dy; \
197 	    } \
198     	} \
199     	else \
200     	{ \
201 	    e = 1 - dy; \
202 	    sign = -1; \
203 	    dx = -dx; \
204 	    if (dx >= dy) { \
205 		step = - (dx / dy); \
206 		dx = dx % dy; \
207 	    } \
208     	} \
209     } \
210     x += origin; \
211     vertex = c; \
212 }
213 
214 #define Step(x,dx,dy,e,sign,step) {\
215     x += step; \
216     if ((e += dx) > 0) \
217     { \
218 	x += sign; \
219 	e -= dy; \
220     } \
221 }
222     for (;;)
223     {
224 	if (y == intToY(vertex1))
225 	{
226 	    do
227 	    {
228 	    	if (vertex1p == (int *) ptsIn)
229 		    vertex1p = endp;
230 	    	c = *--vertex1p;
231 	    	Setup (c,x1,vertex1,dx1,dy1,e1,sign1,step1)
232 	    } while (y >= intToY(vertex1));
233 	    h = dy1;
234 	}
235 	else
236 	{
237 	    Step(x1,dx1,dy1,e1,sign1,step1)
238 	    h = intToY(vertex1) - y;
239 	}
240 	if (y == intToY(vertex2))
241 	{
242 	    do
243 	    {
244 	    	c = *vertex2p++;
245 	    	if (vertex2p == endp)
246 		    vertex2p = (int *) ptsIn;
247 	    	Setup (c,x2,vertex2,dx2,dy2,e2,sign2,step2)
248 	    } while (y >= intToY(vertex2));
249 	    if (dy2 < h)
250 		h = dy2;
251 	}
252 	else
253 	{
254 	    Step(x2,dx2,dy2,e2,sign2,step2)
255 	    if ((c = (intToY(vertex2) - y)) < h)
256 		h = c;
257 	}
258 	/* fill spans for this segment */
259 	y += h;
260 	for (;;)
261 	{
262 	    l = x1;
263 	    r = x2;
264 	    nmiddle = x2 - x1;
265     	    if (nmiddle < 0)
266 	    {
267 	    	nmiddle = -nmiddle;
268 	    	l = x2;
269 	    	r = x1;
270     	    }
271 #if PPW > 1
272 	    c = l & PIM;
273 	    l -= c;
274 #endif
275 
276 #if PGSZ == 32
277 #define LWRD_SHIFT 2
278 #else /* PGSZ == 64 */
279 #define LWRD_SHIFT 3
280 #endif /* PGSZ */
281 
282 #if PSZ == 24
283 	    addr = (unsigned long *)((char *)addrl + ((l * 3) & ~0x03));
284 #else /* PSZ == 24 */
285 #if PWSH > LWRD_SHIFT
286 	    l = l >> (PWSH - LWRD_SHIFT);
287 #endif
288 #if PWSH < LWRD_SHIFT
289 	    l = l << (LWRD_SHIFT - PWSH);
290 #endif
291 	    addr = (unsigned long *) (((char *) addrl) + l);
292 #endif /* PSZ == 24 */
293 #if PSZ == 24
294 	    if (nmiddle <= 1){
295 	      if (nmiddle)
296 	        RROP_SOLID24(addr, l);
297 	    } else {
298 	      maskbits(l, nmiddle, startmask, endmask, nmiddle);
299 	      pidx = l & 3;
300 	      if (startmask){
301 		RROP_SOLID_MASK(addr, startmask, pidx-1);
302 		addr++;
303 		if (pidx == 3)
304 		  pidx = 0;
305 	      }
306 	      while (--nmiddle >= 0){
307 		RROP_SOLID(addr, pidx);
308 		addr++;
309 		if (++pidx == 3)
310 		  pidx = 0;
311 	      }
312 	      if (endmask)
313 		RROP_SOLID_MASK(addr, endmask, pidx);
314 	    }
315 #else /* PSZ == 24 */
316 #if PPW > 1
317 	    if (c + nmiddle < PPW)
318 	    {
319 	    	mask = SCRRIGHT (bits,c) ^ SCRRIGHT (bits,c+nmiddle);
320 	    	RROP_SOLID_MASK(addr,mask);
321 	    }
322 	    else
323 	    {
324 	    	if (c)
325 	    	{
326 	    	    mask = SCRRIGHT(bits, c);
327 	    	    RROP_SOLID_MASK(addr,mask);
328 	    	    nmiddle += c - PPW;
329 	    	    addr++;
330 	    	}
331 #endif
332 	    	nmiddle >>= PWSH;
333 		while (--nmiddle >= 0) {
334 		    RROP_SOLID(addr); addr++;
335 		}
336 #if PPW > 1
337 	    	if (mask = ~SCRRIGHT(bits, r & PIM))
338 	    	    RROP_SOLID_MASK(addr,mask);
339 	    }
340 #endif
341 #endif /* PSZ == 24 */
342 	    if (!--h)
343 		break;
344 	    addrl = AddrYPlus (addrl, 1);
345 	    Step(x1,dx1,dy1,e1,sign1,step1)
346 	    Step(x2,dx2,dy2,e2,sign2,step2)
347 	}
348 	if (y == maxy)
349 	    break;
350 	addrl = AddrYPlus (addrl, 1);
351     }
352 }
353