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