Dmitry Timoshkov : gdiplus: Determine type of the path at the time the region data are written instead of the path creation time .

Alexandre Julliard julliard at winehq.org
Tue Nov 12 14:26:37 CST 2013


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

Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date:   Tue Nov 12 18:16:15 2013 +0900

gdiplus: Determine type of the path at the time the region data are written instead of the path creation time.

---

 dlls/gdiplus/region.c       |  121 +++++++++++++++++++++++++------------------
 dlls/gdiplus/tests/region.c |   13 -----
 2 files changed, 70 insertions(+), 64 deletions(-)

diff --git a/dlls/gdiplus/region.c b/dlls/gdiplus/region.c
index 4cd9636..4f16f62 100644
--- a/dlls/gdiplus/region.c
+++ b/dlls/gdiplus/region.c
@@ -87,6 +87,22 @@ typedef struct packed_point
     short Y;
 } packed_point;
 
+/* Test to see if the path could be stored as an array of shorts */
+static BOOL is_integer_path(const GpPath *path)
+{
+    int i;
+
+    if (!path->pathdata.Count) return FALSE;
+
+    for (i = 0; i < path->pathdata.Count; i++)
+    {
+        if (path->pathdata.Points[i].X != gdip_round(path->pathdata.Points[i].X) ||
+            path->pathdata.Points[i].Y != gdip_round(path->pathdata.Points[i].Y))
+            return FALSE;
+    }
+    return TRUE;
+}
+
 /* Everything is measured in DWORDS; round up if there's a remainder */
 static inline INT get_pathtypes_size(const GpPath* path)
 {
@@ -106,9 +122,20 @@ static inline INT get_element_size(const region_element* element)
         case RegionDataRect:
             return needed + sizeof(GpRect);
         case RegionDataPath:
-             needed += element->elementdata.pathdata.pathheader.size;
-             needed += sizeof(DWORD); /* Extra DWORD for pathheader.size */
-             return needed;
+        {
+            const GpPath *path = element->elementdata.pathdata.path;
+            DWORD flags = is_integer_path(path) ? FLAGS_INTPATH : FLAGS_NOFLAGS;
+            /* 3 for headers, once again size doesn't count itself */
+            needed += sizeof(DWORD) * 3;
+            if (flags & FLAGS_INTPATH)
+                needed += 2 * sizeof(SHORT) * path->pathdata.Count;
+            else
+                needed += 2 * sizeof(FLOAT) * path->pathdata.Count;
+
+            needed += get_pathtypes_size(path);
+            needed += sizeof(DWORD); /* Extra DWORD for pathheader.size */
+            return needed;
+        }
         case RegionDataEmptyRect:
         case RegionDataInfiniteRect:
             return needed;
@@ -128,7 +155,7 @@ static inline GpStatus init_region(GpRegion* region, const RegionType 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);
+    region->header.size     = 0;
 
     return Ok;
 }
@@ -426,8 +453,6 @@ GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **region)
 {
     region_element* element;
     GpStatus stat;
-    DWORD flags;
-    INT count, i;
 
     TRACE("%p, %p\n", path, region);
 
@@ -444,20 +469,6 @@ GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **region)
         return stat;
     }
     element = &(*region)->node;
-    count = path->pathdata.Count;
-
-    flags = count ? FLAGS_INTPATH : FLAGS_NOFLAGS;
-
-    /* Test to see if the path is an Integer path */
-    for (i = 0; i < count; i++)
-    {
-        if (path->pathdata.Points[i].X != gdip_round(path->pathdata.Points[i].X) ||
-            path->pathdata.Points[i].Y != gdip_round(path->pathdata.Points[i].Y))
-        {
-            flags = FLAGS_NOFLAGS;
-            break;
-        }
-    }
 
     stat = GdipClonePath(path, &element->elementdata.pathdata.path);
     if (stat != Ok)
@@ -466,29 +477,6 @@ GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **region)
         return stat;
     }
 
-    /* 3 for headers, once again size doesn't count itself */
-    element->elementdata.pathdata.pathheader.size = ((sizeof(DWORD) * 3));
-    switch(flags)
-    {
-        /* Floats, sent out as floats */
-        case FLAGS_NOFLAGS:
-            element->elementdata.pathdata.pathheader.size +=
-                (sizeof(DWORD) * count * 2);
-            break;
-        /* INTs, sent out as packed shorts */
-        case FLAGS_INTPATH:
-            element->elementdata.pathdata.pathheader.size +=
-                (sizeof(DWORD) * count);
-            break;
-        default:
-            FIXME("Unhandled flags (%08x). Expect wrong results.\n", flags);
-    }
-    element->elementdata.pathdata.pathheader.size += get_pathtypes_size(path);
-    element->elementdata.pathdata.pathheader.magic = VERSION_MAGIC;
-    element->elementdata.pathdata.pathheader.count = count;
-    element->elementdata.pathdata.pathheader.flags = flags;
-    (*region)->header.size = sizeheader_size + get_element_size(element);
-
     return Ok;
 }
 
