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