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