[NtGDI] Update Region code

Wine Sync/Port and update for Regions. See CORE-15906.
This commit is contained in:
jimtabor 2019-04-17 14:43:24 -05:00
parent 7fabc51d73
commit feb9c045cf
3 changed files with 180 additions and 149 deletions

View file

@ -113,6 +113,14 @@ SOFTWARE.
* the y-x-banding that's so nice to have... * the y-x-banding that's so nice to have...
*/ */
// X11 sources for ReactOS region processing.
//
// libX11/src/PolyReg.c
// libX11/src/Region.c
//
//
#include <win32k.h> #include <win32k.h>
#include <suppress.h> #include <suppress.h>
@ -402,8 +410,8 @@ typedef struct _SCANLINE_LISTBLOCK
* *
*************************************************************************/ *************************************************************************/
#define LARGE_COORDINATE 0x7fffffff /* FIXME */ #define LARGE_COORDINATE INT_MAX
#define SMALL_COORDINATE 0x80000000 #define SMALL_COORDINATE INT_MIN
static static
BOOL BOOL
@ -509,8 +517,8 @@ REGION_bAddRect(
return TRUE; return TRUE;
} }
typedef VOID (FASTCALL *overlapProcp)(PREGION, PRECT, PRECT, PRECT, PRECT, INT, INT); typedef BOOL (FASTCALL *overlapProcp)(PREGION, PRECT, PRECT, PRECT, PRECT, INT, INT);
typedef VOID (FASTCALL *nonOverlapProcp)(PREGION, PRECT, PRECT, INT, INT); typedef BOOL (FASTCALL *nonOverlapProcp)(PREGION, PRECT, PRECT, INT, INT);
// Number of points to buffer before sending them off to scanlines() : Must be an even number // Number of points to buffer before sending them off to scanlines() : Must be an even number
#define NUMPTSTOBUFFER 200 #define NUMPTSTOBUFFER 200
@ -947,7 +955,7 @@ REGION_Coalesce(
* *
*/ */
static static
VOID BOOL
FASTCALL FASTCALL
REGION_RegionOp( REGION_RegionOp(
PREGION newReg, /* Place to store result */ PREGION newReg, /* Place to store result */
@ -1001,7 +1009,7 @@ REGION_RegionOp(
if (newReg->Buffer == NULL) if (newReg->Buffer == NULL)
{ {
newReg->rdh.nRgnSize = 0; newReg->rdh.nRgnSize = 0;
return; return FALSE;
} }
/* Initialize ybot and ytop. /* Initialize ybot and ytop.
@ -1062,7 +1070,7 @@ REGION_RegionOp(
if ((top != bot) && (nonOverlap1Func != NULL)) if ((top != bot) && (nonOverlap1Func != NULL))
{ {
(*nonOverlap1Func)(newReg, r1, r1BandEnd, top, bot); if (!(*nonOverlap1Func)(newReg, r1, r1BandEnd, top, bot)) return FALSE;
} }
ytop = r2->top; ytop = r2->top;
@ -1074,7 +1082,7 @@ REGION_RegionOp(
if ((top != bot) && (nonOverlap2Func != NULL)) if ((top != bot) && (nonOverlap2Func != NULL))
{ {
(*nonOverlap2Func)(newReg, r2, r2BandEnd, top, bot); if (!(*nonOverlap2Func)(newReg, r2, r2BandEnd, top, bot) ) return FALSE;
} }
ytop = r1->top; ytop = r1->top;
@ -1099,7 +1107,7 @@ REGION_RegionOp(
curBand = newReg->rdh.nCount; curBand = newReg->rdh.nCount;
if (ybot > ytop) if (ybot > ytop)
{ {
(*overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot); if (!(*overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot)) return FALSE;
} }
if (newReg->rdh.nCount != curBand) if (newReg->rdh.nCount != curBand)
@ -1134,11 +1142,12 @@ REGION_RegionOp(
r1BandEnd++; r1BandEnd++;
} }
(*nonOverlap1Func)(newReg, if (!(*nonOverlap1Func)(newReg,
r1, r1,
r1BandEnd, r1BandEnd,
max(r1->top,ybot), max(r1->top,ybot),
r1->bottom); r1->bottom))
return FALSE;
r1 = r1BandEnd; r1 = r1BandEnd;
} }
while (r1 != r1End); while (r1 != r1End);
@ -1154,11 +1163,12 @@ REGION_RegionOp(
r2BandEnd++; r2BandEnd++;
} }
(*nonOverlap2Func)(newReg, if (!(*nonOverlap2Func)(newReg,
r2, r2,
r2BandEnd, r2BandEnd,
max(r2->top,ybot), max(r2->top,ybot),
r2->bottom); r2->bottom))
return FALSE;
r2 = r2BandEnd; r2 = r2BandEnd;
} }
while (r2 != r2End); while (r2 != r2End);
@ -1216,7 +1226,7 @@ REGION_RegionOp(
if (oldRects != &newReg->rdh.rcBound) if (oldRects != &newReg->rdh.rcBound)
ExFreePoolWithTag(oldRects, TAG_REGION); ExFreePoolWithTag(oldRects, TAG_REGION);
return; return TRUE;
} }
/*********************************************************************** /***********************************************************************
@ -1235,7 +1245,7 @@ REGION_RegionOp(
* *
*/ */
static static
VOID BOOL
FASTCALL FASTCALL
REGION_IntersectO( REGION_IntersectO(
PREGION pReg, PREGION pReg,
@ -1262,7 +1272,7 @@ REGION_IntersectO(
{ {
if (!REGION_bAddRect(pReg, left, top, right, bottom)) if (!REGION_bAddRect(pReg, left, top, right, bottom))
{ {
return; return FALSE;
} }
} }
@ -1284,14 +1294,14 @@ REGION_IntersectO(
} }
} }
return; return TRUE;
} }
/*********************************************************************** /***********************************************************************
* REGION_IntersectRegion * REGION_IntersectRegion
*/ */
static static
VOID BOOL
FASTCALL FASTCALL
REGION_IntersectRegion( REGION_IntersectRegion(
PREGION newReg, PREGION newReg,
@ -1307,12 +1317,13 @@ REGION_IntersectRegion(
} }
else else
{ {
REGION_RegionOp(newReg, if (!REGION_RegionOp(newReg,
reg1, reg1,
reg2, reg2,
REGION_IntersectO, REGION_IntersectO,
NULL, NULL,
NULL); NULL))
return FALSE;
} }
/* Can't alter newReg's extents before we call miRegionOp because /* Can't alter newReg's extents before we call miRegionOp because
@ -1321,6 +1332,7 @@ REGION_IntersectRegion(
* way there's no checking against rectangles that will be nuked * way there's no checking against rectangles that will be nuked
* due to coalescing, so we have to examine fewer rectangles. */ * due to coalescing, so we have to examine fewer rectangles. */
REGION_SetExtents(newReg); REGION_SetExtents(newReg);
return TRUE;
} }
/*********************************************************************** /***********************************************************************
@ -1341,7 +1353,7 @@ REGION_IntersectRegion(
* *
*/ */
static static
VOID BOOL
FASTCALL FASTCALL
REGION_UnionNonO( REGION_UnionNonO(
PREGION pReg, PREGION pReg,
@ -1354,7 +1366,7 @@ REGION_UnionNonO(
{ {
if (!REGION_bEnsureBufferSize(pReg, pReg->rdh.nCount + (rEnd - r))) if (!REGION_bEnsureBufferSize(pReg, pReg->rdh.nCount + (rEnd - r)))
{ {
return; return FALSE;
} }
do do
@ -1365,7 +1377,7 @@ REGION_UnionNonO(
while (r != rEnd); while (r != rEnd);
} }
return; return TRUE;
} }
static __inline static __inline
@ -1411,7 +1423,7 @@ REGION_bMergeRect(
* *
*/ */
static static
VOID BOOL
FASTCALL FASTCALL
REGION_UnionO ( REGION_UnionO (
PREGION pReg, PREGION pReg,
@ -1426,12 +1438,12 @@ REGION_UnionO (
{ {
if (r1->left < r2->left) if (r1->left < r2->left)
{ {
REGION_bMergeRect(pReg, r1->left, top, r1->right, bottom); if (!REGION_bMergeRect(pReg, r1->left, top, r1->right, bottom)) return FALSE;
r1++; r1++;
} }
else else
{ {
REGION_bMergeRect(pReg, r2->left, top, r2->right, bottom); if (!REGION_bMergeRect(pReg, r2->left, top, r2->right, bottom)) return FALSE;
r2++; r2++;
} }
} }
@ -1440,7 +1452,7 @@ REGION_UnionO (
{ {
do do
{ {
REGION_bMergeRect(pReg, r1->left, top, r1->right, bottom); if (!REGION_bMergeRect(pReg, r1->left, top, r1->right, bottom)) return FALSE;
r1++; r1++;
} }
while (r1 != r1End); while (r1 != r1End);
@ -1449,25 +1461,27 @@ REGION_UnionO (
{ {
while (r2 != r2End) while (r2 != r2End)
{ {
REGION_bMergeRect(pReg, r2->left, top, r2->right, bottom); if (!REGION_bMergeRect(pReg, r2->left, top, r2->right, bottom)) return FALSE;
r2++; r2++;
} }
} }
return; return TRUE;
} }
/*********************************************************************** /***********************************************************************
* REGION_UnionRegion * REGION_UnionRegion
*/ */
static static
VOID BOOL
FASTCALL FASTCALL
REGION_UnionRegion( REGION_UnionRegion(
PREGION newReg, PREGION newReg,
PREGION reg1, PREGION reg1,
PREGION reg2) PREGION reg2)
{ {
BOOL ret = TRUE;
/* Checks all the simple cases /* Checks all the simple cases
* Region 1 and 2 are the same or region 1 is empty */ * Region 1 and 2 are the same or region 1 is empty */
if ((reg1 == reg2) || (reg1->rdh.nCount == 0) || if ((reg1 == reg2) || (reg1->rdh.nCount == 0) ||
@ -1476,10 +1490,10 @@ REGION_UnionRegion(
{ {
if (newReg != reg2) if (newReg != reg2)
{ {
REGION_CopyRegion(newReg, reg2); ret = REGION_CopyRegion(newReg, reg2);
} }
return; return ret;
} }
/* If nothing to union (region 2 empty) */ /* If nothing to union (region 2 empty) */
@ -1489,10 +1503,10 @@ REGION_UnionRegion(
{ {
if (newReg != reg1) if (newReg != reg1)
{ {
REGION_CopyRegion(newReg, reg1); ret = REGION_CopyRegion(newReg, reg1);
} }
return; return ret;
} }
/* Region 1 completely subsumes region 2 */ /* Region 1 completely subsumes region 2 */
@ -1504,10 +1518,10 @@ REGION_UnionRegion(
{ {
if (newReg != reg1) if (newReg != reg1)
{ {
REGION_CopyRegion(newReg, reg1); ret = REGION_CopyRegion(newReg, reg1);
} }
return; return ret;
} }
/* Region 2 completely subsumes region 1 */ /* Region 2 completely subsumes region 1 */
@ -1519,23 +1533,25 @@ REGION_UnionRegion(
{ {
if (newReg != reg2) if (newReg != reg2)
{ {
REGION_CopyRegion(newReg, reg2); ret = REGION_CopyRegion(newReg, reg2);
} }
return; return ret;
} }
REGION_RegionOp(newReg, if ((ret = REGION_RegionOp(newReg,
reg1, reg1,
reg2, reg2,
REGION_UnionO, REGION_UnionO,
REGION_UnionNonO, REGION_UnionNonO,
REGION_UnionNonO); REGION_UnionNonO)))
{
newReg->rdh.rcBound.left = min(reg1->rdh.rcBound.left, reg2->rdh.rcBound.left); newReg->rdh.rcBound.left = min(reg1->rdh.rcBound.left, reg2->rdh.rcBound.left);
newReg->rdh.rcBound.top = min(reg1->rdh.rcBound.top, reg2->rdh.rcBound.top); newReg->rdh.rcBound.top = min(reg1->rdh.rcBound.top, reg2->rdh.rcBound.top);
newReg->rdh.rcBound.right = max(reg1->rdh.rcBound.right, reg2->rdh.rcBound.right); newReg->rdh.rcBound.right = max(reg1->rdh.rcBound.right, reg2->rdh.rcBound.right);
newReg->rdh.rcBound.bottom = max(reg1->rdh.rcBound.bottom, reg2->rdh.rcBound.bottom); newReg->rdh.rcBound.bottom = max(reg1->rdh.rcBound.bottom, reg2->rdh.rcBound.bottom);
}
return ret;
} }
/*********************************************************************** /***********************************************************************
@ -1554,7 +1570,7 @@ REGION_UnionRegion(
* *
*/ */
static static
VOID BOOL
FASTCALL FASTCALL
REGION_SubtractNonO1( REGION_SubtractNonO1(
PREGION pReg, PREGION pReg,
@ -1567,7 +1583,7 @@ REGION_SubtractNonO1(
{ {
if (!REGION_bEnsureBufferSize(pReg, pReg->rdh.nCount + (rEnd - r))) if (!REGION_bEnsureBufferSize(pReg, pReg->rdh.nCount + (rEnd - r)))
{ {
return; return FALSE;
} }
do do
@ -1578,7 +1594,7 @@ REGION_SubtractNonO1(
while (r != rEnd); while (r != rEnd);
} }
return; return TRUE;
} }
@ -1594,7 +1610,7 @@ REGION_SubtractNonO1(
* *
*/ */
static static
VOID BOOL
FASTCALL FASTCALL
REGION_SubtractO( REGION_SubtractO(
PREGION pReg, PREGION pReg,
@ -1641,7 +1657,7 @@ REGION_SubtractO(
* part of minuend to region and skip to next subtrahend. */ * part of minuend to region and skip to next subtrahend. */
if (!REGION_bAddRect(pReg, left, top, r2->left, bottom)) if (!REGION_bAddRect(pReg, left, top, r2->left, bottom))
{ {
return; return FALSE;
} }
left = r2->right; left = r2->right;
@ -1665,7 +1681,7 @@ REGION_SubtractO(
{ {
if (!REGION_bAddRect(pReg, left, top, r1->right, bottom)) if (!REGION_bAddRect(pReg, left, top, r1->right, bottom))
{ {
return; return FALSE;
} }
} }
@ -1680,7 +1696,7 @@ REGION_SubtractO(
{ {
if (!REGION_bEnsureBufferSize(pReg, pReg->rdh.nCount + (r1End - r1))) if (!REGION_bEnsureBufferSize(pReg, pReg->rdh.nCount + (r1End - r1)))
{ {
return; return FALSE;
} }
/* Add remaining minuend rectangles to region. */ /* Add remaining minuend rectangles to region. */
@ -1696,7 +1712,7 @@ REGION_SubtractO(
while (r1 != r1End); while (r1 != r1End);
} }
return; return TRUE;
} }
/*! /*!
@ -1711,7 +1727,7 @@ REGION_SubtractO(
* *
*/ */
static static
VOID BOOL
FASTCALL FASTCALL
REGION_SubtractRegion( REGION_SubtractRegion(
PREGION regD, PREGION regD,
@ -1723,16 +1739,16 @@ REGION_SubtractRegion(
(regS->rdh.nCount == 0) || (regS->rdh.nCount == 0) ||
(EXTENTCHECK(&regM->rdh.rcBound, &regS->rdh.rcBound) == 0)) (EXTENTCHECK(&regM->rdh.rcBound, &regS->rdh.rcBound) == 0))
{ {
REGION_CopyRegion(regD, regM); return REGION_CopyRegion(regD, regM);
return;
} }
REGION_RegionOp(regD, if (!REGION_RegionOp(regD,
regM, regM,
regS, regS,
REGION_SubtractO, REGION_SubtractO,
REGION_SubtractNonO1, REGION_SubtractNonO1,
NULL); NULL))
return FALSE;
/* Can't alter newReg's extents before we call miRegionOp because /* Can't alter newReg's extents before we call miRegionOp because
* it might be one of the source regions and miRegionOp depends * it might be one of the source regions and miRegionOp depends
@ -1740,13 +1756,14 @@ REGION_SubtractRegion(
* way there's no checking against rectangles that will be nuked * way there's no checking against rectangles that will be nuked
* due to coalescing, so we have to examine fewer rectangles. */ * due to coalescing, so we have to examine fewer rectangles. */
REGION_SetExtents(regD); REGION_SetExtents(regD);
return TRUE;
} }
/*********************************************************************** /***********************************************************************
* REGION_XorRegion * REGION_XorRegion
*/ */
static static
VOID BOOL
FASTCALL FASTCALL
REGION_XorRegion( REGION_XorRegion(
PREGION dr, PREGION dr,
@ -1755,12 +1772,13 @@ REGION_XorRegion(
{ {
HRGN htra, htrb; HRGN htra, htrb;
PREGION tra, trb; PREGION tra, trb;
BOOL ret;
// FIXME: Don't use a handle // FIXME: Don't use a handle
tra = REGION_AllocRgnWithHandle(sra->rdh.nCount + 1); tra = REGION_AllocRgnWithHandle(sra->rdh.nCount + 1);
if (tra == NULL) if (tra == NULL)
{ {
return; return FALSE;
} }
htra = tra->BaseObject.hHmgr; htra = tra->BaseObject.hHmgr;
@ -1770,26 +1788,26 @@ REGION_XorRegion(
{ {
REGION_UnlockRgn(tra); REGION_UnlockRgn(tra);
GreDeleteObject(htra); GreDeleteObject(htra);
return; return FALSE;
} }
htrb = trb->BaseObject.hHmgr; htrb = trb->BaseObject.hHmgr;
REGION_SubtractRegion(tra, sra, srb); ret = REGION_SubtractRegion(tra, sra, srb) &&
REGION_SubtractRegion(trb, srb, sra); REGION_SubtractRegion(trb, srb, sra) &&
REGION_UnionRegion(dr, tra, trb); REGION_UnionRegion(dr, tra, trb);
REGION_UnlockRgn(tra); REGION_UnlockRgn(tra);
REGION_UnlockRgn(trb); REGION_UnlockRgn(trb);
GreDeleteObject(htra); GreDeleteObject(htra);
GreDeleteObject(htrb); GreDeleteObject(htrb);
return; return ret;
} }
/*! /*!
* Adds a rectangle to a REGION * Adds a rectangle to a REGION
*/ */
VOID BOOL
FASTCALL FASTCALL
REGION_UnionRectWithRgn( REGION_UnionRectWithRgn(
PREGION rgn, PREGION rgn,
@ -1801,7 +1819,7 @@ REGION_UnionRectWithRgn(
region.rdh.nCount = 1; region.rdh.nCount = 1;
region.rdh.nRgnSize = sizeof(RECT); region.rdh.nRgnSize = sizeof(RECT);
region.rdh.rcBound = *rect; region.rdh.rcBound = *rect;
REGION_UnionRegion(rgn, rgn, &region); return REGION_UnionRegion(rgn, rgn, &region);
} }
INT INT
@ -1821,6 +1839,27 @@ REGION_SubtractRectFromRgn(
return REGION_Complexity(prgnDest); return REGION_Complexity(prgnDest);
} }
BOOL
FASTCALL
REGION_bCopy(
PREGION dst,
PREGION src)
{
if ( !dst || !src ) return FALSE;
return REGION_CopyRegion( dst, src);
}
BOOL
FASTCALL
REGION_bIntersectRegion(
PREGION newReg,
PREGION reg1,
PREGION reg2)
{
if ( !newReg || !reg1 || !reg2 ) return FALSE;
return REGION_IntersectRegion( newReg, reg1, reg2);
}
static static
BOOL BOOL
REGION_bMakeSimpleFrameRgn( REGION_bMakeSimpleFrameRgn(
@ -2098,9 +2137,13 @@ REGION_bXformRgn(
RECTL_vMakeWellOrdered(&prgn->Buffer[i]); RECTL_vMakeWellOrdered(&prgn->Buffer[i]);
/* Update bounds */ /* Update bounds */
RECTL_bUnionRect(&prgn->rdh.rcBound, if (!RECTL_bUnionRect(&prgn->rdh.rcBound,
&prgn->rdh.rcBound, &prgn->rdh.rcBound,
&prgn->Buffer[i]); &prgn->Buffer[i]))
{
DPRINT1("NULL Set in Union Rects\n");
return FALSE;
}
} }
/* Loop all rects in the region */ /* Loop all rects in the region */
@ -2469,6 +2512,7 @@ IntGdiCombineRgn(
PREGION prgnSrc2, PREGION prgnSrc2,
INT iCombineMode) INT iCombineMode)
{ {
BOOL Ret = TRUE;
if (prgnDest == NULL) if (prgnDest == NULL)
{ {
@ -2500,20 +2544,20 @@ IntGdiCombineRgn(
switch (iCombineMode) switch (iCombineMode)
{ {
case RGN_AND: case RGN_AND:
REGION_IntersectRegion(prgnDest, prgnSrc1, prgnSrc2); Ret = REGION_IntersectRegion(prgnDest, prgnSrc1, prgnSrc2);
break; break;
case RGN_OR: case RGN_OR:
REGION_UnionRegion(prgnDest, prgnSrc1, prgnSrc2); Ret = REGION_UnionRegion(prgnDest, prgnSrc1, prgnSrc2);
break; break;
case RGN_XOR: case RGN_XOR:
REGION_XorRegion(prgnDest, prgnSrc1, prgnSrc2); Ret = REGION_XorRegion(prgnDest, prgnSrc1, prgnSrc2);
break; break;
case RGN_DIFF: case RGN_DIFF:
REGION_SubtractRegion(prgnDest, prgnSrc1, prgnSrc2); Ret = REGION_SubtractRegion(prgnDest, prgnSrc1, prgnSrc2);
break; break;
} }
return REGION_Complexity(prgnDest); return Ret ? REGION_Complexity(prgnDest) : ERROR;
} }
INT INT
@ -3600,8 +3644,9 @@ NtGdiCreateRoundRectRgn(
{ {
PREGION obj; PREGION obj;
HRGN hrgn; HRGN hrgn;
INT asq, bsq, d, xd, yd; int a, b, i, x, y;
RECTL rect; INT64 asq, bsq, dx, dy, err;
RECT *rects;
/* Make the dimensions sensible */ /* Make the dimensions sensible */
if (left > right) if (left > right)
@ -3618,95 +3663,75 @@ NtGdiCreateRoundRectRgn(
bottom = tmp; bottom = tmp;
} }
ellipse_width = abs(ellipse_width); /* the region is for the rectangle interior, but only at right and bottom for some reason */
ellipse_height = abs(ellipse_height); right--;
bottom--;
/* Check parameters */ ellipse_width = min( right - left, abs( ellipse_width ));
if (ellipse_width > right-left) ellipse_height = min( bottom - top, abs( ellipse_height ));
ellipse_width = right-left;
if (ellipse_height > bottom-top)
ellipse_height = bottom-top;
/* Check if we can do a normal rectangle instead */ /* Check if we can do a normal rectangle instead */
if ((ellipse_width < 2) || (ellipse_height < 2)) if ((ellipse_width < 2) || (ellipse_height < 2))
return NtGdiCreateRectRgn(left, top, right, bottom); return NtGdiCreateRectRgn(left, top, right, bottom);
/* Create region */ obj = REGION_AllocUserRgnWithHandle( ellipse_height );
d = (ellipse_height < 128) ? ((3 * ellipse_height) >> 2) : 64;
obj = REGION_AllocUserRgnWithHandle(d);
if (obj == NULL) if (obj == NULL)
return 0; return 0;
hrgn = obj->BaseObject.hHmgr; hrgn = obj->BaseObject.hHmgr;
/* Ellipse algorithm, based on an article by K. Porter obj->rdh.rcBound.left = left;
in DDJ Graphics Programming Column, 8/89 */ obj->rdh.rcBound.top = top;
asq = ellipse_width * ellipse_width / 4; /* a^2 */ obj->rdh.rcBound.right = right;
bsq = ellipse_height * ellipse_height / 4; /* b^2 */ obj->rdh.rcBound.bottom = bottom;
d = bsq - asq * ellipse_height / 2 + asq / 4; /* b^2 - a^2b + a^2/4 */ rects = obj->Buffer;
xd = 0;
yd = asq * ellipse_height; /* 2a^2b */
rect.left = left + ellipse_width / 2; /* based on an algorithm by Alois Zingl */
rect.right = right - ellipse_width / 2;
/* Loop to draw first half of quadrant */ a = ellipse_width - 1;
while (xd < yd) b = ellipse_height - 1;
asq = (INT64)8 * a * a;
bsq = (INT64)8 * b * b;
dx = (INT64)4 * b * b * (1 - a);
dy = (INT64)4 * a * a * (1 + (b % 2));
err = dx + dy + a * a * (b % 2);
x = 0;
y = ellipse_height / 2;
rects[y].left = left;
rects[y].right = right;
while (x <= ellipse_width / 2)
{ {
/* If nearest pixel is toward the center */ INT64 e2 = 2 * err;
if (d > 0) if (e2 >= dx)
{ {
/* Move toward center */ x++;
rect.top = top++; err += dx += bsq;
rect.bottom = rect.top + 1;
REGION_UnionRectWithRgn(obj, &rect);
rect.top = --bottom;
rect.bottom = rect.top + 1;
REGION_UnionRectWithRgn(obj, &rect);
yd -= 2*asq;
d -= yd;
} }
if (e2 <= dy)
/* Next horiz point */
rect.left--;
rect.right++;
xd += 2*bsq;
d += bsq + xd;
}
/* Loop to draw second half of quadrant */
d += (3 * (asq-bsq) / 2 - (xd+yd)) / 2;
while (yd >= 0)
{
/* next vertical point */
rect.top = top++;
rect.bottom = rect.top + 1;
REGION_UnionRectWithRgn(obj, &rect);
rect.top = --bottom;
rect.bottom = rect.top + 1;
REGION_UnionRectWithRgn(obj, &rect);
/* If nearest pixel is outside ellipse */
if (d < 0)
{ {
/* Move away from center */ y++;
rect.left--; err += dy += asq;
rect.right++; rects[y].left = left + x;
xd += 2*bsq; rects[y].right = right - x;
d += xd;
} }
yd -= 2*asq;
d += asq - yd;
} }
for (i = 0; i < ellipse_height / 2; i++)
/* Add the inside rectangle */
if (top <= bottom)
{ {
rect.top = top; rects[i].left = rects[b - i].left;
rect.bottom = bottom; rects[i].right = rects[b - i].right;
REGION_UnionRectWithRgn(obj, &rect); rects[i].top = top + i;
rects[i].bottom = rects[i].top + 1;
} }
for (; i < ellipse_height; i++)
{
rects[i].top = bottom - ellipse_height + i;
rects[i].bottom = rects[i].top + 1;
}
rects[ellipse_height / 2].top = top + ellipse_height / 2; /* extend to top of rectangle */
REGION_UnlockRgn(obj); REGION_UnlockRgn(obj);
return hrgn; return hrgn;
@ -3860,7 +3885,13 @@ NtGdiExtCreateRegion(
{ {
if ( rects[i].left < rects[i].right && rects[i].top < rects[i].bottom ) if ( rects[i].left < rects[i].right && rects[i].top < rects[i].bottom )
{ {
REGION_UnionRectWithRgn(Region, &rects[i]); if (!REGION_UnionRectWithRgn(Region, &rects[i]))
{
REGION_UnlockRgn(Region);
GreDeleteObject(hRgn);
hRgn = NULL;
_SEH2_LEAVE;
}
} }
} }
@ -3901,7 +3932,7 @@ NtGdiExtCreateRegion(
return NULL; return NULL;
} }
REGION_UnlockRgn(Region); if (hRgn) REGION_UnlockRgn(Region);
return hRgn; return hRgn;
} }

View file

@ -25,7 +25,7 @@ extern HRGN hrgnDefault;
PREGION FASTCALL REGION_AllocRgnWithHandle(INT n); PREGION FASTCALL REGION_AllocRgnWithHandle(INT n);
PREGION FASTCALL REGION_AllocUserRgnWithHandle(INT n); PREGION FASTCALL REGION_AllocUserRgnWithHandle(INT n);
VOID FASTCALL REGION_UnionRectWithRgn(PREGION rgn, const RECTL *rect); BOOL FASTCALL REGION_UnionRectWithRgn(PREGION rgn, const RECTL *rect);
INT FASTCALL REGION_SubtractRectFromRgn(PREGION prgnDest, PREGION prgnSrc, const RECTL *prcl); INT FASTCALL REGION_SubtractRectFromRgn(PREGION prgnDest, PREGION prgnSrc, const RECTL *prcl);
INT FASTCALL REGION_GetRgnBox(PREGION Rgn, RECTL *pRect); INT FASTCALL REGION_GetRgnBox(PREGION Rgn, RECTL *pRect);
BOOL FASTCALL REGION_RectInRegion(PREGION Rgn, const RECTL *rc); BOOL FASTCALL REGION_RectInRegion(PREGION Rgn, const RECTL *rc);
@ -93,6 +93,12 @@ GreCreateFrameRgn(
#define IntSysCreateRectpRgnIndirect(prc) \ #define IntSysCreateRectpRgnIndirect(prc) \
IntSysCreateRectpRgn((prc)->left, (prc)->top, (prc)->right, (prc)->bottom) IntSysCreateRectpRgn((prc)->left, (prc)->top, (prc)->right, (prc)->bottom)
#define GreCreateRectRgnIndirect(prc) \
NtGdiCreateRectRgn((prc)->left, (prc)->top, (prc)->right, (prc)->bottom)
#define GreSetRectRgnIndirect(hRgn, prc) \
NtGdiSetRectRgn(hRgn, (prc)->left, (prc)->top, (prc)->right, (prc)->bottom);
PREGION PREGION
FASTCALL FASTCALL
IntSysCreateRectpRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect); IntSysCreateRectpRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect);

View file

@ -15,12 +15,6 @@
#define RDW_CLIPCHILDREN 4096 #define RDW_CLIPCHILDREN 4096
#define RDW_NOUPDATEDIRTY 32768 #define RDW_NOUPDATEDIRTY 32768
#define GreCreateRectRgnIndirect(prc) \
NtGdiCreateRectRgn((prc)->left, (prc)->top, (prc)->right, (prc)->bottom)
#define GreSetRectRgnIndirect(hRgn, prc) \
NtGdiSetRectRgn(hRgn, (prc)->left, (prc)->top, (prc)->right, (prc)->bottom);
BOOL FASTCALL co_UserRedrawWindow(PWND Wnd, const RECTL* UpdateRect, PREGION UpdateRgn, ULONG Flags); BOOL FASTCALL co_UserRedrawWindow(PWND Wnd, const RECTL* UpdateRect, PREGION UpdateRgn, ULONG Flags);
VOID FASTCALL IntInvalidateWindows(PWND Window, PREGION Rgn, ULONG Flags); VOID FASTCALL IntInvalidateWindows(PWND Window, PREGION Rgn, ULONG Flags);
BOOL FASTCALL IntGetPaintMessage(PWND Window, UINT MsgFilterMin, UINT MsgFilterMax, PTHREADINFO Thread, MSG *Message, BOOL Remove); BOOL FASTCALL IntGetPaintMessage(PWND Window, UINT MsgFilterMin, UINT MsgFilterMax, PTHREADINFO Thread, MSG *Message, BOOL Remove);