]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/cfb/cfbfillarc.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / programs / Xserver / cfb / cfbfillarc.c
1 /************************************************************
2
3 Copyright (c) 1989  X Consortium
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
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 X CONSORTIUM 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.
21
22 Except as contained in this notice, the name of the X Consortium 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 X Consortium.
25
26 ********************************************************/
27
28 /* $XConsortium: cfbfillarc.c /main/17 1995/12/06 16:57:18 dpw $ */
29 /* $XFree86: xc/programs/Xserver/cfb/cfbfillarc.c,v 3.1 1996/08/13 11:27:33 dawes Exp $ */
30
31 #include "X.h"
32 #include "Xprotostr.h"
33 #include "miscstruct.h"
34 #include "gcstruct.h"
35 #include "pixmapstr.h"
36 #include "scrnintstr.h"
37 #include "cfb.h"
38 #include "cfbmskbits.h"
39 #include "mifillarc.h"
40 #include "cfbrrop.h"
41 #include "mi.h"
42
43 /* gcc 1.35 is stupid */
44 #if defined(__GNUC__) && __GNUC__ < 2 && defined(mc68020)
45 #define STUPID volatile
46 #else
47 #define STUPID
48 #endif
49
50 static void
51 RROP_NAME(cfbFillEllipseSolid) (pDraw, pGC, arc)
52     DrawablePtr pDraw;
53     GCPtr pGC;
54     xArc *arc;
55 {
56     STUPID int x, y, e;
57     STUPID int yk, xk, ym, xm, dx, dy, xorg, yorg;
58     miFillArcRec info;
59 #if PSZ == 24
60     unsigned char *addrlt, *addrlb;
61 #else
62     unsigned long *addrlt, *addrlb;
63 #endif
64     register unsigned long *addrl;
65     register int n;
66     int nlwidth;
67     RROP_DECLARE
68     register int xpos;
69     register int slw;
70     unsigned long startmask, endmask;
71     int nlmiddle;
72 #if PSZ == 24
73     register int pidx;
74     int xpos3;
75 #endif
76
77 #if PSZ == 24
78     cfbGetByteWidthAndPointer (pDraw, nlwidth, addrlt)
79 #else
80     cfbGetLongWidthAndPointer (pDraw, nlwidth, addrlt)
81 #endif
82
83     RROP_FETCH_GC(pGC);
84     miFillArcSetup(arc, &info);
85     MIFILLARCSETUP();
86     xorg += pDraw->x;
87     yorg += pDraw->y;
88     addrlb = addrlt;
89     addrlt += nlwidth * (yorg - y);
90     addrlb += nlwidth * (yorg + y + dy);
91     while (y)
92     {
93         addrlt += nlwidth;
94         addrlb -= nlwidth;
95         MIFILLARCSTEP(slw);
96         if (!slw)
97             continue;
98         xpos = xorg - x;
99 #if PSZ == 24
100         xpos3 = (xpos * 3) & ~0x03;
101         addrl = (unsigned long *)((char *)addrlt + xpos3);
102         if (slw == 1){
103           RROP_SOLID24(addrl, xpos);
104           if (miFillArcLower(slw)){
105             addrl = (unsigned long *)((char *)addrlb + xpos3);
106             RROP_SOLID24(addrl, xpos);
107           }
108           continue;
109         }
110         maskbits(xpos, slw, startmask, endmask, nlmiddle);
111         xpos &= 3;
112         pidx = xpos;
113         if (startmask){
114           RROP_SOLID_MASK(addrl, startmask, pidx-1);
115           addrl++;
116           if (pidx == 3)
117             pidx = 0;
118         }
119         n = nlmiddle;
120         while (--n >= 0){
121           RROP_SOLID(addrl, pidx);
122           addrl++;
123           if (++pidx == 3)
124             pidx = 0;
125         }
126         if (endmask)
127           RROP_SOLID_MASK(addrl, endmask, pidx);
128         if (!miFillArcLower(slw))
129           continue;
130         addrl = (unsigned long *)((char *)addrlb + xpos3);
131         pidx = xpos;
132         if (startmask){
133           RROP_SOLID_MASK(addrl, startmask, pidx-1);
134           addrl++;
135           if (pidx == 3)
136             pidx = 0;
137         }
138         n = nlmiddle;
139         while (--n >= 0){
140           RROP_SOLID(addrl, pidx);
141           addrl++;
142           if (++pidx == 3)
143             pidx = 0;
144         }
145         if (endmask)
146           RROP_SOLID_MASK(addrl, endmask, pidx);
147 #else /* PSZ == 24 */
148         addrl = addrlt + (xpos >> PWSH);
149         if (((xpos & PIM) + slw) <= PPW)
150         {
151             maskpartialbits(xpos, slw, startmask);
152             RROP_SOLID_MASK(addrl,startmask);
153             if (miFillArcLower(slw))
154             {
155                 addrl = addrlb + (xpos >> PWSH);
156                 RROP_SOLID_MASK(addrl, startmask);
157             }
158             continue;
159         }
160         maskbits(xpos, slw, startmask, endmask, nlmiddle);
161         if (startmask)
162         {
163             RROP_SOLID_MASK(addrl, startmask);
164             addrl++;
165         }
166         n = nlmiddle;
167         RROP_SPAN(addrl,n)
168
169         if (endmask)
170             RROP_SOLID_MASK(addrl, endmask);
171         if (!miFillArcLower(slw))
172             continue;
173         addrl = addrlb + (xpos >> PWSH);
174         if (startmask)
175         {
176             RROP_SOLID_MASK(addrl, startmask);
177             addrl++;
178         }
179         n = nlmiddle;
180         RROP_SPAN(addrl, n);
181         if (endmask)
182             RROP_SOLID_MASK(addrl, endmask);
183 #endif /* PSZ == 24 */
184     }
185 }
186
187 #if PSZ == 24
188 #define FILLSPAN(xl,xr,addr) \
189     if (xr >= xl){ \
190         n = xr - xl + 1; \
191         addrl = (unsigned long *)((char *)addr + ((xl * 3) & ~0x03)); \
192         if (n <= 1){ \
193           if (n) \
194             RROP_SOLID24(addrl, xl); \
195         } else { \
196           maskbits(xl, n, startmask, endmask, n); \
197           pidx = xl & 3; \
198           if (startmask){ \
199             RROP_SOLID_MASK(addrl, startmask, pidx-1); \
200             addrl++; \
201             if (pidx == 3) \
202               pidx = 0; \
203           } \
204           while (--n >= 0){ \
205             RROP_SOLID(addrl, pidx); \
206             addrl++; \
207             if (++pidx == 3) \
208               pidx = 0; \
209           } \
210           if (endmask) \
211             RROP_SOLID_MASK(addrl, endmask, pidx); \
212         } \
213     }
214 #else /* PSZ == 24 */
215 #define FILLSPAN(xl,xr,addr) \
216     if (xr >= xl) \
217     { \
218         n = xr - xl + 1; \
219         addrl = addr + (xl >> PWSH); \
220         if (((xl & PIM) + n) <= PPW) \
221         { \
222             maskpartialbits(xl, n, startmask); \
223             RROP_SOLID_MASK(addrl, startmask); \
224         } \
225         else \
226         { \
227             maskbits(xl, n, startmask, endmask, n); \
228             if (startmask) \
229             { \
230                 RROP_SOLID_MASK(addrl, startmask); \
231                 addrl++; \
232             } \
233             while (n--) \
234             { \
235                 RROP_SOLID(addrl); \
236                 ++addrl; \
237             } \
238             if (endmask) \
239                 RROP_SOLID_MASK(addrl, endmask); \
240         } \
241     }
242 #endif /* PSZ == 24 */
243
244 #define FILLSLICESPANS(flip,addr) \
245     if (!flip) \
246     { \
247         FILLSPAN(xl, xr, addr); \
248     } \
249     else \
250     { \
251         xc = xorg - x; \
252         FILLSPAN(xc, xr, addr); \
253         xc += slw - 1; \
254         FILLSPAN(xl, xc, addr); \
255     }
256
257 static void
258 RROP_NAME(cfbFillArcSliceSolid)(pDraw, pGC, arc)
259     DrawablePtr pDraw;
260     GCPtr pGC;
261     xArc *arc;
262 {
263     int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
264     register int x, y, e;
265     miFillArcRec info;
266     miArcSliceRec slice;
267     int xl, xr, xc;
268 #if PSZ == 24
269     unsigned char *addrlt, *addrlb;
270 #else
271     unsigned long *addrlt, *addrlb;
272 #endif
273     register unsigned long *addrl;
274     register int n;
275     int nlwidth;
276     RROP_DECLARE
277     unsigned long startmask, endmask;
278 #if PSZ == 24
279     register int pidx;
280 #endif /* PSZ == 24 */
281
282 #if PSZ == 24
283     cfbGetByteWidthAndPointer (pDraw, nlwidth, addrlt)
284 #else
285     cfbGetLongWidthAndPointer (pDraw, nlwidth, addrlt)
286 #endif
287
288     RROP_FETCH_GC(pGC);
289     miFillArcSetup(arc, &info);
290     miFillArcSliceSetup(arc, &slice, pGC);
291     MIFILLARCSETUP();
292     xorg += pDraw->x;
293     yorg += pDraw->y;
294     addrlb = addrlt;
295     addrlt += nlwidth * (yorg - y);
296     addrlb += nlwidth * (yorg + y + dy);
297     slice.edge1.x += pDraw->x;
298     slice.edge2.x += pDraw->x;
299     while (y > 0)
300     {
301         addrlt += nlwidth;
302         addrlb -= nlwidth;
303         MIFILLARCSTEP(slw);
304         MIARCSLICESTEP(slice.edge1);
305         MIARCSLICESTEP(slice.edge2);
306         if (miFillSliceUpper(slice))
307         {
308             MIARCSLICEUPPER(xl, xr, slice, slw);
309             FILLSLICESPANS(slice.flip_top, addrlt);
310         }
311         if (miFillSliceLower(slice))
312         {
313             MIARCSLICELOWER(xl, xr, slice, slw);
314             FILLSLICESPANS(slice.flip_bot, addrlb);
315         }
316     }
317 }
318
319 void
320 RROP_NAME(cfbPolyFillArcSolid) (pDraw, pGC, narcs, parcs)
321     DrawablePtr pDraw;
322     GCPtr       pGC;
323     int         narcs;
324     xArc        *parcs;
325 {
326     register xArc *arc;
327     register int i;
328     int x2, y2;
329     BoxRec box;
330     RegionPtr cclip;
331
332     cclip = cfbGetCompositeClip(pGC);
333     for (arc = parcs, i = narcs; --i >= 0; arc++)
334     {
335         if (miFillArcEmpty(arc))
336             continue;
337         if (miCanFillArc(arc))
338         {
339             box.x1 = arc->x + pDraw->x;
340             box.y1 = arc->y + pDraw->y;
341             /*
342              * Because box.x2 and box.y2 get truncated to 16 bits, and the
343              * RECT_IN_REGION test treats the resulting number as a signed
344              * integer, the RECT_IN_REGION test alone can go the wrong way.
345              * This can result in a server crash because the rendering
346              * routines in this file deal directly with cpu addresses
347              * of pixels to be stored, and do not clip or otherwise check
348              * that all such addresses are within their respective pixmaps.
349              * So we only allow the RECT_IN_REGION test to be used for
350              * values that can be expressed correctly in a signed short.
351              */
352             x2 = box.x1 + (int)arc->width + 1;
353             box.x2 = x2;
354             y2 = box.y1 + (int)arc->height + 1;
355             box.y2 = y2;
356             if ( (x2 <= MAXSHORT) && (y2 <= MAXSHORT) &&
357                     (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) )
358             {
359                 if ((arc->angle2 >= FULLCIRCLE) ||
360                     (arc->angle2 <= -FULLCIRCLE))
361                     RROP_NAME(cfbFillEllipseSolid)(pDraw, pGC, arc);
362                 else
363                     RROP_NAME(cfbFillArcSliceSolid)(pDraw, pGC, arc);
364                 continue;
365             }
366         }
367         miPolyFillArc(pDraw, pGC, 1, arc);
368     }
369 }