3aa8ded08dc57293f42020f49414997c0803df0c
[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: win32ss/gdi/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 VOID
157 FASTCALL
158 IntEngInitClipObj(XCLIPOBJ *Clip)
159 {
160 Clip->Rects = &Clip->ClipObj.rclBounds;
161 }
162
163 VOID FASTCALL
164 IntEngFreeClipResources(XCLIPOBJ *Clip)
165 {
166 if (Clip->Rects != &Clip->ClipObj.rclBounds)
167 EngFreeMem(Clip->Rects);
168 }
169
170
171 VOID
172 FASTCALL
173 IntEngUpdateClipRegion(
174 XCLIPOBJ* Clip,
175 ULONG count,
176 const RECTL* pRect,
177 const RECTL* rcBounds)
178 {
179 if(count > 1)
180 {
181 RECTL* NewRects = EngAllocMem(0, FIELD_OFFSET(ENUMRECTS, arcl[count]), GDITAG_CLIPOBJ);
182
183 if(NewRects != NULL)
184 {
185 Clip->RectCount = count;
186 Clip->EnumOrder = CD_ANY;
187 RtlCopyMemory(NewRects, pRect, count * sizeof(RECTL));
188
189 Clip->ClipObj.iDComplexity = DC_COMPLEX;
190 Clip->ClipObj.iFComplexity = ((Clip->RectCount <= 4) ? FC_RECT4 : FC_COMPLEX);
191 Clip->ClipObj.iMode = TC_RECTANGLES;
192 Clip->ClipObj.rclBounds = *rcBounds;
193
194 if (Clip->Rects != &Clip->ClipObj.rclBounds)
195 EngFreeMem(Clip->Rects);
196 Clip->Rects = NewRects;
197 }
198 }
199 else
200 {
201 Clip->EnumOrder = CD_ANY;
202
203 Clip->ClipObj.iDComplexity = (((rcBounds->top == rcBounds->bottom) &&
204 (rcBounds->left == rcBounds->right))
205 ? DC_TRIVIAL : DC_RECT);
206
207 Clip->ClipObj.iFComplexity = FC_RECT;
208 Clip->ClipObj.iMode = TC_RECTANGLES;
209 Clip->ClipObj.rclBounds = *rcBounds;
210 Clip->RectCount = 1;
211 if (Clip->Rects != &Clip->ClipObj.rclBounds)
212 EngFreeMem(Clip->Rects);
213 Clip->Rects = &Clip->ClipObj.rclBounds;
214 }
215 }
216
217 /*
218 * @implemented
219 */
220 CLIPOBJ *
221 APIENTRY
222 EngCreateClip(VOID)
223 {
224 XCLIPOBJ *Clip = EngAllocMem(FL_ZERO_MEMORY, sizeof(XCLIPOBJ), GDITAG_CLIPOBJ);
225 if(Clip != NULL)
226 {
227 IntEngInitClipObj(Clip);
228 TRACE("Created Clip Obj %p.\n", Clip);
229 return &Clip->ClipObj;
230 }
231
232 ERR("Clip object allocation failed!\n");
233 return NULL;
234 }
235
236 /*
237 * @implemented
238 */
239 VOID
240 APIENTRY
241 EngDeleteClip(
242 _In_ _Post_ptr_invalid_ CLIPOBJ *pco)
243 {
244 XCLIPOBJ* pxco = CONTAINING_RECORD(pco, XCLIPOBJ, ClipObj);
245 TRACE("Deleting %p.\n", pco);
246 IntEngFreeClipResources(pxco);
247 EngFreeMem(pxco);
248 }
249
250 /*
251 * @implemented
252 */
253 ULONG
254 APIENTRY
255 CLIPOBJ_cEnumStart(
256 _Inout_ CLIPOBJ *pco,
257 _In_ BOOL bAll,
258 _In_ ULONG iType,
259 _In_ ULONG iDirection,
260 _In_ ULONG cMaxRects)
261 {
262 XCLIPOBJ* Clip = CONTAINING_RECORD(pco, XCLIPOBJ, ClipObj);
263 SORTCOMP CompareFunc;
264
265 Clip->EnumPos = 0;
266 Clip->EnumMax = (cMaxRects > 0) ? cMaxRects : Clip->RectCount;
267
268 if (CD_ANY != iDirection && Clip->EnumOrder != iDirection)
269 {
270 switch (iDirection)
271 {
272 case CD_RIGHTDOWN:
273 CompareFunc = (SORTCOMP) CompareRightDown;
274 break;
275
276 case CD_RIGHTUP:
277 CompareFunc = (SORTCOMP) CompareRightUp;
278 break;
279
280 case CD_LEFTDOWN:
281 CompareFunc = (SORTCOMP) CompareLeftDown;
282 break;
283
284 case CD_LEFTUP:
285 CompareFunc = (SORTCOMP) CompareLeftUp;
286 break;
287
288 default:
289 ERR("Invalid iDirection %lu\n", iDirection);
290 iDirection = Clip->EnumOrder;
291 CompareFunc = NULL;
292 break;
293 }
294
295 if (NULL != CompareFunc)
296 {
297 EngSort((PBYTE) Clip->Rects, sizeof(RECTL), Clip->RectCount, CompareFunc);
298 }
299
300 Clip->EnumOrder = iDirection;
301 }
302
303 /* Return the number of rectangles enumerated */
304 if ((cMaxRects > 0) && (Clip->RectCount > cMaxRects))
305 {
306 return 0xFFFFFFFF;
307 }
308
309 return Clip->RectCount;
310 }
311
312 /*
313 * @implemented
314 */
315 BOOL
316 APIENTRY
317 CLIPOBJ_bEnum(
318 _In_ CLIPOBJ *pco,
319 _In_ ULONG cj,
320 _Out_bytecap_(cj) ULONG *pulEnumRects)
321 {
322 const RECTL* src;
323 XCLIPOBJ* Clip = CONTAINING_RECORD(pco, XCLIPOBJ, ClipObj);
324 ULONG nCopy;
325 ENUMRECTS* pERects = (ENUMRECTS*)pulEnumRects;
326
327 // Calculate how many rectangles we should copy
328 nCopy = min( Clip->EnumMax - Clip->EnumPos,
329 min( Clip->RectCount - Clip->EnumPos,
330 (cj - sizeof(ULONG)) / sizeof(RECTL)));
331
332 if(nCopy == 0)
333 {
334 return FALSE;
335 }
336
337 /* Copy rectangles */
338 src = &Clip->Rects[Clip->EnumPos];
339 RtlCopyMemory(pERects->arcl, src, nCopy * sizeof(RECTL));
340
341 pERects->c = nCopy;
342
343 Clip->EnumPos+=nCopy;
344
345 return Clip->EnumPos < Clip->RectCount;
346 }
347
348 /* EOF */