@@ -754,11 +742,30 @@ static void write_element(const region_element* element, DWORD *buffer,
         {
             INT i;
             const GpPath* path = element->elementdata.pathdata.path;
+            struct _pathheader
+            {
+                DWORD size;
+                DWORD magic;
+                DWORD count;
+                DWORD flags;
+            } *pathheader;
+
+            pathheader = (struct _pathheader *)(buffer + *filled);
+
+            pathheader->flags = is_integer_path(path) ? FLAGS_INTPATH : FLAGS_NOFLAGS;
+            /* 3 for headers, once again size doesn't count itself */
+            pathheader->size = sizeof(DWORD) * 3;
+            if (pathheader->flags & FLAGS_INTPATH)
+                pathheader->size += 2 * sizeof(SHORT) * path->pathdata.Count;
+            else
+                pathheader->size += 2 * sizeof(FLOAT) * path->pathdata.Count;
+            pathheader->size += get_pathtypes_size(path);
+            pathheader->magic = VERSION_MAGIC;
+            pathheader->count = path->pathdata.Count;
+
+            *filled += 4;
 
-            memcpy(buffer + *filled, &element->elementdata.pathdata.pathheader,
-                    sizeof(element->elementdata.pathdata.pathheader));
-            *filled += sizeof(element->elementdata.pathdata.pathheader) / sizeof(DWORD);
-            switch (element->elementdata.pathdata.pathheader.flags)
+            switch (pathheader->flags & FLAGS_INTPATH)
             {
                 case FLAGS_NOFLAGS:
                     for (i = 0; i < path->pathdata.Count; i++)
@@ -773,6 +780,7 @@ static void write_element(const region_element* element, DWORD *buffer,
                         write_packed_point(buffer, filled,
                                 &path->pathdata.Points[i]);
                     }
+                    break;
             }
             write_path_types(buffer, filled, path);
             break;
@@ -819,6 +827,13 @@ static void write_element(const region_element* element, DWORD *buffer,
 GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size,
         UINT *needed)
 {
+    struct _region_header
+    {
+        DWORD size;
+        DWORD checksum;
+        DWORD magic;
+        DWORD num_children;
+    } *region_header;
     INT filled = 0;
 
     TRACE("%p, %p, %d, %p\n", region, buffer, size, needed);
@@ -826,8 +841,12 @@ GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size,
     if (!(region && buffer && size))
         return InvalidParameter;
 
-    memcpy(buffer, &region->header, sizeof(region->header));
-    filled += sizeof(region->header) / sizeof(DWORD);
+    region_header = (struct _region_header *)buffer;
+    region_header->size = sizeheader_size + get_element_size(&region->node);
+    region_header->checksum = 0;
+    region_header->magic = VERSION_MAGIC;
+    region_header->num_children = region->header.num_children;
+    filled += 4;
     /* With few exceptions, everything written is DWORD aligned,
      * so use that as our base */
     write_element(&region->node, (DWORD*)buffer, &filled);
@@ -849,7 +868,7 @@ GpStatus WINGDIPAPI GdipGetRegionDataSize(GpRegion *region, UINT *needed)
         return InvalidParameter;
 
     /* header.size doesn't count header.size and header.checksum */
-    *needed = region->header.size + sizeof(DWORD) * 2;
+    *needed = sizeof(DWORD) * 2 + sizeheader_size + get_element_size(&region->node);
 
     return Ok;
 }
diff --git a/dlls/gdiplus/tests/region.c b/dlls/gdiplus/tests/region.c
index f509204..23c7a07 100644
--- a/dlls/gdiplus/tests/region.c
+++ b/dlls/gdiplus/tests/region.c
@@ -427,37 +427,24 @@ static void test_getregiondata(void)
     needed = 0;
     status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
     expect(Ok, status);
-todo_wine
     expect(72, needed);
-todo_wine
     expect_dword(buf, 64);
     expect_magic(buf + 2);
     expect_dword(buf + 3 , 0);
     expect_dword(buf + 4 , RGNDATA_PATH);
-todo_wine
     expect_dword(buf + 5, 48);
     expect_magic(buf + 6);
     expect_dword(buf + 7, 4);
     /* flags 0 means that a path is an array of FLOATs */
-todo_wine
     expect_dword(buf + 8, 0);
-todo_wine
     expect_float(buf + 9, 5.6);
-todo_wine
     expect_float(buf + 10, 6.8);
-todo_wine
     expect_float(buf + 11, 7.6);
-todo_wine
     expect_float(buf + 12, 8.8);
-todo_wine
     expect_float(buf + 13, 8.6);
-todo_wine
     expect_float(buf + 14, 1.8);
-todo_wine
     expect_float(buf + 15, 5.6);
-todo_wine
     expect_float(buf + 16, 6.8);
-todo_wine
     expect_dword(buf + 17, 0x81010100); /* 0x01010100 if we don't close the path */
 
     status = GdipDeletePath(path);




More information about the wine-cvs mailing list