[CRT] Remove useless #undef abort from process.h
[reactos.git] / win32ss / gdi / ntgdi / cliprgn.c
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_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_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_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_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_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_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_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_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_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_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 */