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