gdi32: Add helpers to allocate, grow and free regions.
Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
8185c9f024
commit
01c33fb983
|
@ -125,16 +125,25 @@ static inline BOOL overlapping( const RECT *r1, const RECT *r2 )
|
||||||
r1->bottom > r2->top && r1->top < r2->bottom);
|
r1->bottom > r2->top && r1->top < r2->bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL grow_region( WINEREGION *rgn, int size )
|
||||||
|
{
|
||||||
|
RECT *new_rects;
|
||||||
|
|
||||||
|
if (size <= rgn->size) return TRUE;
|
||||||
|
|
||||||
|
new_rects = HeapReAlloc( GetProcessHeap(), 0, rgn->rects, size * sizeof(RECT) );
|
||||||
|
if (!new_rects) return FALSE;
|
||||||
|
rgn->rects = new_rects;
|
||||||
|
rgn->size = size;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL add_rect( WINEREGION *reg, INT left, INT top, INT right, INT bottom )
|
static BOOL add_rect( WINEREGION *reg, INT left, INT top, INT right, INT bottom )
|
||||||
{
|
{
|
||||||
RECT *rect;
|
RECT *rect;
|
||||||
if (reg->numRects >= reg->size)
|
if (reg->numRects >= reg->size && !grow_region( reg, 2 * reg->size ))
|
||||||
{
|
return FALSE;
|
||||||
RECT *newrects = HeapReAlloc( GetProcessHeap(), 0, reg->rects, 2 * sizeof(RECT) * reg->size );
|
|
||||||
if (!newrects) return FALSE;
|
|
||||||
reg->rects = newrects;
|
|
||||||
reg->size *= 2;
|
|
||||||
}
|
|
||||||
rect = reg->rects + reg->numRects++;
|
rect = reg->rects + reg->numRects++;
|
||||||
rect->left = left;
|
rect->left = left;
|
||||||
rect->top = top;
|
rect->top = top;
|
||||||
|
@ -450,6 +459,46 @@ static void destroy_region( WINEREGION *pReg )
|
||||||
HeapFree( GetProcessHeap(), 0, pReg->rects );
|
HeapFree( GetProcessHeap(), 0, pReg->rects );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* free_region
|
||||||
|
*/
|
||||||
|
static void free_region( WINEREGION *rgn )
|
||||||
|
{
|
||||||
|
destroy_region( rgn );
|
||||||
|
HeapFree( GetProcessHeap(), 0, rgn );
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* alloc_region
|
||||||
|
*/
|
||||||
|
static WINEREGION *alloc_region( INT n )
|
||||||
|
{
|
||||||
|
WINEREGION *rgn = HeapAlloc( GetProcessHeap(), 0, sizeof(*rgn) );
|
||||||
|
|
||||||
|
if (rgn && !init_region( rgn, n ))
|
||||||
|
{
|
||||||
|
free_region( rgn );
|
||||||
|
rgn = NULL;
|
||||||
|
}
|
||||||
|
return rgn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************
|
||||||
|
* move_rects
|
||||||
|
*
|
||||||
|
* Move rectangles from src to dst leaving src with no rectangles.
|
||||||
|
*/
|
||||||
|
static inline void move_rects( WINEREGION *dst, WINEREGION *src )
|
||||||
|
{
|
||||||
|
destroy_region( dst );
|
||||||
|
dst->rects = src->rects;
|
||||||
|
dst->size = src->size;
|
||||||
|
dst->numRects = src->numRects;
|
||||||
|
src->rects = NULL;
|
||||||
|
src->size = 0;
|
||||||
|
src->numRects = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* REGION_DeleteObject
|
* REGION_DeleteObject
|
||||||
*/
|
*/
|
||||||
|
@ -458,8 +507,7 @@ static BOOL REGION_DeleteObject( HGDIOBJ handle )
|
||||||
WINEREGION *rgn = free_gdi_handle( handle );
|
WINEREGION *rgn = free_gdi_handle( handle );
|
||||||
|
|
||||||
if (!rgn) return FALSE;
|
if (!rgn) return FALSE;
|
||||||
HeapFree( GetProcessHeap(), 0, rgn->rects );
|
free_region( rgn );
|
||||||
HeapFree( GetProcessHeap(), 0, rgn );
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,18 +643,11 @@ HRGN WINAPI CreateRectRgn(INT left, INT top, INT right, INT bottom)
|
||||||
HRGN hrgn;
|
HRGN hrgn;
|
||||||
WINEREGION *obj;
|
WINEREGION *obj;
|
||||||
|
|
||||||
if (!(obj = HeapAlloc( GetProcessHeap(), 0, sizeof(*obj) ))) return 0;
|
if (!(obj = alloc_region( RGN_DEFAULT_RECTS ))) return 0;
|
||||||
|
|
||||||
/* Allocate 2 rects by default to reduce the number of reallocs */
|
|
||||||
if (!init_region( obj, RGN_DEFAULT_RECTS ))
|
|
||||||
{
|
|
||||||
HeapFree( GetProcessHeap(), 0, obj );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!(hrgn = alloc_gdi_handle( obj, OBJ_REGION, ®ion_funcs )))
|
if (!(hrgn = alloc_gdi_handle( obj, OBJ_REGION, ®ion_funcs )))
|
||||||
{
|
{
|
||||||
HeapFree( GetProcessHeap(), 0, obj->rects );
|
free_region( obj );
|
||||||
HeapFree( GetProcessHeap(), 0, obj );
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
TRACE( "%d,%d-%d,%d returning %p\n", left, top, right, bottom, hrgn );
|
TRACE( "%d,%d-%d,%d returning %p\n", left, top, right, bottom, hrgn );
|
||||||
|
@ -727,16 +768,13 @@ HRGN WINAPI CreateRoundRectRgn( INT left, INT top,
|
||||||
if ((ellipse_width < 2) || (ellipse_height < 2))
|
if ((ellipse_width < 2) || (ellipse_height < 2))
|
||||||
return CreateRectRgn( left, top, right, bottom );
|
return CreateRectRgn( left, top, right, bottom );
|
||||||
|
|
||||||
if (!(obj = HeapAlloc( GetProcessHeap(), 0, sizeof(*obj) ))) return 0;
|
if (!(obj = alloc_region( ellipse_height ))) return 0;
|
||||||
obj->size = ellipse_height;
|
|
||||||
obj->numRects = ellipse_height;
|
obj->numRects = ellipse_height;
|
||||||
obj->extents.left = left;
|
obj->extents.left = left;
|
||||||
obj->extents.top = top;
|
obj->extents.top = top;
|
||||||
obj->extents.right = right;
|
obj->extents.right = right;
|
||||||
obj->extents.bottom = bottom;
|
obj->extents.bottom = bottom;
|
||||||
|
rects = obj->rects;
|
||||||
obj->rects = rects = HeapAlloc( GetProcessHeap(), 0, obj->size * sizeof(RECT) );
|
|
||||||
if (!rects) goto done;
|
|
||||||
|
|
||||||
/* based on an algorithm by Alois Zingl */
|
/* based on an algorithm by Alois Zingl */
|
||||||
|
|
||||||
|
@ -788,12 +826,7 @@ HRGN WINAPI CreateRoundRectRgn( INT left, INT top,
|
||||||
|
|
||||||
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) free_region( obj );
|
||||||
if (!hrgn)
|
|
||||||
{
|
|
||||||
HeapFree( GetProcessHeap(), 0, obj->rects );
|
|
||||||
HeapFree( GetProcessHeap(), 0, obj );
|
|
||||||
}
|
|
||||||
return hrgn;
|
return hrgn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -941,6 +974,7 @@ HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA*
|
||||||
{
|
{
|
||||||
HRGN hrgn = 0;
|
HRGN hrgn = 0;
|
||||||
WINEREGION *obj;
|
WINEREGION *obj;
|
||||||
|
const RECT *pCurRect, *pEndRect;
|
||||||
|
|
||||||
if (!rgndata)
|
if (!rgndata)
|
||||||
{
|
{
|
||||||
|
@ -985,34 +1019,21 @@ HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA*
|
||||||
return hrgn;
|
return hrgn;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(obj = HeapAlloc( GetProcessHeap(), 0, sizeof(*obj) ))) return 0;
|
if (!(obj = alloc_region( rgndata->rdh.nCount ))) return 0;
|
||||||
|
|
||||||
if (init_region( obj, rgndata->rdh.nCount ))
|
pEndRect = (const RECT *)rgndata->Buffer + rgndata->rdh.nCount;
|
||||||
|
for(pCurRect = (const RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
|
||||||
{
|
{
|
||||||
const RECT *pCurRect, *pEndRect;
|
if (pCurRect->left < pCurRect->right && pCurRect->top < pCurRect->bottom)
|
||||||
|
|
||||||
pEndRect = (const RECT *)rgndata->Buffer + rgndata->rdh.nCount;
|
|
||||||
for(pCurRect = (const RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
|
|
||||||
{
|
{
|
||||||
if (pCurRect->left < pCurRect->right && pCurRect->top < pCurRect->bottom)
|
if (!REGION_UnionRectWithRegion( pCurRect, obj )) goto done;
|
||||||
{
|
|
||||||
if (!REGION_UnionRectWithRegion( pCurRect, obj )) goto done;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
hrgn = alloc_gdi_handle( obj, OBJ_REGION, ®ion_funcs );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HeapFree( GetProcessHeap(), 0, obj );
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
hrgn = alloc_gdi_handle( obj, OBJ_REGION, ®ion_funcs );
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (!hrgn)
|
if (!hrgn) free_region( obj );
|
||||||
{
|
|
||||||
HeapFree( GetProcessHeap(), 0, obj->rects );
|
|
||||||
HeapFree( GetProcessHeap(), 0, obj );
|
|
||||||
}
|
|
||||||
TRACE("%p %d %p returning %p\n", lpXform, dwCount, rgndata, hrgn );
|
TRACE("%p %d %p returning %p\n", lpXform, dwCount, rgndata, hrgn );
|
||||||
return hrgn;
|
return hrgn;
|
||||||
}
|
}
|
||||||
|
@ -1207,7 +1228,7 @@ BOOL REGION_FrameRgn( HRGN hDest, HRGN hSrc, INT x, INT y )
|
||||||
bRet = TRUE;
|
bRet = TRUE;
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
HeapFree( GetProcessHeap(), 0, tmprgn.rects );
|
destroy_region( &tmprgn );
|
||||||
if (destObj) GDI_ReleaseObj ( hDest );
|
if (destObj) GDI_ReleaseObj ( hDest );
|
||||||
GDI_ReleaseObj( hSrc );
|
GDI_ReleaseObj( hSrc );
|
||||||
return bRet;
|
return bRet;
|
||||||
|
@ -1354,13 +1375,9 @@ 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 && !grow_region( dst, src->numRects ))
|
||||||
{
|
return FALSE;
|
||||||
RECT *rects = HeapReAlloc( GetProcessHeap(), 0, dst->rects, src->numRects * sizeof(RECT) );
|
|
||||||
if (!rects) return FALSE;
|
|
||||||
dst->rects = rects;
|
|
||||||
dst->size = src->numRects;
|
|
||||||
}
|
|
||||||
dst->numRects = src->numRects;
|
dst->numRects = src->numRects;
|
||||||
dst->extents.left = src->extents.left;
|
dst->extents.left = src->extents.left;
|
||||||
dst->extents.top = src->extents.top;
|
dst->extents.top = src->extents.top;
|
||||||
|
@ -1378,9 +1395,21 @@ static BOOL REGION_MirrorRegion( WINEREGION *dst, WINEREGION *src, int width )
|
||||||
{
|
{
|
||||||
int i, start, end;
|
int i, start, end;
|
||||||
RECT extents;
|
RECT extents;
|
||||||
RECT *rects = HeapAlloc( GetProcessHeap(), 0, src->numRects * sizeof(RECT) );
|
RECT *rects;
|
||||||
|
WINEREGION tmp;
|
||||||
|
|
||||||
if (!rects) return FALSE;
|
if (dst != src)
|
||||||
|
{
|
||||||
|
if (!grow_region( dst, src->numRects )) return FALSE;
|
||||||
|
rects = dst->rects;
|
||||||
|
dst->numRects = src->numRects;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!init_region( &tmp, src->numRects )) return FALSE;
|
||||||
|
rects = tmp.rects;
|
||||||
|
tmp.numRects = src->numRects;
|
||||||
|
}
|
||||||
|
|
||||||
extents.left = width - src->extents.right;
|
extents.left = width - src->extents.right;
|
||||||
extents.right = width - src->extents.left;
|
extents.right = width - src->extents.left;
|
||||||
|
@ -1402,11 +1431,10 @@ static BOOL REGION_MirrorRegion( WINEREGION *dst, WINEREGION *src, int width )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapFree( GetProcessHeap(), 0, dst->rects );
|
if (dst == src)
|
||||||
dst->rects = rects;
|
move_rects( dst, &tmp );
|
||||||
dst->size = src->numRects;
|
|
||||||
dst->numRects = src->numRects;
|
dst->extents = extents;
|
||||||
dst->extents = extents;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1850,10 +1878,7 @@ static BOOL REGION_RegionOp(
|
||||||
}
|
}
|
||||||
|
|
||||||
REGION_compact( &newReg );
|
REGION_compact( &newReg );
|
||||||
HeapFree( GetProcessHeap(), 0, destReg->rects );
|
move_rects( destReg, &newReg );
|
||||||
destReg->rects = newReg.rects;
|
|
||||||
destReg->size = newReg.size;
|
|
||||||
destReg->numRects = newReg.numRects;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2581,18 +2606,18 @@ static void REGION_FreeStorage(ScanLineListBlock *pSLLBlock)
|
||||||
*
|
*
|
||||||
* Create an array of rectangles from a list of points.
|
* Create an array of rectangles from a list of points.
|
||||||
*/
|
*/
|
||||||
static BOOL REGION_PtsToRegion( struct point_block *FirstPtBlock, WINEREGION *reg )
|
static WINEREGION *REGION_PtsToRegion( struct point_block *FirstPtBlock )
|
||||||
{
|
{
|
||||||
POINT *pts;
|
POINT *pts;
|
||||||
struct point_block *pb;
|
struct point_block *pb;
|
||||||
int i, size, cur_band = 0, prev_band = 0;
|
int i, size, cur_band = 0, prev_band = 0;
|
||||||
RECT *extents;
|
RECT *extents;
|
||||||
|
WINEREGION *reg;
|
||||||
extents = ®->extents;
|
|
||||||
|
|
||||||
for (pb = FirstPtBlock, size = 0; pb; pb = pb->next) size += pb->count;
|
for (pb = FirstPtBlock, size = 0; pb; pb = pb->next) size += pb->count;
|
||||||
if (!init_region( reg, size )) return FALSE;
|
if (!(reg = alloc_region( size ))) return NULL;
|
||||||
|
|
||||||
|
extents = ®->extents;
|
||||||
extents->left = LARGE_COORDINATE, extents->right = SMALL_COORDINATE;
|
extents->left = LARGE_COORDINATE, extents->right = SMALL_COORDINATE;
|
||||||
|
|
||||||
for (pb = FirstPtBlock; pb; pb = pb->next)
|
for (pb = FirstPtBlock; pb; pb = pb->next)
|
||||||
|
@ -2629,7 +2654,7 @@ static BOOL REGION_PtsToRegion( struct point_block *FirstPtBlock, WINEREGION *re
|
||||||
}
|
}
|
||||||
REGION_compact( reg );
|
REGION_compact( reg );
|
||||||
|
|
||||||
return TRUE;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -2758,18 +2783,9 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(obj = HeapAlloc( GetProcessHeap(), 0, sizeof(*obj) ))) goto done;
|
if (!(obj = REGION_PtsToRegion( &FirstPtBlock ))) goto done;
|
||||||
|
|
||||||
if (!REGION_PtsToRegion(&FirstPtBlock, obj))
|
|
||||||
{
|
|
||||||
HeapFree( GetProcessHeap(), 0, obj );
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (!(hrgn = alloc_gdi_handle( obj, OBJ_REGION, ®ion_funcs )))
|
if (!(hrgn = alloc_gdi_handle( obj, OBJ_REGION, ®ion_funcs )))
|
||||||
{
|
free_region( obj );
|
||||||
HeapFree( GetProcessHeap(), 0, obj->rects );
|
|
||||||
HeapFree( GetProcessHeap(), 0, obj );
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
REGION_FreeStorage(SLLBlock.next);
|
REGION_FreeStorage(SLLBlock.next);
|
||||||
|
|
Loading…
Reference in New Issue