Fix build
[reactos.git] / reactos / win32ss / gdi / eng / clip.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: GDI Clipping Functions
5 * FILE: subsystems/win32/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
192 FASTCALL
193 IntEngDeleteClipRegion(CLIPOBJ *ClipObj)
194 {
195 EngFreeMem(ObjToGDI(ClipObj, CLIP));
196 }
197
198 CLIPOBJ*
199 FASTCALL
200 IntEngCreateClipRegion(ULONG count, PRECTL pRect, PRECTL rcBounds)
201 {
202 CLIPGDI *Clip;
203
204 if(count > 1)
205 {
206 RECTL *dest;
207
208 Clip = EngAllocMem(0, sizeof(CLIPGDI) + ((count - 1) * sizeof(RECTL)), GDITAG_CLIPOBJ);
209
210 if(Clip != NULL)
211 {
212 Clip->EnumRects.c = count;
213 Clip->EnumOrder = CD_ANY;
214 for(dest = Clip->EnumRects.arcl;count > 0; count--, dest++, pRect++)
215 {
216 *dest = *pRect;
217 }
218
219 Clip->ClipObj.iDComplexity = DC_COMPLEX;
220 Clip->ClipObj.iFComplexity = ((Clip->EnumRects.c <= 4) ? FC_RECT4 : FC_COMPLEX);
221 Clip->ClipObj.iMode = TC_RECTANGLES;
222 Clip->ClipObj.rclBounds = *rcBounds;
223
224 return GDIToObj(Clip, CLIP);
225 }
226 }
227 else
228 {
229 Clip = EngAllocMem(0, sizeof(CLIPGDI), GDITAG_CLIPOBJ);
230
231 if(Clip != NULL)
232 {
233 Clip->EnumRects.c = 1;
234 Clip->EnumOrder = CD_ANY;
235 Clip->EnumRects.arcl[0] = *rcBounds;
236
237 Clip->ClipObj.iDComplexity = (((rcBounds->top == rcBounds->bottom) &&
238 (rcBounds->left == rcBounds->right))
239 ? DC_TRIVIAL : DC_RECT);
240
241 Clip->ClipObj.iFComplexity = FC_RECT;
242 Clip->ClipObj.iMode = TC_RECTANGLES;
243 Clip->ClipObj.rclBounds = *rcBounds;
244
245 return GDIToObj(Clip, CLIP);
246 }
247 }
248
249 return NULL;
250 }
251
252 /*
253 * @implemented
254 */
255 CLIPOBJ *
256 APIENTRY
257 EngCreateClip(VOID)
258 {
259 CLIPGDI *Clip = EngAllocMem(FL_ZERO_MEMORY, sizeof(CLIPGDI), GDITAG_CLIPOBJ);
260 if(Clip != NULL)
261 {
262 return GDIToObj(Clip, CLIP);
263 }
264
265 return NULL;
266 }
267
268 /*
269 * @implemented
270 */
271 VOID
272 APIENTRY
273 EngDeleteClip(
274 _In_ _Post_ptr_invalid_ CLIPOBJ *pco)
275 {
276 EngFreeMem(ObjToGDI(pco, CLIP));
277 }
278
279 /*
280 * @implemented
281 */
282 ULONG
283 APIENTRY
284 CLIPOBJ_cEnumStart(
285 _Inout_ CLIPOBJ *pco,
286 _In_ BOOL bAll,
287 _In_ ULONG iType,
288 _In_ ULONG iDirection,
289 _In_ ULONG cMaxRects)
290 {
291 CLIPGDI *ClipGDI = ObjToGDI(pco, CLIP);
292 SORTCOMP CompareFunc;
293
294 ClipGDI->EnumPos = 0;
295 ClipGDI->EnumMax = (cMaxRects > 0) ? cMaxRects : ClipGDI->EnumRects.c;
296
297 if (CD_ANY != iDirection && ClipGDI->EnumOrder != iDirection)
298 {
299 switch (iDirection)
300 {
301 case CD_RIGHTDOWN:
302 CompareFunc = (SORTCOMP) CompareRightDown;
303 break;
304
305 case CD_RIGHTUP:
306 CompareFunc = (SORTCOMP) CompareRightUp;
307 break;
308
309 case CD_LEFTDOWN:
310 CompareFunc = (SORTCOMP) CompareLeftDown;
311 break;
312
313 case CD_LEFTUP:
314 CompareFunc = (SORTCOMP) CompareLeftUp;
315 break;
316
317 default:
318 DPRINT1("Invalid iDirection %lu\n", iDirection);
319 iDirection = ClipGDI->EnumOrder;
320 CompareFunc = NULL;
321 break;
322 }
323
324 if (NULL != CompareFunc)
325 {
326 EngSort((PBYTE) ClipGDI->EnumRects.arcl, sizeof(RECTL), ClipGDI->EnumRects.c, CompareFunc);
327 }
328
329 ClipGDI->EnumOrder = iDirection;
330 }
331
332 /* Return the number of rectangles enumerated */
333 if ((cMaxRects > 0) && (ClipGDI->EnumRects.c > cMaxRects))
334 {
335 return 0xFFFFFFFF;
336 }
337
338 return ClipGDI->EnumRects.c;
339 }
340
341 /*
342 * @implemented
343 */
344 BOOL
345 APIENTRY
346 CLIPOBJ_bEnum(
347 _In_ CLIPOBJ *pco,
348 _In_ ULONG cj,
349 _Out_bytecap_(cj) ULONG *pulEnumRects)
350 {
351 RECTL *dest, *src;
352 CLIPGDI *ClipGDI = ObjToGDI(pco, CLIP);
353 ULONG nCopy, i;
354 ENUMRECTS* pERects = (ENUMRECTS*)pulEnumRects;
355
356 // Calculate how many rectangles we should copy
357 nCopy = min( ClipGDI->EnumMax - ClipGDI->EnumPos,
358 min( ClipGDI->EnumRects.c - ClipGDI->EnumPos,
359 (cj - sizeof(ULONG)) / sizeof(RECTL)));
360
361 if(nCopy == 0)
362 {
363 return FALSE;
364 }
365
366 /* Copy rectangles */
367 src = ClipGDI->EnumRects.arcl + ClipGDI->EnumPos;
368 for(i = 0, dest = pERects->arcl; i < nCopy; i++, dest++, src++)
369 {
370 *dest = *src;
371 }
372
373 pERects->c = nCopy;
374
375 ClipGDI->EnumPos+=nCopy;
376
377 return ClipGDI->EnumPos < ClipGDI->EnumRects.c;
378 }
379
380 /* EOF */