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