Removed dependencies on the internals of the region object.

Do not store the region type in the object, it's trivial to determine
from the rectangle count.
Rewrote a few routines to not depend on internal clipping or region
functions.
This commit is contained in:
Alexandre Julliard 2002-05-25 22:16:12 +00:00
parent 6a96749209
commit 07439cd2d0
15 changed files with 239 additions and 413 deletions

View File

@ -22,7 +22,6 @@
#include <string.h>
#include "gdi.h"
#include "region.h"
#include "mfdrv/metafiledrv.h"
#include "wine/debug.h"

View File

@ -22,7 +22,6 @@
#include "gdi.h"
#include "ttydrv.h"
#include "region.h"
#include "win.h"
#include "winpos.h"
#include "wine/debug.h"
@ -203,6 +202,7 @@ static void DCE_AddClipRects( HWND parent, HWND end, HRGN hrgnClip, LPRECT lpRec
WND *pWnd;
int i;
HWND *list = WIN_ListChildren( parent );
HRGN hrgn = 0;
if (!list) return;
for (i = 0; list[i]; i++)
@ -217,15 +217,14 @@ static void DCE_AddClipRects( HWND parent, HWND end, HRGN hrgnClip, LPRECT lpRec
rect.bottom = pWnd->rectWindow.bottom + y;
if( IntersectRect( &rect, &rect, lpRect ))
{
if(!REGION_UnionRectWithRgn( hrgnClip, &rect ))
{
WIN_ReleaseWndPtr( pWnd );
break;
}
if (!hrgn) hrgn = CreateRectRgnIndirect( &rect );
else SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
CombineRgn( hrgnClip, hrgnClip, hrgn, RGN_OR );
}
}
WIN_ReleaseWndPtr( pWnd );
}
if (hrgn) DeleteObject( hrgn );
HeapFree( GetProcessHeap(), 0, list );
}

View File

@ -34,7 +34,6 @@
#include "hook.h"
#include "win.h"
#include "winpos.h"
#include "region.h"
#include "dce.h"
#include "cursoricon.h"
#include "nonclient.h"

View File

