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