Andrew Eikum : gdiplus: Support regions of more than one rectangle in GdipCreateRegionHrgn.

Alexandre Julliard julliard at winehq.org
Tue Aug 25 08:44:03 CDT 2009


Module: wine
Branch: master
Commit: 9ec5f9ad6fb97deaa443ce68ce4ca67c4b2f7298
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9ec5f9ad6fb97deaa443ce68ce4ca67c4b2f7298

Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Mon Aug 24 16:49:31 2009 -0500

gdiplus: Support regions of more than one rectangle in GdipCreateRegionHrgn.

---

 dlls/gdiplus/region.c       |   66 +++++++++++++++++++++++++-----------------
 dlls/gdiplus/tests/region.c |   14 ++++-----
 2 files changed, 45 insertions(+), 35 deletions(-)

diff --git a/dlls/gdiplus/region.c b/dlls/gdiplus/region.c
index 039e789..ce6b60d 100644
--- a/dlls/gdiplus/region.c
+++ b/dlls/gdiplus/region.c
@@ -579,51 +579,63 @@ GpStatus WINGDIPAPI GdipCreateRegionRgnData(GDIPCONST BYTE *data, INT size, GpRe
  */
 GpStatus WINGDIPAPI GdipCreateRegionHrgn(HRGN hrgn, GpRegion **region)
 {
-    union {
-        RGNDATA data;
-        char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)];
-    } rdata;
     DWORD size;
-    GpRectF rectf;
-    GpPath *path;
+    LPRGNDATA buf;
+    LPRECT rect;
     GpStatus stat;
+    GpPath* path;
+    GpRegion* local;
+    int i;
 
     TRACE("(%p, %p)\n", hrgn, region);
 
     if(!region || !(size = GetRegionData(hrgn, 0, NULL)))
         return InvalidParameter;
 
-    if(size > sizeof(RGNDATAHEADER) + sizeof(RECT)){
-        FIXME("Only simple rect regions supported.\n");
-        *region = NULL;
-        return NotImplemented;
-    }
+    buf = GdipAlloc(size);
+    if(!buf)
+        return OutOfMemory;
 
-    if(!GetRegionData(hrgn, sizeof(rdata), &rdata.data))
+    if(!GetRegionData(hrgn, size, buf)){
+        GdipFree(buf);
         return GenericError;
-
-    /* return empty region */
-    if(IsRectEmpty(&rdata.data.rdh.rcBound)){
-        stat = GdipCreateRegion(region);
-        if(stat == Ok)
-            GdipSetEmpty(*region);
-        return stat;
     }
 
-    rectf.X = (REAL)rdata.data.rdh.rcBound.left;
-    rectf.Y = (REAL)rdata.data.rdh.rcBound.top;
-    rectf.Width  = (REAL)rdata.data.rdh.rcBound.right - rectf.X;
-    rectf.Height = (REAL)rdata.data.rdh.rcBound.bottom - rectf.Y;
+    if(buf->rdh.nCount == 0){
+        if((stat = GdipCreateRegion(&local)) != Ok){
+            GdipFree(buf);
+            return stat;
+        }
+        if((stat = GdipSetEmpty(local)) != Ok){
+            GdipFree(buf);
+            GdipDeleteRegion(local);
+            return stat;
+        }
+        *region = local;
+        GdipFree(buf);
+        return Ok;
+    }
 
-    stat = GdipCreatePath(FillModeAlternate, &path);
-    if(stat != Ok)
+    if((stat = GdipCreatePath(FillModeAlternate, &path)) != Ok){
+        GdipFree(buf);
         return stat;
+    }
 
-    GdipAddPathRectangle(path, rectf.X, rectf.Y, rectf.Width, rectf.Height);
+    rect = (LPRECT)buf->Buffer;
+    for(i = 0; i < buf->rdh.nCount; i++){
+        if((stat = GdipAddPathRectangle(path, (REAL)rect->left, (REAL)rect->top,
+                        (REAL)(rect->right - rect->left), (REAL)(rect->bottom - rect->top))) != Ok){
+            GdipFree(buf);
+            GdipDeletePath(path);
+            return stat;
+        }
+        rect++;
+    }
 
     stat = GdipCreateRegionPath(path, region);
-    GdipDeletePath(path);
 
+    GdipFree(buf);
+    GdipDeletePath(path);
     return stat;
 }
 
diff --git a/dlls/gdiplus/tests/region.c b/dlls/gdiplus/tests/region.c
index 8b1b04e..fddceb3 100644
--- a/dlls/gdiplus/tests/region.c
+++ b/dlls/gdiplus/tests/region.c
@@ -704,7 +704,7 @@ static void test_combinereplace(void)
 static void test_fromhrgn(void)
 {
     GpStatus status;
-    GpRegion *region;
+    GpRegion *region = (GpRegion*)0xabcdef01;
     HRGN hrgn;
     UINT needed;
     DWORD buf[220];
@@ -720,6 +720,7 @@ static void test_fromhrgn(void)
     expect(InvalidParameter, status);
     status = GdipCreateRegionHrgn((HRGN)0xdeadbeef, &region);
     expect(InvalidParameter, status);
+    ok(region == (GpRegion*)0xabcdef01, "Expected region not to be created\n");
 
     /* empty rectangle */
     hrgn = CreateRectRgn(0, 0, 0, 0);
@@ -788,21 +789,19 @@ static void test_fromhrgn(void)
     /* ellipse */
     hrgn = CreateEllipticRgn(0, 0, 100, 10);
     status = GdipCreateRegionHrgn(hrgn, &region);
-    todo_wine expect(Ok, status);
+    expect(Ok, status);
 
     status = GdipGetRegionDataSize(region, &needed);
-todo_wine{
     expect(Ok, status);
     ok(needed == 216 ||
        needed == 196, /* win98 */
        "Got %.8x\n", needed);
-}
+
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
-    todo_wine expect(Ok, status);
+    expect(Ok, status);
 
     if(status == Ok && needed == 216) /* Don't try to test win98 layout */
     {
-todo_wine{
     expect(Ok, status);
     expect(216, needed);
     expect_dword(buf, 208);
@@ -812,8 +811,7 @@ todo_wine{
     expect_dword(buf + 5, 0x000000C0);
     expect_magic((DWORD*)(buf + 6));
     expect_dword(buf + 7, 0x00000024);
-    expect_dword(buf + 8, 0x00006000); /* ?? */
-}
+    todo_wine expect_dword(buf + 8, 0x00006000); /* ?? */
     }
 
     GdipDeleteRegion(region);




More information about the wine-cvs mailing list