@ -27,7 +27,6 @@
#include "winnt.h"
#include "x11drv.h"
#include "bitmap.h"
#include "region.h"
#include "wine/unicode.h"
#include "wine/debug.h"
@ -563,8 +562,7 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
XRenderColor col;
int idx;
TEXTMETRICW tm;
RGNOBJ *obj;
XRectangle *pXrect;
RGNDATA *data;
SIZE sz;
RECT rc;
BOOL done_extents = FALSE;
@ -713,12 +711,9 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
if (flags & ETO_CLIPPED)
{
SaveVisRgn16( hdc );
CLIPPING_IntersectVisRect( dc, rc.left, rc.top, rc.right,
rc.bottom, FALSE );
IntersectVisRect16( dc->hSelf, lprect->left, lprect->top, lprect->right, lprect->bottom );
}
if(!physDev->xrender->pict) {
XRenderPictureAttributes pa;
pa.subwindow_mode = IncludeInferiors;
@ -736,52 +731,14 @@ BOOL X11DRV_XRender_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flag
TRACE("using existing pict = %lx dc = %p\n", physDev->xrender->pict, dc);
}
obj = (RGNOBJ *) GDI_GetObjPtr(dc->hGCClipRgn, REGION_MAGIC);
if (!obj)
if ((data = X11DRV_GetRegionData( dc->hGCClipRgn, 0 )))
{
ERR("Rgn is 0. Please report this.\n");
return FALSE;
wine_tsx11_lock();
pXRenderSetPictureClipRectangles( gdi_display, physDev->xrender->pict,
0, 0, (XRectangle *)data->Buffer, data->rdh.nCount );
wine_tsx11_unlock();
HeapFree( GetProcessHeap(), 0, data );
}
if (obj->rgn->numRects > 0)
{
XRectangle *pXr;
RECT *pRect = obj->rgn->rects;
RECT *pEndRect = obj->rgn->rects + obj->rgn->numRects;
pXrect = HeapAlloc( GetProcessHeap(), 0,
sizeof(*pXrect) * obj->rgn->numRects );
if(!pXrect)
{
WARN("Can't alloc buffer\n");
GDI_ReleaseObj( dc->hGCClipRgn );
return FALSE;
}
for(pXr = pXrect; pRect < pEndRect; pRect++, pXr++)
{
pXr->x = pRect->left;
pXr->y = pRect->top;
pXr->width = pRect->right - pRect->left;
pXr->height = pRect->bottom - pRect->top;
TRACE("Adding clip rect %d,%d - %d,%d\n", pRect->left, pRect->top,
pRect->right, pRect->bottom);
}
}
else {
TRACE("no clip rgn\n");
pXrect = NULL;
}
wine_tsx11_lock();
pXRenderSetPictureClipRectangles( gdi_display, physDev->xrender->pict,
0, 0, pXrect, obj->rgn->numRects );
wine_tsx11_unlock();
if(pXrect)
HeapFree( GetProcessHeap(), 0, pXrect );
GDI_ReleaseObj( dc->hGCClipRgn );
if(GetBkMode(hdc) != TRANSPARENT) {
if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE))) {

View File

@ -26,62 +26,100 @@
#include "gdi.h"
#include "x11drv.h"
#include "region.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
/***********************************************************************
* X11DRV_SetDeviceClipping
* Copy RECT32s to a temporary buffer of XRectangles and call
* TSXSetClipRectangles().
* X11DRV_GetRegionData
*
* Could write using GetRegionData but this would be slower.
* Calls GetRegionData on the given region and converts the rectangle
* array to XRectangle format. The returned buffer must be freed by
* caller using HeapFree(GetProcessHeap(),...).
* If hdc_lptodp is not 0, the rectangles are converted through LPtoDP.
*/
void X11DRV_SetDeviceClipping( X11DRV_PDEVICE *physDev, HRGN hrgn )
RGNDATA *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp )
{
XRectangle *pXrect;
RGNDATA *data;
DWORD size;
int i;
RECT *rect, tmp;
XRectangle *xrect;
RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr(hrgn, REGION_MAGIC);
if (!obj)
if (!(size = GetRegionData( hrgn, 0, NULL ))) return NULL;
if (sizeof(XRectangle) > sizeof(RECT))
{
ERR("Rgn is 0. Please report this.\n");
return;
/* add extra size for XRectangle array */
int count = (size - sizeof(RGNDATAHEADER)) / sizeof(RECT);
size += count * (sizeof(XRectangle) - sizeof(RECT));
}
if (obj->rgn->numRects > 0)
if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
if (!GetRegionData( hrgn, size, data ))
{
XRectangle *pXr;
RECT *pRect = obj->rgn->rects;
RECT *pEndRect = obj->rgn->rects + obj->rgn->numRects;
HeapFree( GetProcessHeap(), 0, data );
return NULL;
}
pXrect = HeapAlloc( GetProcessHeap(), 0,
sizeof(*pXrect) * obj->rgn->numRects );
if(!pXrect)
{
WARN("Can't alloc buffer\n");
GDI_ReleaseObj( hrgn );
return;
}
for(pXr = pXrect; pRect < pEndRect; pRect++, pXr++)
rect = (RECT *)data->Buffer;
xrect = (XRectangle *)data->Buffer;
if (hdc_lptodp) /* map to device coordinates */
{
LPtoDP( hdc_lptodp, (POINT *)rect, data->rdh.nCount * 2 );
for (i = 0; i < data->rdh.nCount; i++)
{
pXr->x = pRect->left;
pXr->y = pRect->top;
pXr->width = pRect->right - pRect->left;
pXr->height = pRect->bottom - pRect->top;
if (rect[i].right < rect[i].left)
{
INT tmp = rect[i].right;
rect[i].right = rect[i].left;
rect[i].left = tmp;
}
if (rect[i].bottom < rect[i].top)
{
INT tmp = rect[i].bottom;
rect[i].bottom = rect[i].top;
rect[i].top = tmp;
}
}
}
if (sizeof(XRectangle) > sizeof(RECT))
{
/* need to start from the end */
for (i = data->rdh.nCount-1; i >=0; i--)
{
tmp = rect[i];
xrect[i].x = tmp.left;
xrect[i].y = tmp.top;
xrect[i].width = tmp.right - tmp.left;
xrect[i].height = tmp.bottom - tmp.top;
}
}
else
pXrect = NULL;
{
for (i = 0; i < data->rdh.nCount; i++)
{
tmp = rect[i];
xrect[i].x = tmp.left;
xrect[i].y = tmp.top;
xrect[i].width = tmp.right - tmp.left;
xrect[i].height = tmp.bottom - tmp.top;
}
}
return data;
}
/***********************************************************************
* X11DRV_SetDeviceClipping
*/
void X11DRV_SetDeviceClipping( X11DRV_PDEVICE *physDev, HRGN hrgn )
{
RGNDATA *data;
if (!(data = X11DRV_GetRegionData( hrgn, 0 ))) return;
TSXSetClipRectangles( gdi_display, physDev->gc, 0, 0,
pXrect, obj->rgn->numRects, YXBanded );
if(pXrect)
HeapFree( GetProcessHeap(), 0, pXrect );
GDI_ReleaseObj( hrgn );
(XRectangle *)data->Buffer, data->rdh.nCount, YXBanded );
HeapFree( GetProcessHeap(), 0, data );
}

