[WIN32K]
[reactos.git] / reactos / win32ss / gdi / ntgdi / cliprgn.c
1 /*
2 * COPYRIGHT: GNU GPL, See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Clip region functions
5 * FILE: subsystems/win32/win32k/objects/cliprgn.c
6 * PROGRAMER: Unknown
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 VOID
15 FASTCALL
16 GdiSelectVisRgn(
17 HDC hdc,
18 PREGION prgn)
19 {
20 DC *dc;
21
22 if (!(dc = DC_LockDc(hdc)))
23 {
24 EngSetLastError(ERROR_INVALID_HANDLE);
25 return;
26 }
27
28 dc->fs |= DC_FLAG_DIRTY_RAO;
29
30 ASSERT(dc->prgnVis != NULL);
31 ASSERT(prgn != NULL);
32
33 IntGdiCombineRgn(dc->prgnVis, prgn, NULL, RGN_COPY);
34 IntGdiOffsetRgn(dc->prgnVis, -dc->ptlDCOrig.x, -dc->ptlDCOrig.y);
35
36 DC_UnlockDc(dc);
37 }
38
39
40 int
41 FASTCALL
42 IntGdiExtSelectClipRgn(
43 PDC dc,
44 PREGION prgn,
45 int fnMode)
46 {
47 if (!prgn)
48 {
49 if (fnMode == RGN_COPY)
50 {
51 if (dc->dclevel.prgnClip != NULL)
52 {
53 REGION_Delete(dc->dclevel.prgnClip);
54 dc->dclevel.prgnClip = NULL;
55 dc->fs |= DC_FLAG_DIRTY_RAO;
56 }
57 return SIMPLEREGION;
58 }
59 else
60 {
61 EngSetLastError(ERROR_INVALID_PARAMETER);
62 return ERROR;
63 }
64 }
65
66 if (!dc->dclevel.prgnClip)
67 {
68 RECTL rect;
69
70 REGION_GetRgnBox(dc->prgnVis, &rect);
71 dc->dclevel.prgnClip = IntSysCreateRectpRgnIndirect(&rect);
72 }
73
74 dc->fs |= DC_FLAG_DIRTY_RAO;
75
76 if(fnMode == RGN_COPY)
77 return IntGdiCombineRgn(dc->dclevel.prgnClip, prgn, 0, fnMode);
78
79 return IntGdiCombineRgn(dc->dclevel.prgnClip, dc->dclevel.prgnClip, prgn, fnMode);
80 }
81
82
83 int
84 APIENTRY
85 NtGdiExtSelectClipRgn(
86 HDC hDC,
87 HRGN hrgn,
88 int fnMode)
89 {
90 int retval;
91 DC *dc;
92 PREGION prgn;
93
94 if (!(dc = DC_LockDc(hDC)))
95 {
96 EngSetLastError(ERROR_INVALID_HANDLE);
97 return ERROR;
98 }
99
100 prgn = REGION_LockRgn(hrgn);
101
102 /* IntGdiExtSelectClipRgn takes care of checking for NULL region */
103 retval = IntGdiExtSelectClipRgn(dc, prgn, fnMode);
104
105 if (prgn)
106 REGION_UnlockRgn(prgn);
107
108 DC_UnlockDc(dc);
109 return retval;
110 }
111
112 INT FASTCALL
113 GdiGetClipBox(HDC hDC, PRECTL rc)
114 {
115 INT retval;
116 PDC dc;
117 PROSRGNDATA pRgnNew, pRgn = NULL;
118
119 if (!(dc = DC_LockDc(hDC)))
120 {
121 return ERROR;
122 }
123
124 /* FIXME: Rao and Vis only! */
125 if (dc->prgnAPI) // APIRGN
126 {
127 pRgn = dc->prgnAPI;
128 }
129 else if (dc->dclevel.prgnMeta) // METARGN
130 {
131 pRgn = dc->dclevel.prgnMeta;
132 }
133 else if (dc->dclevel.prgnClip) // CLIPRGN
134 {
135 pRgn = dc->dclevel.prgnClip;
136 }
137
138 if (pRgn)
139 {
140 pRgnNew = IntSysCreateRectpRgn( 0, 0, 0, 0 );
141
142 if (!pRgnNew)
143 {
144 DC_UnlockDc(dc);
145 return ERROR;
146 }
147
148 IntGdiCombineRgn(pRgnNew, dc->prgnVis, pRgn, RGN_AND);
149
150 retval = REGION_GetRgnBox(pRgnNew, rc);
151
152 REGION_Delete(pRgnNew);
153
154 DC_UnlockDc(dc);
155 return retval;
156 }
157
158 retval = REGION_GetRgnBox(dc->prgnVis, rc);
159
160 DC_UnlockDc(dc);
161
162 return retval;
163 }
164
165 INT APIENTRY
166 NtGdiGetAppClipBox(HDC hDC, PRECTL rc)
167 {
168 INT Ret;
169 NTSTATUS Status = STATUS_SUCCESS;
170 RECTL Saferect;
171
172 Ret = GdiGetClipBox(hDC, &Saferect);
173
174 _SEH2_TRY
175 {
176 ProbeForWrite(rc,
177 sizeof(RECT),
178 1);
179 *rc = Saferect;
180 }
181 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
182 {
183 Status = _SEH2_GetExceptionCode();
184 }
185 _SEH2_END;
186
187 if(!NT_SUCCESS(Status))
188 {
189 SetLastNtError(Status);
190 return ERROR;
191 }
192
193 return Ret;
194 }
195
196 int APIENTRY NtGdiExcludeClipRect(HDC hDC,
197 int LeftRect,
198 int TopRect,
199 int RightRect,
200 int BottomRect)
201 {
202 INT Result;
203 RECTL Rect;
204 PREGION prgnNew;
205 PDC dc = DC_LockDc(hDC);
206
207 if (!dc)
208 {
209 EngSetLastError(ERROR_INVALID_HANDLE);
210 return ERROR;
211 }
212
213 Rect.left = LeftRect;
214 Rect.top = TopRect;
215 Rect.right = RightRect;
216 Rect.bottom = BottomRect;
217
218 IntLPtoDP(dc, (LPPOINT)&Rect, 2);
219
220 prgnNew = IntSysCreateRectpRgnIndirect(&Rect);
221 if (!prgnNew)
222 {
223 Result = ERROR;
224 }
225 else
226 {
227 if (!dc->dclevel.prgnClip)
228 {
229 dc->dclevel.prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0);
230 IntGdiCombineRgn(dc->dclevel.prgnClip, dc->prgnVis, prgnNew, RGN_DIFF);
231 Result = SIMPLEREGION;
232 }
233 else
234 {
235 Result = IntGdiCombineRgn(dc->dclevel.prgnClip, dc->dclevel.prgnClip, prgnNew, RGN_DIFF);
236 }
237 REGION_Delete(prgnNew);
238 }
239 if (Result != ERROR)
240 dc->fs |= DC_FLAG_DIRTY_RAO;
241
242 DC_UnlockDc(dc);
243
244 return Result;
245 }
246
247 int APIENTRY NtGdiIntersectClipRect(HDC hDC,
248 int LeftRect,
249 int TopRect,
250 int RightRect,
251 int BottomRect)
252 {
253 INT Result;
254 RECTL Rect;
255 PREGION pNewRgn;
256 PDC dc = DC_LockDc(hDC);
257
258 DPRINT("NtGdiIntersectClipRect(%p, %d,%d-%d,%d)\n",
259 hDC, LeftRect, TopRect, RightRect, BottomRect);
260
261 if (!dc)
262 {
263 EngSetLastError(ERROR_INVALID_HANDLE);
264 return ERROR;
265 }
266
267 Rect.left = LeftRect;
268 Rect.top = TopRect;
269 Rect.right = RightRect;
270 Rect.bottom = BottomRect;
271
272 IntLPtoDP(dc, (LPPOINT)&Rect, 2);
273
274 pNewRgn = IntSysCreateRectpRgnIndirect(&Rect);
275 if (!pNewRgn)
276 {
277 Result = ERROR;
278 }
279 else if (!dc->dclevel.prgnClip)
280 {
281 dc->dclevel.prgnClip = pNewRgn;
282 Result = SIMPLEREGION;
283 }
284 else
285 {
286 Result = IntGdiCombineRgn(dc->dclevel.prgnClip, dc->dclevel.prgnClip, pNewRgn, RGN_AND);
287 REGION_Delete(pNewRgn);
288 }
289 if (Result != ERROR)
290 dc->fs |= DC_FLAG_DIRTY_RAO;
291
292 DC_UnlockDc(dc);
293
294 return Result;
295 }
296
297 int APIENTRY NtGdiOffsetClipRgn(HDC hDC,
298 int XOffset,
299 int YOffset)
300 {
301 INT Result;
302 DC *dc;
303
304 if(!(dc = DC_LockDc(hDC)))
305 {
306 EngSetLastError(ERROR_INVALID_HANDLE);
307 return ERROR;
308 }
309
310 if(dc->dclevel.prgnClip != NULL)
311 {
312 Result = IntGdiOffsetRgn(dc->dclevel.prgnClip,
313 XOffset,
314 YOffset);
315 dc->fs |= DC_FLAG_DIRTY_RAO;
316 }
317 else
318 {
319 Result = NULLREGION;
320 }
321
322 DC_UnlockDc(dc);
323 return Result;
324 }
325
326 BOOL APIENTRY NtGdiPtVisible(HDC hDC,
327 int X,
328 int Y)
329 {
330 BOOL ret = FALSE;
331 PDC dc;
332
333 if(!(dc = DC_LockDc(hDC)))
334 {
335 EngSetLastError(ERROR_INVALID_HANDLE);
336 return FALSE;
337 }
338
339 if (dc->prgnRao)
340 {
341 POINT pt = {X, Y};
342 IntLPtoDP(dc, &pt, 1);
343 ret = REGION_PtInRegion(dc->prgnRao, pt.x, pt.y);
344 }
345
346 DC_UnlockDc(dc);
347
348 return ret;
349 }
350
351 BOOL
352 APIENTRY
353 NtGdiRectVisible(
354 HDC hDC,
355 LPRECT UnsafeRect)
356 {
357 NTSTATUS Status = STATUS_SUCCESS;
358 PDC dc = DC_LockDc(hDC);
359 BOOL Result = FALSE;
360 RECTL Rect;
361
362 if (!dc)
363 {
364 EngSetLastError(ERROR_INVALID_HANDLE);
365 return FALSE;
366 }
367
368 _SEH2_TRY
369 {
370 ProbeForRead(UnsafeRect,
371 sizeof(RECT),
372 1);
373 Rect = *UnsafeRect;
374 }
375 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
376 {
377 Status = _SEH2_GetExceptionCode();
378 }
379 _SEH2_END;
380
381 if(!NT_SUCCESS(Status))
382 {
383 DC_UnlockDc(dc);
384 SetLastNtError(Status);
385 return FALSE;
386 }
387
388 if (dc->fs & DC_FLAG_DIRTY_RAO)
389 CLIPPING_UpdateGCRegion(dc);
390
391 if (dc->prgnRao)
392 {
393 IntLPtoDP(dc, (LPPOINT)&Rect, 2);
394 Result = REGION_RectInRegion(dc->prgnRao, &Rect);
395 }
396 DC_UnlockDc(dc);
397
398 return Result;
399 }
400
401 int
402 FASTCALL
403 IntGdiSetMetaRgn(PDC pDC)
404 {
405 INT Ret = ERROR;
406
407 if ( pDC->dclevel.prgnMeta )
408 {
409 if ( pDC->dclevel.prgnClip )
410 {
411 Ret = IntGdiCombineRgn(pDC->dclevel.prgnMeta, pDC->dclevel.prgnMeta, pDC->dclevel.prgnClip, RGN_AND);
412 if (Ret != ERROR)
413 {
414 REGION_Delete(pDC->dclevel.prgnClip);
415 pDC->dclevel.prgnClip = NULL;
416 IntGdiReleaseRaoRgn(pDC);
417 }
418 }
419 else
420 Ret = REGION_Complexity(pDC->dclevel.prgnMeta);
421 }
422 else
423 {
424 if ( pDC->dclevel.prgnClip )
425 {
426 Ret = REGION_Complexity(pDC->dclevel.prgnClip);
427 pDC->dclevel.prgnMeta = pDC->dclevel.prgnClip;
428 pDC->dclevel.prgnClip = NULL;
429 }
430 else
431 Ret = SIMPLEREGION;
432 }
433
434 if (Ret != ERROR)
435 pDC->fs |= DC_FLAG_DIRTY_RAO;
436
437 return Ret;
438 }
439
440
441 int APIENTRY NtGdiSetMetaRgn(HDC hDC)
442 {
443 INT Ret;
444 PDC pDC = DC_LockDc(hDC);
445
446 if (!pDC)
447 {
448 EngSetLastError(ERROR_INVALID_PARAMETER);
449 return ERROR;
450 }
451 Ret = IntGdiSetMetaRgn(pDC);
452
453 DC_UnlockDc(pDC);
454 return Ret;
455 }
456
457 VOID
458 FASTCALL
459 CLIPPING_UpdateGCRegion(PDC pDC)
460 {
461 CLIPOBJ * co;
462
463 /* Must have VisRgn set to a valid state! */
464 ASSERT (pDC->prgnVis);
465
466 if (pDC->prgnAPI)
467 {
468 REGION_Delete(pDC->prgnAPI);
469 pDC->prgnAPI = NULL;
470 }
471
472 if (pDC->prgnRao)
473 REGION_Delete(pDC->prgnRao);
474
475 pDC->prgnRao = IntSysCreateRectpRgn(0,0,0,0);
476
477 ASSERT(pDC->prgnRao);
478
479 if (pDC->dclevel.prgnMeta || pDC->dclevel.prgnClip)
480 {
481 pDC->prgnAPI = IntSysCreateRectpRgn(0,0,0,0);
482 if (!pDC->dclevel.prgnMeta)
483 {
484 IntGdiCombineRgn(pDC->prgnAPI,
485 pDC->dclevel.prgnClip,
486 NULL,
487 RGN_COPY);
488 }
489 else if (!pDC->dclevel.prgnClip)
490 {
491 IntGdiCombineRgn(pDC->prgnAPI,
492 pDC->dclevel.prgnMeta,
493 NULL,
494 RGN_COPY);
495 }
496 else
497 {
498 IntGdiCombineRgn(pDC->prgnAPI,
499 pDC->dclevel.prgnClip,
500 pDC->dclevel.prgnMeta,
501 RGN_AND);
502 }
503 }
504
505 if (pDC->prgnAPI)
506 {
507 IntGdiCombineRgn(pDC->prgnRao,
508 pDC->prgnVis,
509 pDC->prgnAPI,
510 RGN_AND);
511 }
512 else
513 {
514 IntGdiCombineRgn(pDC->prgnRao,
515 pDC->prgnVis,
516 NULL,
517 RGN_COPY);
518 }
519
520
521 IntGdiOffsetRgn(pDC->prgnRao, pDC->ptlDCOrig.x, pDC->ptlDCOrig.y);
522
523 RtlCopyMemory(&pDC->erclClip,
524 &pDC->prgnRao->rdh.rcBound,
525 sizeof(RECTL));
526
527 pDC->fs &= ~DC_FLAG_DIRTY_RAO;
528
529 // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
530 // the rects from region objects rects in pClipRgn->Buffer.
531 // With pDC->co.pClipRgn->Buffer,
532 // pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
533
534 co = IntEngCreateClipRegion(pDC->prgnRao->rdh.nCount,
535 pDC->prgnRao->Buffer,
536 &pDC->erclClip);
537 if (co)
538 {
539 if (pDC->rosdc.CombinedClip != NULL)
540 IntEngDeleteClipRegion(pDC->rosdc.CombinedClip);
541
542 pDC->rosdc.CombinedClip = co;
543 }
544
545 IntGdiOffsetRgn(pDC->prgnRao, -pDC->ptlDCOrig.x, -pDC->ptlDCOrig.y);
546 }
547
548 /* EOF */