First import
[xorg_rtime.git] / xorg-server-1.4 / mfb / mfbfillarc.c
blob30ec00dc3818dacbee3786093d0be1a517018bad
1 /************************************************************
3 Copyright 1989, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
25 ********************************************************/
28 #ifdef HAVE_DIX_CONFIG_H
29 #include <dix-config.h>
30 #endif
32 #include <limits.h>
34 #include <X11/X.h>
35 #include <X11/Xprotostr.h>
36 #include "regionstr.h"
37 #include "gcstruct.h"
38 #include "pixmapstr.h"
39 #include "scrnintstr.h"
40 #include "mfb.h"
41 #include "maskbits.h"
42 #include "mifillarc.h"
43 #include "mi.h"
45 static void
46 mfbFillEllipseSolid(
47 DrawablePtr pDraw,
48 xArc *arc,
49 register int rop)
51 int x, y, e;
52 int yk, xk, ym, xm, dx, dy, xorg, yorg;
53 register int slw;
54 miFillArcRec info;
55 PixelType *addrlt, *addrlb;
56 register PixelType *addrl;
57 register int n;
58 int nlwidth;
59 register int xpos;
60 PixelType startmask, endmask;
61 int nlmiddle;
63 mfbGetPixelWidthAndPointer(pDraw, nlwidth, addrlt);
64 miFillArcSetup(arc, &info);
65 MIFILLARCSETUP();
66 xorg += pDraw->x;
67 yorg += pDraw->y;
68 addrlb = addrlt;
69 addrlt += nlwidth * (yorg - y);
70 addrlb += nlwidth * (yorg + y + dy);
71 while (y)
73 addrlt += nlwidth;
74 addrlb -= nlwidth;
75 MIFILLARCSTEP(slw);
76 if (!slw)
77 continue;
78 xpos = xorg - x;
79 addrl = mfbScanlineOffset(addrlt, (xpos >> PWSH));
80 if (((xpos & PIM) + slw) < PPW)
82 maskpartialbits(xpos, slw, startmask);
83 if (rop == RROP_BLACK)
84 *addrl &= ~startmask;
85 else if (rop == RROP_WHITE)
86 *addrl |= startmask;
87 else
88 *addrl ^= startmask;
89 if (miFillArcLower(slw))
91 addrl = mfbScanlineOffset(addrlb, (xpos >> PWSH));
92 if (rop == RROP_BLACK)
93 *addrl &= ~startmask;
94 else if (rop == RROP_WHITE)
95 *addrl |= startmask;
96 else
97 *addrl ^= startmask;
99 continue;
101 maskbits(xpos, slw, startmask, endmask, nlmiddle);
102 if (startmask)
104 if (rop == RROP_BLACK)
105 *addrl++ &= ~startmask;
106 else if (rop == RROP_WHITE)
107 *addrl++ |= startmask;
108 else
109 *addrl++ ^= startmask;
111 n = nlmiddle;
112 if (rop == RROP_BLACK)
113 while (n--)
114 *addrl++ = 0;
115 else if (rop == RROP_WHITE)
116 while (n--)
117 *addrl++ = ~0;
118 else
119 while (n--)
120 *addrl++ ^= ~0;
121 if (endmask)
123 if (rop == RROP_BLACK)
124 *addrl &= ~endmask;
125 else if (rop == RROP_WHITE)
126 *addrl |= endmask;
127 else
128 *addrl ^= endmask;
130 if (!miFillArcLower(slw))
131 continue;
132 addrl = mfbScanlineOffset(addrlb, (xpos >> PWSH));
133 if (startmask)
135 if (rop == RROP_BLACK)
136 *addrl++ &= ~startmask;
137 else if (rop == RROP_WHITE)
138 *addrl++ |= startmask;
139 else
140 *addrl++ ^= startmask;
142 n = nlmiddle;
143 if (rop == RROP_BLACK)
144 while (n--)
145 *addrl++ = 0;
146 else if (rop == RROP_WHITE)
147 while (n--)
148 *addrl++ = ~0;
149 else
150 while (n--)
151 *addrl++ ^= ~0;
152 if (endmask)
154 if (rop == RROP_BLACK)
155 *addrl &= ~endmask;
156 else if (rop == RROP_WHITE)
157 *addrl |= endmask;
158 else
159 *addrl ^= endmask;
164 #define FILLSPAN(xl,xr,addr) \
165 if (xr >= xl) \
167 width = xr - xl + 1; \
168 addrl = mfbScanlineOffset(addr, (xl >> PWSH)); \
169 if (((xl & PIM) + width) < PPW) \
171 maskpartialbits(xl, width, startmask); \
172 if (rop == RROP_BLACK) \
173 *addrl &= ~startmask; \
174 else if (rop == RROP_WHITE) \
175 *addrl |= startmask; \
176 else \
177 *addrl ^= startmask; \
179 else \
181 maskbits(xl, width, startmask, endmask, nlmiddle); \
182 if (startmask) \
184 if (rop == RROP_BLACK) \
185 *addrl++ &= ~startmask; \
186 else if (rop == RROP_WHITE) \
187 *addrl++ |= startmask; \
188 else \
189 *addrl++ ^= startmask; \
191 n = nlmiddle; \
192 if (rop == RROP_BLACK) \
193 while (n--) \
194 *addrl++ = 0; \
195 else if (rop == RROP_WHITE) \
196 while (n--) \
197 *addrl++ = ~0; \
198 else \
199 while (n--) \
200 *addrl++ ^= ~0; \
201 if (endmask) \
203 if (rop == RROP_BLACK) \
204 *addrl &= ~endmask; \
205 else if (rop == RROP_WHITE) \
206 *addrl |= endmask; \
207 else \
208 *addrl ^= endmask; \
213 #define FILLSLICESPANS(flip,addr) \
214 if (!flip) \
216 FILLSPAN(xl, xr, addr); \
218 else \
220 xc = xorg - x; \
221 FILLSPAN(xc, xr, addr); \
222 xc += slw - 1; \
223 FILLSPAN(xl, xc, addr); \
226 static void
227 mfbFillArcSliceSolidCopy(
228 DrawablePtr pDraw,
229 GCPtr pGC,
230 xArc *arc,
231 register int rop)
233 register PixelType *addrl;
234 register int n;
235 int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
236 register int x, y, e;
237 miFillArcRec info;
238 miArcSliceRec slice;
239 int xl, xr, xc;
240 PixelType *addrlt, *addrlb;
241 int nlwidth;
242 int width;
243 PixelType startmask, endmask;
244 int nlmiddle;
246 mfbGetPixelWidthAndPointer(pDraw, nlwidth, addrlt);
247 miFillArcSetup(arc, &info);
248 miFillArcSliceSetup(arc, &slice, pGC);
249 MIFILLARCSETUP();
250 xorg += pDraw->x;
251 yorg += pDraw->y;
252 addrlb = addrlt;
253 addrlt = mfbScanlineDeltaNoBankSwitch(addrlt, yorg - y, nlwidth);
254 addrlb = mfbScanlineDeltaNoBankSwitch(addrlb, yorg + y + dy, nlwidth);
255 slice.edge1.x += pDraw->x;
256 slice.edge2.x += pDraw->x;
257 while (y > 0)
259 mfbScanlineIncNoBankSwitch(addrlt, nlwidth);
260 mfbScanlineIncNoBankSwitch(addrlb, -nlwidth);
261 MIFILLARCSTEP(slw);
262 MIARCSLICESTEP(slice.edge1);
263 MIARCSLICESTEP(slice.edge2);
264 if (miFillSliceUpper(slice))
266 MIARCSLICEUPPER(xl, xr, slice, slw);
267 FILLSLICESPANS(slice.flip_top, addrlt);
269 if (miFillSliceLower(slice))
271 MIARCSLICELOWER(xl, xr, slice, slw);
272 FILLSLICESPANS(slice.flip_bot, addrlb);
277 void
278 mfbPolyFillArcSolid(pDraw, pGC, narcs, parcs)
279 register DrawablePtr pDraw;
280 GCPtr pGC;
281 int narcs;
282 xArc *parcs;
284 mfbPrivGC *priv;
285 register xArc *arc;
286 register int i;
287 BoxRec box;
288 int x2, y2;
289 RegionPtr cclip;
290 int rop;
292 priv = (mfbPrivGC *) pGC->devPrivates[mfbGCPrivateIndex].ptr;
293 rop = priv->rop;
294 if ((rop == RROP_NOP) || !(pGC->planemask & 1))
295 return;
296 cclip = pGC->pCompositeClip;
297 for (arc = parcs, i = narcs; --i >= 0; arc++)
299 if (miFillArcEmpty(arc))
300 continue;
301 if (miCanFillArc(arc))
303 box.x1 = arc->x + pDraw->x;
304 box.y1 = arc->y + pDraw->y;
306 * Because box.x2 and box.y2 get truncated to 16 bits, and the
307 * RECT_IN_REGION test treats the resulting number as a signed
308 * integer, the RECT_IN_REGION test alone can go the wrong way.
309 * This can result in a server crash because the rendering
310 * routines in this file deal directly with cpu addresses
311 * of pixels to be stored, and do not clip or otherwise check
312 * that all such addresses are within their respective pixmaps.
313 * So we only allow the RECT_IN_REGION test to be used for
314 * values that can be expressed correctly in a signed short.
316 x2 = box.x1 + (int)arc->width + 1;
317 box.x2 = x2;
318 y2 = box.y1 + (int)arc->height + 1;
319 box.y2 = y2;
320 if ( (x2 <= SHRT_MAX) && (y2 <= SHRT_MAX) &&
321 (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) )
323 if ((arc->angle2 >= FULLCIRCLE) ||
324 (arc->angle2 <= -FULLCIRCLE))
325 mfbFillEllipseSolid(pDraw, arc, rop);
326 else
327 mfbFillArcSliceSolidCopy(pDraw, pGC, arc, rop);
328 continue;
331 miPolyFillArc(pDraw, pGC, 1, arc);