1 /*
2 * COPYRIGHT: GNU GPL, See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Clip region functions
5 * FILE: win32ss/gdi/ntgdi/cliprgn.c
6 * PROGRAMER: Unknown
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 DBG_DEFAULT_CHANNEL(GdiClipRgn);
15
16 VOID
17 FASTCALL
IntGdiReleaseRaoRgn(PDC pDC)18 IntGdiReleaseRaoRgn(PDC pDC)
19 {
20 INT Index = GDI_HANDLE_GET_INDEX(pDC->BaseObject.hHmgr);
21 PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
22 pDC->fs |= DC_DIRTY_RAO;
23 Entry->Flags |= GDI_ENTRY_VALIDATE_VIS; // Need to validate Vis.
24 }
25
26 VOID
27 FASTCALL
IntGdiReleaseVisRgn(PDC pDC)28 IntGdiReleaseVisRgn(PDC pDC)
29 {
30 IntGdiReleaseRaoRgn(pDC);
31 REGION_Delete(pDC->prgnVis);
32 pDC->prgnVis = prgnDefault; // Vis can not be NULL!!!
33 }
34
35 //
36 // Updating Vis Region Attribute for DC Attributes.
37 // BTW: This system region has an user attribute for it.
38 //
39 VOID
40 FASTCALL
UpdateVisRgn(PDC pdc)41 UpdateVisRgn(
42 PDC pdc)
43 {
44 INT Index = GDI_HANDLE_GET_INDEX(pdc->BaseObject.hHmgr);
45 PGDI_TABLE_ENTRY pEntry = &GdiHandleTable->Entries[Index];
46
47 /* Setup Vis Region Attribute information to User side */
48 pEntry->Flags |= GDI_ENTRY_VALIDATE_VIS;
49 pdc->pdcattr->VisRectRegion.iComplexity = REGION_GetRgnBox(pdc->prgnVis, &pdc->pdcattr->VisRectRegion.Rect);
50 pdc->pdcattr->VisRectRegion.AttrFlags = ATTR_RGN_VALID;
51 pEntry->Flags &= ~GDI_ENTRY_VALIDATE_VIS;
52 }
53
54 //
55 // Selecting Vis Region.
56 //
57 VOID
58 FASTCALL
GdiSelectVisRgn(HDC hdc,PREGION prgn)59 GdiSelectVisRgn(
60 HDC hdc,
61 PREGION prgn)
62 {
63 DC *dc;
64
65 if (!(dc = DC_LockDc(hdc)))
66 {
67 EngSetLastError(ERROR_INVALID_HANDLE);
68 return;
69 }
70
71 if (!prgn)
72 {
73 DPRINT1("SVR: Setting NULL Region\n");
74 IntGdiReleaseVisRgn(dc);
75 IntSetDefaultRegion(dc);
76 DC_UnlockDc(dc);
77 return;
78 }
79
80 dc->fs |= DC_DIRTY_RAO;
81
82 ASSERT(dc->prgnVis != NULL);
83 ASSERT(prgn != NULL);
84
85 REGION_bCopy(dc->prgnVis, prgn);
86 REGION_bOffsetRgn(dc->prgnVis, -dc->ptlDCOrig.x, -dc->ptlDCOrig.y);
87
88 DC_UnlockDc(dc);
89 }
90
91 _Success_(return!=ERROR)
92 int
93 FASTCALL
IntSelectClipRgn(_In_ PDC dc,_In_ PREGION prgn,_In_ int fnMode)94 IntSelectClipRgn(
95 _In_ PDC dc,
96 _In_ PREGION prgn,
97 _In_ int fnMode)
98 {
99 int Ret = ERROR;
100 PREGION prgnNClip, prgnOrigClip = dc->dclevel.prgnClip;
101
102 //
103 // No Coping Regions and no intersecting Regions or an User calling w NULL Region or have the Original Clip Region.
104 //
105 if (fnMode != RGN_COPY && (fnMode != RGN_AND || !prgn || prgnOrigClip))
106 {
107 prgnNClip = IntSysCreateRectpRgn(0, 0, 0, 0);
108
109 // Have Original Clip Region.
110 if (prgnOrigClip)
111 {
112 // This will fail on NULL prgn.
113 Ret = IntGdiCombineRgn(prgnNClip, prgnOrigClip, prgn, fnMode);
114
115 if (Ret)
116 {
117 REGION_Delete(prgnOrigClip);
118 dc->dclevel.prgnClip = prgnNClip;
119 IntGdiReleaseRaoRgn(dc);
120 }
121 else
122 REGION_Delete(prgnNClip);
123 }
124 else // NULL Original Clip Region, setup a new one and process mode.
125 {
126 PREGION prgnClip;
127 RECTL rcl;
128 #if 0
129 PSURFACE pSurface;
130
131 // See IntSetDefaultRegion.
132
133 rcl.left = 0;
134 rcl.top = 0;
135 rcl.right = dc->dclevel.sizl.cx;
136 rcl.bottom = dc->dclevel.sizl.cy;
137
138 //EngAcquireSemaphoreShared(pdc->ppdev->hsemDevLock);
139 if (dc->ppdev->flFlags & PDEV_META_DEVICE)
140 {
141 pSurface = dc->dclevel.pSurface;
142 if (pSurface && pSurface->flags & PDEV_SURFACE)
143 {
144 rcl.left += dc->ppdev->ptlOrigion.x;
145 rcl.top += dc->ppdev->ptlOrigion.y;
146 rcl.right += dc->ppdev->ptlOrigion.x;
147 rcl.bottom += dc->ppdev->ptlOrigion.y;
148 }
149 }
150 //EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
151 //#if 0
152 rcl.left += dc->ptlDCOrig.x;
153 rcl.top += dc->ptlDCOrig.y;
154 rcl.right += dc->ptlDCOrig.x;
155 rcl.bottom += dc->ptlDCOrig.y;
156 #endif
157 REGION_GetRgnBox(dc->prgnVis, &rcl);
158
159 prgnClip = IntSysCreateRectpRgnIndirect(&rcl);
160
161 Ret = IntGdiCombineRgn(prgnNClip, prgnClip, prgn, fnMode);
162
163 if (Ret)
164 {
165 dc->dclevel.prgnClip = prgnNClip;
166 IntGdiReleaseRaoRgn(dc);
167 }
168 else
169 REGION_Delete(prgnNClip);
170
171 REGION_Delete(prgnClip);
172 }
173 return Ret;
174 }
175
176 // Fall through to normal RectOS mode.
177
178 //
179 // Handle NULL Region and Original Clip Region.
180 //
181 if (!prgn)
182 {
183 if (prgnOrigClip)
184 {
185 REGION_Delete(dc->dclevel.prgnClip);
186 dc->dclevel.prgnClip = NULL;
187 IntGdiReleaseRaoRgn(dc);
188 }
189 return SIMPLEREGION;
190 }
191
192 //
193 // Combine the new Clip region with original Clip and caller Region.
194 //
195 if ( prgnOrigClip &&
196 (Ret = IntGdiCombineRgn(prgnOrigClip, prgn, NULL, RGN_COPY)) ) // Clip could fail.
197 {
198 IntGdiReleaseRaoRgn(dc);
199 }
200 else // NULL original Clip, just copy caller region to new.
201 {
202 prgnNClip = IntSysCreateRectpRgn(0, 0, 0, 0);
203 REGION_bCopy(prgnNClip, prgn);
204 Ret = REGION_Complexity(prgnNClip);
205 dc->dclevel.prgnClip = prgnNClip;
206 IntGdiReleaseRaoRgn(dc);
207 }
208 return Ret;
209 }
210
211 //
212 // Call from Gdi Batch Subsystem.
213 //
214 // Was setup to just handle RGN_COPY only and return VOID, since this was called from Gdi32.
215 // Tested in place of the other, complexity aside.
216 //
217
218 _Success_(return!=ERROR)
219 int
220 FASTCALL
IntGdiExtSelectClipRect(_In_ PDC dc,_In_ PRECTL prcl,_In_ int fnMode)221 IntGdiExtSelectClipRect(
222 _In_ PDC dc,
223 _In_ PRECTL prcl,
224 _In_ int fnMode)
225 {
226 int Ret = ERROR;
227 PREGION prgn;
228 RECTL rect;
229 BOOL NoRegion = fnMode & GDIBS_NORECT;
230
231 fnMode &= ~GDIBS_NORECT;
232
233 if (NoRegion) // NULL Region.
234 {
235 if (fnMode == RGN_COPY)
236 {
237 Ret = IntSelectClipRgn( dc, NULL, RGN_COPY);
238
239 if (dc->fs & DC_DIRTY_RAO)
240 CLIPPING_UpdateGCRegion(dc);
241
242 if (Ret) // Copy? Return Vis complexity.
243 Ret = REGION_Complexity(dc->prgnVis);
244 }
245 }
246 else // Have a box to build a region with.
247 { // See CORE-16246 : Needs to be a one box Clip Region.
248 if ( dc->dclevel.prgnClip && (REGION_Complexity(dc->dclevel.prgnClip) == SIMPLEREGION) )
249 {
250 REGION_GetRgnBox(dc->dclevel.prgnClip, &rect);
251
252 if (prcl->left == rect.left &&
253 prcl->top == rect.top &&
254 prcl->right == rect.right &&
255 prcl->bottom == rect.bottom)
256 {
257 return REGION_Complexity( dc->prgnRao ? dc->prgnRao : dc->prgnVis );
258 }
259 }
260
261 prgn = IntSysCreateRectpRgnIndirect(prcl);
262
263 Ret = IntSelectClipRgn( dc, prgn, fnMode);
264
265 if (dc->fs & DC_DIRTY_RAO)
266 CLIPPING_UpdateGCRegion(dc);
267
268 if (Ret) // In this case NtGdiExtSelectClipRgn tests pass.
269 Ret = REGION_Complexity( dc->prgnRao ? dc->prgnRao : dc->prgnVis );
270
271 REGION_Delete(prgn);
272 }
273 return Ret;
274 }
275
276 _Success_(return!=ERROR)
277 int
278 FASTCALL
IntGdiExtSelectClipRgn(_In_ PDC dc,_In_ PREGION prgn,_In_ int fnMode)279 IntGdiExtSelectClipRgn(
280 _In_ PDC dc,
281 _In_ PREGION prgn,
282 _In_ int fnMode)
283 {
284 int Ret = ERROR;
285
286 if (!prgn)
287 {
288 if (fnMode == RGN_COPY)
289 {
290 if ((Ret = IntSelectClipRgn( dc, NULL, RGN_COPY)))
291 Ret = REGION_Complexity(dc->prgnVis);
292 }
293 }
294 else
295 {
296 if ((Ret = IntSelectClipRgn( dc, prgn, fnMode)))
297 {
298 DPRINT("IntGdiExtSelectClipRgn A %d\n",Ret);
299 // Update the Rao, it must be this way for now.
300 if (dc->fs & DC_DIRTY_RAO)
301 CLIPPING_UpdateGCRegion(dc);
302
303 Ret = REGION_Complexity( dc->prgnRao ? dc->prgnRao : dc->prgnVis );
304 DPRINT("IntGdiExtSelectClipRgn B %d\n",Ret);
305 }
306 }
307 return Ret;
308 }
309
310 int
311 APIENTRY
NtGdiExtSelectClipRgn(HDC hDC,HRGN hrgn,int fnMode)312 NtGdiExtSelectClipRgn(
313 HDC hDC,
314 HRGN hrgn,
315 int fnMode)
316 {
317 int retval;
318 DC *dc;
319 PREGION prgn;
320
321 if ( fnMode < RGN_AND || fnMode > RGN_COPY )
322 {
323 EngSetLastError(ERROR_INVALID_PARAMETER);
324 return ERROR;
325 }
326
327 if (!(dc = DC_LockDc(hDC)))
328 {
329 EngSetLastError(ERROR_INVALID_HANDLE);
330 return ERROR;
331 }
332
333 prgn = REGION_LockRgn(hrgn);
334
335 if ((prgn == NULL) && (fnMode != RGN_COPY))
336 {
337 //EngSetLastError(ERROR_INVALID_HANDLE); doesn't set this.
338 retval = ERROR;
339 }
340 else
341 {
342 #if 0 // Testing GDI Batch.
343 {
344 RECTL rcl;
345 if (prgn)
346 REGION_GetRgnBox(prgn, &rcl);
347 else
348 fnMode |= GDIBS_NORECT;
349 retval = IntGdiExtSelectClipRect(dc, &rcl, fnMode);
350 }
351 #else
352 retval = IntGdiExtSelectClipRgn(dc, prgn, fnMode);
353 #endif
354 }
355
356 if (prgn)
357 REGION_UnlockRgn(prgn);
358
359 DC_UnlockDc(dc);
360 return retval;
361 }
362
363 _Success_(return!=ERROR)
364 INT
365 FASTCALL
GdiGetClipBox(_In_ HDC hdc,_Out_ LPRECT prc)366 GdiGetClipBox(
367 _In_ HDC hdc,
368 _Out_ LPRECT prc)
369 {
370 PDC pdc;
371 INT iComplexity;
372
373 /* Lock the DC */
374 pdc = DC_LockDc(hdc);
375 if (!pdc)
376 {
377 return ERROR;
378 }
379
380 /* Update RAO region if necessary */
381 if (pdc->fs & DC_DIRTY_RAO)
382 CLIPPING_UpdateGCRegion(pdc);
383
384 /* Check if we have a RAO region (intersection of API and VIS region) */
385 if (pdc->prgnRao)
386 {
387 /* We have a RAO region, use it */
388 iComplexity = REGION_GetRgnBox(pdc->prgnRao, prc);
389 }
390 else
391 {
392 /* No RAO region means no API region, so use the VIS region */
393 ASSERT(pdc->prgnVis);
394 iComplexity = REGION_GetRgnBox(pdc->prgnVis, prc);
395 }
396
397 /* Unlock the DC */
398 DC_UnlockDc(pdc);
399
400 /* Convert the rect to logical coordinates */
401 IntDPtoLP(pdc, (LPPOINT)prc, 2);
402
403 /* Return the complexity */
404 return iComplexity;
405 }
406
407 _Success_(return!=ERROR)
408 INT
409 APIENTRY
NtGdiGetAppClipBox(_In_ HDC hdc,_Out_ LPRECT prc)410 NtGdiGetAppClipBox(
411 _In_ HDC hdc,
412 _Out_ LPRECT prc)
413 {
414 RECT rect;
415 INT iComplexity;
416
417 /* Call the internal function */
418 iComplexity = GdiGetClipBox(hdc, &rect);
419
420 if (iComplexity != ERROR)
421 {
422 _SEH2_TRY
423 {
424 ProbeForWrite(prc, sizeof(RECT), 1);
425 *prc = rect;
426 }
427 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
428 {
429 iComplexity = ERROR;
430 }
431 _SEH2_END
432 }
433
434 /* Return the complexity */
435 return iComplexity;
436 }
437
438 INT
439 APIENTRY
NtGdiExcludeClipRect(_In_ HDC hdc,_In_ INT xLeft,_In_ INT yTop,_In_ INT xRight,_In_ INT yBottom)440 NtGdiExcludeClipRect(
441 _In_ HDC hdc,
442 _In_ INT xLeft,
443 _In_ INT yTop,
444 _In_ INT xRight,
445 _In_ INT yBottom)
446 {
447 INT iComplexity = ERROR;
448 RECTL rect;
449 PDC pdc;
450 PREGION prgn;
451
452 /* Lock the DC */
453 pdc = DC_LockDc(hdc);
454 if (pdc == NULL)
455 {
456 EngSetLastError(ERROR_INVALID_HANDLE);
457 return ERROR;
458 }
459
460 /* Convert coordinates to device space */
461 rect.left = xLeft;
462 rect.top = yTop;
463 rect.right = xRight;
464 rect.bottom = yBottom;
465 RECTL_vMakeWellOrdered(&rect);
466 IntLPtoDP(pdc, (LPPOINT)&rect, 2);
467
468 prgn = IntSysCreateRectpRgnIndirect(&rect);
469 if ( prgn )
470 {
471 iComplexity = IntSelectClipRgn( pdc, prgn, RGN_DIFF );
472
473 REGION_Delete(prgn);
474 }
475
476 /* Emulate Windows behavior */
477 if (iComplexity == SIMPLEREGION)
478 iComplexity = COMPLEXREGION;
479
480 /* Unlock the DC */
481 DC_UnlockDc(pdc);
482
483 return iComplexity;
484 }
485
486 INT
487 APIENTRY
NtGdiIntersectClipRect(_In_ HDC hdc,_In_ INT xLeft,_In_ INT yTop,_In_ INT xRight,_In_ INT yBottom)488 NtGdiIntersectClipRect(
489 _In_ HDC hdc,
490 _In_ INT xLeft,
491 _In_ INT yTop,
492 _In_ INT xRight,
493 _In_ INT yBottom)
494 {
495 INT iComplexity = ERROR;
496 RECTL rect;
497 PDC pdc;
498 PREGION prgn;
499
500 DPRINT("NtGdiIntersectClipRect(%p, %d,%d-%d,%d)\n",
501 hdc, xLeft, yTop, xRight, yBottom);
502
503 /* Lock the DC */
504 pdc = DC_LockDc(hdc);
505 if (!pdc)
506 {
507 EngSetLastError(ERROR_INVALID_HANDLE);
508 return ERROR;
509 }
510
511 /* Convert coordinates to device space */
512 rect.left = xLeft;
513 rect.top = yTop;
514 rect.right = xRight;
515 rect.bottom = yBottom;
516 RECTL_vMakeWellOrdered(&rect);
517 IntLPtoDP(pdc, (LPPOINT)&rect, 2);
518
519 prgn = IntSysCreateRectpRgnIndirect(&rect);
520 if ( prgn )
521 {
522 iComplexity = IntSelectClipRgn( pdc, prgn, RGN_AND );
523
524 REGION_Delete(prgn);
525 }
526
527 /* Emulate Windows behavior */
528 if ( iComplexity == SIMPLEREGION )
529 iComplexity = COMPLEXREGION;
530
531 /* Unlock the DC */
532 DC_UnlockDc(pdc);
533
534 return iComplexity;
535 }
536
537 INT
538 APIENTRY
NtGdiOffsetClipRgn(_In_ HDC hdc,_In_ INT xOffset,_In_ INT yOffset)539 NtGdiOffsetClipRgn(
540 _In_ HDC hdc,
541 _In_ INT xOffset,
542 _In_ INT yOffset)
543 {
544 INT iComplexity;
545 PDC pdc;
546 POINTL apt[2];
547
548 /* Lock the DC */
549 pdc = DC_LockDc(hdc);
550 if (pdc == NULL)
551 {
552 if (!hdc) EngSetLastError(ERROR_INVALID_HANDLE);
553 return ERROR;
554 }
555
556 /* Check if we have a clip region */
557 if (pdc->dclevel.prgnClip != NULL)
558 {
559 /* Convert coordinates into device space. Note that we need to convert
560 2 coordinates to account for rotation / shear / offset */
561 apt[0].x = 0;
562 apt[0].y = 0;
563 apt[1].x = xOffset;
564 apt[1].y = yOffset;
565 IntLPtoDP(pdc, apt, 2);
566
567 /* Offset the clip region */
568 if (!REGION_bOffsetRgn(pdc->dclevel.prgnClip,
569 apt[1].x - apt[0].x,
570 apt[1].y - apt[0].y))
571 {
572 iComplexity = ERROR;
573 }
574 else
575 {
576 IntGdiReleaseRaoRgn(pdc);
577 UpdateVisRgn(pdc);
578 iComplexity = REGION_Complexity(pdc->dclevel.prgnClip);
579 }
580
581 /* Mark the RAO region as dirty */
582 pdc->fs |= DC_DIRTY_RAO;
583 }
584 else
585 {
586 /* NULL means no clipping, i.e. the "whole" region */
587 iComplexity = SIMPLEREGION;
588 }
589
590 /* Unlock the DC and return the complexity */
591 DC_UnlockDc(pdc);
592 return iComplexity;
593 }
594
NtGdiPtVisible(HDC hDC,int X,int Y)595 BOOL APIENTRY NtGdiPtVisible(HDC hDC,
596 int X,
597 int Y)
598 {
599 BOOL ret = FALSE;
600 PDC dc;
601 PREGION prgn;
602
603 if(!(dc = DC_LockDc(hDC)))
604 {
605 EngSetLastError(ERROR_INVALID_HANDLE);
606 return FALSE;
607 }
608
609 prgn = dc->prgnRao ? dc->prgnRao : dc->prgnVis;
610
611 if (prgn)
612 {
613 POINT pt = {X, Y};
614 IntLPtoDP(dc, &pt, 1);
615 ret = REGION_PtInRegion(prgn, pt.x, pt.y);
616 }
617
618 DC_UnlockDc(dc);
619
620 return ret;
621 }
622
623 BOOL
624 APIENTRY
NtGdiRectVisible(HDC hDC,LPRECT UnsafeRect)625 NtGdiRectVisible(
626 HDC hDC,
627 LPRECT UnsafeRect)
628 {
629 NTSTATUS Status = STATUS_SUCCESS;
630 PDC dc = DC_LockDc(hDC);
631 BOOL Result = FALSE;
632 RECTL Rect;
633 PREGION prgn;
634
635 if (!dc)
636 {
637 EngSetLastError(ERROR_INVALID_HANDLE);
638 return FALSE;
639 }
640
641 _SEH2_TRY
642 {
643 ProbeForRead(UnsafeRect,
644 sizeof(RECT),
645 1);
646 Rect = *UnsafeRect;
647 }
648 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
649 {
650 Status = _SEH2_GetExceptionCode();
651 }
652 _SEH2_END;
653
654 if(!NT_SUCCESS(Status))
655 {
656 DC_UnlockDc(dc);
657 SetLastNtError(Status);
658 return FALSE;
659 }
660
661 if (dc->fs & DC_DIRTY_RAO)
662 CLIPPING_UpdateGCRegion(dc);
663
664 prgn = dc->prgnRao ? dc->prgnRao : dc->prgnVis;
665 if (prgn)
666 {
667 IntLPtoDP(dc, (LPPOINT)&Rect, 2);
668 Result = REGION_RectInRegion(prgn, &Rect);
669 }
670 DC_UnlockDc(dc);
671
672 return Result;
673 }
674
675 int
676 FASTCALL
IntGdiSetMetaRgn(PDC pDC)677 IntGdiSetMetaRgn(PDC pDC)
678 {
679 INT Ret = ERROR;
680
681 if ( pDC->dclevel.prgnMeta )
682 {
683 if ( pDC->dclevel.prgnClip )
684 {
685 PREGION prgn = IntSysCreateRectpRgn(0,0,0,0);
686 if ( prgn )
687 {
688 if (REGION_bIntersectRegion(prgn, pDC->dclevel.prgnMeta, pDC->dclevel.prgnClip))
689 {
690 // See Restore/SaveDC
691 REGION_Delete(pDC->dclevel.prgnMeta);
692 pDC->dclevel.prgnMeta = prgn;
693
694 REGION_Delete(pDC->dclevel.prgnClip);
695 pDC->dclevel.prgnClip = NULL;
696 IntGdiReleaseRaoRgn(pDC);
697
698 Ret = REGION_Complexity(pDC->dclevel.prgnMeta);
699 }
700 else
701 REGION_Delete(prgn);
702 }
703 }
704 else
705 Ret = REGION_Complexity(pDC->dclevel.prgnMeta);
706 }
707 else
708 {
709 if ( pDC->dclevel.prgnClip )
710 {
711 Ret = REGION_Complexity(pDC->dclevel.prgnClip);
712 pDC->dclevel.prgnMeta = pDC->dclevel.prgnClip;
713 pDC->dclevel.prgnClip = NULL;
714 }
715 else
716 Ret = SIMPLEREGION;
717 }
718
719 return Ret;
720 }
721
722
NtGdiSetMetaRgn(HDC hDC)723 int APIENTRY NtGdiSetMetaRgn(HDC hDC)
724 {
725 INT Ret;
726 PDC pDC = DC_LockDc(hDC);
727
728 if (!pDC)
729 {
730 EngSetLastError(ERROR_INVALID_PARAMETER);
731 return ERROR;
732 }
733 Ret = IntGdiSetMetaRgn(pDC);
734
735 DC_UnlockDc(pDC);
736 return Ret;
737 }
738
739 VOID
740 FASTCALL
CLIPPING_UpdateGCRegion(PDC pDC)741 CLIPPING_UpdateGCRegion(PDC pDC)
742 {
743 // Moved from Release Rao. Though it still gets over written.
744 RECTL_vSetEmptyRect(&pDC->erclClip);
745
746 /* Must have VisRgn set to a valid state! */
747 ASSERT (pDC->prgnVis);
748 #if 0 // (w2k3) This works with limitations. (w7u) ReactOS relies on Rao.
749 if ( !pDC->dclevel.prgnClip &&
750 !pDC->dclevel.prgnMeta &&
751 !pDC->prgnAPI)
752 {
753 if (pDC->prgnRao)
754 REGION_Delete(pDC->prgnRao);
755 pDC->prgnRao = NULL;
756
757 REGION_bOffsetRgn(pDC->prgnVis, pDC->ptlDCOrig.x, pDC->ptlDCOrig.y);
758
759 RtlCopyMemory(&pDC->erclClip,
760 &pDC->prgnVis->rdh.rcBound,
761 sizeof(RECTL));
762
763 IntEngUpdateClipRegion(&pDC->co,
764 pDC->prgnVis->rdh.nCount,
765 pDC->prgnVis->Buffer,
766 &pDC->erclClip);
767
768 REGION_bOffsetRgn(pDC->prgnVis, -pDC->ptlDCOrig.x, -pDC->ptlDCOrig.y);
769
770 pDC->fs &= ~DC_DIRTY_RAO;
771 UpdateVisRgn(pDC);
772 return;
773 }
774 #endif
775 if (pDC->prgnAPI)
776 {
777 REGION_Delete(pDC->prgnAPI);
778 pDC->prgnAPI = NULL;
779 }
780
781 if (pDC->dclevel.prgnMeta || pDC->dclevel.prgnClip)
782 {
783 pDC->prgnAPI = IntSysCreateRectpRgn(0,0,0,0);
784 if (!pDC->prgnAPI)
785 {
786 /* Best we can do here. Better than crashing. */
787 ERR("Failed to allocate prgnAPI! Expect drawing issues!\n");
788 return;
789 }
790
791 if (!pDC->dclevel.prgnMeta)
792 {
793 REGION_bCopy(pDC->prgnAPI,
794 pDC->dclevel.prgnClip);
795 }
796 else if (!pDC->dclevel.prgnClip)
797 {
798 REGION_bCopy(pDC->prgnAPI,
799 pDC->dclevel.prgnMeta);
800 }
801 else
802 {
803 REGION_bIntersectRegion(pDC->prgnAPI,
804 pDC->dclevel.prgnClip,
805 pDC->dclevel.prgnMeta);
806 }
807 }
808
809 if (pDC->prgnRao)
810 REGION_Delete(pDC->prgnRao);
811
812 pDC->prgnRao = IntSysCreateRectpRgn(0,0,0,0);
813 if (!pDC->prgnRao)
814 {
815 /* Best we can do here. Better than crashing. */
816 ERR("Failed to allocate prgnRao! Expect drawing issues!\n");
817 return;
818 }
819
820 if (pDC->prgnAPI)
821 {
822 REGION_bIntersectRegion(pDC->prgnRao,
823 pDC->prgnVis,
824 pDC->prgnAPI);
825 }
826 else
827 {
828 REGION_bCopy(pDC->prgnRao,
829 pDC->prgnVis);
830 }
831
832
833 REGION_bOffsetRgn(pDC->prgnRao, pDC->ptlDCOrig.x, pDC->ptlDCOrig.y);
834
835 RtlCopyMemory(&pDC->erclClip,
836 &pDC->prgnRao->rdh.rcBound,
837 sizeof(RECTL));
838
839 pDC->fs &= ~DC_DIRTY_RAO;
840 UpdateVisRgn(pDC);
841
842 // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
843 // the rects from region objects rects in pClipRgn->Buffer.
844 // With pDC->co.pClipRgn->Buffer,
845 // pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
846
847 IntEngUpdateClipRegion(&pDC->co,
848 pDC->prgnRao->rdh.nCount,
849 pDC->prgnRao->Buffer,
850 &pDC->erclClip);
851
852 REGION_bOffsetRgn(pDC->prgnRao, -pDC->ptlDCOrig.x, -pDC->ptlDCOrig.y);
853 }
854
855 /* EOF */
856