[WIN32K]
[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 DBG_DEFAULT_CHANNEL(EngClip);
11
12
13 static __inline int
14 CompareRightDown(
15 const RECTL *r1,
16 const RECTL *r2)
17 {
18 int Cmp;
19
20 if (r1->top < r2->top)
21 {
22 Cmp = -1;
23 }
24 else if (r2->top < r1->top)
25 {
26 Cmp = +1;
27 }
28 else
29 {
30 ASSERT(r1->bottom == r2->bottom);
31 if (r1->left < r2->left)
32 {
33 Cmp = -1;
34 }
35 else if (r2->left < r1->left)
36 {
37 Cmp = +1;
38 }
39 else
40 {
41 ASSERT(r1->right == r2->right);
42 Cmp = 0;
43 }
44 }
45
46 return Cmp;
47 }
48
49 static __inline int
50 CompareRightUp(
51 const RECTL *r1,
52 const RECTL *r2)
53 {
54 int Cmp;
55
56 if (r1->bottom < r2->bottom)
57 {
58 Cmp = +1;
59 }
60 else if (r2->bottom < r1->bottom)
61 {
62 Cmp = -1;
63 }
64 else
65 {
66 ASSERT(r1->top == r2->top);
67 if (r1->left < r2->left)
68 {
69 Cmp = -1;
70 }
71 else if (r2->left < r1->left)
72 {
73 Cmp = +1;
74 }
75 else
76 {
77 ASSERT(r1->right == r2->right);
78 Cmp = 0;
79 }
80 }
81
82 return Cmp;
83 }
84
85 static __inline int
86 CompareLeftDown(
87 const RECTL *r1,
88 const RECTL *r2)
89 {
90 int Cmp;
91
92 if (r1->top < r2->top)
93 {
94 Cmp = -1;
95 }
96 else if (r2->top < r1->top)
97 {
98 Cmp = +1;
99 }
100 else
101 {
102 ASSERT(r1->bottom == r2->bottom);
103 if (r1->right < r2->right)
104 {
105 Cmp = +1;
106 }
107 else if (r2->right < r1->right)
108 {
109 Cmp = -1;
110 }
111 else
112 {
113 ASSERT(r1->left == r2->left);
114 Cmp = 0;
115 }
116 }
117
118 return Cmp;
119 }
120
121 static __inline int
122 CompareLeftUp(
123 const RECTL *r1,
124 const RECTL *r2)
125 {
126 int Cmp;
127
128 if (r1->bottom < r2->bottom)
129 {
130 Cmp = +1;
131 }
132 else if (r2->bottom < r1->bottom)
133 {
134 Cmp = -1;
135 }
136 else
137 {
138 ASSERT(r1->top == r2->top);
139 if (r1->right < r2->right)
140 {
141 Cmp = +1;
142 }
143 else if (r2->right < r1->right)
144 {
145 Cmp = -1;
146 }
147 else
148 {
149 ASSERT(r1->left == r2->left);
150 Cmp = 0;
151 }
152 }
153 return Cmp;
154 }
155
156 static __inline int
157 CompareSpans(
158 const SPAN *Span1,
159 const SPAN *Span2)
160 {
161 int Cmp;
162
163 if (Span1->Y < Span2->Y)
164 {
165 Cmp = -1;
166 }
167 else if (Span2->Y < Span1->Y)
168 {
169 Cmp = +1;
170 }
171 else
172 {
173 if (Span1->X < Span2->X)
174 {
175 Cmp = -1;
176 }
177 else if (Span2->X < Span1->X)
178 {
179 Cmp = +1;
180 }
181 else
182 {
183 Cmp = 0;
184 }
185 }
186
187 return Cmp;
188 }
189
190 VOID
191 FASTCALL
192 IntEngInitClipObj(XCLIPOBJ *Clip)
193 {
194 Clip->Rects = &Clip->ClipObj.rclBounds;
195 }
196
197 VOID FASTCALL
198 IntEngFreeClipResources(XCLIPOBJ *Clip)
199 {
200 if (Clip->Rects != &Clip->ClipObj.rclBounds)
201 EngFreeMem(Clip->Rects);
202 }
203
204
205 VOID
206 FASTCALL
207 IntEngUpdateClipRegion(
208 XCLIPOBJ* Clip,
209 ULONG count,
210 const RECTL* pRect,
211 const RECTL* rcBounds)
212 {
213 if(count > 1)
214 {
215 RECTL* NewRects = EngAllocMem(0, FIELD_OFFSET(ENUMRECTS, arcl[count]), GDITAG_CLIPOBJ);
216
217 if(NewRects != NULL)
218 {
219 Clip->RectCount = count;
220 Clip->EnumOrder = CD_ANY;
221 RtlCopyMemory(NewRects, pRect, count * sizeof(RECTL));
222
223 Clip->ClipObj.iDComplexity = DC_COMPLEX;
224 Clip->ClipObj.iFComplexity = ((Clip->RectCount <= 4) ? FC_RECT4 : FC_COMPLEX);
225 Clip->ClipObj.iMode = TC_RECTANGLES;
226 Clip->ClipObj.rclBounds = *rcBounds;
227
228 if (Clip->Rects != &Clip->ClipObj.rclBounds)
229 EngFreeMem(Clip->Rects);
230 Clip->Rects = NewRects;
231 }
232 }
233 else
234 {
235 Clip->EnumOrder = CD_ANY;
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 Clip->RectCount = 1;
245 if (Clip->Rects != &Clip->ClipObj.rclBounds)
246 EngFreeMem(Clip->Rects);
247 Clip->Rects = &Clip->ClipObj.rclBounds;
248 }
249 }
250
251 /*
252 * @implemented
253 */
254 CLIPOBJ *
255 APIENTRY
256 EngCreateClip(VOID)
257 {
258 XCLIPOBJ *Clip = EngAllocMem(FL_ZERO_MEMORY, sizeof(XCLIPOBJ), GDITAG_CLIPOBJ);
259 if(Clip != NULL)
260 {
261 IntEngInitClipObj(Clip);
262 TRACE("Created Clip Obj %p.\n", Clip);
263 return &Clip->ClipObj;
264 }
265
266 ERR("Clip object allocation failed!\n");
267 return NULL;
268 }
269
270 /*
271 * @implemented
272 */
273 VOID
274 APIENTRY
275 EngDeleteClip(
276 _In_ _Post_ptr_invalid_ CLIPOBJ *pco)
277 {
278 XCLIPOBJ* Clip = CONTAINING_RECORD(pco, XCLIPOBJ, ClipObj);
279 TRACE("Deleting %p.\n");
280 IntEngFreeClipResources(Clip);
281 EngFreeMem(Clip);
282 }
283
284 /*
285 * @implemented
286 */
287 ULONG
288 APIENTRY
289 CLIPOBJ_cEnumStart(
290 _Inout_ CLIPOBJ *pco,
291 _In_ BOOL bAll,
292 _In_ ULONG iType,
293 _In_ ULONG iDirection,
294 _In_ ULONG cMaxRects)
295 {
296 XCLIPOBJ* Clip = CONTAINING_RECORD(pco, XCLIPOBJ, ClipObj);
297 SORTCOMP CompareFunc;
298
299 Clip->EnumPos = 0;
300 Clip->EnumMax = (cMaxRects > 0) ? cMaxRects : Clip->RectCount;
301
302 if (CD_ANY != iDirection && Clip->EnumOrder != iDirection)
303 {
304 switch (iDirection)
305 {
306 case CD_RIGHTDOWN:
307 CompareFunc = (SORTCOMP) CompareRightDown;
308 break;
309
310 case CD_RIGHTUP:
311 CompareFunc = (SORTCOMP) CompareRightUp;
312 break;
313
314 case CD_LEFTDOWN:
315 CompareFunc = (SORTCOMP) CompareLeftDown;
316 break;
317
318 case CD_LEFTUP:
319 CompareFunc = (SORTCOMP) CompareLeftUp;
320 break;
321
322 default:
323 ERR("Invalid iDirection %lu\n", iDirection);
324 iDirection = Clip->EnumOrder;
325 CompareFunc = NULL;
326 break;
327 }
328
329 if (NULL != CompareFunc)
330 {
331 EngSort((PBYTE) Clip->Rects, sizeof(RECTL), Clip->RectCount, CompareFunc);
332 }
333
334 Clip->EnumOrder = iDirection;
335 }
336
337 /* Return the number of rectangles enumerated */
338 if ((cMaxRects > 0) && (Clip->RectCount > cMaxRects))
339 {
340 return 0xFFFFFFFF;
341 }
342
343 return Clip->RectCount;
344 }
345
346 /*
347 * @implemented
348 */
349 BOOL
350 APIENTRY
351 CLIPOBJ_bEnum(
352 _In_ CLIPOBJ *pco,
353 _In_ ULONG cj,
354 _Out_bytecap_(cj) ULONG *pulEnumRects)
355 {
356 const RECTL* src;
357 XCLIPOBJ* Clip = CONTAINING_RECORD(pco, XCLIPOBJ, ClipObj);
358 ULONG nCopy;
359 ENUMRECTS* pERects = (ENUMRECTS*)pulEnumRects;
360
361 // Calculate how many rectangles we should copy
362 nCopy = min( Clip->EnumMax - Clip->EnumPos,
363 min( Clip->RectCount - Clip->EnumPos,
364 (cj - sizeof(ULONG)) / sizeof(RECTL)));
365
366 if(nCopy == 0)
367 {
368 return FALSE;
369 }
370
371 /* Copy rectangles */
372 src = &Clip->Rects[Clip->EnumPos];
373 RtlCopyMemory(pERects->arcl, src, nCopy * sizeof(RECTL));
374
375 pERects->c = nCopy;
376
377 Clip->EnumPos+=nCopy;
378
379 return Clip->EnumPos < Clip->RectCount;
380 }
381
382 /* EOF */