Commit f52b92ef authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Alexandre Julliard

gdi32: Add a test for ExtCreateRegion, make it pass under Wine.

parent ae9fe5e3
...@@ -985,6 +985,19 @@ DWORD WINAPI GetRegionData(HRGN hrgn, DWORD count, LPRGNDATA rgndata) ...@@ -985,6 +985,19 @@ DWORD WINAPI GetRegionData(HRGN hrgn, DWORD count, LPRGNDATA rgndata)
} }
static void translate( POINT *pt, UINT count, const XFORM *xform )
{
while (count--)
{
FLOAT x = pt->x;
FLOAT y = pt->y;
pt->x = floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
pt->y = floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
pt++;
}
}
/*********************************************************************** /***********************************************************************
* ExtCreateRegion (GDI32.@) * ExtCreateRegion (GDI32.@)
* *
...@@ -1008,16 +1021,47 @@ HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA* ...@@ -1008,16 +1021,47 @@ HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA*
TRACE(" %p %d %p\n", lpXform, dwCount, rgndata ); TRACE(" %p %d %p\n", lpXform, dwCount, rgndata );
if( lpXform ) if (!rgndata)
WARN("(Xform not implemented - ignored)\n"); {
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
if (rgndata->rdh.dwSize < sizeof(RGNDATAHEADER))
return 0;
/* XP doesn't care about the type */
if( rgndata->rdh.iType != RDH_RECTANGLES ) if( rgndata->rdh.iType != RDH_RECTANGLES )
WARN("(Unsupported region data type: %u)\n", rgndata->rdh.iType);
if (lpXform)
{ {
/* FIXME: We can use CreatePolyPolygonRgn() here RECT *pCurRect, *pEndRect;
* for trapezoidal data */
WARN("(Unsupported region data type: %u)\n", rgndata->rdh.iType); hrgn = CreateRectRgn( 0, 0, 0, 0 );
goto fail;
pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
for (pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
{
static const INT count = 4;
HRGN poly_hrgn;
POINT pt[4];
pt[0].x = pCurRect->left;
pt[0].y = pCurRect->top;
pt[1].x = pCurRect->right;
pt[1].y = pCurRect->top;
pt[2].x = pCurRect->right;
pt[2].y = pCurRect->bottom;
pt[3].x = pCurRect->left;
pt[3].y = pCurRect->bottom;
translate( pt, 4, lpXform );
poly_hrgn = CreatePolyPolygonRgn( pt, &count, 1, WINDING );
CombineRgn( hrgn, hrgn, poly_hrgn, RGN_OR );
DeleteObject( poly_hrgn );
}
return hrgn;
} }
if( (hrgn = REGION_CreateRegion( rgndata->rdh.nCount )) ) if( (hrgn = REGION_CreateRegion( rgndata->rdh.nCount )) )
...@@ -1039,8 +1083,7 @@ HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA* ...@@ -1039,8 +1083,7 @@ HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA*
} }
else ERR("Could not get pointer to newborn Region!\n"); else ERR("Could not get pointer to newborn Region!\n");
} }
fail:
WARN("Failed\n");
return 0; return 0;
} }
...@@ -2743,6 +2786,8 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count, ...@@ -2743,6 +2786,8 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
int numFullPtBlocks = 0; int numFullPtBlocks = 0;
INT poly, total; INT poly, total;
TRACE("%p, count %d, polygons %d, mode %d\n", Pts, *Count, nbpolygons, mode);
if(!(hrgn = REGION_CreateRegion(nbpolygons))) if(!(hrgn = REGION_CreateRegion(nbpolygons)))
return 0; return 0;
obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ); obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
......
...@@ -119,7 +119,143 @@ static void test_GetRandomRgn(void) ...@@ -119,7 +119,143 @@ static void test_GetRandomRgn(void)
DestroyWindow(hwnd); DestroyWindow(hwnd);
} }
static void verify_region(HRGN hrgn, const RECT *rc)
{
union
{
RGNDATA data;
char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
} rgn;
const RECT *rect;
DWORD ret;
ret = GetRegionData(hrgn, 0, NULL);
if (IsRectEmpty(rc))
ok(ret == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", ret);
else
ok(ret == sizeof(rgn.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
if (!ret) return;
ret = GetRegionData(hrgn, sizeof(rgn), &rgn.data);
if (IsRectEmpty(rc))
ok(ret == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", ret);
else
ok(ret == sizeof(rgn.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret);
trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n",
rgn.data.rdh.dwSize, rgn.data.rdh.iType,
rgn.data.rdh.nCount, rgn.data.rdh.nRgnSize,
rgn.data.rdh.rcBound.left, rgn.data.rdh.rcBound.top,
rgn.data.rdh.rcBound.right, rgn.data.rdh.rcBound.bottom);
if (rgn.data.rdh.nCount != 0)
{
rect = (const RECT *)rgn.data.Buffer;
trace("rect (%d,%d-%d,%d)\n", rect->left, rect->top, rect->right, rect->bottom);
ok(EqualRect(rect, rc), "rects don't match\n");
}
ok(rgn.data.rdh.dwSize == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u", rgn.data.rdh.dwSize);
ok(rgn.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn.data.rdh.iType);
if (IsRectEmpty(rc))
{
ok(rgn.data.rdh.nCount == 0, "expected 0, got %u\n", rgn.data.rdh.nCount);
ok(rgn.data.rdh.nRgnSize == 0, "expected 0, got %u\n", rgn.data.rdh.nRgnSize);
}
else
{
ok(rgn.data.rdh.nCount == 1, "expected 1, got %u\n", rgn.data.rdh.nCount);
ok(rgn.data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn.data.rdh.nRgnSize);
}
ok(EqualRect(&rgn.data.rdh.rcBound, rc), "rects don't match\n");
}
static void test_ExtCreateRegion(void)
{
static const RECT empty_rect;
static const RECT rc = { 111, 222, 333, 444 };
static const RECT rc_xformed = { 76, 151, 187, 262 };
union
{
RGNDATA data;
char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
} rgn;
HRGN hrgn;
XFORM xform;
if (0) /* crashes under Win9x */
{
SetLastError(0xdeadbeef);
hrgn = ExtCreateRegion(NULL, 0, NULL);
ok(!hrgn, "ExtCreateRegion should fail\n");
ok(GetLastError() == ERROR_INVALID_PARAMETER, "ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
}
rgn.data.rdh.dwSize = 0;
rgn.data.rdh.iType = 0;
rgn.data.rdh.nCount = 0;
rgn.data.rdh.nRgnSize = 0;
SetRectEmpty(&rgn.data.rdh.rcBound);
memcpy(rgn.data.Buffer, &rc, sizeof(rc));
SetLastError(0xdeadbeef);
hrgn = ExtCreateRegion(NULL, sizeof(rgn), &rgn.data);
ok(!hrgn, "ExtCreateRegion should fail\n");
ok(GetLastError() == 0xdeadbeef, "0xdeadbeef, got %u\n", GetLastError());
rgn.data.rdh.dwSize = sizeof(rgn.data.rdh) - 1;
SetLastError(0xdeadbeef);
hrgn = ExtCreateRegion(NULL, sizeof(rgn), &rgn.data);
ok(!hrgn, "ExtCreateRegion should fail\n");
ok(GetLastError() == 0xdeadbeef, "0xdeadbeef, got %u\n", GetLastError());
/* although XP doesn't care about the type Win9x does */
rgn.data.rdh.iType = RDH_RECTANGLES;
rgn.data.rdh.dwSize = sizeof(rgn.data.rdh);
SetLastError(0xdeadbeef);
hrgn = ExtCreateRegion(NULL, sizeof(rgn), &rgn.data);
ok(hrgn != 0, "ExtCreateRegion error %u\n", GetLastError());
verify_region(hrgn, &empty_rect);
DeleteObject(hrgn);
rgn.data.rdh.nCount = 1;
SetRectEmpty(&rgn.data.rdh.rcBound);
memcpy(rgn.data.Buffer, &rc, sizeof(rc));
SetLastError(0xdeadbeef);
hrgn = ExtCreateRegion(NULL, sizeof(rgn), &rgn.data);
ok(hrgn != 0, "ExtCreateRegion error %u\n", GetLastError());
verify_region(hrgn, &rc);
DeleteObject(hrgn);
rgn.data.rdh.dwSize = sizeof(rgn.data.rdh) + 1;
SetLastError(0xdeadbeef);
hrgn = ExtCreateRegion(NULL, 1, &rgn.data);
ok(hrgn != 0, "ExtCreateRegion error %u\n", GetLastError());
verify_region(hrgn, &rc);
DeleteObject(hrgn);
xform.eM11 = 0.5; /* 50% width */
xform.eM12 = 0.0;
xform.eM21 = 0.0;
xform.eM22 = 0.5; /* 50% height */
xform.eDx = 20.0;
xform.eDy = 40.0;
rgn.data.rdh.dwSize = sizeof(rgn.data.rdh);
SetLastError(0xdeadbeef);
hrgn = ExtCreateRegion(&xform, sizeof(rgn), &rgn.data);
ok(hrgn != 0, "ExtCreateRegion error %u/%x\n", GetLastError(), GetLastError());
verify_region(hrgn, &rc_xformed);
DeleteObject(hrgn);
}
START_TEST(clipping) START_TEST(clipping)
{ {
test_GetRandomRgn(); test_GetRandomRgn();
test_ExtCreateRegion();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment