gdi32: Add a test for ExtCreateRegion, make it pass under Wine
Dmitry Timoshkov
dmitry at codeweavers.com
Fri Apr 18 08:42:43 CDT 2008
Hello,
Changelog:
gdi32: Add a test for ExtCreateRegion, make it pass under Wine.
---
dlls/gdi32/region.c | 61 +++++++++++++++++---
dlls/gdi32/tests/clipping.c | 136 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 189 insertions(+), 8 deletions(-)
diff --git a/dlls/gdi32/region.c b/dlls/gdi32/region.c
index d0d8580..c9b9e1d 100644
--- a/dlls/gdi32/region.c
+++ b/dlls/gdi32/region.c
@@ -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.@)
*
@@ -1008,16 +1021,47 @@ HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA*
TRACE(" %p %d %p\n", lpXform, dwCount, rgndata );
- if( lpXform )
- WARN("(Xform not implemented - ignored)\n");
+ if (!rgndata)
+ {
+ 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 )
+ WARN("(Unsupported region data type: %u)\n", rgndata->rdh.iType);
+
+ if (lpXform)
{
- /* FIXME: We can use CreatePolyPolygonRgn() here
- * for trapezoidal data */
+ RECT *pCurRect, *pEndRect;
- WARN("(Unsupported region data type: %u)\n", rgndata->rdh.iType);
- goto fail;
+ hrgn = CreateRectRgn( 0, 0, 0, 0 );
+
+ 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 )) )
@@ -1039,8 +1083,7 @@ HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA*
}
else ERR("Could not get pointer to newborn Region!\n");
}
-fail:
- WARN("Failed\n");
+
return 0;
}
@@ -2743,6 +2786,8 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count,
int numFullPtBlocks = 0;
INT poly, total;
+ TRACE("%p, count %d, polygons %d, mode %d\n", Pts, *Count, nbpolygons, mode);
+
if(!(hrgn = REGION_CreateRegion(nbpolygons)))
return 0;
obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
diff --git a/dlls/gdi32/tests/clipping.c b/dlls/gdi32/tests/clipping.c
index 5e1d35f..25cc146 100644
--- a/dlls/gdi32/tests/clipping.c
+++ b/dlls/gdi32/tests/clipping.c
@@ -119,7 +119,143 @@ static void test_GetRandomRgn(void)
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)
{
test_GetRandomRgn();
+ test_ExtCreateRegion();
}
--
1.5.4.5
More information about the wine-patches
mailing list