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