update for HEAD-2003091401
[reactos.git] / subsys / win32k / eng / clip.c
1 /*
2  *  ReactOS W32 Subsystem
3  *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /* $Id$
20  * 
21  * COPYRIGHT:         See COPYING in the top level directory
22  * PROJECT:           ReactOS kernel
23  * PURPOSE:           GDI Clipping Functions
24  * FILE:              subsys/win32k/eng/clip.c
25  * PROGRAMER:         Jason Filby
26  * REVISION HISTORY:
27  *                 21/8/1999: Created
28  */
29
30 #include <ddk/winddi.h>
31 #include <ddk/ntddk.h>
32 #include "objects.h"
33 #include "clip.h"
34 #include <include/object.h>
35
36 #define NDEBUG
37 #include <win32k/debug1.h>
38
39 VOID STDCALL IntEngDeleteClipRegion(CLIPOBJ *ClipObj)
40 {
41   HCLIP HClip      = AccessHandleFromUserObject(ClipObj);
42   FreeGDIHandle(HClip);
43 }
44
45 CLIPOBJ* STDCALL
46 IntEngCreateClipRegion(ULONG count, PRECTL pRect, RECTL rcBounds)
47 {
48   HCLIP hClip;
49   CLIPGDI* clipInt;
50   CLIPOBJ* clipUser;
51
52   DPRINT("IntEngCreateClipRegion count: %d\n", count);
53   if (1 < count)
54     {
55       hClip = (HCLIP) CreateGDIHandle(sizeof(CLIPGDI) + count * sizeof(RECTL),
56                                       sizeof(CLIPOBJ));
57
58       if (hClip)
59         {
60           clipInt = (CLIPGDI *) AccessInternalObject(hClip);
61           RtlCopyMemory(clipInt->EnumRects.arcl, pRect, count * sizeof(RECTL));
62           clipInt->EnumRects.c = count;
63           clipInt->EnumOrder = CD_ANY;
64
65           clipUser = (CLIPOBJ *) AccessUserObject(hClip);
66           ASSERT(NULL != clipUser);
67
68           clipUser->iDComplexity = DC_COMPLEX;
69           clipUser->iFComplexity = (count <= 4) ? FC_RECT4: FC_COMPLEX;
70           clipUser->iMode = TC_RECTANGLES;
71           RtlCopyMemory(&(clipUser->rclBounds), &rcBounds, sizeof(RECTL));
72
73           return clipUser;
74         }
75     }
76   else
77     {
78       hClip = (HCLIP) CreateGDIHandle(sizeof(CLIPGDI),
79                                       sizeof(CLIPOBJ));
80       if (hClip)
81         {
82           clipInt = (CLIPGDI *) AccessInternalObject(hClip);
83           RtlCopyMemory(clipInt->EnumRects.arcl, &rcBounds, sizeof(RECTL));
84           clipInt->EnumRects.c = 1;
85           clipInt->EnumOrder = CD_ANY;
86
87           clipUser = (CLIPOBJ *) AccessUserObject(hClip);
88           ASSERT(NULL != clipUser);
89
90           clipUser->iDComplexity = ((rcBounds.top==rcBounds.bottom)
91                                     && (rcBounds.left==rcBounds.right))
92                                    ? DC_TRIVIAL : DC_RECT;
93           clipUser->iFComplexity = FC_RECT;
94           clipUser->iMode = TC_RECTANGLES;
95           DPRINT("IntEngCreateClipRegion: iDComplexity: %d\n", clipUser->iDComplexity);
96           RtlCopyMemory(&(clipUser->rclBounds), &rcBounds, sizeof(RECTL));
97           return clipUser;
98         }
99     }
100
101   return NULL;
102 }
103
104 /*
105  * @implemented
106  */
107 CLIPOBJ * STDCALL
108 EngCreateClip(VOID)
109 {
110   return EngAllocMem(FL_ZERO_MEMORY, sizeof(CLIPOBJ), 0);
111 }
112
113 /*
114  * @implemented
115  */
116 VOID STDCALL
117 EngDeleteClip(CLIPOBJ *ClipRegion)
118 {
119   EngFreeMem(ClipRegion);
120 }
121
122 static int 
123 CompareRightDown(const PRECT r1, const PRECT r2)
124 {
125   int Cmp;
126
127   if (r1->top < r2->top)
128     {
129       Cmp = -1;
130     }
131   else if (r2->top < r1->top)
132     {
133       Cmp = +1;
134     }
135   else 
136     {
137       ASSERT(r1->bottom == r2->bottom);
138       if (r1->left < r2->left)
139         {
140           Cmp = -1;
141         }
142       else if (r2->left < r1->left)
143         {
144           Cmp = +1;
145         }
146       else
147         {
148           ASSERT(r1->right == r2->right);
149           Cmp = 0;
150         }
151     }
152
153   return Cmp;
154 }
155
156 static int 
157 CompareRightUp(const PRECT r1, const PRECT r2)
158 {
159   int Cmp;
160
161   if (r1->bottom < r2->bottom)
162     {
163       Cmp = +1;
164     }
165   else if (r2->bottom < r1->bottom)
166     {
167       Cmp = -1;
168     }
169   else 
170     {
171       ASSERT(r1->top == r2->top);
172       if (r1->left < r2->left)
173         {
174           Cmp = -1;
175         }
176       else if (r2->left < r1->left)
177         {
178           Cmp = +1;
179         }
180       else
181         {
182           ASSERT(r1->right == r2->right);
183           Cmp = 0;
184         }
185     }
186
187   return Cmp;
188 }
189
190 static int 
191 CompareLeftDown(const PRECT r1, const PRECT r2)
192 {
193   int Cmp;
194
195   if (r1->top < r2->top)
196     {
197       Cmp = -1;
198     }
199   else if (r2->top < r1->top)
200     {
201       Cmp = +1;
202     }
203   else 
204     {
205       ASSERT(r1->bottom == r2->bottom);
206       if (r1->right < r2->right)
207         {
208           Cmp = +1;
209         }
210       else if (r2->right < r1->right)
211         {
212           Cmp = -1;
213         }
214       else
215         {
216           ASSERT(r1->left == r2->left);
217           Cmp = 0;
218         }
219     }
220
221   return Cmp;
222 }
223
224 static int 
225 CompareLeftUp(const PRECT r1, const PRECT r2)
226 {
227   int Cmp;
228
229   if (r1->bottom < r2->bottom)
230     {
231       Cmp = +1;
232     }
233   else if (r2->bottom < r1->bottom)
234     {
235       Cmp = -1;
236     }
237   else 
238     {
239       ASSERT(r1->top == r2->top);
240       if (r1->right < r2->right)
241         {
242           Cmp = +1;
243         }
244       else if (r2->right < r1->right)
245         {
246           Cmp = -1;
247         }
248       else
249         {
250           ASSERT(r1->left == r2->left);
251           Cmp = 0;
252         }
253     }
254
255   return Cmp;
256 }
257
258 /*
259  * @implemented
260  */
261 ULONG STDCALL
262 CLIPOBJ_cEnumStart(IN PCLIPOBJ ClipObj,
263                    IN BOOL ShouldDoAll,
264                    IN ULONG ClipType,
265                    IN ULONG BuildOrder,
266                    IN ULONG MaxRects)
267 {
268   CLIPGDI *ClipGDI = (CLIPGDI*)AccessInternalObjectFromUserObject(ClipObj);
269   SORTCOMP CompareFunc;
270
271   ClipGDI->EnumPos = 0;
272   ClipGDI->EnumMax = (MaxRects > 0) ? MaxRects : ClipGDI->EnumRects.c;
273
274   if (CD_ANY != BuildOrder && ClipGDI->EnumOrder != BuildOrder)
275     {
276       switch (BuildOrder)
277         {
278         case CD_RIGHTDOWN:
279           CompareFunc = (SORTCOMP) CompareRightDown;
280           break;
281         case CD_RIGHTUP:
282           CompareFunc = (SORTCOMP) CompareRightUp;
283           break;
284         case CD_LEFTDOWN:
285           CompareFunc = (SORTCOMP) CompareLeftDown;
286           break;
287         case CD_LEFTUP:
288           CompareFunc = (SORTCOMP) CompareLeftUp;
289           break;
290         default:
291           DPRINT1("Invalid BuildOrder %d\n", BuildOrder);
292           BuildOrder = ClipGDI->EnumOrder;
293           CompareFunc = NULL;
294           break;
295         }
296
297       if (NULL != CompareFunc)
298         {
299           EngSort((PBYTE) ClipGDI->EnumRects.arcl, sizeof(RECTL), ClipGDI->EnumRects.c,
300                   CompareFunc);
301         }
302
303       ClipGDI->EnumOrder = BuildOrder;
304     }
305
306   /* Return the number of rectangles enumerated */
307   if ((MaxRects > 0) && (ClipGDI->EnumRects.c > MaxRects))
308     {
309       return 0xFFFFFFFF;
310     }
311
312   return ClipGDI->EnumRects.c;
313 }
314
315 /*
316  * @implemented
317  */
318 BOOL STDCALL
319 CLIPOBJ_bEnum(IN PCLIPOBJ ClipObj,
320               IN ULONG ObjSize,
321               OUT ULONG *EnumRects)
322 {
323   CLIPGDI *ClipGDI = (CLIPGDI*)AccessInternalObjectFromUserObject(ClipObj);
324   ULONG nCopy;
325   PENUMRECTS pERects = (PENUMRECTS)EnumRects;
326
327   //calculate how many rectangles we should copy
328   nCopy = MIN( ClipGDI->EnumMax - ClipGDI->EnumPos,
329                MIN( ClipGDI->EnumRects.c - ClipGDI->EnumPos,
330                     (ObjSize - sizeof(ULONG)) / sizeof(RECTL)));
331
332   RtlCopyMemory( pERects->arcl, ClipGDI->EnumRects.arcl + ClipGDI->EnumPos,
333                  nCopy * sizeof(RECTL) );
334   pERects->c = nCopy;
335
336   ClipGDI->EnumPos+=nCopy;
337
338   return ClipGDI->EnumPos < ClipGDI->EnumRects.c;
339 }
340
341 /* EOF */