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