View File

@ -45,7 +45,6 @@
#include "bitmap.h"
#include "gdi.h"
#include "palette.h"
#include "region.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(graphics);
@ -940,48 +939,29 @@ X11DRV_GetPixel( X11DRV_PDEVICE *physDev, INT x, INT y )
BOOL
X11DRV_PaintRgn( X11DRV_PDEVICE *physDev, HRGN hrgn )
{
RECT box;
HRGN tmpVisRgn, prevVisRgn;
DC *dc = physDev->dc;
HDC hdc = physDev->hdc; /* FIXME: should not mix dc/hdc this way */
if (!(tmpVisRgn = CreateRectRgn( 0, 0, 0, 0 ))) return FALSE;
/* Transform region into device co-ords */
if ( !REGION_LPTODP( hdc, tmpVisRgn, hrgn )
|| OffsetRgn( tmpVisRgn, dc->DCOrgX, dc->DCOrgY ) == ERROR) {
DeleteObject( tmpVisRgn );
return FALSE;
}
/* Modify visible region */
if (!(prevVisRgn = SaveVisRgn16( hdc ))) {
DeleteObject( tmpVisRgn );
return FALSE;
}
CombineRgn( tmpVisRgn, prevVisRgn, tmpVisRgn, RGN_AND );
SelectVisRgn16( hdc, tmpVisRgn );
DeleteObject( tmpVisRgn );
/* Fill the region */
GetRgnBox( dc->hGCClipRgn, &box );
if (X11DRV_SetupGCForBrush( physDev ))
{
/* Update the pixmap from the DIB section */
X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
int i;
XRectangle *rect;
RGNDATA *data = X11DRV_GetRegionData( hrgn, physDev->hdc );
TSXFillRectangle( gdi_display, physDev->drawable, physDev->gc,
box.left, box.top,
box.right-box.left, box.bottom-box.top );
/* Update the DIBSection from the pixmap */
X11DRV_UnlockDIBSection(physDev, TRUE);
if (!data) return FALSE;
rect = (XRectangle *)data->Buffer;
for (i = 0; i < data->rdh.nCount; i++)
{
rect[i].x += dc->DCOrgX;
rect[i].y += dc->DCOrgY;
}
X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
wine_tsx11_lock();
XFillRectangles( gdi_display, physDev->drawable, physDev->gc, rect, data->rdh.nCount );
wine_tsx11_unlock();
X11DRV_UnlockDIBSection(physDev, TRUE);
HeapFree( GetProcessHeap(), 0, data );
}
/* Restore the visible region */
RestoreVisRgn16( hdc );
return TRUE;
}

View File

@ -151,7 +151,10 @@ X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
{
SIZE sz;
if (!X11DRV_GetTextExtentPoint( physDev, wstr, count, &sz ))
return FALSE;
{
result = FALSE;
goto END;
}
width = INTERNAL_XWSTODS(dc, sz.cx);
}
ascent = pfo->lpX11Trans ? pfo->lpX11Trans->ascent : font->ascent;
@ -206,8 +209,7 @@ X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
if (flags & ETO_CLIPPED)
{
SaveVisRgn16( dc->hSelf );
CLIPPING_IntersectVisRect( dc, rect.left, rect.top, rect.right,
rect.bottom, FALSE );
IntersectVisRect16( dc->hSelf, lprect->left, lprect->top, lprect->right, lprect->bottom );
}
/* Draw the text background if necessary */
@ -395,9 +397,7 @@ X11DRV_ExtTextOut( X11DRV_PDEVICE *physDev, INT x, INT y, UINT flags,
dc->DCOrgX + x + width, dc->DCOrgY + y - lineAscent );
}
if (flags & ETO_CLIPPED)
RestoreVisRgn16( dc->hSelf );
if (flags & ETO_CLIPPED) RestoreVisRgn16( dc->hSelf );
goto END;
FAIL:

View File

@ -580,16 +580,7 @@ extern DC * DC_GetDCUpdate( HDC hdc );
extern void DC_InitDC( DC * dc );
extern void DC_UpdateXforms( DC * dc );
#define CLIP_INTERSECT 0x0001
#define CLIP_EXCLUDE 0x0002
#define CLIP_KEEPRGN 0x0004
/* objects/clipping.c */
INT CLIPPING_IntersectClipRect( DC * dc, INT left, INT top,
INT right, INT bottom, UINT flags );
INT CLIPPING_IntersectVisRect( DC * dc, INT left, INT top,
INT right, INT bottom, BOOL exclude );
extern void CLIPPING_UpdateGCRegion( DC * dc );
/* objects/enhmetafile.c */

View File

