gdi32: Check for memory allocation failure in region functions and propagate the error correctly.

This commit is contained in:
Alexandre Julliard 2009-01-29 18:18:53 +01:00
parent ec4af0764b
commit 687dfd69e9

View File

@ -166,8 +166,6 @@ static BOOL add_rect( WINEREGION *reg, INT left, INT top, INT right, INT bottom
(pReg)->extents.right = (pReg)->extents.bottom = 0; \ (pReg)->extents.right = (pReg)->extents.bottom = 0; \
} while(0) } while(0)
#define REGION_NOT_EMPTY(pReg) ((pReg)->numRects)
#define INRECT(r, x, y) \ #define INRECT(r, x, y) \
( ( ((r).right > x)) && \ ( ( ((r).right > x)) && \
( ((r).left <= x)) && \ ( ((r).left <= x)) && \
@ -441,13 +439,13 @@ typedef struct _ScanLineListBlock {
/* Note the parameter order is different from the X11 equivalents */ /* Note the parameter order is different from the X11 equivalents */
static void REGION_CopyRegion(WINEREGION *d, WINEREGION *s); static BOOL REGION_CopyRegion(WINEREGION *d, WINEREGION *s);
static void REGION_OffsetRegion(WINEREGION *d, WINEREGION *s, INT x, INT y); static BOOL REGION_OffsetRegion(WINEREGION *d, WINEREGION *s, INT x, INT y);
static void REGION_IntersectRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2); static BOOL REGION_IntersectRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2);
static void REGION_UnionRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2); static BOOL REGION_UnionRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2);
static void REGION_SubtractRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2); static BOOL REGION_SubtractRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2);
static void REGION_XorRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2); static BOOL REGION_XorRegion(WINEREGION *d, WINEREGION *s1, WINEREGION *s2);
static void REGION_UnionRectWithRegion(const RECT *rect, WINEREGION *rgn); static BOOL REGION_UnionRectWithRegion(const RECT *rect, WINEREGION *rgn);
#define RGN_DEFAULT_RECTS 2 #define RGN_DEFAULT_RECTS 2
@ -531,11 +529,12 @@ static HGDIOBJ REGION_SelectObject( HGDIOBJ handle, HDC hdc )
* REGION_OffsetRegion * REGION_OffsetRegion
* Offset a WINEREGION by x,y * Offset a WINEREGION by x,y
*/ */
static void REGION_OffsetRegion( WINEREGION *rgn, WINEREGION *srcrgn, static BOOL REGION_OffsetRegion( WINEREGION *rgn, WINEREGION *srcrgn, INT x, INT y )
INT x, INT y )
{ {
if( rgn != srcrgn) if( rgn != srcrgn)
REGION_CopyRegion( rgn, srcrgn); {
if (!REGION_CopyRegion( rgn, srcrgn)) return FALSE;
}
if(x || y) { if(x || y) {
int nbox = rgn->numRects; int nbox = rgn->numRects;
RECT *pbox = rgn->rects; RECT *pbox = rgn->rects;
@ -554,6 +553,7 @@ static void REGION_OffsetRegion( WINEREGION *rgn, WINEREGION *srcrgn,
rgn->extents.bottom += y; rgn->extents.bottom += y;
} }
} }
return TRUE;
} }
/*********************************************************************** /***********************************************************************
@ -760,7 +760,7 @@ HRGN WINAPI CreateRoundRectRgn( INT left, INT top,
INT ellipse_width, INT ellipse_height ) INT ellipse_width, INT ellipse_height )
{ {
RGNOBJ * obj; RGNOBJ * obj;
HRGN hrgn; HRGN hrgn = 0;
int asq, bsq, d, xd, yd; int asq, bsq, d, xd, yd;
RECT rect; RECT rect;
@ -813,10 +813,10 @@ HRGN WINAPI CreateRoundRectRgn( INT left, INT top,
/* move toward center */ /* move toward center */
rect.top = top++; rect.top = top++;
rect.bottom = rect.top + 1; rect.bottom = rect.top + 1;
REGION_UnionRectWithRegion( &rect, &obj->rgn ); if (!REGION_UnionRectWithRegion( &rect, &obj->rgn )) goto done;
rect.top = --bottom; rect.top = --bottom;
rect.bottom = rect.top + 1; rect.bottom = rect.top + 1;
REGION_UnionRectWithRegion( &rect, &obj->rgn ); if (!REGION_UnionRectWithRegion( &rect, &obj->rgn )) goto done;
yd -= 2*asq; yd -= 2*asq;
d -= yd; d -= yd;
} }
@ -834,10 +834,10 @@ HRGN WINAPI CreateRoundRectRgn( INT left, INT top,
/* next vertical point */ /* next vertical point */
rect.top = top++; rect.top = top++;
rect.bottom = rect.top + 1; rect.bottom = rect.top + 1;
REGION_UnionRectWithRegion( &rect, &obj->rgn ); if (!REGION_UnionRectWithRegion( &rect, &obj->rgn )) goto done;
rect.top = --bottom; rect.top = --bottom;
rect.bottom = rect.top + 1; rect.bottom = rect.top + 1;
REGION_UnionRectWithRegion( &rect, &obj->rgn ); if (!REGION_UnionRectWithRegion( &rect, &obj->rgn )) goto done;
if (d < 0) /* if nearest pixel is outside ellipse */ if (d < 0) /* if nearest pixel is outside ellipse */
{ {
rect.left--; /* move away from center */ rect.left--; /* move away from center */
@ -855,14 +855,14 @@ HRGN WINAPI CreateRoundRectRgn( INT left, INT top,
{ {
rect.top = top; rect.top = top;
rect.bottom = bottom; rect.bottom = bottom;
REGION_UnionRectWithRegion( &rect, &obj->rgn ); if (!REGION_UnionRectWithRegion( &rect, &obj->rgn )) goto done;
} }
hrgn = alloc_gdi_handle( &obj->header, OBJ_REGION, &region_funcs ); hrgn = alloc_gdi_handle( &obj->header, OBJ_REGION, &region_funcs );
TRACE("(%d,%d-%d,%d %dx%d): ret=%p\n", TRACE("(%d,%d-%d,%d %dx%d): ret=%p\n",
left, top, right, bottom, ellipse_width, ellipse_height, hrgn ); left, top, right, bottom, ellipse_width, ellipse_height, hrgn );
done:
if (!hrgn) if (!hrgn)
{ {
HeapFree( GetProcessHeap(), 0, obj->rgn.rects ); HeapFree( GetProcessHeap(), 0, obj->rgn.rects );
@ -1013,7 +1013,7 @@ static void translate( POINT *pt, UINT count, const XFORM *xform )
*/ */
HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA* rgndata) HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA* rgndata)
{ {
HRGN hrgn; HRGN hrgn = 0;
RGNOBJ *obj; RGNOBJ *obj;
if (!rgndata) if (!rgndata)
@ -1069,7 +1069,9 @@ HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA*
for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++) for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
{ {
if (pCurRect->left < pCurRect->right && pCurRect->top < pCurRect->bottom) if (pCurRect->left < pCurRect->right && pCurRect->top < pCurRect->bottom)
REGION_UnionRectWithRegion( pCurRect, &obj->rgn ); {
if (!REGION_UnionRectWithRegion( pCurRect, &obj->rgn )) goto done;
}
} }
hrgn = alloc_gdi_handle( &obj->header, OBJ_REGION, &region_funcs ); hrgn = alloc_gdi_handle( &obj->header, OBJ_REGION, &region_funcs );
} }
@ -1079,6 +1081,7 @@ HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA*
return 0; return 0;
} }
done:
if (!hrgn) if (!hrgn)
{ {
HeapFree( GetProcessHeap(), 0, obj->rgn.rects ); HeapFree( GetProcessHeap(), 0, obj->rgn.rects );
@ -1228,7 +1231,7 @@ BOOL WINAPI EqualRgn( HRGN hrgn1, HRGN hrgn2 )
* REGION_UnionRectWithRegion * REGION_UnionRectWithRegion
* Adds a rectangle to a WINEREGION * Adds a rectangle to a WINEREGION
*/ */
static void REGION_UnionRectWithRegion(const RECT *rect, WINEREGION *rgn) static BOOL REGION_UnionRectWithRegion(const RECT *rect, WINEREGION *rgn)
{ {
WINEREGION region; WINEREGION region;
@ -1236,7 +1239,7 @@ static void REGION_UnionRectWithRegion(const RECT *rect, WINEREGION *rgn)
region.numRects = 1; region.numRects = 1;
region.size = 1; region.size = 1;
region.extents = *rect; region.extents = *rect;
REGION_UnionRegion(rgn, rgn, &region); return REGION_UnionRegion(rgn, rgn, &region);
} }
@ -1250,31 +1253,30 @@ static void REGION_UnionRectWithRegion(const RECT *rect, WINEREGION *rgn)
*/ */
BOOL REGION_FrameRgn( HRGN hDest, HRGN hSrc, INT x, INT y ) BOOL REGION_FrameRgn( HRGN hDest, HRGN hSrc, INT x, INT y )
{ {
WINEREGION tmprgn;
BOOL bRet = FALSE; BOOL bRet = FALSE;
RGNOBJ* destObj = NULL; RGNOBJ* destObj = NULL;
RGNOBJ *srcObj = GDI_GetObjPtr( hSrc, OBJ_REGION ); RGNOBJ *srcObj = GDI_GetObjPtr( hSrc, OBJ_REGION );
tmprgn.rects = NULL;
if (!srcObj) return FALSE; if (!srcObj) return FALSE;
if (srcObj->rgn.numRects != 0) if (srcObj->rgn.numRects != 0)
{ {
WINEREGION tmprgn;
if (!(destObj = GDI_GetObjPtr( hDest, OBJ_REGION ))) goto done; if (!(destObj = GDI_GetObjPtr( hDest, OBJ_REGION ))) goto done;
if (!init_region( &tmprgn, srcObj->rgn.numRects )) goto done; if (!init_region( &tmprgn, srcObj->rgn.numRects )) goto done;
REGION_OffsetRegion( &destObj->rgn, &srcObj->rgn, -x, 0); if (!REGION_OffsetRegion( &destObj->rgn, &srcObj->rgn, -x, 0)) goto done;
REGION_OffsetRegion( &tmprgn, &srcObj->rgn, x, 0); if (!REGION_OffsetRegion( &tmprgn, &srcObj->rgn, x, 0)) goto done;
REGION_IntersectRegion( &destObj->rgn, &destObj->rgn, &tmprgn ); if (!REGION_IntersectRegion( &destObj->rgn, &destObj->rgn, &tmprgn )) goto done;
REGION_OffsetRegion( &tmprgn, &srcObj->rgn, 0, -y); if (!REGION_OffsetRegion( &tmprgn, &srcObj->rgn, 0, -y)) goto done;
REGION_IntersectRegion( &destObj->rgn, &destObj->rgn, &tmprgn ); if (!REGION_IntersectRegion( &destObj->rgn, &destObj->rgn, &tmprgn )) goto done;
REGION_OffsetRegion( &tmprgn, &srcObj->rgn, 0, y); if (!REGION_OffsetRegion( &tmprgn, &srcObj->rgn, 0, y)) goto done;
REGION_IntersectRegion( &destObj->rgn, &destObj->rgn, &tmprgn ); if (!REGION_IntersectRegion( &destObj->rgn, &destObj->rgn, &tmprgn )) goto done;
REGION_SubtractRegion( &destObj->rgn, &srcObj->rgn, &destObj->rgn ); if (!REGION_SubtractRegion( &destObj->rgn, &srcObj->rgn, &destObj->rgn )) goto done;
destroy_region( &tmprgn );
bRet = TRUE; bRet = TRUE;
} }
done: done:
HeapFree( GetProcessHeap(), 0, tmprgn.rects );
if (destObj) GDI_ReleaseObj ( hDest ); if (destObj) GDI_ReleaseObj ( hDest );
GDI_ReleaseObj( hSrc ); GDI_ReleaseObj( hSrc );
return bRet; return bRet;
@ -1326,8 +1328,8 @@ INT WINAPI CombineRgn(HRGN hDest, HRGN hSrc1, HRGN hSrc2, INT mode)
REGION_DumpRegion(&src1Obj->rgn); REGION_DumpRegion(&src1Obj->rgn);
if (mode == RGN_COPY) if (mode == RGN_COPY)
{ {
REGION_CopyRegion( &destObj->rgn, &src1Obj->rgn ); if (REGION_CopyRegion( &destObj->rgn, &src1Obj->rgn ))
result = get_region_type( destObj ); result = get_region_type( destObj );
} }
else else
{ {
@ -1341,19 +1343,22 @@ INT WINAPI CombineRgn(HRGN hDest, HRGN hSrc1, HRGN hSrc2, INT mode)
switch (mode) switch (mode)
{ {
case RGN_AND: case RGN_AND:
REGION_IntersectRegion( &destObj->rgn, &src1Obj->rgn, &src2Obj->rgn ); if (REGION_IntersectRegion( &destObj->rgn, &src1Obj->rgn, &src2Obj->rgn ))
result = get_region_type( destObj );
break; break;
case RGN_OR: case RGN_OR:
REGION_UnionRegion( &destObj->rgn, &src1Obj->rgn, &src2Obj->rgn ); if (REGION_UnionRegion( &destObj->rgn, &src1Obj->rgn, &src2Obj->rgn ))
result = get_region_type( destObj );
break; break;
case RGN_XOR: case RGN_XOR:
REGION_XorRegion( &destObj->rgn, &src1Obj->rgn, &src2Obj->rgn ); if (REGION_XorRegion( &destObj->rgn, &src1Obj->rgn, &src2Obj->rgn ))
result = get_region_type( destObj );
break; break;
case RGN_DIFF: case RGN_DIFF:
REGION_SubtractRegion( &destObj->rgn, &src1Obj->rgn, &src2Obj->rgn ); if (REGION_SubtractRegion( &destObj->rgn, &src1Obj->rgn, &src2Obj->rgn ))
result = get_region_type( destObj );
break; break;
} }
result = get_region_type( destObj );
GDI_ReleaseObj( hSrc2 ); GDI_ReleaseObj( hSrc2 );
} }
} }
@ -1364,8 +1369,6 @@ INT WINAPI CombineRgn(HRGN hDest, HRGN hSrc1, HRGN hSrc2, INT mode)
REGION_DumpRegion(&destObj->rgn); REGION_DumpRegion(&destObj->rgn);
GDI_ReleaseObj( hDest ); GDI_ReleaseObj( hDest );
} else {
ERR("Invalid rgn=%p\n", hDest);
} }
return result; return result;
} }
@ -1416,15 +1419,15 @@ static void REGION_SetExtents (WINEREGION *pReg)
/*********************************************************************** /***********************************************************************
* REGION_CopyRegion * REGION_CopyRegion
*/ */
static void REGION_CopyRegion(WINEREGION *dst, WINEREGION *src) static BOOL REGION_CopyRegion(WINEREGION *dst, WINEREGION *src)
{ {
if (dst != src) /* don't want to copy to itself */ if (dst != src) /* don't want to copy to itself */
{ {
if (dst->size < src->numRects) if (dst->size < src->numRects)
{ {
if (! (dst->rects = HeapReAlloc( GetProcessHeap(), 0, dst->rects, RECT *rects = HeapReAlloc( GetProcessHeap(), 0, dst->rects, src->numRects * sizeof(RECT) );
src->numRects * sizeof(RECT) ))) if (!rects) return FALSE;
return; dst->rects = rects;
dst->size = src->numRects; dst->size = src->numRects;
} }
dst->numRects = src->numRects; dst->numRects = src->numRects;
@ -1434,7 +1437,7 @@ static void REGION_CopyRegion(WINEREGION *dst, WINEREGION *src)
dst->extents.bottom = src->extents.bottom; dst->extents.bottom = src->extents.bottom;
memcpy(dst->rects, src->rects, src->numRects * sizeof(RECT)); memcpy(dst->rects, src->rects, src->numRects * sizeof(RECT));
} }
return; return TRUE;
} }
/*********************************************************************** /***********************************************************************
@ -1599,21 +1602,21 @@ static INT REGION_Coalesce (
* to reduce the number of rectangles in the region. * to reduce the number of rectangles in the region.
* *
*/ */
static void REGION_RegionOp( static BOOL REGION_RegionOp(
WINEREGION *newReg, /* Place to store result */ WINEREGION *destReg, /* Place to store result */
WINEREGION *reg1, /* First region in operation */ WINEREGION *reg1, /* First region in operation */
WINEREGION *reg2, /* 2nd region in operation */ WINEREGION *reg2, /* 2nd region in operation */
void (*overlapFunc)(WINEREGION*, RECT*, RECT*, RECT*, RECT*, INT, INT), /* Function to call for over-lapping bands */ BOOL (*overlapFunc)(WINEREGION*, RECT*, RECT*, RECT*, RECT*, INT, INT), /* Function to call for over-lapping bands */
void (*nonOverlap1Func)(WINEREGION*, RECT*, RECT*, INT, INT), /* Function to call for non-overlapping bands in region 1 */ BOOL (*nonOverlap1Func)(WINEREGION*, RECT*, RECT*, INT, INT), /* Function to call for non-overlapping bands in region 1 */
void (*nonOverlap2Func)(WINEREGION*, RECT*, RECT*, INT, INT) /* Function to call for non-overlapping bands in region 2 */ BOOL (*nonOverlap2Func)(WINEREGION*, RECT*, RECT*, INT, INT) /* Function to call for non-overlapping bands in region 2 */
) { ) {
WINEREGION newReg;
RECT *r1; /* Pointer into first region */ RECT *r1; /* Pointer into first region */
RECT *r2; /* Pointer into 2d region */ RECT *r2; /* Pointer into 2d region */
RECT *r1End; /* End of 1st region */ RECT *r1End; /* End of 1st region */
RECT *r2End; /* End of 2d region */ RECT *r2End; /* End of 2d region */
INT ybot; /* Bottom of intersection */ INT ybot; /* Bottom of intersection */
INT ytop; /* Top of intersection */ INT ytop; /* Top of intersection */
RECT *oldRects; /* Old rects for newReg */
INT prevBand; /* Index of start of INT prevBand; /* Index of start of
* previous band in newReg */ * previous band in newReg */
INT curBand; /* Index of start of current INT curBand; /* Index of start of current
@ -1635,16 +1638,6 @@ static void REGION_RegionOp(
r1End = r1 + reg1->numRects; r1End = r1 + reg1->numRects;
r2End = r2 + reg2->numRects; r2End = r2 + reg2->numRects;
/*
* newReg may be one of the src regions so we can't empty it. We keep a
* note of its rects pointer (so that we can free them later), preserve its
* extents and simply set numRects to zero.
*/
oldRects = newReg->rects;
newReg->numRects = 0;
/* /*
* Allocate a reasonable number of rectangles for the new region. The idea * Allocate a reasonable number of rectangles for the new region. The idea
* is to allocate enough so the individual functions don't need to * is to allocate enough so the individual functions don't need to
@ -1652,14 +1645,7 @@ static void REGION_RegionOp(
* have to worry about using too much memory. I hope to be able to * have to worry about using too much memory. I hope to be able to
* nuke the Xrealloc() at the end of this function eventually. * nuke the Xrealloc() at the end of this function eventually.
*/ */
newReg->size = max(reg1->numRects,reg2->numRects) * 2; if (!init_region( &newReg, max(reg1->numRects,reg2->numRects) * 2 )) return FALSE;
if (! (newReg->rects = HeapAlloc( GetProcessHeap(), 0,
sizeof(RECT) * newReg->size )))
{
newReg->size = 0;
return;
}
/* /*
* Initialize ybot and ytop. * Initialize ybot and ytop.
@ -1692,7 +1678,7 @@ static void REGION_RegionOp(
do do
{ {
curBand = newReg->numRects; curBand = newReg.numRects;
/* /*
* This algorithm proceeds one source-band (as opposed to a * This algorithm proceeds one source-band (as opposed to a
@ -1728,7 +1714,7 @@ static void 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;
@ -1740,7 +1726,7 @@ static void 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;
@ -1756,9 +1742,9 @@ static void REGION_RegionOp(
* this test in miCoalesce, but some machines incur a not * this test in miCoalesce, but some machines incur a not
* inconsiderable cost for function calls, so... * inconsiderable cost for function calls, so...
*/ */
if (newReg->numRects != curBand) if (newReg.numRects != curBand)
{ {
prevBand = REGION_Coalesce (newReg, prevBand, curBand); prevBand = REGION_Coalesce (&newReg, prevBand, curBand);
} }
/* /*
@ -1766,16 +1752,15 @@ static void REGION_RegionOp(
* intersect if ybot > ytop * intersect if ybot > ytop
*/ */
ybot = min(r1->bottom, r2->bottom); ybot = min(r1->bottom, r2->bottom);
curBand = newReg->numRects; curBand = newReg.numRects;
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->numRects != curBand) if (newReg.numRects != curBand)
{ {
prevBand = REGION_Coalesce (newReg, prevBand, curBand); prevBand = REGION_Coalesce (&newReg, prevBand, curBand);
} }
/* /*
@ -1795,7 +1780,7 @@ static void REGION_RegionOp(
/* /*
* Deal with whichever region still has rectangles left. * Deal with whichever region still has rectangles left.
*/ */
curBand = newReg->numRects; curBand = newReg.numRects;
if (r1 != r1End) if (r1 != r1End)
{ {
if (nonOverlap1Func != NULL) if (nonOverlap1Func != NULL)
@ -1807,8 +1792,8 @@ static void REGION_RegionOp(
{ {
r1BandEnd++; r1BandEnd++;
} }
(* nonOverlap1Func) (newReg, r1, r1BandEnd, if (!nonOverlap1Func(&newReg, r1, r1BandEnd, max(r1->top,ybot), r1->bottom))
max(r1->top,ybot), r1->bottom); return FALSE;
r1 = r1BandEnd; r1 = r1BandEnd;
} while (r1 != r1End); } while (r1 != r1End);
} }
@ -1822,15 +1807,15 @@ static void REGION_RegionOp(
{ {
r2BandEnd++; r2BandEnd++;
} }
(* nonOverlap2Func) (newReg, r2, r2BandEnd, if (!nonOverlap2Func(&newReg, r2, r2BandEnd, max(r2->top,ybot), r2->bottom))
max(r2->top,ybot), r2->bottom); return FALSE;
r2 = r2BandEnd; r2 = r2BandEnd;
} while (r2 != r2End); } while (r2 != r2End);
} }
if (newReg->numRects != curBand) if (newReg.numRects != curBand)
{ {
(void) REGION_Coalesce (newReg, prevBand, curBand); REGION_Coalesce (&newReg, prevBand, curBand);
} }
/* /*
@ -1841,30 +1826,20 @@ static void REGION_RegionOp(
* Only do this stuff if the number of rectangles allocated is more than * Only do this stuff if the number of rectangles allocated is more than
* twice the number of rectangles in the region (a simple optimization...). * twice the number of rectangles in the region (a simple optimization...).
*/ */
if ((newReg->numRects < (newReg->size >> 1)) && (newReg->numRects > 2)) if ((newReg.numRects < (newReg.size >> 1)) && (newReg.numRects > 2))
{ {
if (REGION_NOT_EMPTY(newReg)) RECT *new_rects = HeapReAlloc( GetProcessHeap(), 0, newReg.rects, newReg.numRects * sizeof(RECT) );
{ if (new_rects)
RECT *prev_rects = newReg->rects; {
newReg->size = newReg->numRects; newReg.rects = new_rects;
newReg->rects = HeapReAlloc( GetProcessHeap(), 0, newReg->rects, newReg.size = newReg.numRects;
sizeof(RECT) * newReg->size ); }
if (! newReg->rects)
newReg->rects = prev_rects;
}
else
{
/*
* No point in doing the extra work involved in an Xrealloc if
* the region is empty
*/
newReg->size = 1;
HeapFree( GetProcessHeap(), 0, newReg->rects );
newReg->rects = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT) );
}
} }
HeapFree( GetProcessHeap(), 0, oldRects ); HeapFree( GetProcessHeap(), 0, destReg->rects );
return; destReg->rects = newReg.rects;
destReg->size = newReg.size;
destReg->numRects = newReg.numRects;
return TRUE;
} }
/*********************************************************************** /***********************************************************************
@ -1884,8 +1859,8 @@ static void REGION_RegionOp(
* Rectangles may be added to the region. * Rectangles may be added to the region.
* *
*/ */
static void REGION_IntersectO(WINEREGION *pReg, RECT *r1, RECT *r1End, static BOOL REGION_IntersectO(WINEREGION *pReg, RECT *r1, RECT *r1End,
RECT *r2, RECT *r2End, INT top, INT bottom) RECT *r2, RECT *r2End, INT top, INT bottom)
{ {
INT left, right; INT left, right;
@ -1903,7 +1878,9 @@ static void REGION_IntersectO(WINEREGION *pReg, RECT *r1, RECT *r1End,
* right next to each other. Since that should never happen... * right next to each other. Since that should never happen...
*/ */
if (left < right) if (left < right)
add_rect( pReg, left, top, right, bottom ); {
if (!add_rect( pReg, left, top, right, bottom )) return FALSE;
}
/* /*
* Need to advance the pointers. Shift the one that extends * Need to advance the pointers. Shift the one that extends
@ -1924,13 +1901,13 @@ static void REGION_IntersectO(WINEREGION *pReg, RECT *r1, RECT *r1End,
r2++; r2++;
} }
} }
return; return TRUE;
} }
/*********************************************************************** /***********************************************************************
* REGION_IntersectRegion * REGION_IntersectRegion
*/ */
static void REGION_IntersectRegion(WINEREGION *newReg, WINEREGION *reg1, static BOOL REGION_IntersectRegion(WINEREGION *newReg, WINEREGION *reg1,
WINEREGION *reg2) WINEREGION *reg2)
{ {
/* check for trivial reject */ /* check for trivial reject */
@ -1938,7 +1915,7 @@ static void REGION_IntersectRegion(WINEREGION *newReg, WINEREGION *reg1,
(!EXTENTCHECK(&reg1->extents, &reg2->extents))) (!EXTENTCHECK(&reg1->extents, &reg2->extents)))
newReg->numRects = 0; newReg->numRects = 0;
else else
REGION_RegionOp (newReg, reg1, reg2, REGION_IntersectO, NULL, NULL); if (!REGION_RegionOp (newReg, reg1, reg2, REGION_IntersectO, 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
@ -1948,6 +1925,7 @@ static void REGION_IntersectRegion(WINEREGION *newReg, WINEREGION *reg1,
* 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;
} }
/*********************************************************************** /***********************************************************************
@ -1969,15 +1947,14 @@ static void REGION_IntersectRegion(WINEREGION *newReg, WINEREGION *reg1,
* with the rectangles we're passed. * with the rectangles we're passed.
* *
*/ */
static void REGION_UnionNonO (WINEREGION *pReg, RECT *r, RECT *rEnd, static BOOL REGION_UnionNonO(WINEREGION *pReg, RECT *r, RECT *rEnd, INT top, INT bottom)
INT top, INT bottom)
{ {
while (r != rEnd) while (r != rEnd)
{ {
add_rect( pReg, r->left, top, r->right, bottom ); if (!add_rect( pReg, r->left, top, r->right, bottom )) return FALSE;
r++; r++;
} }
return; return TRUE;
} }
/*********************************************************************** /***********************************************************************
@ -1994,7 +1971,7 @@ static void REGION_UnionNonO (WINEREGION *pReg, RECT *r, RECT *rEnd,
* be changed. * be changed.
* *
*/ */
static void REGION_UnionO (WINEREGION *pReg, RECT *r1, RECT *r1End, static BOOL REGION_UnionO (WINEREGION *pReg, RECT *r1, RECT *r1End,
RECT *r2, RECT *r2End, INT top, INT bottom) RECT *r2, RECT *r2End, INT top, INT bottom)
{ {
#define MERGERECT(r) \ #define MERGERECT(r) \
@ -2007,7 +1984,9 @@ static void REGION_UnionO (WINEREGION *pReg, RECT *r1, RECT *r1End,
pReg->rects[pReg->numRects-1].right = r->right; \ pReg->rects[pReg->numRects-1].right = r->right; \
} \ } \
else \ else \
add_rect( pReg, r->left, top, r->right, bottom ); \ { \
if (!add_rect( pReg, r->left, top, r->right, bottom )) return FALSE; \
} \
r++; r++;
while ((r1 != r1End) && (r2 != r2End)) while ((r1 != r1End) && (r2 != r2End))
@ -2033,16 +2012,17 @@ static void REGION_UnionO (WINEREGION *pReg, RECT *r1, RECT *r1End,
{ {
MERGERECT(r2); MERGERECT(r2);
} }
return; return TRUE;
#undef MERGERECT #undef MERGERECT
} }
/*********************************************************************** /***********************************************************************
* REGION_UnionRegion * REGION_UnionRegion
*/ */
static void REGION_UnionRegion(WINEREGION *newReg, WINEREGION *reg1, static BOOL REGION_UnionRegion(WINEREGION *newReg, WINEREGION *reg1, WINEREGION *reg2)
WINEREGION *reg2)
{ {
BOOL ret = TRUE;
/* checks all the simple cases */ /* checks all the simple cases */
/* /*
@ -2051,8 +2031,8 @@ static void REGION_UnionRegion(WINEREGION *newReg, WINEREGION *reg1,
if ( (reg1 == reg2) || (!(reg1->numRects)) ) if ( (reg1 == reg2) || (!(reg1->numRects)) )
{ {
if (newReg != reg2) if (newReg != reg2)
REGION_CopyRegion(newReg, reg2); ret = REGION_CopyRegion(newReg, reg2);
return; return ret;
} }
/* /*
@ -2061,8 +2041,8 @@ static void REGION_UnionRegion(WINEREGION *newReg, WINEREGION *reg1,
if (!(reg2->numRects)) if (!(reg2->numRects))
{ {
if (newReg != reg1) if (newReg != reg1)
REGION_CopyRegion(newReg, reg1); ret = REGION_CopyRegion(newReg, reg1);
return; return ret;
} }
/* /*
@ -2075,8 +2055,8 @@ static void REGION_UnionRegion(WINEREGION *newReg, WINEREGION *reg1,
(reg1->extents.bottom >= reg2->extents.bottom)) (reg1->extents.bottom >= reg2->extents.bottom))
{ {
if (newReg != reg1) if (newReg != reg1)
REGION_CopyRegion(newReg, reg1); ret = REGION_CopyRegion(newReg, reg1);
return; return ret;
} }
/* /*
@ -2089,16 +2069,18 @@ static void REGION_UnionRegion(WINEREGION *newReg, WINEREGION *reg1,
(reg2->extents.bottom >= reg1->extents.bottom)) (reg2->extents.bottom >= reg1->extents.bottom))
{ {
if (newReg != reg2) if (newReg != reg2)
REGION_CopyRegion(newReg, reg2); ret = REGION_CopyRegion(newReg, reg2);
return; return ret;
} }
REGION_RegionOp (newReg, reg1, reg2, REGION_UnionO, REGION_UnionNonO, REGION_UnionNonO); if ((ret = REGION_RegionOp (newReg, reg1, reg2, REGION_UnionO, REGION_UnionNonO, REGION_UnionNonO)))
{
newReg->extents.left = min(reg1->extents.left, reg2->extents.left); newReg->extents.left = min(reg1->extents.left, reg2->extents.left);
newReg->extents.top = min(reg1->extents.top, reg2->extents.top); newReg->extents.top = min(reg1->extents.top, reg2->extents.top);
newReg->extents.right = max(reg1->extents.right, reg2->extents.right); newReg->extents.right = max(reg1->extents.right, reg2->extents.right);
newReg->extents.bottom = max(reg1->extents.bottom, reg2->extents.bottom); newReg->extents.bottom = max(reg1->extents.bottom, reg2->extents.bottom);
}
return ret;
} }
/*********************************************************************** /***********************************************************************
@ -2118,15 +2100,14 @@ static void REGION_UnionRegion(WINEREGION *newReg, WINEREGION *reg1,
* pReg may be affected. * pReg may be affected.
* *
*/ */
static void REGION_SubtractNonO1 (WINEREGION *pReg, RECT *r, RECT *rEnd, static BOOL REGION_SubtractNonO1 (WINEREGION *pReg, RECT *r, RECT *rEnd, INT top, INT bottom)
INT top, INT bottom)
{ {
while (r != rEnd) while (r != rEnd)
{ {
add_rect( pReg, r->left, top, r->right, bottom ); if (!add_rect( pReg, r->left, top, r->right, bottom )) return FALSE;
r++; r++;
} }
return; return TRUE;
} }
@ -2143,14 +2124,10 @@ static void REGION_SubtractNonO1 (WINEREGION *pReg, RECT *r, RECT *rEnd,
* pReg may have rectangles added to it. * pReg may have rectangles added to it.
* *
*/ */
static void REGION_SubtractO (WINEREGION *pReg, RECT *r1, RECT *r1End, static BOOL REGION_SubtractO (WINEREGION *pReg, RECT *r1, RECT *r1End,
RECT *r2, RECT *r2End, INT top, INT bottom) RECT *r2, RECT *r2End, INT top, INT bottom)
{ {
RECT *pNextRect; INT left = r1->left;
INT left;
left = r1->left;
pNextRect = &pReg->rects[pReg->numRects];
while ((r1 != r1End) && (r2 != r2End)) while ((r1 != r1End) && (r2 != r2End))
{ {
@ -2192,7 +2169,7 @@ static void REGION_SubtractO (WINEREGION *pReg, RECT *r1, RECT *r1End,
* Left part of subtrahend covers part of minuend: add uncovered * Left part of subtrahend covers part of minuend: add uncovered
* part of minuend to region and skip to next subtrahend. * part of minuend to region and skip to next subtrahend.
*/ */
add_rect( pReg, left, top, r2->left, bottom ); if (!add_rect( pReg, left, top, r2->left, bottom )) return FALSE;
left = r2->right; left = r2->right;
if (left >= r1->right) if (left >= r1->right)
{ {
@ -2218,7 +2195,7 @@ static void REGION_SubtractO (WINEREGION *pReg, RECT *r1, RECT *r1End,
*/ */
if (r1->right > left) if (r1->right > left)
{ {
add_rect( pReg, left, top, r1->right, bottom ); if (!add_rect( pReg, left, top, r1->right, bottom )) return FALSE;
} }
r1++; r1++;
left = r1->left; left = r1->left;
@ -2230,14 +2207,14 @@ static void REGION_SubtractO (WINEREGION *pReg, RECT *r1, RECT *r1End,
*/ */
while (r1 != r1End) while (r1 != r1End)
{ {
add_rect( pReg, left, top, r1->right, bottom ); if (!add_rect( pReg, left, top, r1->right, bottom )) return FALSE;
r1++; r1++;
if (r1 != r1End) if (r1 != r1End)
{ {
left = r1->left; left = r1->left;
} }
} }
return; return TRUE;
} }
/*********************************************************************** /***********************************************************************
@ -2253,18 +2230,15 @@ static void REGION_SubtractO (WINEREGION *pReg, RECT *r1, RECT *r1End,
* regD is overwritten. * regD is overwritten.
* *
*/ */
static void REGION_SubtractRegion(WINEREGION *regD, WINEREGION *regM, static BOOL REGION_SubtractRegion(WINEREGION *regD, WINEREGION *regM, WINEREGION *regS )
WINEREGION *regS )
{ {
/* check for trivial reject */ /* check for trivial reject */
if ( (!(regM->numRects)) || (!(regS->numRects)) || if ( (!(regM->numRects)) || (!(regS->numRects)) ||
(!EXTENTCHECK(&regM->extents, &regS->extents)) ) (!EXTENTCHECK(&regM->extents, &regS->extents)) )
{ return REGION_CopyRegion(regD, regM);
REGION_CopyRegion(regD, regM);
return;
}
REGION_RegionOp (regD, regM, regS, REGION_SubtractO, REGION_SubtractNonO1, NULL); if (!REGION_RegionOp (regD, regM, regS, REGION_SubtractO, REGION_SubtractNonO1, 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
@ -2274,24 +2248,27 @@ static void REGION_SubtractRegion(WINEREGION *regD, WINEREGION *regM,
* 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 void REGION_XorRegion(WINEREGION *dr, WINEREGION *sra, WINEREGION *srb) static BOOL REGION_XorRegion(WINEREGION *dr, WINEREGION *sra, WINEREGION *srb)
{ {
WINEREGION tra, trb; WINEREGION tra, trb;
BOOL ret;
if (!init_region( &tra, sra->numRects + 1 )) return; if (!init_region( &tra, sra->numRects + 1 )) return FALSE;
if (init_region( &trb, srb->numRects + 1 )) if ((ret = init_region( &trb, srb->numRects + 1 )))
{ {
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);
destroy_region(&trb); destroy_region(&trb);
} }
destroy_region(&tra); destroy_region(&tra);
return ret;
} }
/************************************************************************** /**************************************************************************