/*
|
/*
|
* Portions Copyright (c) 1999, 2000 Greg Haerr <greg@censoft.com>
|
* Portions Copyright (c) 1999, 2000 Greg Haerr <greg@censoft.com>
|
* Somewhat less shamelessly ripped from the Wine distribution
|
* Somewhat less shamelessly ripped from the Wine distribution
|
*
|
*
|
* Win32 API Region Management Routines.
|
* Win32 API Region Management Routines.
|
* Win32 API Complex Rectangle Routines.
|
* Win32 API Complex Rectangle Routines.
|
*
|
*
|
* GDI region objects. Shamelessly ripped out from the X11 distribution
|
* GDI region objects. Shamelessly ripped out from the X11 distribution
|
* Thanks for the nice licence.
|
* Thanks for the nice licence.
|
*
|
*
|
* Copyright 1993, 1994, 1995 Alexandre Julliard
|
* Copyright 1993, 1994, 1995 Alexandre Julliard
|
* Modifications and additions: Copyright 1998 Huw Davies
|
* Modifications and additions: Copyright 1998 Huw Davies
|
*/
|
*/
|
#include "windows.h"
|
#include "windows.h"
|
#include "device.h"
|
#include "device.h"
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <string.h>
|
|
|
/* later, error checking can be built into this get*/
|
/* later, error checking can be built into this get*/
|
#define GDI_GetObjPtr(hrgn,type) (hrgn)
|
#define GDI_GetObjPtr(hrgn,type) (hrgn)
|
|
|
/* local functions*/
|
/* local functions*/
|
static HRGN REGION_CreateRegion(void);
|
static HRGN REGION_CreateRegion(void);
|
/*BOOL REGION_UnionRectWithRgn( HRGN hrgn, const RECT *lpRect );*/
|
/*BOOL REGION_UnionRectWithRgn( HRGN hrgn, const RECT *lpRect );*/
|
/*BOOL REGION_FrameRgn( HRGN hDest, HRGN hSrc, INT x, INT y );*/
|
/*BOOL REGION_FrameRgn( HRGN hDest, HRGN hSrc, INT x, INT y );*/
|
|
|
#define EMPTY_REGION(pReg) { \
|
#define EMPTY_REGION(pReg) { \
|
(pReg)->numRects = 0; \
|
(pReg)->numRects = 0; \
|
(pReg)->extents.left = (pReg)->extents.top = 0; \
|
(pReg)->extents.left = (pReg)->extents.top = 0; \
|
(pReg)->extents.right = (pReg)->extents.bottom = 0; \
|
(pReg)->extents.right = (pReg)->extents.bottom = 0; \
|
(pReg)->type = NULLREGION; \
|
(pReg)->type = NULLREGION; \
|
}
|
}
|
|
|
/*
|
/*
|
* Create a new empty region.
|
* Create a new empty region.
|
*/
|
*/
|
static HRGN
|
static HRGN
|
REGION_CreateRegion(void)
|
REGION_CreateRegion(void)
|
{
|
{
|
MWRGNOBJ *obj;
|
MWRGNOBJ *obj;
|
|
|
obj = GdItemNew(MWRGNOBJ);
|
obj = GdItemNew(MWRGNOBJ);
|
if(!obj)
|
if(!obj)
|
return NULL;
|
return NULL;
|
obj->hdr.type = OBJ_REGION;
|
obj->hdr.type = OBJ_REGION;
|
obj->hdr.stockobj = FALSE;
|
obj->hdr.stockobj = FALSE;
|
if(!(obj->rgn = GdAllocRegion())) {
|
if(!(obj->rgn = GdAllocRegion())) {
|
GdItemFree(obj);
|
GdItemFree(obj);
|
return NULL;
|
return NULL;
|
}
|
}
|
return (HRGN)obj;
|
return (HRGN)obj;
|
}
|
}
|
|
|
|
|
INT WINAPI
|
INT WINAPI
|
OffsetRgn( HRGN hrgn, INT x, INT y )
|
OffsetRgn( HRGN hrgn, INT x, INT y )
|
{
|
{
|
MWRGNOBJ * obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION );
|
MWRGNOBJ * obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION );
|
|
|
if (obj)
|
if (obj)
|
{
|
{
|
GdOffsetRegion(obj->rgn, x, y);
|
GdOffsetRegion(obj->rgn, x, y);
|
return obj->rgn->type;
|
return obj->rgn->type;
|
}
|
}
|
return ERRORREGION;
|
return ERRORREGION;
|
}
|
}
|
|
|
|
|
INT WINAPI
|
INT WINAPI
|
GetRgnBox( HRGN hrgn, LPRECT rect )
|
GetRgnBox( HRGN hrgn, LPRECT rect )
|
{
|
{
|
MWRGNOBJ * obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION );
|
MWRGNOBJ * obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION );
|
if (obj)
|
if (obj)
|
return GdGetRegionBox(obj->rgn, rect);
|
return GdGetRegionBox(obj->rgn, rect);
|
return ERRORREGION;
|
return ERRORREGION;
|
}
|
}
|
|
|
|
|
HRGN WINAPI
|
HRGN WINAPI
|
CreateRectRgn(INT left, INT top, INT right, INT bottom)
|
CreateRectRgn(INT left, INT top, INT right, INT bottom)
|
{
|
{
|
HRGN hrgn;
|
HRGN hrgn;
|
|
|
if (!(hrgn = REGION_CreateRegion()))
|
if (!(hrgn = REGION_CreateRegion()))
|
return 0;
|
return 0;
|
/*TRACE(region, "\n");*/
|
/*TRACE(region, "\n");*/
|
SetRectRgn(hrgn, left, top, right, bottom);
|
SetRectRgn(hrgn, left, top, right, bottom);
|
return hrgn;
|
return hrgn;
|
}
|
}
|
|
|
|
|
HRGN WINAPI
|
HRGN WINAPI
|
CreateRectRgnIndirect( const RECT* rect )
|
CreateRectRgnIndirect( const RECT* rect )
|
{
|
{
|
return CreateRectRgn( rect->left, rect->top, rect->right, rect->bottom );
|
return CreateRectRgn( rect->left, rect->top, rect->right, rect->bottom );
|
}
|
}
|
|
|
|
|
/*
|
/*
|
* Allows either or both left and top to be greater than right or bottom.
|
* Allows either or both left and top to be greater than right or bottom.
|
*/
|
*/
|
VOID WINAPI
|
VOID WINAPI
|
SetRectRgn( HRGN hrgn, INT left, INT top, INT right, INT bottom )
|
SetRectRgn( HRGN hrgn, INT left, INT top, INT right, INT bottom )
|
{
|
{
|
MWRGNOBJ * obj;
|
MWRGNOBJ * obj;
|
MWCLIPREGION *rgn;
|
MWCLIPREGION *rgn;
|
|
|
/*TRACE(region, " %04x %d,%d-%d,%d\n", hrgn, left, top, right, bottom );*/
|
/*TRACE(region, " %04x %d,%d-%d,%d\n", hrgn, left, top, right, bottom );*/
|
|
|
if (!(obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION ))) return;
|
if (!(obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION ))) return;
|
|
|
if (left > right) { INT tmp = left; left = right; right = tmp; }
|
if (left > right) { INT tmp = left; left = right; right = tmp; }
|
if (top > bottom) { INT tmp = top; top = bottom; bottom = tmp; }
|
if (top > bottom) { INT tmp = top; top = bottom; bottom = tmp; }
|
|
|
rgn = obj->rgn;
|
rgn = obj->rgn;
|
GdSetRectRegion(rgn, left, top, right, bottom);
|
GdSetRectRegion(rgn, left, top, right, bottom);
|
}
|
}
|
|
|
|
|
HRGN WINAPI
|
HRGN WINAPI
|
CreateRoundRectRgn( INT left, INT top, INT right, INT bottom,
|
CreateRoundRectRgn( INT left, INT top, INT right, INT bottom,
|
INT ellipse_width, INT ellipse_height )
|
INT ellipse_width, INT ellipse_height )
|
{
|
{
|
MWRGNOBJ * obj;
|
MWRGNOBJ * obj;
|
HRGN hrgn;
|
HRGN hrgn;
|
int asq, bsq, d, xd, yd;
|
int asq, bsq, d, xd, yd;
|
RECT rect;
|
RECT rect;
|
|
|
/* Check if we can do a normal rectangle instead */
|
/* Check if we can do a normal rectangle instead */
|
if (ellipse_width == 0 || ellipse_height == 0)
|
if (ellipse_width == 0 || ellipse_height == 0)
|
return CreateRectRgn( left, top, right, bottom );
|
return CreateRectRgn( left, top, right, bottom );
|
|
|
/* Make the dimensions sensible */
|
/* Make the dimensions sensible */
|
if (left > right) { INT tmp = left; left = right; right = tmp; }
|
if (left > right) { INT tmp = left; left = right; right = tmp; }
|
if (top > bottom) { INT tmp = top; top = bottom; bottom = tmp; }
|
if (top > bottom) { INT tmp = top; top = bottom; bottom = tmp; }
|
|
|
ellipse_width = abs(ellipse_width);
|
ellipse_width = abs(ellipse_width);
|
ellipse_height = abs(ellipse_height);
|
ellipse_height = abs(ellipse_height);
|
|
|
/* Create region */
|
/* Create region */
|
|
|
if (!(hrgn = REGION_CreateRegion()))
|
if (!(hrgn = REGION_CreateRegion()))
|
return 0;
|
return 0;
|
obj = (MWRGNOBJ *)hrgn;
|
obj = (MWRGNOBJ *)hrgn;
|
/*TRACE(region,"(%d,%d-%d,%d %dx%d): ret=%04x\n",
|
/*TRACE(region,"(%d,%d-%d,%d %dx%d): ret=%04x\n",
|
left, top, right, bottom, ellipse_width, ellipse_height, hrgn);*/
|
left, top, right, bottom, ellipse_width, ellipse_height, hrgn);*/
|
|
|
/* Check parameters */
|
/* Check parameters */
|
|
|
if (ellipse_width > right-left) ellipse_width = right-left;
|
if (ellipse_width > right-left) ellipse_width = right-left;
|
if (ellipse_height > bottom-top) ellipse_height = bottom-top;
|
if (ellipse_height > bottom-top) ellipse_height = bottom-top;
|
|
|
/* Ellipse algorithm, based on an article by K. Porter */
|
/* Ellipse algorithm, based on an article by K. Porter */
|
/* in DDJ Graphics Programming Column, 8/89 */
|
/* in DDJ Graphics Programming Column, 8/89 */
|
|
|
asq = ellipse_width * ellipse_width / 4; /* a^2 */
|
asq = ellipse_width * ellipse_width / 4; /* a^2 */
|
bsq = ellipse_height * ellipse_height / 4; /* b^2 */
|
bsq = ellipse_height * ellipse_height / 4; /* b^2 */
|
if (asq == 0) asq = 1;
|
if (asq == 0) asq = 1;
|
if (bsq == 0) bsq = 1;
|
if (bsq == 0) bsq = 1;
|
d = bsq - asq * ellipse_height / 2 + asq / 4; /* b^2 - a^2b + a^2/4 */
|
d = bsq - asq * ellipse_height / 2 + asq / 4; /* b^2 - a^2b + a^2/4 */
|
xd = 0;
|
xd = 0;
|
yd = asq * ellipse_height; /* 2a^2b */
|
yd = asq * ellipse_height; /* 2a^2b */
|
|
|
rect.left = left + ellipse_width / 2;
|
rect.left = left + ellipse_width / 2;
|
rect.right = right - ellipse_width / 2;
|
rect.right = right - ellipse_width / 2;
|
|
|
/* Loop to draw first half of quadrant */
|
/* Loop to draw first half of quadrant */
|
|
|
while (xd < yd)
|
while (xd < yd)
|
{
|
{
|
if (d > 0) /* if nearest pixel is toward the center */
|
if (d > 0) /* if nearest pixel is toward the center */
|
{
|
{
|
/* move toward center */
|
/* move toward center */
|
rect.top = top++;
|
rect.top = top++;
|
rect.bottom = rect.top + 1;
|
rect.bottom = rect.top + 1;
|
GdUnionRectWithRegion( &rect, obj->rgn );
|
GdUnionRectWithRegion( &rect, obj->rgn );
|
rect.top = --bottom;
|
rect.top = --bottom;
|
rect.bottom = rect.top + 1;
|
rect.bottom = rect.top + 1;
|
GdUnionRectWithRegion( &rect, obj->rgn );
|
GdUnionRectWithRegion( &rect, obj->rgn );
|
yd -= 2*asq;
|
yd -= 2*asq;
|
d -= yd;
|
d -= yd;
|
}
|
}
|
rect.left--; /* next horiz point */
|
rect.left--; /* next horiz point */
|
rect.right++;
|
rect.right++;
|
xd += 2*bsq;
|
xd += 2*bsq;
|
d += bsq + xd;
|
d += bsq + xd;
|
}
|
}
|
|
|
/* Loop to draw second half of quadrant */
|
/* Loop to draw second half of quadrant */
|
|
|
d += (3 * (asq-bsq) / 2 - (xd+yd)) / 2;
|
d += (3 * (asq-bsq) / 2 - (xd+yd)) / 2;
|
while (yd >= 0)
|
while (yd >= 0)
|
{
|
{
|
/* next vertical point */
|
/* next vertical point */
|
rect.top = top++;
|
rect.top = top++;
|
rect.bottom = rect.top + 1;
|
rect.bottom = rect.top + 1;
|
GdUnionRectWithRegion( &rect, obj->rgn );
|
GdUnionRectWithRegion( &rect, obj->rgn );
|
rect.top = --bottom;
|
rect.top = --bottom;
|
rect.bottom = rect.top + 1;
|
rect.bottom = rect.top + 1;
|
GdUnionRectWithRegion( &rect, obj->rgn );
|
GdUnionRectWithRegion( &rect, obj->rgn );
|
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 */
|
rect.right++;
|
rect.right++;
|
xd += 2*bsq;
|
xd += 2*bsq;
|
d += xd;
|
d += xd;
|
}
|
}
|
yd -= 2*asq;
|
yd -= 2*asq;
|
d += asq - yd;
|
d += asq - yd;
|
}
|
}
|
|
|
/* Add the inside rectangle */
|
/* Add the inside rectangle */
|
|
|
if (top <= bottom)
|
if (top <= bottom)
|
{
|
{
|
rect.top = top;
|
rect.top = top;
|
rect.bottom = bottom;
|
rect.bottom = bottom;
|
GdUnionRectWithRegion( &rect, obj->rgn );
|
GdUnionRectWithRegion( &rect, obj->rgn );
|
}
|
}
|
obj->rgn->type = SIMPLEREGION; /* FIXME? */
|
obj->rgn->type = SIMPLEREGION; /* FIXME? */
|
return hrgn;
|
return hrgn;
|
}
|
}
|
|
|
|
|
HRGN WINAPI
|
HRGN WINAPI
|
CreateEllipticRgn( INT left, INT top, INT right, INT bottom )
|
CreateEllipticRgn( INT left, INT top, INT right, INT bottom )
|
{
|
{
|
return CreateRoundRectRgn(left, top, right, bottom, right-left, bottom-top);
|
return CreateRoundRectRgn(left, top, right, bottom, right-left, bottom-top);
|
}
|
}
|
|
|
|
|
HRGN WINAPI
|
HRGN WINAPI
|
CreateEllipticRgnIndirect( const RECT *rect )
|
CreateEllipticRgnIndirect( const RECT *rect )
|
{
|
{
|
return CreateRoundRectRgn( rect->left, rect->top, rect->right,
|
return CreateRoundRectRgn( rect->left, rect->top, rect->right,
|
rect->bottom, rect->right - rect->left,
|
rect->bottom, rect->right - rect->left,
|
rect->bottom - rect->top );
|
rect->bottom - rect->top );
|
}
|
}
|
|
|
HRGN WINAPI
|
HRGN WINAPI
|
CreatePolygonRgn(const POINT *points, INT count, INT mode)
|
CreatePolygonRgn(const POINT *points, INT count, INT mode)
|
{
|
{
|
#if POLYREGIONS
|
#if POLYREGIONS
|
HRGN hrgn;
|
HRGN hrgn;
|
MWRGNOBJ * obj;
|
MWRGNOBJ * obj;
|
MWCLIPREGION * rgn;
|
MWCLIPREGION * rgn;
|
|
|
if (!(hrgn = REGION_CreateRegion()))
|
if (!(hrgn = REGION_CreateRegion()))
|
return NULL;
|
return NULL;
|
obj = (MWRGNOBJ *)GDI_GetObjPtr(hrgn, OBJ_REGION);
|
obj = (MWRGNOBJ *)GDI_GetObjPtr(hrgn, OBJ_REGION);
|
if (!obj)
|
if (!obj)
|
return NULL;
|
return NULL;
|
|
|
rgn = GdAllocPolygonRegion((POINT *)points, count, mode);
|
rgn = GdAllocPolygonRegion((POINT *)points, count, mode);
|
if (!rgn)
|
if (!rgn)
|
return hrgn;
|
return hrgn;
|
GdDestroyRegion(obj->rgn);
|
GdDestroyRegion(obj->rgn);
|
obj->rgn = rgn;
|
obj->rgn = rgn;
|
return hrgn;
|
return hrgn;
|
#endif
|
#endif
|
}
|
}
|
|
|
DWORD WINAPI
|
DWORD WINAPI
|
GetRegionData(HRGN hrgn, DWORD count, LPRGNDATA rgndata)
|
GetRegionData(HRGN hrgn, DWORD count, LPRGNDATA rgndata)
|
{
|
{
|
DWORD size;
|
DWORD size;
|
MWRGNOBJ *obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION );
|
MWRGNOBJ *obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION );
|
MWCLIPREGION *rgn;
|
MWCLIPREGION *rgn;
|
|
|
/*TRACE(region," %04x count = %ld, rgndata = %p\n", hrgn, count, rgndata);*/
|
/*TRACE(region," %04x count = %ld, rgndata = %p\n", hrgn, count, rgndata);*/
|
|
|
if(!obj) return 0;
|
if(!obj) return 0;
|
|
|
rgn = obj->rgn;
|
rgn = obj->rgn;
|
size = rgn->numRects * sizeof(RECT);
|
size = rgn->numRects * sizeof(RECT);
|
if(count < (size + sizeof(RGNDATAHEADER)) || rgndata == NULL)
|
if(count < (size + sizeof(RGNDATAHEADER)) || rgndata == NULL)
|
return size + sizeof(RGNDATAHEADER);
|
return size + sizeof(RGNDATAHEADER);
|
|
|
rgndata->rdh.dwSize = sizeof(RGNDATAHEADER);
|
rgndata->rdh.dwSize = sizeof(RGNDATAHEADER);
|
rgndata->rdh.iType = RDH_RECTANGLES;
|
rgndata->rdh.iType = RDH_RECTANGLES;
|
rgndata->rdh.nCount = rgn->numRects;
|
rgndata->rdh.nCount = rgn->numRects;
|
rgndata->rdh.nRgnSize = size;
|
rgndata->rdh.nRgnSize = size;
|
rgndata->rdh.rcBound.left = rgn->extents.left;
|
rgndata->rdh.rcBound.left = rgn->extents.left;
|
rgndata->rdh.rcBound.top = rgn->extents.top;
|
rgndata->rdh.rcBound.top = rgn->extents.top;
|
rgndata->rdh.rcBound.right = rgn->extents.right;
|
rgndata->rdh.rcBound.right = rgn->extents.right;
|
rgndata->rdh.rcBound.bottom = rgn->extents.bottom;
|
rgndata->rdh.rcBound.bottom = rgn->extents.bottom;
|
|
|
memcpy( rgndata->Buffer, rgn->rects, size );
|
memcpy( rgndata->Buffer, rgn->rects, size );
|
|
|
return 1;
|
return 1;
|
}
|
}
|
|
|
|
|
#if 0
|
#if 0
|
HRGN WINAPI
|
HRGN WINAPI
|
ExtCreateRegion(const XFORM* lpXform, DWORD dwCount, const RGNDATA* rgndata)
|
ExtCreateRegion(const XFORM* lpXform, DWORD dwCount, const RGNDATA* rgndata)
|
{
|
{
|
HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
|
HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
|
MWRGNOBJ *obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION );
|
MWRGNOBJ *obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION );
|
RECT *pCurRect, *pEndRect;
|
RECT *pCurRect, *pEndRect;
|
|
|
/*TRACE(region, " %p %ld %p. Returning %04x\n",
|
/*TRACE(region, " %p %ld %p. Returning %04x\n",
|
lpXform, dwCount, rgndata, hrgn);*/
|
lpXform, dwCount, rgndata, hrgn);*/
|
if(!hrgn)
|
if(!hrgn)
|
{
|
{
|
WARN(region, "Can't create a region!\n");
|
WARN(region, "Can't create a region!\n");
|
return 0;
|
return 0;
|
}
|
}
|
if(lpXform)
|
if(lpXform)
|
WARN(region, "Xform not implemented - ignoring\n");
|
WARN(region, "Xform not implemented - ignoring\n");
|
|
|
if(rgndata->rdh.iType != RDH_RECTANGLES)
|
if(rgndata->rdh.iType != RDH_RECTANGLES)
|
{
|
{
|
WARN(region, "Type not RDH_RECTANGLES\n");
|
WARN(region, "Type not RDH_RECTANGLES\n");
|
DeleteObject( hrgn );
|
DeleteObject( hrgn );
|
return 0;
|
return 0;
|
}
|
}
|
|
|
pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
|
pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
|
for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
|
for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
|
GdUnionRectWithRegion( pCurRect, obj->rgn );
|
GdUnionRectWithRegion( pCurRect, obj->rgn );
|
|
|
return hrgn;
|
return hrgn;
|
}
|
}
|
#endif
|
#endif
|
|
|
|
|
BOOL WINAPI
|
BOOL WINAPI
|
PtInRegion( HRGN hrgn, INT x, INT y )
|
PtInRegion( HRGN hrgn, INT x, INT y )
|
{
|
{
|
MWRGNOBJ * obj;
|
MWRGNOBJ * obj;
|
|
|
obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION );
|
obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION );
|
if(!obj)
|
if(!obj)
|
return FALSE;
|
return FALSE;
|
return GdPtInRegion(obj->rgn, x, y);
|
return GdPtInRegion(obj->rgn, x, y);
|
}
|
}
|
|
|
/*
|
/*
|
* Returns TRUE if rect is at least partly inside hrgn
|
* Returns TRUE if rect is at least partly inside hrgn
|
*/
|
*/
|
BOOL WINAPI
|
BOOL WINAPI
|
RectInRegion( HRGN hrgn, const RECT *rect )
|
RectInRegion( HRGN hrgn, const RECT *rect )
|
{
|
{
|
MWRGNOBJ * obj;
|
MWRGNOBJ * obj;
|
|
|
obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION );
|
obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION );
|
if(!obj)
|
if(!obj)
|
return FALSE;
|
return FALSE;
|
return (GdRectInRegion(obj->rgn, rect) == MWRECT_OUT? FALSE: TRUE);
|
return (GdRectInRegion(obj->rgn, rect) == MWRECT_OUT? FALSE: TRUE);
|
}
|
}
|
|
|
BOOL WINAPI
|
BOOL WINAPI
|
EqualRgn( HRGN hrgn1, HRGN hrgn2 )
|
EqualRgn( HRGN hrgn1, HRGN hrgn2 )
|
{
|
{
|
MWRGNOBJ *obj1, *obj2;
|
MWRGNOBJ *obj1, *obj2;
|
|
|
if ((obj1 = (MWRGNOBJ *) GDI_GetObjPtr( hrgn1, OBJ_REGION )))
|
if ((obj1 = (MWRGNOBJ *) GDI_GetObjPtr( hrgn1, OBJ_REGION )))
|
if ((obj2 = (MWRGNOBJ *) GDI_GetObjPtr( hrgn2, OBJ_REGION )))
|
if ((obj2 = (MWRGNOBJ *) GDI_GetObjPtr( hrgn2, OBJ_REGION )))
|
return GdEqualRegion(obj1->rgn, obj2->rgn);
|
return GdEqualRegion(obj1->rgn, obj2->rgn);
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
|
#if 0
|
#if 0
|
/*
|
/*
|
* REGION_UnionRectWithRgn
|
* REGION_UnionRectWithRgn
|
* Adds a rectangle to a HRGN
|
* Adds a rectangle to a HRGN
|
* A helper used by scroll.c
|
* A helper used by scroll.c
|
*/
|
*/
|
BOOL
|
BOOL
|
REGION_UnionRectWithRgn( HRGN hrgn, const RECT *lpRect )
|
REGION_UnionRectWithRgn( HRGN hrgn, const RECT *lpRect )
|
{
|
{
|
MWRGNOBJ *obj = (MWRGNOBJ *)hrgn;
|
MWRGNOBJ *obj = (MWRGNOBJ *)hrgn;
|
|
|
if(!obj) return FALSE;
|
if(!obj) return FALSE;
|
GdUnionRectWithRegion( lpRect, obj->rgn );
|
GdUnionRectWithRegion( lpRect, obj->rgn );
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
/*
|
/*
|
* REGION_FrameRgn
|
* REGION_FrameRgn
|
* Create a region that is a frame around another region.
|
* Create a region that is a frame around another region.
|
* Expand all rectangles by +/- x and y, then subtract original region.
|
* Expand all rectangles by +/- x and y, then subtract original region.
|
*/
|
*/
|
BOOL
|
BOOL
|
REGION_FrameRgn( HRGN hDest, HRGN hSrc, INT x, INT y )
|
REGION_FrameRgn( HRGN hDest, HRGN hSrc, INT x, INT y )
|
{
|
{
|
BOOL bRet;
|
BOOL bRet;
|
MWRGNOBJ *srcObj = (MWRGNOBJ*) GDI_GetObjPtr( hSrc, OBJ_REGION );
|
MWRGNOBJ *srcObj = (MWRGNOBJ*) GDI_GetObjPtr( hSrc, OBJ_REGION );
|
|
|
if (srcObj->rgn->numRects != 0)
|
if (srcObj->rgn->numRects != 0)
|
{
|
{
|
MWRGNOBJ* destObj = (MWRGNOBJ*) GDI_GetObjPtr( hDest, OBJ_REGION );
|
MWRGNOBJ* destObj = (MWRGNOBJ*) GDI_GetObjPtr( hDest, OBJ_REGION );
|
RECT *pRect, *pEndRect;
|
RECT *pRect, *pEndRect;
|
RECT tempRect;
|
RECT tempRect;
|
|
|
EMPTY_REGION( destObj->rgn );
|
EMPTY_REGION( destObj->rgn );
|
|
|
pEndRect = srcObj->rgn->rects + srcObj->rgn->numRects;
|
pEndRect = srcObj->rgn->rects + srcObj->rgn->numRects;
|
for(pRect = srcObj->rgn->rects; pRect < pEndRect; pRect++)
|
for(pRect = srcObj->rgn->rects; pRect < pEndRect; pRect++)
|
{
|
{
|
tempRect.left = pRect->left - x;
|
tempRect.left = pRect->left - x;
|
tempRect.top = pRect->top - y;
|
tempRect.top = pRect->top - y;
|
tempRect.right = pRect->right + x;
|
tempRect.right = pRect->right + x;
|
tempRect.bottom = pRect->bottom + y;
|
tempRect.bottom = pRect->bottom + y;
|
GdUnionRectWithRegion( &tempRect, destObj->rgn );
|
GdUnionRectWithRegion( &tempRect, destObj->rgn );
|
}
|
}
|
GdSubtractRegion( destObj->rgn, destObj->rgn, srcObj->rgn );
|
GdSubtractRegion( destObj->rgn, destObj->rgn, srcObj->rgn );
|
bRet = TRUE;
|
bRet = TRUE;
|
}
|
}
|
else
|
else
|
bRet = FALSE;
|
bRet = FALSE;
|
return bRet;
|
return bRet;
|
}
|
}
|
#endif
|
#endif
|
|
|
/*
|
/*
|
* Note: The behavior is correct even if src and dest regions are the same.
|
* Note: The behavior is correct even if src and dest regions are the same.
|
*/
|
*/
|
INT WINAPI
|
INT WINAPI
|
CombineRgn(HRGN hDest, HRGN hSrc1, HRGN hSrc2, INT mode)
|
CombineRgn(HRGN hDest, HRGN hSrc1, HRGN hSrc2, INT mode)
|
{
|
{
|
MWRGNOBJ *destObj = (MWRGNOBJ *) GDI_GetObjPtr( hDest, OBJ_REGION);
|
MWRGNOBJ *destObj = (MWRGNOBJ *) GDI_GetObjPtr( hDest, OBJ_REGION);
|
INT result = ERRORREGION;
|
INT result = ERRORREGION;
|
|
|
/*TRACE(region, " %04x,%04x -> %04x mode=%x\n", hSrc1, hSrc2, hDest,mode);*/
|
/*TRACE(region, " %04x,%04x -> %04x mode=%x\n", hSrc1, hSrc2, hDest,mode);*/
|
|
|
if (destObj)
|
if (destObj)
|
{
|
{
|
MWRGNOBJ *src1Obj = (MWRGNOBJ *) GDI_GetObjPtr( hSrc1, OBJ_REGION);
|
MWRGNOBJ *src1Obj = (MWRGNOBJ *) GDI_GetObjPtr( hSrc1, OBJ_REGION);
|
|
|
if (src1Obj)
|
if (src1Obj)
|
{
|
{
|
/*TRACE(region, "dump:\n");
|
/*TRACE(region, "dump:\n");
|
if(TRACE_ON(region))
|
if(TRACE_ON(region))
|
REGION_DumpRegion(src1Obj->rgn);*/
|
REGION_DumpRegion(src1Obj->rgn);*/
|
if (mode == RGN_COPY)
|
if (mode == RGN_COPY)
|
{
|
{
|
GdCopyRegion( destObj->rgn, src1Obj->rgn );
|
GdCopyRegion( destObj->rgn, src1Obj->rgn );
|
result = destObj->rgn->type;
|
result = destObj->rgn->type;
|
}
|
}
|
else
|
else
|
{
|
{
|
MWRGNOBJ *src2Obj = (MWRGNOBJ *) GDI_GetObjPtr( hSrc2, OBJ_REGION);
|
MWRGNOBJ *src2Obj = (MWRGNOBJ *) GDI_GetObjPtr( hSrc2, OBJ_REGION);
|
|
|
if (src2Obj)
|
if (src2Obj)
|
{
|
{
|
/*TRACE(region, "dump:\n");
|
/*TRACE(region, "dump:\n");
|
if(TRACE_ON(region))
|
if(TRACE_ON(region))
|
REGION_DumpRegion(src2Obj->rgn);*/
|
REGION_DumpRegion(src2Obj->rgn);*/
|
switch (mode)
|
switch (mode)
|
{
|
{
|
case RGN_AND:
|
case RGN_AND:
|
GdIntersectRegion( destObj->rgn, src1Obj->rgn, src2Obj->rgn);
|
GdIntersectRegion( destObj->rgn, src1Obj->rgn, src2Obj->rgn);
|
break;
|
break;
|
case RGN_OR:
|
case RGN_OR:
|
GdUnionRegion( destObj->rgn, src1Obj->rgn, src2Obj->rgn );
|
GdUnionRegion( destObj->rgn, src1Obj->rgn, src2Obj->rgn );
|
break;
|
break;
|
case RGN_XOR:
|
case RGN_XOR:
|
GdXorRegion( destObj->rgn, src1Obj->rgn, src2Obj->rgn );
|
GdXorRegion( destObj->rgn, src1Obj->rgn, src2Obj->rgn );
|
break;
|
break;
|
case RGN_DIFF:
|
case RGN_DIFF:
|
GdSubtractRegion( destObj->rgn, src1Obj->rgn, src2Obj->rgn );
|
GdSubtractRegion( destObj->rgn, src1Obj->rgn, src2Obj->rgn );
|
break;
|
break;
|
}
|
}
|
result = destObj->rgn->type;
|
result = destObj->rgn->type;
|
}
|
}
|
}
|
}
|
}
|
}
|
/*TRACE(region, "dump:\n");
|
/*TRACE(region, "dump:\n");
|
if(TRACE_ON(region))
|
if(TRACE_ON(region))
|
REGION_DumpRegion(destObj->rgn);*/
|
REGION_DumpRegion(destObj->rgn);*/
|
}
|
}
|
return result;
|
return result;
|
}
|
}
|
|
|
/*
|
/*
|
* Rectangle-related functions
|
* Rectangle-related functions
|
*
|
*
|
* Copyright 1993, 1996 Alexandre Julliard
|
* Copyright 1993, 1996 Alexandre Julliard
|
*
|
*
|
*/
|
*/
|
BOOL WINAPI
|
BOOL WINAPI
|
IntersectRect( LPRECT dest, const RECT *src1, const RECT *src2 )
|
IntersectRect( LPRECT dest, const RECT *src1, const RECT *src2 )
|
{
|
{
|
if (IsRectEmpty(src1) || IsRectEmpty(src2) ||
|
if (IsRectEmpty(src1) || IsRectEmpty(src2) ||
|
(src1->left >= src2->right) || (src2->left >= src1->right) ||
|
(src1->left >= src2->right) || (src2->left >= src1->right) ||
|
(src1->top >= src2->bottom) || (src2->top >= src1->bottom))
|
(src1->top >= src2->bottom) || (src2->top >= src1->bottom))
|
{
|
{
|
SetRectEmpty( dest );
|
SetRectEmpty( dest );
|
return FALSE;
|
return FALSE;
|
}
|
}
|
dest->left = MWMAX( src1->left, src2->left );
|
dest->left = MWMAX( src1->left, src2->left );
|
dest->right = MWMIN( src1->right, src2->right );
|
dest->right = MWMIN( src1->right, src2->right );
|
dest->top = MWMAX( src1->top, src2->top );
|
dest->top = MWMAX( src1->top, src2->top );
|
dest->bottom = MWMIN( src1->bottom, src2->bottom );
|
dest->bottom = MWMIN( src1->bottom, src2->bottom );
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
|
|
BOOL WINAPI
|
BOOL WINAPI
|
UnionRect( LPRECT dest, const RECT *src1, const RECT *src2 )
|
UnionRect( LPRECT dest, const RECT *src1, const RECT *src2 )
|
{
|
{
|
if (IsRectEmpty(src1))
|
if (IsRectEmpty(src1))
|
{
|
{
|
if (IsRectEmpty(src2))
|
if (IsRectEmpty(src2))
|
{
|
{
|
SetRectEmpty( dest );
|
SetRectEmpty( dest );
|
return FALSE;
|
return FALSE;
|
}
|
}
|
else *dest = *src2;
|
else *dest = *src2;
|
}
|
}
|
else
|
else
|
{
|
{
|
if (IsRectEmpty(src2)) *dest = *src1;
|
if (IsRectEmpty(src2)) *dest = *src1;
|
else
|
else
|
{
|
{
|
dest->left = MWMIN( src1->left, src2->left );
|
dest->left = MWMIN( src1->left, src2->left );
|
dest->right = MWMAX( src1->right, src2->right );
|
dest->right = MWMAX( src1->right, src2->right );
|
dest->top = MWMIN( src1->top, src2->top );
|
dest->top = MWMIN( src1->top, src2->top );
|
dest->bottom = MWMAX( src1->bottom, src2->bottom );
|
dest->bottom = MWMAX( src1->bottom, src2->bottom );
|
}
|
}
|
}
|
}
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
|
|
BOOL WINAPI
|
BOOL WINAPI
|
EqualRect( const RECT* rect1, const RECT* rect2 )
|
EqualRect( const RECT* rect1, const RECT* rect2 )
|
{
|
{
|
return ((rect1->left == rect2->left) && (rect1->right == rect2->right) &&
|
return ((rect1->left == rect2->left) && (rect1->right == rect2->right) &&
|
(rect1->top == rect2->top) && (rect1->bottom == rect2->bottom));
|
(rect1->top == rect2->top) && (rect1->bottom == rect2->bottom));
|
}
|
}
|
|
|
|
|
BOOL WINAPI
|
BOOL WINAPI
|
SubtractRect( LPRECT dest, const RECT *src1, const RECT *src2 )
|
SubtractRect( LPRECT dest, const RECT *src1, const RECT *src2 )
|
{
|
{
|
RECT tmp;
|
RECT tmp;
|
|
|
if (IsRectEmpty( src1 ))
|
if (IsRectEmpty( src1 ))
|
{
|
{
|
SetRectEmpty( dest );
|
SetRectEmpty( dest );
|
return FALSE;
|
return FALSE;
|
}
|
}
|
*dest = *src1;
|
*dest = *src1;
|
if (IntersectRect( &tmp, src1, src2 ))
|
if (IntersectRect( &tmp, src1, src2 ))
|
{
|
{
|
if (EqualRect( &tmp, dest ))
|
if (EqualRect( &tmp, dest ))
|
{
|
{
|
SetRectEmpty( dest );
|
SetRectEmpty( dest );
|
return FALSE;
|
return FALSE;
|
}
|
}
|
if ((tmp.top == dest->top) && (tmp.bottom == dest->bottom))
|
if ((tmp.top == dest->top) && (tmp.bottom == dest->bottom))
|
{
|
{
|
if (tmp.left == dest->left) dest->left = tmp.right;
|
if (tmp.left == dest->left) dest->left = tmp.right;
|
else if (tmp.right == dest->right) dest->right = tmp.left;
|
else if (tmp.right == dest->right) dest->right = tmp.left;
|
}
|
}
|
else if ((tmp.left == dest->left) && (tmp.right == dest->right))
|
else if ((tmp.left == dest->left) && (tmp.right == dest->right))
|
{
|
{
|
if (tmp.top == dest->top) dest->top = tmp.bottom;
|
if (tmp.top == dest->top) dest->top = tmp.bottom;
|
else if (tmp.bottom == dest->bottom) dest->bottom = tmp.top;
|
else if (tmp.bottom == dest->bottom) dest->bottom = tmp.top;
|
}
|
}
|
}
|
}
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|