@ -25,26 +25,11 @@
#include "windef.h"
#include "wingdi.h"
typedef struct {
INT size;
INT numRects;
INT type; /* NULL, SIMPLE or COMPLEX */
RECT *rects;
RECT extents;
} WINEREGION;
struct _RGNOBJ;
/* GDI logical region object */
typedef struct
{
GDIOBJHDR header;
WINEREGION *rgn;
} RGNOBJ;
extern BOOL REGION_DeleteObject( HRGN hrgn, RGNOBJ * obj );
extern BOOL REGION_UnionRectWithRgn( HRGN hrgn, const RECT *lpRect );
extern BOOL REGION_DeleteObject( HRGN hrgn, struct _RGNOBJ * obj );
extern HRGN REGION_CropRgn( HRGN hDst, HRGN hSrc, const RECT *lpRect, const POINT *lpPt );
extern BOOL REGION_FrameRgn( HRGN dest, HRGN src, INT x, INT y );
extern BOOL REGION_LPTODP( HDC hdc, HRGN hDest, HRGN hSrc );
#endif /* __WINE_REGION_H */

View File

@ -198,6 +198,7 @@ extern HBITMAP X11DRV_BITMAP_CreateBitmapFromPixmap(Pixmap pixmap, BOOL bDeleteP
extern Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc );
extern Pixmap X11DRV_BITMAP_CreatePixmapFromBitmap( HBITMAP hBmp, HDC hdc );
extern RGNDATA *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp );
extern void X11DRV_SetDrawable( HDC hdc, Drawable drawable, int mode, int org_x, int org_y );
extern void X11DRV_StartGraphicsExposures( HDC hdc );
extern void X11DRV_EndGraphicsExposures( HDC hdc, HRGN hrgn );

View File

