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->rclBounds; 161 } 162 163 VOID FASTCALL 164 IntEngFreeClipResources(XCLIPOBJ *Clip) 165 { 166 if (Clip->Rects != &Clip->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->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 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 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 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 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