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