@ -23,7 +23,6 @@
#include "wingdi.h"
#include "wine/winuser16.h"
#include "gdi.h"
#include "region.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(clipping);
@ -204,54 +203,6 @@ INT16 WINAPI OffsetVisRgn16( HDC16 hdc, INT16 x, INT16 y )
}
/***********************************************************************
* CLIPPING_IntersectClipRect
*
* Helper function for {Intersect,Exclude}ClipRect, can be called from
* elsewhere (like ExtTextOut()) to skip redundant metafile update and
* coordinate conversion.
*/
INT CLIPPING_IntersectClipRect( DC * dc, INT left, INT top,
INT right, INT bottom, UINT flags )
{
HRGN newRgn;
INT ret;
left += dc->DCOrgX;
right += dc->DCOrgX;
top += dc->DCOrgY;
bottom += dc->DCOrgY;
if (!(newRgn = CreateRectRgn( left, top, right, bottom ))) return ERROR;
if (!dc->hClipRgn)
{
if( flags & CLIP_INTERSECT )
{
dc->hClipRgn = newRgn;
CLIPPING_UpdateGCRegion( dc );
return SIMPLEREGION;
}
else if( flags & CLIP_EXCLUDE )
{
dc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
CombineRgn( dc->hClipRgn, dc->hVisRgn, 0, RGN_COPY );
}
else WARN("No hClipRgn and flags are %x\n",flags);
}
ret = CombineRgn( newRgn, dc->hClipRgn, newRgn,
(flags & CLIP_EXCLUDE) ? RGN_DIFF : RGN_AND );
if (ret != ERROR)
{
if (!(flags & CLIP_KEEPRGN)) DeleteObject( dc->hClipRgn );
dc->hClipRgn = newRgn;
CLIPPING_UpdateGCRegion( dc );
}
else DeleteObject( newRgn );
return ret;
}
/***********************************************************************
* ExcludeClipRect (GDI.21)
*/
@ -268,6 +219,7 @@ INT16 WINAPI ExcludeClipRect16( HDC16 hdc, INT16 left, INT16 top,
INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
INT right, INT bottom )
{
HRGN newRgn;
INT ret;
DC *dc = DC_GetDCUpdate( hdc );
if (!dc) return ERROR;
@ -276,13 +228,25 @@ INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
if(dc->funcs->pExcludeClipRect)
ret = dc->funcs->pExcludeClipRect( dc->physDev, left, top, right, bottom );
else {
left = XLPTODP( dc, left );
right = XLPTODP( dc, right );
top = YLPTODP( dc, top );
bottom = YLPTODP( dc, bottom );
else
{
left = dc->DCOrgX + XLPTODP( dc, left );
right = dc->DCOrgX + XLPTODP( dc, right );
top = dc->DCOrgY + YLPTODP( dc, top );
bottom = dc->DCOrgY + YLPTODP( dc, bottom );
ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
if (!(newRgn = CreateRectRgn( left, top, right, bottom ))) ret = ERROR;
else
{
if (!dc->hClipRgn)
{
dc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
CombineRgn( dc->hClipRgn, dc->hVisRgn, 0, RGN_COPY );
}
ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_DIFF );
DeleteObject( newRgn );
}
if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
}
GDI_ReleaseObj( hdc );
return ret;
@ -313,88 +277,61 @@ INT WINAPI IntersectClipRect( HDC hdc, INT left, INT top,
if(dc->funcs->pIntersectClipRect)
ret = dc->funcs->pIntersectClipRect( dc->physDev, left, top, right, bottom );
else {
left = XLPTODP( dc, left );
right = XLPTODP( dc, right );
top = YLPTODP( dc, top );
bottom = YLPTODP( dc, bottom );
else
{
left = dc->DCOrgX + XLPTODP( dc, left );
right = dc->DCOrgX + XLPTODP( dc, right );
top = dc->DCOrgY + YLPTODP( dc, top );
bottom = dc->DCOrgY + YLPTODP( dc, bottom );
ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
if (!dc->hClipRgn)
{
dc->hClipRgn = CreateRectRgn( left, top, right, bottom );
ret = SIMPLEREGION;
}
else
{
HRGN newRgn;
if (!(newRgn = CreateRectRgn( left, top, right, bottom ))) ret = ERROR;
else
{
ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_AND );
DeleteObject( newRgn );
}
}
if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
}
GDI_ReleaseObj( hdc );
return ret;
}
/***********************************************************************
* CLIPPING_IntersectVisRect
*
* Helper function for {Intersect,Exclude}VisRect, can be called from
* elsewhere (like ExtTextOut()) to skip redundant metafile update and
* coordinate conversion.
*/
INT CLIPPING_IntersectVisRect( DC * dc, INT left, INT top,
INT right, INT bottom,
BOOL exclude )
{
HRGN tempRgn, newRgn;
INT ret;
left += dc->DCOrgX;
right += dc->DCOrgX;
top += dc->DCOrgY;
bottom += dc->DCOrgY;
if (!(newRgn = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
if (!(tempRgn = CreateRectRgn( left, top, right, bottom )))
{
DeleteObject( newRgn );
return ERROR;
}
ret = CombineRgn( newRgn, dc->hVisRgn, tempRgn,
exclude ? RGN_DIFF : RGN_AND );
DeleteObject( tempRgn );
if (ret != ERROR)
{
RGNOBJ *newObj = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
if (newObj)
{
RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC);
if (prevObj)
{
newObj->header.hNext = prevObj->header.hNext;
GDI_ReleaseObj( dc->hVisRgn );
}
GDI_ReleaseObj( newRgn );
}
DeleteObject( dc->hVisRgn );
dc->hVisRgn = newRgn;
CLIPPING_UpdateGCRegion( dc );
}
else DeleteObject( newRgn );
return ret;
}
/***********************************************************************
* ExcludeVisRect (GDI.73)
*/
INT16 WINAPI ExcludeVisRect16( HDC16 hdc, INT16 left, INT16 top,
INT16 right, INT16 bottom )
{
HRGN tempRgn;
INT16 ret;
DC * dc = DC_GetDCUpdate( hdc );
if (!dc) return ERROR;
if (!dc) return ERROR;
left = XLPTODP( dc, left );
right = XLPTODP( dc, right );
top = YLPTODP( dc, top );
bottom = YLPTODP( dc, bottom );
left = dc->DCOrgX + XLPTODP( dc, left );
right = dc->DCOrgX + XLPTODP( dc, right );
top = dc->DCOrgY + YLPTODP( dc, top );
bottom = dc->DCOrgY + YLPTODP( dc, bottom );
TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
ret = CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
if (!(tempRgn = CreateRectRgn( left, top, right, bottom ))) ret = ERROR;
else
{
ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_DIFF );
DeleteObject( tempRgn );
}
if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
GDI_ReleaseObj( hdc );
return ret;
}
@ -406,18 +343,25 @@ INT16 WINAPI ExcludeVisRect16( HDC16 hdc, INT16 left, INT16 top,
INT16 WINAPI IntersectVisRect16( HDC16 hdc, INT16 left, INT16 top,
INT16 right, INT16 bottom )
{
HRGN tempRgn;
INT16 ret;
DC * dc = DC_GetDCUpdate( hdc );
if (!dc) return ERROR;
if (!dc) return ERROR;
left = XLPTODP( dc, left );
right = XLPTODP( dc, right );
top = YLPTODP( dc, top );
bottom = YLPTODP( dc, bottom );
left = dc->DCOrgX + XLPTODP( dc, left );
right = dc->DCOrgX + XLPTODP( dc, right );
top = dc->DCOrgY + YLPTODP( dc, top );
bottom = dc->DCOrgY + YLPTODP( dc, bottom );
TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
ret = CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
if (!(tempRgn = CreateRectRgn( left, top, right, bottom ))) ret = ERROR;
else
{
ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_AND );
DeleteObject( tempRgn );
}
if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
GDI_ReleaseObj( hdc );
return ret;
}
@ -562,13 +506,13 @@ INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
HRGN16 WINAPI SaveVisRgn16( HDC16 hdc )
{
HRGN copy;
RGNOBJ *obj, *copyObj;
GDIOBJHDR *obj, *copyObj;
DC *dc = DC_GetDCUpdate( hdc );
if (!dc) return 0;
TRACE("%04x\n", hdc );
if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC )))
if (!(obj = GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC )))
{
GDI_ReleaseObj( hdc );
return 0;
@ -580,15 +524,15 @@ HRGN16 WINAPI SaveVisRgn16( HDC16 hdc )
return 0;
}
CombineRgn( copy, dc->hVisRgn, 0, RGN_COPY );
if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
if (!(copyObj = GDI_GetObjPtr( copy, REGION_MAGIC )))
{
DeleteObject( copy );
GDI_ReleaseObj( dc->hVisRgn );
GDI_ReleaseObj( hdc );
return 0;
}
copyObj->header.hNext = obj->header.hNext;
obj->header.hNext = copy;
copyObj->hNext = obj->hNext;
obj->hNext = copy;
GDI_ReleaseObj( copy );
GDI_ReleaseObj( dc->hVisRgn );
GDI_ReleaseObj( hdc );
@ -602,25 +546,27 @@ HRGN16 WINAPI SaveVisRgn16( HDC16 hdc )
INT16 WINAPI RestoreVisRgn16( HDC16 hdc )
{
HRGN saved;
RGNOBJ *obj, *savedObj;
GDIOBJHDR *obj, *savedObj;
DC *dc = DC_GetDCPtr( hdc );
INT16 ret = ERROR;
if (!dc) return ERROR;
if (!dc->hVisRgn) goto done;
if (!dc) return ERROR;
TRACE("%04x\n", hdc );
if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC ))) goto done;
saved = obj->header.hNext;
if (!(obj = GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC ))) goto done;
saved = obj->hNext;
if ((savedObj = GDI_GetObjPtr( saved, REGION_MAGIC )))
{
ret = CombineRgn( dc->hVisRgn, saved, 0, RGN_COPY );
obj->hNext = savedObj->hNext;
GDI_ReleaseObj( saved );
DeleteObject( saved );
dc->flags &= ~DC_DIRTY;
CLIPPING_UpdateGCRegion( dc );
}
GDI_ReleaseObj( dc->hVisRgn );
if (!saved || !(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC ))) goto done;
DeleteObject( dc->hVisRgn );
dc->hVisRgn = saved;
dc->flags &= ~DC_DIRTY;
CLIPPING_UpdateGCRegion( dc );
ret = savedObj->rgn->type; /* FIXME */
GDI_ReleaseObj( saved );
done:
GDI_ReleaseObj( hdc );
return ret;

