[try 5][Gdiplus 1/6] Implement GdipCreateRegion and mark the tests todo_wine instead of skipping over them all.

Adam Petaccia adam at tpetaccia.com
Thu Jul 24 18:01:21 CDT 2008


This patch also addresses some Valgrind warnings that will pop up once
everything is implemented.  Also, be more descriptive when we fail some tests
by using the expect() macro.

Changelog:
(try5):
    tests: Don't set buffer to 0, but 0xee.

(try4):
    Merge with what was previous patch (test todo'ing)
    Make region directly hold its node
    Use lowercase struct names and members.
    Move InitRegion to the top, and rename to init_region
    Move enumeration to region.c, as its not public.
    pathHeader->{pointCount,storageFlags} --> pathheader->{count, flags}
    numOps --> num_children
    Add const qualifier

(try3):
Fix a mistake which caused SetEmpty to be incorrectly filled out.
Remove a comment that should be added later.
---
 dlls/gdiplus/gdiplus_private.h |   38 +++++++++++++++++++++++
 dlls/gdiplus/region.c          |   60 ++++++++++++++++++++++++++++++++++--
 dlls/gdiplus/tests/region.c    |   66 +++++++++++++++++++++++++---------------
 3 files changed, 136 insertions(+), 28 deletions(-)

diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index 1b806cd..620f822 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -37,6 +37,8 @@
 #define MAX_DASHLEN (16) /* this is a limitation of gdi */
 #define INCH_HIMETRIC (2540)
 
+#define VERSION_MAGIC 0xdbc01001
+
 COLORREF ARGB2COLORREF(ARGB color);
 extern INT arc2polybezier(GpPointF * points, REAL x1, REAL y1, REAL x2, REAL y2,
     REAL startAngle, REAL sweepAngle);
@@ -199,4 +201,40 @@ struct GpFontFamily{
     WCHAR FamilyName[LF_FACESIZE];
 };
 
+typedef struct region_element
+{
+    DWORD type; /* Rectangle, Path, SpecialRectangle, or CombineMode */
+    union
+    {
+        GpRectF rect;
+        struct
+        {
+            GpPath* path;
+            struct
+            {
+                DWORD size;
+                DWORD magic;
+                DWORD count;
+                DWORD flags;
+            } pathheader;
+        } pathdata;
+        struct
+        {
+            struct region_element *left;  /* the original region */
+            struct region_element *right; /* what *left was combined with */
+        } combine;
+    } elementdata;
+} region_element;
+
+struct GpRegion{
+    struct
+    {
+        DWORD size;
+        DWORD checksum;
+        DWORD magic;
+        DWORD num_children;
+    } header;
+    region_element node;
+};
+
 #endif
diff --git a/dlls/gdiplus/region.c b/dlls/gdiplus/region.c
index fc53c86..d2997f4 100644
--- a/dlls/gdiplus/region.c
+++ b/dlls/gdiplus/region.c
@@ -73,6 +73,54 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
  *
  */
 
+typedef enum RegionType
+{
+    RegionDataRect          = 0x10000000,
+    RegionDataPath          = 0x10000001,
+    RegionDataEmptyRect     = 0x10000002,
+    RegionDataInfiniteRect  = 0x10000003,
+} RegionType;
+
+/* Header size as far as header->size is concerned. This doesn't include
+ * header->size or header->checksum
+ */
+static const INT sizeheader_size = sizeof(DWORD) * 2;
+
+static inline INT get_element_size(const region_element* element)
+{
+    INT needed = sizeof(DWORD); /* DWORD for the type */
+    switch(element->type)
+    {
+        case RegionDataRect:
+            return needed + sizeof(GpRect);
+        case RegionDataPath:
+             needed += element->elementdata.pathdata.pathheader.size;
+             needed += sizeof(DWORD); /* Extra DWORD for pathheader.size */
+             return needed;
+        case RegionDataEmptyRect:
+        case RegionDataInfiniteRect:
+            return needed;
+        default:
+            needed += get_element_size(element->elementdata.combine.left);
+            needed += get_element_size(element->elementdata.combine.right);
+            return needed;
+    }
+
+    return 0;
+}
+
+/* Does not check parameters, caller must do that */
+static inline GpStatus init_region(GpRegion* region, const RegionType type)
+{
+    region->node.type       = type;
+    region->header.checksum = 0xdeadbeef;
+    region->header.magic    = VERSION_MAGIC;
+    region->header.num_children  = 0;
+    region->header.size     = sizeheader_size + get_element_size(&region->node);
+
+    return Ok;
+}
+
 GpStatus WINGDIPAPI GdipCloneRegion(GpRegion *region, GpRegion **clone)
 {
     FIXME("(%p %p): stub\n", region, clone);
@@ -110,10 +158,16 @@ GpStatus WINGDIPAPI GdipCombineRegionRegion(GpRegion *region1, GpRegion *region2
 
 GpStatus WINGDIPAPI GdipCreateRegion(GpRegion **region)
 {
-    FIXME("(%p): stub\n", region);
+    if(!region)
+        return InvalidParameter;
 
-    *region = NULL;
-    return NotImplemented;
+    TRACE("%p\n", region);
+
+    *region = GdipAlloc(sizeof(GpRegion));
+    if(!*region)
+        return OutOfMemory;
+
+    return init_region(*region, RegionDataInfiniteRect);
 }
 
 GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **region)
diff --git a/dlls/gdiplus/tests/region.c b/dlls/gdiplus/tests/region.c
index 6b1c5f0..e3ed8ec 100644
--- a/dlls/gdiplus/tests/region.c
+++ b/dlls/gdiplus/tests/region.c
@@ -62,18 +62,19 @@ static void test_getregiondata(void)
     GpRect rect;
     GpPath *path;
 
+    memset(buf, 0xee, sizeof(buf));
+
     status = GdipCreateRegion(&region);
-todo_wine
     ok(status == Ok, "status %08x\n", status);
 
-    if(status != Ok) return;
-
+todo_wine
+{
     status = GdipGetRegionDataSize(region, &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 20, "got %d\n", needed);
+    expect(20, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 20, "got %d\n", needed);
+    expect(20, needed);
     expect_dword(buf, 12);
     trace("buf[1] = %08x\n", buf[1]);
     expect_magic((DWORD*)(buf + 2));
@@ -84,10 +85,10 @@ todo_wine
     ok(status == Ok, "status %08x\n", status);
     status = GdipGetRegionDataSize(region, &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 20, "got %d\n", needed);
+    expect(20, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 20, "got %d\n", needed);
+    expect(20, needed);
     expect_dword(buf, 12);
     trace("buf[1] = %08x\n", buf[1]);
     expect_magic((DWORD*)(buf + 2));
@@ -98,10 +99,10 @@ todo_wine
     ok(status == Ok, "status %08x\n", status);
     status = GdipGetRegionDataSize(region, &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 20, "got %d\n", needed);
+    expect(20, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 20, "got %d\n", needed);
+    expect(20, needed);
     expect_dword(buf, 12);
     trace("buf[1] = %08x\n", buf[1]);
     expect_magic((DWORD*)(buf + 2));
@@ -119,10 +120,10 @@ todo_wine
     ok(status == Ok, "status %08x\n", status);
     status = GdipGetRegionDataSize(region, &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 36, "got %d\n", needed);
+    expect(36, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 36, "got %d\n", needed);
+    expect(36, needed);
     expect_dword(buf, 28);
     trace("buf[1] = %08x\n", buf[1]);
     expect_magic((DWORD*)(buf + 2));
@@ -171,10 +172,10 @@ todo_wine
 
     status = GdipGetRegionDataSize(region, &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 156, "got %d\n", needed);
+    expect(156, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 156, "got %d\n", needed);
+    expect(156, needed);
     expect_dword(buf, 148);
     trace("buf[1] = %08x\n", buf[1]);
     expect_magic((DWORD*)(buf + 2));
@@ -220,21 +221,24 @@ todo_wine
     ok(status == Ok, "status %08x\n", status);
     status = GdipDeleteRegion(region);
     ok(status == Ok, "status %08x\n", status);
+}
 
     /* Try some paths */
 
     status = GdipCreatePath(FillModeAlternate, &path);
     ok(status == Ok, "status %08x\n", status);
+todo_wine
+{
     GdipAddPathRectangle(path, 12.5, 13.0, 14.0, 15.0);
 
     status = GdipCreateRegionPath(path, &region);
     ok(status == Ok, "status %08x\n", status);
     status = GdipGetRegionDataSize(region, &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 72, "got %d\n", needed);
+    expect(72, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 72, "got %d\n", needed);
+    expect(72, needed);
     expect_dword(buf, 64);
     trace("buf[1] = %08x\n", buf[1]);
     expect_magic((DWORD*)(buf + 2));
@@ -263,10 +267,10 @@ todo_wine
     ok(status == Ok, "status %08x\n", status);
     status = GdipGetRegionDataSize(region, &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 96, "got %d\n", needed);
+    expect(96, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     ok(status == Ok, "status %08x\n", status);
-    ok(needed == 96, "got %d\n", needed);
+    expect(96, needed);
     expect_dword(buf, 88);
     trace("buf[1] = %08x\n", buf[1]);
     expect_magic((DWORD*)(buf + 2));
@@ -294,20 +298,23 @@ todo_wine
 
     status = GdipDeleteRegion(region);
     ok(status == Ok, "status %08x\n", status);
+}
     status = GdipDeletePath(path);
     ok(status == Ok, "status %08x\n", status);
 
     /* Test an empty path */
     status = GdipCreatePath(FillModeAlternate, &path);
     expect(Ok, status);
+todo_wine
+{
     status = GdipCreateRegionPath(path, &region);
     expect(Ok, status);
     status = GdipGetRegionDataSize(region, &needed);
     expect(Ok, status);
-    ok(needed == 36, "got %d\n", needed);
+    expect(36, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     expect(Ok, status);
-    ok(needed == 36, "got %d\n", needed);
+    expect(36, needed);
     expect_dword(buf, 28);
     trace("buf[1] = %08x\n", buf[1]);
     expect_magic((DWORD*)(buf + 2));
@@ -322,23 +329,25 @@ todo_wine
 
     status = GdipDeleteRegion(region);
     expect(Ok, status);
+}
 
     /* Test a simple triangle of INTs */
     status = GdipAddPathLine(path, 5, 6, 7, 8);
     expect(Ok, status);
-    status = GdipAddPathLine(path, 7, 8, 8, 1);
-    expect(Ok, status);
     status = GdipAddPathLine(path, 8, 1, 5, 6);
     expect(Ok, status);
     status = GdipClosePathFigure(path);
     expect(Ok, status);
+todo_wine
+{
     status = GdipCreateRegionPath(path, &region);
     expect(Ok, status);
     status = GdipGetRegionDataSize(region, &needed);
     expect(Ok, status);
-    ok(needed == 56, "Expected 56, got %d\n", needed);
+    expect(56, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     expect(Ok, status);
+    expect(56, needed);
     expect_dword(buf, 48);
     trace("buf[1] = %08x\n", buf[1]);
     expect_magic((DWORD*)(buf + 2));
@@ -360,9 +369,11 @@ todo_wine
     expect(5, point[3].X); /* buf + 12 */
     expect(6, point[3].Y);
     expect_dword(buf + 13, 0x81010100); /* 0x01010100 if we don't close the path */
+}
     status = GdipDeletePath(path);
     expect(Ok, status);
     status = GdipDeleteRegion(region);
+todo_wine
     expect(Ok, status);
 
     /* Test a floating-point triangle */
@@ -370,17 +381,18 @@ todo_wine
     expect(Ok, status);
     status = GdipAddPathLine(path, 5.6, 6.2, 7.2, 8.9);
     expect(Ok, status);
-    status = GdipAddPathLine(path, 7.2, 8.9, 8.1, 1.6);
-    expect(Ok, status);
     status = GdipAddPathLine(path, 8.1, 1.6, 5.6, 6.2);
     expect(Ok, status);
+todo_wine
+{
     status = GdipCreateRegionPath(path, &region);
     expect(Ok, status);
     status = GdipGetRegionDataSize(region, &needed);
     expect(Ok, status);
-    ok(needed == 72, "Expected 72, got %d\n", needed);
+    expect(72, needed);
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     expect(Ok, status);
+    expect(72, needed);
     expect_dword(buf, 64);
     trace("buf[1] = %08x\n", buf[1]);
     expect_magic((DWORD*)(buf + 2));
@@ -399,8 +411,12 @@ todo_wine
     expect_float(buf + 14, 1.6);
     expect_float(buf + 15, 5.6);
     expect_float(buf + 16, 6.2);
+}
 
+    status = GdipDeletePath(path);
+    expect(Ok, status);
     status = GdipDeleteRegion(region);
+todo_wine
     expect(Ok, status);
 }
 
-- 
1.5.4.3




More information about the wine-patches mailing list