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