Added support for the DC meta region.
diff --git a/dlls/gdi/clipping.c b/dlls/gdi/clipping.c
index 0b98b46..0f69be7 100644
--- a/dlls/gdi/clipping.c
+++ b/dlls/gdi/clipping.c
@@ -33,12 +33,27 @@
/***********************************************************************
+ * get_clip_region
+ *
+ * Return the total clip region (if any).
+ */
+static inline HRGN get_clip_region( DC * dc )
+{
+ if (dc->hMetaClipRgn) return dc->hMetaClipRgn;
+ if (dc->hMetaRgn) return dc->hMetaRgn;
+ return dc->hClipRgn;
+}
+
+
+/***********************************************************************
* CLIPPING_UpdateGCRegion
*
* Update the GC clip region when the ClipRgn or VisRgn have changed.
*/
void CLIPPING_UpdateGCRegion( DC * dc )
{
+ HRGN clip_rgn;
+
if (!dc->hVisRgn)
{
ERR("hVisRgn is zero. Please report this.\n" );
@@ -47,12 +62,26 @@
if (dc->flags & DC_DIRTY) ERR( "DC is dirty. Please report this.\n" );
+ /* update the intersection of meta and clip regions */
+ if (dc->hMetaRgn && dc->hClipRgn)
+ {
+ if (!dc->hMetaClipRgn) dc->hMetaClipRgn = CreateRectRgn( 0, 0, 0, 0 );
+ CombineRgn( dc->hMetaClipRgn, dc->hClipRgn, dc->hMetaRgn, RGN_AND );
+ clip_rgn = dc->hMetaClipRgn;
+ }
+ else /* only one is set, no need for an intersection */
+ {
+ if (dc->hMetaClipRgn) DeleteObject( dc->hMetaClipRgn );
+ dc->hMetaClipRgn = 0;
+ clip_rgn = dc->hMetaRgn ? dc->hMetaRgn : dc->hClipRgn;
+ }
+
if (dc->funcs->pSetDeviceClipping)
- dc->funcs->pSetDeviceClipping( dc->physDev, dc->hVisRgn, dc->hClipRgn );
+ dc->funcs->pSetDeviceClipping( dc->physDev, dc->hVisRgn, clip_rgn );
}
/***********************************************************************
- * create_default_clip_rgn
+ * create_default_clip_region
*
* Create a default clipping region when none already exists.
*/
@@ -346,6 +375,7 @@
{
POINT pt;
BOOL ret;
+ HRGN clip;
DC *dc = DC_GetDCUpdate( hdc );
TRACE("%p %d,%d\n", hdc, x, y );
@@ -355,7 +385,7 @@
pt.y = y;
LPtoDP( hdc, &pt, 1 );
ret = PtInRegion( dc->hVisRgn, pt.x, pt.y );
- if (ret && dc->hClipRgn) ret = PtInRegion( dc->hClipRgn, pt.x, pt.y );
+ if (ret && (clip = get_clip_region(dc))) ret = PtInRegion( clip, pt.x, pt.y );
GDI_ReleaseObj( hdc );
return ret;
}
@@ -368,6 +398,7 @@
{
RECT tmpRect;
BOOL ret;
+ HRGN clip;
DC *dc = DC_GetDCUpdate( hdc );
if (!dc) return FALSE;
TRACE("%p %ld,%ldx%ld,%ld\n", hdc, rect->left, rect->top, rect->right, rect->bottom );
@@ -375,10 +406,10 @@
tmpRect = *rect;
LPtoDP( hdc, (POINT *)&tmpRect, 2 );
- if (dc->hClipRgn)
+ if ((clip = get_clip_region(dc)))
{
HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
- CombineRgn( hrgn, dc->hVisRgn, dc->hClipRgn, RGN_AND );
+ CombineRgn( hrgn, dc->hVisRgn, clip, RGN_AND );
ret = RectInRegion( hrgn, &tmpRect );
DeleteObject( hrgn );
}
@@ -394,12 +425,13 @@
INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
{
INT ret;
+ HRGN clip;
DC *dc = DC_GetDCUpdate( hdc );
if (!dc) return ERROR;
- if (dc->hClipRgn)
+ if ((clip = get_clip_region(dc)))
{
HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
- CombineRgn( hrgn, dc->hVisRgn, dc->hClipRgn, RGN_AND );
+ CombineRgn( hrgn, dc->hVisRgn, clip, RGN_AND );
ret = GetRgnBox( hrgn, rect );
DeleteObject( hrgn );
}
@@ -429,6 +461,25 @@
return ret;
}
+
+/***********************************************************************
+ * GetMetaRgn (GDI32.@)
+ */
+INT WINAPI GetMetaRgn( HDC hdc, HRGN hRgn )
+{
+ INT ret = 0;
+ DC * dc = DC_GetDCPtr( hdc );
+
+ if (dc)
+ {
+ if (dc->hMetaRgn && CombineRgn( hRgn, dc->hMetaRgn, 0, RGN_COPY ) != ERROR)
+ ret = 1;
+ GDI_ReleaseObj( hdc );
+ }
+ return ret;
+}
+
+
/***********************************************************************
* SaveVisRgn (GDI.129)
*/
@@ -500,50 +551,41 @@
*/
INT WINAPI GetRandomRgn(HDC hDC, HRGN hRgn, INT iCode)
{
+ HRGN rgn;
+ DC *dc = DC_GetDCPtr( hDC );
+
+ if (!dc) return -1;
+
switch (iCode)
{
+ case 1:
+ rgn = dc->hClipRgn;
+ break;
+ case 2:
+ rgn = dc->hMetaRgn;
+ break;
+ case 3:
+ rgn = dc->hMetaClipRgn;
+ break;
case SYSRGN: /* == 4 */
- {
- DC *dc = DC_GetDCPtr (hDC);
- if (!dc) return -1;
-
- CombineRgn (hRgn, dc->hVisRgn, 0, RGN_COPY);
- GDI_ReleaseObj( hDC );
- /*
- * On Windows NT/2000,
- * the region returned is in screen coordinates.
- * On Windows 95/98,
- * the region returned is in window coordinates
- */
- if (!(GetVersion() & 0x80000000))
- {
- POINT org;
- GetDCOrgEx(hDC, &org);
- OffsetRgn(hRgn, org.x, org.y);
- }
- return 1;
- }
-
- case 1: /* clip region */
- return GetClipRgn (hDC, hRgn);
-
+ rgn = dc->hVisRgn;
+ break;
default:
- WARN("Unknown iCode %d\n", iCode);
+ WARN("Unknown code %d\n", iCode);
+ GDI_ReleaseObj( hDC );
return -1;
}
+ if (rgn) CombineRgn( hRgn, rgn, 0, RGN_COPY );
+ GDI_ReleaseObj( hDC );
- return -1;
-}
-
-
-/***********************************************************************
- * GetMetaRgn (GDI32.@)
- */
-INT WINAPI GetMetaRgn( HDC hdc, HRGN hRgn )
-{
- FIXME( "stub\n" );
-
- return 0;
+ /* On Windows NT/2000, the region returned is in screen coordinates */
+ if (!(GetVersion() & 0x80000000))
+ {
+ POINT org;
+ GetDCOrgEx( hDC, &org );
+ OffsetRgn( hRgn, org.x, org.y );
+ }
+ return (rgn != 0);
}
@@ -552,7 +594,31 @@
*/
INT WINAPI SetMetaRgn( HDC hdc )
{
- FIXME( "stub\n" );
+ INT ret;
+ RECT dummy;
+ DC *dc = DC_GetDCPtr( hdc );
- return ERROR;
+ if (!dc) return ERROR;
+
+ if (dc->hMetaClipRgn)
+ {
+ /* the intersection becomes the new meta region */
+ DeleteObject( dc->hMetaRgn );
+ DeleteObject( dc->hClipRgn );
+ dc->hMetaRgn = dc->hMetaClipRgn;
+ dc->hClipRgn = 0;
+ dc->hMetaClipRgn = 0;
+ }
+ else if (dc->hClipRgn)
+ {
+ dc->hMetaRgn = dc->hClipRgn;
+ dc->hClipRgn = 0;
+ }
+ /* else nothing to do */
+
+ /* Note: no need to call CLIPPING_UpdateGCRegion, the overall clip region hasn't changed */
+
+ ret = GetRgnBox( dc->hMetaRgn, &dummy );
+ GDI_ReleaseObj( hdc );
+ return ret;
}
diff --git a/dlls/gdi/dc.c b/dlls/gdi/dc.c
index 90b84f4..077ec53 100644
--- a/dlls/gdi/dc.c
+++ b/dlls/gdi/dc.c
@@ -80,6 +80,8 @@
dc->flags = 0;
dc->layout = 0;
dc->hClipRgn = 0;
+ dc->hMetaRgn = 0;
+ dc->hMetaClipRgn = 0;
dc->hVisRgn = 0;
dc->hPen = GetStockObject( BLACK_PEN );
dc->hBrush = GetStockObject( WHITE_BRUSH );
@@ -347,14 +349,21 @@
/* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
- newdc->hVisRgn = 0;
+ newdc->hVisRgn = 0;
+ newdc->hClipRgn = 0;
+ newdc->hMetaRgn = 0;
+ newdc->hMetaClipRgn = 0;
if (dc->hClipRgn)
{
- newdc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
- CombineRgn( newdc->hClipRgn, dc->hClipRgn, 0, RGN_COPY );
+ newdc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
+ CombineRgn( newdc->hClipRgn, dc->hClipRgn, 0, RGN_COPY );
}
- else
- newdc->hClipRgn = 0;
+ if (dc->hMetaRgn)
+ {
+ newdc->hMetaRgn = CreateRectRgn( 0, 0, 0, 0 );
+ CombineRgn( newdc->hMetaRgn, dc->hMetaRgn, 0, RGN_COPY );
+ }
+ /* don't bother recomputing hMetaClipRgn, we'll do that in SetDCState */
if(dc->gdiFont) {
newdc->gdiFont = dc->gdiFont;
@@ -436,6 +445,16 @@
if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
dc->hClipRgn = 0;
}
+ if (dcs->hMetaRgn)
+ {
+ if (!dc->hMetaRgn) dc->hMetaRgn = CreateRectRgn( 0, 0, 0, 0 );
+ CombineRgn( dc->hMetaRgn, dcs->hMetaRgn, 0, RGN_COPY );
+ }
+ else
+ {
+ if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
+ dc->hMetaRgn = 0;
+ }
CLIPPING_UpdateGCRegion( dc );
SelectObject( hdc, dcs->hBitmap );
@@ -777,6 +796,8 @@
dc->saved_dc = dcs->saved_dc;
dc->saveLevel--;
if (dcs->hClipRgn) DeleteObject( dcs->hClipRgn );
+ if (dcs->hMetaRgn) DeleteObject( dcs->hMetaRgn );
+ if (dcs->hMetaClipRgn) DeleteObject( dcs->hMetaClipRgn );
if (dcs->hVisRgn) DeleteObject( dcs->hVisRgn );
PATH_DestroyGdiPath(&dcs->path);
GDI_FreeObject( hdcs, dcs );
@@ -801,6 +822,8 @@
dc->saved_visrgn = next;
}
if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
+ if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
+ if (dc->hMetaClipRgn) DeleteObject( dc->hMetaClipRgn );
if (dc->hVisRgn) DeleteObject( dc->hVisRgn );
PATH_DestroyGdiPath(&dc->path);
diff --git a/dlls/gdi/gdi_private.h b/dlls/gdi/gdi_private.h
index a7717bc..fc71da3 100644
--- a/dlls/gdi/gdi_private.h
+++ b/dlls/gdi/gdi_private.h
@@ -229,8 +229,10 @@
int flags;
DWORD layout;
- HRGN hClipRgn; /* Clip region (may be 0) */
- HRGN hVisRgn; /* Visible region (must never be 0) */
+ HRGN hClipRgn; /* Clip region (may be 0) */
+ HRGN hMetaRgn; /* Meta region (may be 0) */
+ HRGN hMetaClipRgn; /* Intersection of meta and clip regions (may be 0) */
+ HRGN hVisRgn; /* Visible region (must never be 0) */
HPEN hPen;
HBRUSH hBrush;
HFONT hFont;