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