2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
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.
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.
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.
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
36 CompareRightDown(const PRECT r1
, const PRECT r2
)
40 if (r1
->top
< r2
->top
)
44 else if (r2
->top
< r1
->top
)
50 ASSERT(r1
->bottom
== r2
->bottom
);
51 if (r1
->left
< r2
->left
)
55 else if (r2
->left
< r1
->left
)
61 ASSERT(r1
->right
== r2
->right
);
70 CompareRightUp(const PRECT r1
, const PRECT r2
)
74 if (r1
->bottom
< r2
->bottom
)
78 else if (r2
->bottom
< r1
->bottom
)
84 ASSERT(r1
->top
== r2
->top
);
85 if (r1
->left
< r2
->left
)
89 else if (r2
->left
< r1
->left
)
95 ASSERT(r1
->right
== r2
->right
);
104 CompareLeftDown(const PRECT r1
, const PRECT r2
)
108 if (r1
->top
< r2
->top
)
112 else if (r2
->top
< r1
->top
)
118 ASSERT(r1
->bottom
== r2
->bottom
);
119 if (r1
->right
< r2
->right
)
123 else if (r2
->right
< r1
->right
)
129 ASSERT(r1
->left
== r2
->left
);
138 CompareLeftUp(const PRECT r1
, const PRECT r2
)
142 if (r1
->bottom
< r2
->bottom
)
146 else if (r2
->bottom
< r1
->bottom
)
152 ASSERT(r1
->top
== r2
->top
);
153 if (r1
->right
< r2
->right
)
157 else if (r2
->right
< r1
->right
)
163 ASSERT(r1
->left
== r2
->left
);
172 CompareSpans(const PSPAN Span1
, const PSPAN Span2
)
176 if (Span1
->Y
< Span2
->Y
)
180 else if (Span2
->Y
< Span1
->Y
)
186 if (Span1
->X
< Span2
->X
)
190 else if (Span2
->X
< Span1
->X
)
204 IntEngDeleteClipRegion(CLIPOBJ
*ClipObj
)
206 EngFreeMem(ObjToGDI(ClipObj
, CLIP
));
210 IntEngCreateClipRegion(ULONG count
, PRECTL pRect
, PRECTL rcBounds
)
218 Clip
= EngAllocMem(0, sizeof(CLIPGDI
) + ((count
- 1) * sizeof(RECTL
)), TAG_CLIPOBJ
);
222 Clip
->EnumRects
.c
= count
;
223 Clip
->EnumOrder
= CD_ANY
;
224 for(dest
= Clip
->EnumRects
.arcl
;
226 count
--, dest
++, pRect
++)
231 Clip
->ClipObj
.iDComplexity
= DC_COMPLEX
;
232 Clip
->ClipObj
.iFComplexity
= ((Clip
->EnumRects
.c
<= 4) ? FC_RECT4
: FC_COMPLEX
);
233 Clip
->ClipObj
.iMode
= TC_RECTANGLES
;
234 Clip
->ClipObj
.rclBounds
= *rcBounds
;
236 return GDIToObj(Clip
, CLIP
);
241 Clip
= EngAllocMem(0, sizeof(CLIPGDI
), TAG_CLIPOBJ
);
245 Clip
->EnumRects
.c
= 1;
246 Clip
->EnumOrder
= CD_ANY
;
247 Clip
->EnumRects
.arcl
[0] = *rcBounds
;
249 Clip
->ClipObj
.iDComplexity
= (((rcBounds
->top
== rcBounds
->bottom
) &&
250 (rcBounds
->left
== rcBounds
->right
))
251 ? DC_TRIVIAL
: DC_RECT
);
252 Clip
->ClipObj
.iFComplexity
= FC_RECT
;
253 Clip
->ClipObj
.iMode
= TC_RECTANGLES
;
254 Clip
->ClipObj
.rclBounds
= *rcBounds
;
256 return GDIToObj(Clip
, CLIP
);
269 CLIPGDI
*Clip
= EngAllocMem(FL_ZERO_MEMORY
, sizeof(CLIPOBJ
), TAG_CLIPOBJ
);
272 return GDIToObj(Clip
, CLIP
);
282 EngDeleteClip(CLIPOBJ
*ClipRegion
)
284 EngFreeMem(ObjToGDI(ClipRegion
, CLIP
));
291 CLIPOBJ_cEnumStart(IN CLIPOBJ
* ClipObj
,
297 CLIPGDI
*ClipGDI
= ObjToGDI(ClipObj
, CLIP
);
298 SORTCOMP CompareFunc
;
300 ClipGDI
->EnumPos
= 0;
301 ClipGDI
->EnumMax
= (MaxRects
> 0) ? MaxRects
: ClipGDI
->EnumRects
.c
;
303 if (CD_ANY
!= BuildOrder
&& ClipGDI
->EnumOrder
!= BuildOrder
)
308 CompareFunc
= (SORTCOMP
) CompareRightDown
;
311 CompareFunc
= (SORTCOMP
) CompareRightUp
;
314 CompareFunc
= (SORTCOMP
) CompareLeftDown
;
317 CompareFunc
= (SORTCOMP
) CompareLeftUp
;
320 DPRINT1("Invalid BuildOrder %d\n", BuildOrder
);
321 BuildOrder
= ClipGDI
->EnumOrder
;
326 if (NULL
!= CompareFunc
)
328 EngSort((PBYTE
) ClipGDI
->EnumRects
.arcl
, sizeof(RECTL
), ClipGDI
->EnumRects
.c
,
332 ClipGDI
->EnumOrder
= BuildOrder
;
335 /* Return the number of rectangles enumerated */
336 if ((MaxRects
> 0) && (ClipGDI
->EnumRects
.c
> MaxRects
))
341 return ClipGDI
->EnumRects
.c
;
348 CLIPOBJ_bEnum(IN CLIPOBJ
* ClipObj
,
350 OUT ULONG
*EnumRects
)
353 CLIPGDI
*ClipGDI
= ObjToGDI(ClipObj
, CLIP
);
355 ENUMRECTS
* pERects
= (ENUMRECTS
*)EnumRects
;
357 //calculate how many rectangles we should copy
358 nCopy
= min( ClipGDI
->EnumMax
- ClipGDI
->EnumPos
,
359 min( ClipGDI
->EnumRects
.c
- ClipGDI
->EnumPos
,
360 (ObjSize
- sizeof(ULONG
)) / sizeof(RECTL
)));
366 /* copy rectangles */
367 src
= ClipGDI
->EnumRects
.arcl
+ ClipGDI
->EnumPos
;
368 for(i
= 0, dest
= pERects
->arcl
;
377 ClipGDI
->EnumPos
+=nCopy
;
379 return ClipGDI
->EnumPos
< ClipGDI
->EnumRects
.c
;
383 ClipobjToSpans(PSPAN
*Spans
, UINT
*Count
, CLIPOBJ
*ClipRegion
, PRECTL Boundary
)
391 ASSERT(Boundary
->top
<= Boundary
->bottom
&& Boundary
->left
<= Boundary
->right
);
394 if (NULL
== ClipRegion
|| DC_TRIVIAL
== ClipRegion
->iDComplexity
)
396 *Count
= Boundary
->bottom
- Boundary
->top
;
399 *Spans
= ExAllocatePoolWithTag(PagedPool
, *Count
* sizeof(SPAN
), TAG_CLIP
);
405 for (i
= 0; i
< Boundary
->bottom
- Boundary
->top
; i
++)
407 (*Spans
)[i
].X
= Boundary
->left
;
408 (*Spans
)[i
].Y
= Boundary
->top
+ i
;
409 (*Spans
)[i
].Width
= Boundary
->right
- Boundary
->left
;
417 CLIPOBJ_cEnumStart(ClipRegion
, FALSE
, CT_RECTANGLES
, CD_ANY
, 0);
420 EnumMore
= CLIPOBJ_bEnum(ClipRegion
, (ULONG
) sizeof(RECT_ENUM
), (PVOID
) &RectEnum
);
423 for (i
= 0; i
< RectEnum
.c
; i
++)
425 NewCount
+= RectEnum
.arcl
[i
].bottom
- RectEnum
.arcl
[i
].top
;
427 if (NewCount
!= *Count
)
429 NewSpans
= ExAllocatePoolWithTag(PagedPool
, NewCount
* sizeof(SPAN
), TAG_CLIP
);
430 if (NULL
== NewSpans
)
444 for(dest
= NewSpans
, src
= *Spans
;
454 for (Rect
= RectEnum
.arcl
; Rect
< RectEnum
.arcl
+ RectEnum
.c
; Rect
++)
456 for (i
= 0; i
< Rect
->bottom
- Rect
->top
; i
++)
458 (*Spans
)[*Count
].X
= Rect
->left
;
459 (*Spans
)[*Count
].Y
= Rect
->top
+ i
;
460 (*Spans
)[*Count
].Width
= Rect
->right
- Rect
->left
;
464 ASSERT(*Count
== NewCount
);
470 EngSort((PBYTE
) *Spans
, sizeof(SPAN
), *Count
, (SORTCOMP
) CompareSpans
);