9a54fa96e584e0a71fd207ba90d64d99bfc927de
[reactos.git] / reactos / subsystems / win32 / win32k / eng / clip.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI Clipping Functions
5 * FILE: subsys/win32k/eng/clip.c
6 * PROGRAMER: Jason Filby
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 static __inline int
15 CompareRightDown(
16 const RECTL *r1,
17 const RECTL *r2)
18 {
19 int Cmp;
20
21 if (r1->top < r2->top)
22 {
23 Cmp = -1;
24 }
25 else if (r2->top < r1->top)
26 {
27 Cmp = +1;
28 }
29 else
30 {
31 ASSERT(r1->bottom == r2->bottom);
32 if (r1->left < r2->left)
33 {
34 Cmp = -1;
35 }
36 else if (r2->left < r1->left)
37 {
38 Cmp = +1;
39 }
40 else
41 {
42 ASSERT(r1->right == r2->right);
43 Cmp = 0;
44 }
45 }
46
47 return Cmp;
48 }
49
50 static __inline int
51 CompareRightUp(
52 const RECTL *r1,
53 const RECTL *r2)
54 {
55 int Cmp;
56
57 if (r1->bottom < r2->bottom)
58 {
59 Cmp = +1;
60 }
61 else if (r2->bottom < r1->bottom)
62 {
63 Cmp = -1;
64 }
65 else
66 {
67 ASSERT(r1->top == r2->top);
68 if (r1->left < r2->left)
69 {
70 Cmp = -1;
71 }
72 else if (r2->left < r1->left)
73 {
74 Cmp = +1;
75 }
76 else
77 {
78 ASSERT(r1->right == r2->right);
79 Cmp = 0;
80 }
81 }
82
83 return Cmp;
84 }
85
86 static __inline int
87 CompareLeftDown(
88 const RECTL *r1,
89 const RECTL *r2)
90 {
91 int Cmp;
92
93 if (r1->top < r2->top)
94 {
95 Cmp = -1;
96 }
97 else if (r2->top < r1->top)
98 {
99 Cmp = +1;
100 }
101 else
102 {
103 ASSERT(r1->bottom == r2->bottom);
104 if (r1->right < r2->right)
105 {
106 Cmp = +1;
107 }
108 else if (r2->right < r1->right)
109 {
110 Cmp = -1;
111 }
112 else
113 {
114 ASSERT(r1->left == r2->left);
115 Cmp = 0;
116 }
117 }
118
119 return Cmp;
120 }
121
122 static __inline int
123 CompareLeftUp(
124 const RECTL *r1,
125 const RECTL *r2)
126 {
127 int Cmp;
128
129 if (r1->bottom < r2->bottom)
130 {
131 Cmp = +1;
132 }
133 else if (r2->bottom < r1->bottom)
134 {
135 Cmp = -1;
136 }
137 else
138 {
139 ASSERT(r1->top == r2->top);
140 if (r1->right < r2->right)
141 {
142 Cmp = +1;
143 }
144 else if (r2->right < r1->right)
145 {
146 Cmp = -1;
147 }
148 else
149 {
150 ASSERT(r1->left == r2->left);
151 Cmp = 0;
152 }
153 }
154 return Cmp;
155 }
156
157 static __inline int
158 CompareSpans(
159 const SPAN *Span1,
160 const SPAN *Span2)
161 {
162 int Cmp;
163
164 if (Span1->Y < Span2->Y)
165 {
166 Cmp = -1;
167 }
168 else if (Span2->Y < Span1->Y)
169 {
170 Cmp = +1;
171 }
172 else
173 {
174 if (Span1->X < Span2->X)
175 {
176 Cmp = -1;
177 }
178 else if (Span2->X < Span1->X)
179 {
180 Cmp = +1;
181 }
182 else
183 {
184 Cmp = 0;
185 }
186 }
187
188 return Cmp;
189 }
190
191 VOID FASTCALL
192 IntEngDeleteClipRegion(CLIPOBJ *ClipObj)
193 {
194 EngFreeMem(ObjToGDI(ClipObj, CLIP));
195 }
196
197 CLIPOBJ* FASTCALL
198 IntEngCreateClipRegion(ULONG count, PRECTL pRect, PRECTL rcBounds)
199 {
200 CLIPGDI *Clip;
201
202 if(count > 1)
203 {
204 RECTL *dest;
205
206 Clip = EngAllocMem(0, sizeof(CLIPGDI) + ((count - 1) * sizeof(RECTL)), GDITAG_CLIPOBJ);
207
208 if(Clip != NULL)
209 {
210 Clip->EnumRects.c = count;
211 Clip->EnumOrder = CD_ANY;
212 for(dest = Clip->EnumRects.arcl;count > 0; count--, dest++, pRect++)
213 {
214 *dest = *pRect;
215 }
216
217 Clip->ClipObj.iDComplexity = DC_COMPLEX;
218 Clip->ClipObj.iFComplexity = ((Clip->EnumRects.c <= 4) ? FC_RECT4 : FC_COMPLEX);
219 Clip->ClipObj.iMode = TC_RECTANGLES;
220 Clip->ClipObj.rclBounds = *rcBounds;
221
222 return GDIToObj(Clip, CLIP);
223 }
224 }
225 else
226 {
227 Clip = EngAllocMem(0, sizeof(CLIPGDI), GDITAG_CLIPOBJ);
228
229 if(Clip != NULL)
230 {
231 Clip->EnumRects.c = 1;
232 Clip->EnumOrder = CD_ANY;
233 Clip->EnumRects.arcl[0] = *rcBounds;
234
235 Clip->ClipObj.iDComplexity = (((rcBounds->top == rcBounds->bottom) &&
236 (rcBounds->left == rcBounds->right))
237 ? DC_TRIVIAL : DC_RECT);
238
239 Clip->ClipObj.iFComplexity = FC_RECT;
240 Clip->ClipObj.iMode = TC_RECTANGLES;
241 Clip->ClipObj.rclBounds = *rcBounds;
242
243 return GDIToObj(Clip, CLIP);
244 }
245 }
246
247 return NULL;
248 }
249
250 /*
251 * @implemented
252 */
253 CLIPOBJ * APIENTRY
254 EngCreateClip(VOID)
255 {
256 CLIPGDI *Clip = EngAllocMem(FL_ZERO_MEMORY, sizeof(CLIPGDI), GDITAG_CLIPOBJ);
257 if(Clip != NULL)
258 {
259 return GDIToObj(Clip, CLIP);
260 }
261
262 return NULL;
263 }
264
265 /*
266 * @implemented
267 */
268 VOID APIENTRY
269 EngDeleteClip(CLIPOBJ *ClipRegion)
270 {
271 EngFreeMem(ObjToGDI(ClipRegion, CLIP));
272 }
273
274 /*
275 * @implemented
276 */
277 ULONG APIENTRY
278 CLIPOBJ_cEnumStart(
279 IN CLIPOBJ* ClipObj,
280 IN BOOL ShouldDoAll,
281 IN ULONG ClipType,
282 IN ULONG BuildOrder,
283 IN ULONG MaxRects)
284 {
285 CLIPGDI *ClipGDI = ObjToGDI(ClipObj, CLIP);
286 SORTCOMP CompareFunc;
287
288 ClipGDI->EnumPos = 0;
289 ClipGDI->EnumMax = (MaxRects > 0) ? MaxRects : ClipGDI->EnumRects.c;
290
291 if (CD_ANY != BuildOrder && ClipGDI->EnumOrder != BuildOrder)
292 {
293 switch (BuildOrder)
294 {
295 case CD_RIGHTDOWN:
296 CompareFunc = (SORTCOMP) CompareRightDown;
297 break;
298
299 case CD_RIGHTUP:
300 CompareFunc = (SORTCOMP) CompareRightUp;
301 break;
302
303 case CD_LEFTDOWN:
304 CompareFunc = (SORTCOMP) CompareLeftDown;
305 break;
306
307 case CD_LEFTUP:
308 CompareFunc = (SORTCOMP) CompareLeftUp;
309 break;
310
311 default:
312 DPRINT1("Invalid BuildOrder %d\n", BuildOrder);
313 BuildOrder = ClipGDI->EnumOrder;
314 CompareFunc = NULL;
315 break;
316 }
317
318 if (NULL != CompareFunc)
319 {
320 EngSort((PBYTE) ClipGDI->EnumRects.arcl, sizeof(RECTL), ClipGDI->EnumRects.c, CompareFunc);
321 }
322
323 ClipGDI->EnumOrder = BuildOrder;
324 }
325
326 /* Return the number of rectangles enumerated */
327 if ((MaxRects > 0) && (ClipGDI->EnumRects.c > MaxRects))
328 {
329 return 0xFFFFFFFF;
330 }
331
332 return ClipGDI->EnumRects.c;
333 }
334
335 /*
336 * @implemented
337 */
338 BOOL APIENTRY
339 CLIPOBJ_bEnum(
340 IN CLIPOBJ* ClipObj,
341 IN ULONG ObjSize,
342 OUT ULONG *EnumRects)
343 {
344 RECTL *dest, *src;
345 CLIPGDI *ClipGDI = ObjToGDI(ClipObj, CLIP);
346 ULONG nCopy, i;
347 ENUMRECTS* pERects = (ENUMRECTS*)EnumRects;
348
349 //calculate how many rectangles we should copy
350 nCopy = min( ClipGDI->EnumMax - ClipGDI->EnumPos,
351 min( ClipGDI->EnumRects.c - ClipGDI->EnumPos,
352 (ObjSize - sizeof(ULONG)) / sizeof(RECTL)));
353
354 if(nCopy == 0)
355 {
356 return FALSE;
357 }
358
359 /* copy rectangles */
360 src = ClipGDI->EnumRects.arcl + ClipGDI->EnumPos;
361 for(i = 0, dest = pERects->arcl; i < nCopy; i++, dest++, src++)
362 {
363 *dest = *src;
364 }
365
366 pERects->c = nCopy;
367
368 ClipGDI->EnumPos+=nCopy;
369
370 return ClipGDI->EnumPos < ClipGDI->EnumRects.c;
371 }
372
373 /* EOF */