View File

@ -897,7 +897,7 @@ BOOL WINAPI DeleteObject( HGDIOBJ obj )
case FONT_MAGIC: return FONT_DeleteObject( obj, (FONTOBJ*)header );
case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
case BITMAP_MAGIC: return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
case REGION_MAGIC: return REGION_DeleteObject( obj, (RGNOBJ*)header );
case REGION_MAGIC: return REGION_DeleteObject( obj, (struct _RGNOBJ*)header );
case DC_MAGIC:
GDI_ReleaseObj( obj );
return DeleteDC(obj);

View File

@ -104,6 +104,21 @@ SOFTWARE.
WINE_DEFAULT_DEBUG_CHANNEL(region);
typedef struct {
INT size;
INT numRects;
RECT *rects;
RECT extents;
} WINEREGION;
/* GDI logical region object */
typedef struct _RGNOBJ
{
GDIOBJHDR header;
WINEREGION *rgn;
} RGNOBJ;
/* 1 if two RECTs overlap.
* 0 if two RECTs do not overlap.
*/
@ -134,7 +149,6 @@ static inline int xmemcheck(WINEREGION *reg, LPRECT *rect, LPRECT *firstrect ) {
(pReg)->numRects = 0; \
(pReg)->extents.left = (pReg)->extents.top = 0; \
(pReg)->extents.right = (pReg)->extents.bottom = 0; \
(pReg)->type = NULLREGION; \
}
#define REGION_NOT_EMPTY(pReg) pReg->numRects
@ -423,6 +437,21 @@ static void REGION_UnionRectWithRegion(const RECT *rect, WINEREGION *rgn);
#define RGN_DEFAULT_RECTS 2
/***********************************************************************
* get_region_type
*/
inline static INT get_region_type( const RGNOBJ *obj )
{
switch(obj->rgn->numRects)
{
case 0: return NULLREGION;
case 1: return SIMPLEREGION;
default: return COMPLEXREGION;
}
}
/***********************************************************************
* REGION_DumpRegion
* Outputs the contents of a WINEREGION
@ -542,7 +571,7 @@ INT WINAPI OffsetRgn( HRGN hrgn, INT x, INT y )
obj->rgn->extents.bottom += y;
}
}
ret = obj->rgn->type;
ret = get_region_type( obj );
GDI_ReleaseObj( hrgn );
return ret;
}
@ -573,7 +602,7 @@ INT WINAPI GetRgnBox( HRGN hrgn, LPRECT rect )
rect->top = obj->rgn->extents.top;
rect->right = obj->rgn->extents.right;
rect->bottom = obj->rgn->extents.bottom;
ret = obj->rgn->type;
ret = get_region_type( obj );
GDI_ReleaseObj(hrgn);
return ret;
}
@ -671,8 +700,7 @@ BOOL WINAPI SetRectRgn( HRGN hrgn, INT left, INT top,
obj->rgn->rects->top = obj->rgn->extents.top = top;
obj->rgn->rects->right = obj->rgn->extents.right = right;
obj->rgn->rects->bottom = obj->rgn->extents.bottom = bottom;
obj->rgn->numRects = 1;
obj->rgn->type = SIMPLEREGION;
obj->rgn->numRects = 1;
}
else
EMPTY_REGION(obj->rgn);
@ -804,7 +832,6 @@ HRGN WINAPI CreateRoundRectRgn( INT left, INT top,
rect.bottom = bottom;
REGION_UnionRectWithRegion( &rect, obj->rgn );
}
obj->rgn->type = SIMPLEREGION; /* FIXME? */
GDI_ReleaseObj( hrgn );
return hrgn;
}
@ -1091,10 +1118,10 @@ BOOL WINAPI EqualRgn( HRGN hrgn1, HRGN hrgn2 )
}
return ret;
}
/***********************************************************************
* REGION_UnionRectWithRegion
* Adds a rectangle to a WINEREGION
* See below for REGION_UnionRectWithRgn
*/
static void REGION_UnionRectWithRegion(const RECT *rect, WINEREGION *rgn)
{
@ -1103,26 +1130,10 @@ static void REGION_UnionRectWithRegion(const RECT *rect, WINEREGION *rgn)
region.rects = &region.extents;
region.numRects = 1;
region.size = 1;
region.type = SIMPLEREGION;
region.extents = *rect;
REGION_UnionRegion(rgn, rgn, &region);
return;
}
/***********************************************************************
* REGION_UnionRectWithRgn
* Adds a rectangle to a HRGN
* A helper used by scroll.c
*/
BOOL REGION_UnionRectWithRgn( HRGN hrgn, const RECT *lpRect )
{
RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
if(!obj) return FALSE;
REGION_UnionRectWithRegion( lpRect, obj->rgn );
GDI_ReleaseObj(hrgn);
return TRUE;
}
/***********************************************************************
* REGION_CreateFrameRgn
@ -1163,66 +1174,7 @@ BOOL REGION_FrameRgn( HRGN hDest, HRGN hSrc, INT x, INT y )
return bRet;
}
/***********************************************************************
* REGION_LPTODP
*
* Convert region to device co-ords for the supplied dc.
*/
BOOL REGION_LPTODP( HDC hdc, HRGN hDest, HRGN hSrc )
{
RECT *pCurRect, *pEndRect;
RGNOBJ *srcObj, *destObj;
DC * dc = DC_GetDCPtr( hdc );
RECT tmpRect;
BOOL ret = FALSE;
TRACE(" hdc=%04x dest=%04x src=%04x\n",
hdc, hDest, hSrc) ;
if (!dc) return ret;
if (dc->MapMode == MM_TEXT) /* Requires only a translation */
{
if( CombineRgn( hDest, hSrc, 0, RGN_COPY ) == ERROR ) goto done;
OffsetRgn( hDest, dc->vportOrgX - dc->wndOrgX,
dc->vportOrgY - dc->wndOrgY );
ret = TRUE;
goto done;
}
if(!( srcObj = (RGNOBJ *) GDI_GetObjPtr( hSrc, REGION_MAGIC) ))
goto done;
if(!( destObj = (RGNOBJ *) GDI_GetObjPtr( hDest, REGION_MAGIC) ))
{
GDI_ReleaseObj( hSrc );
goto done;
}
EMPTY_REGION( destObj->rgn );
pEndRect = srcObj->rgn->rects + srcObj->rgn->numRects;
for(pCurRect = srcObj->rgn->rects; pCurRect < pEndRect; pCurRect++)
{
tmpRect = *pCurRect;
tmpRect.left = XLPTODP( dc, tmpRect.left );
tmpRect.top = YLPTODP( dc, tmpRect.top );
tmpRect.right = XLPTODP( dc, tmpRect.right );
tmpRect.bottom = YLPTODP( dc, tmpRect.bottom );
if (tmpRect.left > tmpRect.right)
{ INT tmp = tmpRect.left; tmpRect.left = tmpRect.right; tmpRect.right = tmp; }
if (tmpRect.top > tmpRect.bottom)
{ INT tmp = tmpRect.top; tmpRect.top = tmpRect.bottom; tmpRect.bottom = tmp; }
REGION_UnionRectWithRegion( &tmpRect, destObj->rgn );
}
ret = TRUE;
GDI_ReleaseObj( hDest );
GDI_ReleaseObj( hSrc );
done:
GDI_ReleaseObj( hdc );
return ret;
}
/***********************************************************************
* CombineRgn (GDI.47)
*/
@ -1256,7 +1208,7 @@ INT WINAPI CombineRgn(HRGN hDest, HRGN hSrc1, HRGN hSrc2, INT mode)
if (mode == RGN_COPY)
{
REGION_CopyRegion( destObj->rgn, src1Obj->rgn );
result = destObj->rgn->type;
result = get_region_type( destObj );
}
else
{
@ -1282,7 +1234,7 @@ INT WINAPI CombineRgn(HRGN hDest, HRGN hSrc1, HRGN hSrc2, INT mode)
REGION_SubtractRegion( destObj->rgn, src1Obj->rgn, src2Obj->rgn );
break;
}
result = destObj->rgn->type;
result = get_region_type( destObj );
GDI_ReleaseObj( hSrc2 );
}
}
@ -1361,8 +1313,6 @@ static void REGION_CopyRegion(WINEREGION *dst, WINEREGION *src)
dst->extents.top = src->extents.top;
dst->extents.right = src->extents.right;
dst->extents.bottom = src->extents.bottom;
dst->type = src->type;
memcpy((char *) dst->rects, (char *) src->rects,
(int) (src->numRects * sizeof(RECT)));
}
@ -1892,10 +1842,6 @@ static void REGION_IntersectRegion(WINEREGION *newReg, WINEREGION *reg1,
* due to coalescing, so we have to examine fewer rectangles.
*/
REGION_SetExtents(newReg);
newReg->type = (newReg->numRects) ?
((newReg->numRects > 1) ? COMPLEXREGION : SIMPLEREGION)
: NULLREGION ;
return;
}
/***********************************************************************
@ -2071,10 +2017,6 @@ static void REGION_UnionRegion(WINEREGION *newReg, WINEREGION *reg1,
newReg->extents.top = min(reg1->extents.top, reg2->extents.top);
newReg->extents.right = max(reg1->extents.right, reg2->extents.right);
newReg->extents.bottom = max(reg1->extents.bottom, reg2->extents.bottom);
newReg->type = (newReg->numRects) ?
((newReg->numRects > 1) ? COMPLEXREGION : SIMPLEREGION)
: NULLREGION ;
return;
}
/***********************************************************************
@ -2279,10 +2221,6 @@ static void REGION_SubtractRegion(WINEREGION *regD, WINEREGION *regM,
* due to coalescing, so we have to examine fewer rectangles.
*/
REGION_SetExtents (regD);
regD->type = (regD->numRects) ?
((regD->numRects > 1) ? COMPLEXREGION : SIMPLEREGION)
: NULLREGION ;
return;
}
/***********************************************************************
@ -2876,9 +2814,6 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
}
REGION_FreeStorage(SLLBlock.next);
REGION_PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
region->type = (region->numRects) ?
((region->numRects > 1) ? COMPLEXREGION : SIMPLEREGION)
: NULLREGION;
for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
tmpPtBlock = curPtBlock->next;
@ -3120,8 +3055,6 @@ empty:
rgnDst->extents.top = rgnDst->rects[0].top;
rgnDst->extents.bottom = rgnDst->rects[j].bottom;
rgnDst->type = (j >= 1) ? COMPLEXREGION : SIMPLEREGION;
if( TRACE_ON(region) )
{
TRACE("result:\n");

View File

@ -35,7 +35,6 @@
#include "dce.h"
#include "win.h"
#include "gdi.h"
#include "region.h"
#include "user.h"
#include "wine/debug.h"
#include "windef.h"

View File

@ -28,7 +28,6 @@
#include "wine/server.h"
#include "controls.h"
#include "user.h"
#include "region.h"
#include "win.h"
#include "hook.h"
#include "message.h"