mirror of
https://github.com/reactos/reactos.git
synced 2024-10-04 00:13:57 +00:00
[GDI32]
Rewrite CombineRgn, enabling full handling in usermode if the resulting region is either a rectangular or a NULL region. svn path=/trunk/; revision=65738
This commit is contained in:
parent
383e40f59f
commit
f3f9526d93
|
@ -187,216 +187,365 @@ MirrorRgnDC(HDC hdc, HRGN hRgn, HRGN *phRgn)
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
FORCEINLINE
|
||||||
|
ULONG
|
||||||
|
SetRectRgnEx(
|
||||||
|
HRGN hrgn,
|
||||||
|
PRGN_ATTR prgnattr,
|
||||||
|
INT xLeft,
|
||||||
|
INT yTop,
|
||||||
|
INT xRight,
|
||||||
|
INT yBottom)
|
||||||
|
{
|
||||||
|
if (!SetRectRgn(hrgn, xLeft, yTop, xRight, yBottom))
|
||||||
|
{
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prgnattr->iComplexity;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
INT
|
INT
|
||||||
WINAPI
|
WINAPI
|
||||||
CombineRgn(HRGN hDest,
|
CombineRgn(
|
||||||
HRGN hSrc1,
|
_In_ HRGN hrgnDest,
|
||||||
HRGN hSrc2,
|
_In_ HRGN hrgnSrc1,
|
||||||
INT CombineMode)
|
_In_ HRGN hrgnSrc2,
|
||||||
|
_In_ INT iCombineMode)
|
||||||
{
|
{
|
||||||
PRGN_ATTR pRgn_Attr_Dest = NULL;
|
PRGN_ATTR prngattrDest = NULL;
|
||||||
PRGN_ATTR pRgn_Attr_Src1 = NULL;
|
PRGN_ATTR prngattrSrc1 = NULL;
|
||||||
PRGN_ATTR pRgn_Attr_Src2 = NULL;
|
PRGN_ATTR prngattrSrc2 = NULL;
|
||||||
INT Complexity;
|
RECT rcTemp;
|
||||||
BOOL Ret;
|
|
||||||
|
|
||||||
// HACK
|
/* Get the region attribute for dest and source 1 */
|
||||||
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
prngattrDest = GdiGetRgnAttr(hrgnDest);
|
||||||
|
prngattrSrc1 = GdiGetRgnAttr(hrgnSrc1);
|
||||||
|
|
||||||
Ret = GdiGetHandleUserData((HGDIOBJ) hDest, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr_Dest);
|
/* If that failed or if the source 1 region is complex, go to win32k */
|
||||||
Ret = GdiGetHandleUserData((HGDIOBJ) hSrc1, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr_Src1);
|
if ((prngattrDest == NULL) || (prngattrSrc1 == NULL) ||
|
||||||
|
(prngattrSrc1->iComplexity > SIMPLEREGION))
|
||||||
if ( !Ret ||
|
|
||||||
!pRgn_Attr_Dest ||
|
|
||||||
!pRgn_Attr_Src1 ||
|
|
||||||
pRgn_Attr_Src1->iComplexity > SIMPLEREGION )
|
|
||||||
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
||||||
|
|
||||||
/* Handle COPY and use only src1. */
|
|
||||||
if ( CombineMode == RGN_COPY )
|
|
||||||
{
|
{
|
||||||
switch (pRgn_Attr_Src1->iComplexity)
|
return NtGdiCombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, iCombineMode);
|
||||||
{
|
|
||||||
case NULLREGION:
|
|
||||||
Ret = SetRectRgn( hDest, 0, 0, 0, 0);
|
|
||||||
if (Ret)
|
|
||||||
return NULLREGION;
|
|
||||||
goto ERROR_Exit;
|
|
||||||
|
|
||||||
case SIMPLEREGION:
|
|
||||||
Ret = SetRectRgn( hDest,
|
|
||||||
pRgn_Attr_Src1->Rect.left,
|
|
||||||
pRgn_Attr_Src1->Rect.top,
|
|
||||||
pRgn_Attr_Src1->Rect.right,
|
|
||||||
pRgn_Attr_Src1->Rect.bottom );
|
|
||||||
if (Ret)
|
|
||||||
return SIMPLEREGION;
|
|
||||||
goto ERROR_Exit;
|
|
||||||
|
|
||||||
case COMPLEXREGION:
|
|
||||||
default:
|
|
||||||
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ret = GdiGetHandleUserData((HGDIOBJ) hSrc2, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr_Src2);
|
/* Handle RGN_COPY first, it needs only hrgnSrc1 */
|
||||||
if ( !Ret ||
|
if (iCombineMode == RGN_COPY)
|
||||||
!pRgn_Attr_Src2 ||
|
|
||||||
pRgn_Attr_Src2->iComplexity > SIMPLEREGION )
|
|
||||||
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
||||||
|
|
||||||
/* All but AND. */
|
|
||||||
if ( CombineMode != RGN_AND)
|
|
||||||
{
|
{
|
||||||
if ( CombineMode <= RGN_AND)
|
/* Check if the source region is a NULLREGION */
|
||||||
|
if (prngattrSrc1->iComplexity == NULLREGION)
|
||||||
{
|
{
|
||||||
/*
|
/* The dest region is a NULLREGION, too */
|
||||||
There might be some type of junk in the call, so go K.
|
return SetRectRgn(hrgnDest, 0, 0, 0, 0) ? NULLREGION : ERROR;
|
||||||
If this becomes a problem, need to setup parameter check at the top.
|
|
||||||
*/
|
|
||||||
DPRINT1("Might be junk! CombineMode %d\n",CombineMode);
|
|
||||||
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( CombineMode > RGN_XOR) /* Handle DIFF. */
|
/* We already know that the source region cannot be complex, so
|
||||||
|
create a rect region from the bounds of the source rect */
|
||||||
|
return SetRectRgnEx(hrgnDest,
|
||||||
|
prngattrDest,
|
||||||
|
prngattrSrc1->Rect.left,
|
||||||
|
prngattrSrc1->Rect.top,
|
||||||
|
prngattrSrc1->Rect.right,
|
||||||
|
prngattrSrc1->Rect.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For all other operations we need hrgnSrc2 */
|
||||||
|
prngattrSrc2 = GdiGetRgnAttr(hrgnSrc2);
|
||||||
|
|
||||||
|
/* If we got no attribute or the region is complex, go to win32k */
|
||||||
|
if ((prngattrSrc2 == NULL) || (prngattrSrc2->iComplexity > SIMPLEREGION))
|
||||||
|
{
|
||||||
|
return NtGdiCombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, iCombineMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle RGN_AND */
|
||||||
|
if (iCombineMode == RGN_AND)
|
||||||
|
{
|
||||||
|
/* Check if either of the regions is a NULLREGION */
|
||||||
|
if ((prngattrSrc1->iComplexity == NULLREGION) ||
|
||||||
|
(prngattrSrc2->iComplexity == NULLREGION))
|
||||||
{
|
{
|
||||||
if ( CombineMode != RGN_DIFF)
|
/* Result is also a NULLREGION */
|
||||||
|
return SetRectRgn(hrgnDest, 0, 0, 0, 0) ? NULLREGION : ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the intersection of the 2 rects */
|
||||||
|
if (!IntersectRect(&rcTemp, &prngattrSrc1->Rect, &prngattrSrc2->Rect))
|
||||||
|
{
|
||||||
|
/* The rects do not intersect, result is a NULLREGION */
|
||||||
|
return SetRectRgn(hrgnDest, 0, 0, 0, 0) ? NULLREGION : ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use the intersection of the rects */
|
||||||
|
return SetRectRgnEx(hrgnDest,
|
||||||
|
prngattrDest,
|
||||||
|
rcTemp.left,
|
||||||
|
rcTemp.top,
|
||||||
|
rcTemp.right,
|
||||||
|
rcTemp.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle RGN_DIFF */
|
||||||
|
if (iCombineMode == RGN_DIFF)
|
||||||
|
{
|
||||||
|
/* Check if source 1 is a NULLREGION */
|
||||||
|
if (prngattrSrc1->iComplexity == NULLREGION)
|
||||||
|
{
|
||||||
|
/* The result is a NULLREGION as well */
|
||||||
|
return SetRectRgn(hrgnDest, 0, 0, 0, 0) ? NULLREGION : ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the intersection of the 2 rects */
|
||||||
|
if ((prngattrSrc2->iComplexity == NULLREGION) ||
|
||||||
|
!IntersectRect(&rcTemp, &prngattrSrc1->Rect, &prngattrSrc2->Rect))
|
||||||
|
{
|
||||||
|
/* The rects do not intersect, dest equals source 1 */
|
||||||
|
return SetRectRgnEx(hrgnDest,
|
||||||
|
prngattrDest,
|
||||||
|
prngattrSrc1->Rect.left,
|
||||||
|
prngattrSrc1->Rect.top,
|
||||||
|
prngattrSrc1->Rect.right,
|
||||||
|
prngattrSrc1->Rect.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We need to check is whether we can subtract the rects. For that
|
||||||
|
we call SubtractRect, which will give us the bounding box of the
|
||||||
|
subtraction. The function returns FALSE if the resulting rect is
|
||||||
|
empty */
|
||||||
|
if (!SubtractRect(&rcTemp, &prngattrSrc1->Rect, &rcTemp))
|
||||||
|
{
|
||||||
|
/* The result is a NULLREGION */
|
||||||
|
return SetRectRgn(hrgnDest, 0, 0, 0, 0) ? NULLREGION : ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now check if the result of SubtractRect matches the source 1 rect.
|
||||||
|
Since we already know that the rects intersect, the result can
|
||||||
|
only match the source 1 rect, if it could not be "cut" on either
|
||||||
|
side, but the overlapping was on a corner, so the new bounding box
|
||||||
|
equals the previous rect */
|
||||||
|
if (!EqualRect(&rcTemp, &prngattrSrc1->Rect))
|
||||||
|
{
|
||||||
|
/* We got a properly subtracted rect, so use it. */
|
||||||
|
return SetRectRgnEx(hrgnDest,
|
||||||
|
prngattrDest,
|
||||||
|
rcTemp.left,
|
||||||
|
rcTemp.top,
|
||||||
|
rcTemp.right,
|
||||||
|
rcTemp.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The result would be a complex region, go to win32k */
|
||||||
|
return NtGdiCombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, iCombineMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle OR and XOR */
|
||||||
|
if ((iCombineMode == RGN_OR) || (iCombineMode == RGN_XOR))
|
||||||
|
{
|
||||||
|
/* Check if source 1 is a NULLREGION */
|
||||||
|
if (prngattrSrc1->iComplexity == NULLREGION)
|
||||||
|
{
|
||||||
|
/* Check if source 2 is also a NULLREGION */
|
||||||
|
if (prngattrSrc2->iComplexity == NULLREGION)
|
||||||
{
|
{
|
||||||
/* Filter check! Well, must be junk?, so go K. */
|
/* Both are NULLREGIONs, result is also a NULLREGION */
|
||||||
DPRINT1("RGN_COPY was handled! CombineMode %d\n",CombineMode);
|
return SetRectRgn(hrgnDest, 0, 0, 0, 0) ? NULLREGION : ERROR;
|
||||||
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
||||||
}
|
|
||||||
/* Now handle DIFF. */
|
|
||||||
if ( pRgn_Attr_Src1->iComplexity == NULLREGION )
|
|
||||||
{
|
|
||||||
if (SetRectRgn( hDest, 0, 0, 0, 0))
|
|
||||||
return NULLREGION;
|
|
||||||
goto ERROR_Exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pRgn_Attr_Src2->iComplexity != NULLREGION )
|
/* The result is equal to source 2 */
|
||||||
{
|
return SetRectRgnEx(hrgnDest,
|
||||||
Complexity = ComplexityFromRects( &pRgn_Attr_Src1->Rect, &pRgn_Attr_Src2->Rect);
|
prngattrDest,
|
||||||
|
prngattrSrc2->Rect.left,
|
||||||
|
prngattrSrc2->Rect.top,
|
||||||
|
prngattrSrc2->Rect.right,
|
||||||
|
prngattrSrc2->Rect.bottom );
|
||||||
|
}
|
||||||
|
|
||||||
if ( Complexity != DIFF_RGN )
|
/* Check if only source 2 is a NULLREGION */
|
||||||
|
if (prngattrSrc2->iComplexity == NULLREGION)
|
||||||
|
{
|
||||||
|
/* The result is equal to source 1 */
|
||||||
|
return SetRectRgnEx(hrgnDest,
|
||||||
|
prngattrDest,
|
||||||
|
prngattrSrc1->Rect.left,
|
||||||
|
prngattrSrc1->Rect.top,
|
||||||
|
prngattrSrc1->Rect.right,
|
||||||
|
prngattrSrc1->Rect.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the rects have the same x extent */
|
||||||
|
if ((prngattrSrc1->Rect.left == prngattrSrc2->Rect.left) &&
|
||||||
|
(prngattrSrc1->Rect.right == prngattrSrc2->Rect.right))
|
||||||
|
{
|
||||||
|
/* Do the rects also have the same y extent */
|
||||||
|
if ((prngattrSrc1->Rect.top == prngattrSrc2->Rect.top) &&
|
||||||
|
(prngattrSrc1->Rect.bottom == prngattrSrc2->Rect.bottom))
|
||||||
|
{
|
||||||
|
/* Rects are equal, if this is RGN_OR, the result is source 1 */
|
||||||
|
if (iCombineMode == RGN_OR)
|
||||||
{
|
{
|
||||||
if ( Complexity != INVERTED_RGN)
|
/* The result is equal to source 1 */
|
||||||
/* If same or overlapping and norm just go K. */
|
return SetRectRgnEx(hrgnDest,
|
||||||
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
prngattrDest,
|
||||||
|
prngattrSrc1->Rect.left,
|
||||||
|
prngattrSrc1->Rect.top,
|
||||||
|
prngattrSrc1->Rect.right,
|
||||||
|
prngattrSrc1->Rect.bottom );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* XORing with itself yields an empty region */
|
||||||
|
return SetRectRgn(hrgnDest, 0, 0, 0, 0) ? NULLREGION : ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (SetRectRgn( hDest, 0, 0, 0, 0))
|
/* Check if the rects are disjoint */
|
||||||
return NULLREGION;
|
if ((prngattrSrc2->Rect.bottom < prngattrSrc1->Rect.top) ||
|
||||||
goto ERROR_Exit;
|
(prngattrSrc2->Rect.top > prngattrSrc1->Rect.bottom))
|
||||||
|
{
|
||||||
|
/* The result would be a complex region, go to win32k */
|
||||||
|
return NtGdiCombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, iCombineMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if this is OR */
|
||||||
|
if (iCombineMode == RGN_OR)
|
||||||
|
{
|
||||||
|
/* Use the maximum extent of both rects combined */
|
||||||
|
return SetRectRgnEx(hrgnDest,
|
||||||
|
prngattrDest,
|
||||||
|
prngattrSrc1->Rect.left,
|
||||||
|
min(prngattrSrc1->Rect.top, prngattrSrc2->Rect.top),
|
||||||
|
prngattrSrc1->Rect.right,
|
||||||
|
max(prngattrSrc1->Rect.bottom, prngattrSrc2->Rect.bottom));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the rects are adjacent */
|
||||||
|
if (prngattrSrc2->Rect.bottom == prngattrSrc1->Rect.top)
|
||||||
|
{
|
||||||
|
/* The result is the combined rects */
|
||||||
|
return SetRectRgnEx(hrgnDest,
|
||||||
|
prngattrDest,
|
||||||
|
prngattrSrc1->Rect.left,
|
||||||
|
prngattrSrc2->Rect.top,
|
||||||
|
prngattrSrc1->Rect.right,
|
||||||
|
prngattrSrc1->Rect.bottom );
|
||||||
|
}
|
||||||
|
else if (prngattrSrc2->Rect.top == prngattrSrc1->Rect.bottom)
|
||||||
|
{
|
||||||
|
/* The result is the combined rects */
|
||||||
|
return SetRectRgnEx(hrgnDest,
|
||||||
|
prngattrDest,
|
||||||
|
prngattrSrc1->Rect.left,
|
||||||
|
prngattrSrc1->Rect.top,
|
||||||
|
prngattrSrc1->Rect.right,
|
||||||
|
prngattrSrc2->Rect.bottom );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When we are here, this is RGN_XOR and the rects overlap */
|
||||||
|
return NtGdiCombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, iCombineMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the rects have the same y extent */
|
||||||
|
if ((prngattrSrc1->Rect.top == prngattrSrc2->Rect.top) &&
|
||||||
|
(prngattrSrc1->Rect.bottom == prngattrSrc2->Rect.bottom))
|
||||||
|
{
|
||||||
|
/* Check if the rects are disjoint */
|
||||||
|
if ((prngattrSrc2->Rect.right < prngattrSrc1->Rect.left) ||
|
||||||
|
(prngattrSrc2->Rect.left > prngattrSrc1->Rect.right))
|
||||||
|
{
|
||||||
|
/* The result would be a complex region, go to win32k */
|
||||||
|
return NtGdiCombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, iCombineMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if this is OR */
|
||||||
|
if (iCombineMode == RGN_OR)
|
||||||
|
{
|
||||||
|
/* Use the maximum extent of both rects combined */
|
||||||
|
return SetRectRgnEx(hrgnDest,
|
||||||
|
prngattrDest,
|
||||||
|
min(prngattrSrc1->Rect.left, prngattrSrc2->Rect.left),
|
||||||
|
prngattrSrc1->Rect.top,
|
||||||
|
max(prngattrSrc1->Rect.right, prngattrSrc2->Rect.right),
|
||||||
|
prngattrSrc1->Rect.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the rects are adjacent */
|
||||||
|
if (prngattrSrc2->Rect.right == prngattrSrc1->Rect.left)
|
||||||
|
{
|
||||||
|
/* The result is the combined rects */
|
||||||
|
return SetRectRgnEx(hrgnDest,
|
||||||
|
prngattrDest,
|
||||||
|
prngattrSrc2->Rect.left,
|
||||||
|
prngattrSrc1->Rect.top,
|
||||||
|
prngattrSrc1->Rect.right,
|
||||||
|
prngattrSrc1->Rect.bottom );
|
||||||
|
}
|
||||||
|
else if (prngattrSrc2->Rect.left == prngattrSrc1->Rect.right)
|
||||||
|
{
|
||||||
|
/* The result is the combined rects */
|
||||||
|
return SetRectRgnEx(hrgnDest,
|
||||||
|
prngattrDest,
|
||||||
|
prngattrSrc1->Rect.left,
|
||||||
|
prngattrSrc1->Rect.top,
|
||||||
|
prngattrSrc2->Rect.right,
|
||||||
|
prngattrSrc1->Rect.bottom );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When we are here, this is RGN_XOR and the rects overlap */
|
||||||
|
return NtGdiCombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, iCombineMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Last case: RGN_OR and one rect is completely within the other */
|
||||||
|
if (iCombineMode == RGN_OR)
|
||||||
|
{
|
||||||
|
/* Check if rect 1 can contain rect 2 */
|
||||||
|
if (prngattrSrc1->Rect.left <= prngattrSrc2->Rect.left)
|
||||||
|
{
|
||||||
|
/* rect 1 might be the outer one, check of that is true */
|
||||||
|
if ((prngattrSrc1->Rect.right >= prngattrSrc2->Rect.right) &&
|
||||||
|
(prngattrSrc1->Rect.top <= prngattrSrc2->Rect.top) &&
|
||||||
|
(prngattrSrc1->Rect.bottom >= prngattrSrc2->Rect.bottom))
|
||||||
|
{
|
||||||
|
/* Rect 1 contains rect 2, use it */
|
||||||
|
return SetRectRgnEx(hrgnDest,
|
||||||
|
prngattrDest,
|
||||||
|
prngattrSrc1->Rect.left,
|
||||||
|
prngattrSrc1->Rect.top,
|
||||||
|
prngattrSrc1->Rect.right,
|
||||||
|
prngattrSrc1->Rect.bottom );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* rect 2 might be the outer one, check of that is true */
|
||||||
|
if ((prngattrSrc2->Rect.right >= prngattrSrc1->Rect.right) &&
|
||||||
|
(prngattrSrc2->Rect.top <= prngattrSrc1->Rect.top) &&
|
||||||
|
(prngattrSrc2->Rect.bottom >= prngattrSrc1->Rect.bottom))
|
||||||
|
{
|
||||||
|
/* Rect 2 contains rect 1, use it */
|
||||||
|
return SetRectRgnEx(hrgnDest,
|
||||||
|
prngattrDest,
|
||||||
|
prngattrSrc2->Rect.left,
|
||||||
|
prngattrSrc2->Rect.top,
|
||||||
|
prngattrSrc2->Rect.right,
|
||||||
|
prngattrSrc2->Rect.bottom );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* Handle OR or XOR. */
|
|
||||||
{
|
|
||||||
if ( pRgn_Attr_Src1->iComplexity == NULLREGION )
|
|
||||||
{
|
|
||||||
if ( pRgn_Attr_Src2->iComplexity != NULLREGION )
|
|
||||||
{
|
|
||||||
/* Src1 null and not NULL, set from src2. */
|
|
||||||
Ret = SetRectRgn( hDest,
|
|
||||||
pRgn_Attr_Src2->Rect.left,
|
|
||||||
pRgn_Attr_Src2->Rect.top,
|
|
||||||
pRgn_Attr_Src2->Rect.right,
|
|
||||||
pRgn_Attr_Src2->Rect.bottom );
|
|
||||||
if (Ret)
|
|
||||||
return SIMPLEREGION;
|
|
||||||
goto ERROR_Exit;
|
|
||||||
}
|
|
||||||
/* Both are NULL. */
|
|
||||||
if (SetRectRgn( hDest, 0, 0, 0, 0))
|
|
||||||
return NULLREGION;
|
|
||||||
goto ERROR_Exit;
|
|
||||||
}
|
|
||||||
/* Src1 is not NULL. */
|
|
||||||
if ( pRgn_Attr_Src2->iComplexity != NULLREGION )
|
|
||||||
{
|
|
||||||
if ( CombineMode != RGN_OR ) /* Filter XOR, so go K. */
|
|
||||||
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
||||||
|
|
||||||
Complexity = ComplexityFromRects( &pRgn_Attr_Src1->Rect, &pRgn_Attr_Src2->Rect);
|
/* We couldn't handle the operation, go to win32k */
|
||||||
/* If inverted use Src2. */
|
return NtGdiCombineRgn(hrgnDest, hrgnSrc1, hrgnSrc2, iCombineMode);
|
||||||
if ( Complexity == INVERTED_RGN)
|
|
||||||
{
|
|
||||||
Ret = SetRectRgn( hDest,
|
|
||||||
pRgn_Attr_Src2->Rect.left,
|
|
||||||
pRgn_Attr_Src2->Rect.top,
|
|
||||||
pRgn_Attr_Src2->Rect.right,
|
|
||||||
pRgn_Attr_Src2->Rect.bottom );
|
|
||||||
if (Ret)
|
|
||||||
return SIMPLEREGION;
|
|
||||||
goto ERROR_Exit;
|
|
||||||
}
|
|
||||||
/* Not NULL or overlapping or differentiated, go to K. */
|
|
||||||
if ( Complexity != SAME_RGN)
|
|
||||||
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
||||||
/* If same, just fall through. */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ret = SetRectRgn( hDest,
|
|
||||||
pRgn_Attr_Src1->Rect.left,
|
|
||||||
pRgn_Attr_Src1->Rect.top,
|
|
||||||
pRgn_Attr_Src1->Rect.right,
|
|
||||||
pRgn_Attr_Src1->Rect.bottom );
|
|
||||||
if (Ret)
|
|
||||||
return SIMPLEREGION;
|
|
||||||
goto ERROR_Exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle AND. */
|
DPRINT1("Invalid iCombineMode %d\n", iCombineMode);
|
||||||
if ( pRgn_Attr_Src1->iComplexity != NULLREGION &&
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
pRgn_Attr_Src2->iComplexity != NULLREGION )
|
|
||||||
{
|
|
||||||
Complexity = ComplexityFromRects( &pRgn_Attr_Src1->Rect, &pRgn_Attr_Src2->Rect);
|
|
||||||
|
|
||||||
if ( Complexity == DIFF_RGN ) /* Differentiated in anyway just NULL rgn. */
|
|
||||||
{
|
|
||||||
if (SetRectRgn( hDest, 0, 0, 0, 0))
|
|
||||||
return NULLREGION;
|
|
||||||
goto ERROR_Exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( Complexity != INVERTED_RGN) /* Not inverted and overlapping. */
|
|
||||||
{
|
|
||||||
if ( Complexity != SAME_RGN) /* Must be norm and overlapping. */
|
|
||||||
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
|
|
||||||
/* Merge from src2. */
|
|
||||||
Ret = SetRectRgn( hDest,
|
|
||||||
pRgn_Attr_Src2->Rect.left,
|
|
||||||
pRgn_Attr_Src2->Rect.top,
|
|
||||||
pRgn_Attr_Src2->Rect.right,
|
|
||||||
pRgn_Attr_Src2->Rect.bottom );
|
|
||||||
if (Ret)
|
|
||||||
return SIMPLEREGION;
|
|
||||||
goto ERROR_Exit;
|
|
||||||
}
|
|
||||||
/* Inverted so merge from src1. */
|
|
||||||
Ret = SetRectRgn( hDest,
|
|
||||||
pRgn_Attr_Src1->Rect.left,
|
|
||||||
pRgn_Attr_Src1->Rect.top,
|
|
||||||
pRgn_Attr_Src1->Rect.right,
|
|
||||||
pRgn_Attr_Src1->Rect.bottom );
|
|
||||||
if (Ret)
|
|
||||||
return SIMPLEREGION;
|
|
||||||
goto ERROR_Exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* It's all NULL! */
|
|
||||||
if (SetRectRgn( hDest, 0, 0, 0, 0))
|
|
||||||
return NULLREGION;
|
|
||||||
|
|
||||||
ERROR_Exit:
|
|
||||||
/* Even on error the flag is set dirty and force server side to redraw. */
|
|
||||||
pRgn_Attr_Dest->AttrFlags |= ATTR_RGN_DIRTY;
|
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
@ -670,7 +819,7 @@ ExtSelectClipRgn( IN HDC hdc, IN HRGN hrgn, IN INT iMode)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Ret = pDc_Attr->VisRectRegion.iComplexity;
|
Ret = pDc_Attr->VisRectRegion.Flags;
|
||||||
pgO->fnMode |= 0x80000000; // Set no hrgn mode.
|
pgO->fnMode |= 0x80000000; // Set no hrgn mode.
|
||||||
}
|
}
|
||||||
pTeb->GdiTebBatch.Offset += sizeof(GDIBSEXTSELCLPRGN);
|
pTeb->GdiTebBatch.Offset += sizeof(GDIBSEXTSELCLPRGN);
|
||||||
|
|
Loading…
Reference in a new issue