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