Nikolay Sivov : gdiplus/metafile: Partially implement EmfPlusPath deserialization.

Alexandre Julliard julliard at winehq.org
Mon Oct 16 14:38:31 CDT 2017


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Mon Oct 16 10:12:23 2017 +0300

gdiplus/metafile: Partially implement EmfPlusPath deserialization.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/gdiplus/gdiplus_private.h |  1 +
 dlls/gdiplus/metafile.c        | 75 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+)

diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index f659ccf..dc2f0892 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -394,6 +394,7 @@ struct emfplus_object {
     EmfPlusObjectType type;
     union {
         GpBrush *brush;
+        GpPath *path;
         GpImage *image;
         GpImageAttributes *image_attributes;
         void *object;
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c
index fa4bafd..db74c9dc 100644
--- a/dlls/gdiplus/metafile.c
+++ b/dlls/gdiplus/metafile.c
@@ -388,6 +388,9 @@ static void metafile_free_object_table_entry(GpMetafile *metafile, BYTE id)
     case ObjectTypeBrush:
         GdipDeleteBrush(object->u.brush);
         break;
+    case ObjectTypePath:
+        GdipDeletePath(object->u.path);
+        break;
     case ObjectTypeImage:
         GdipDisposeImage(object->u.image);
         break;
@@ -1572,6 +1575,75 @@ static GpStatus metafile_deserialize_image(const BYTE *record_data, UINT data_si
     return status;
 }
 
+static GpStatus metafile_deserialize_path(const BYTE *record_data, UINT data_size, GpPath **path)
+{
+    EmfPlusPath *data = (EmfPlusPath *)record_data;
+    GpStatus status;
+    BYTE *types;
+    UINT size;
+    DWORD i;
+
+    *path = NULL;
+
+    if (data_size <= FIELD_OFFSET(EmfPlusPath, data))
+        return InvalidParameter;
+    data_size -= FIELD_OFFSET(EmfPlusPath, data);
+
+    if (data->PathPointFlags & 0x800) /* R */
+    {
+        FIXME("RLE encoded path data is not supported.\n");
+        return NotImplemented;
+    }
+    else
+    {
+        if (data->PathPointFlags & 0x4000) /* C */
+            size = sizeof(EmfPlusPoint);
+        else
+            size = sizeof(EmfPlusPointF);
+        size += sizeof(BYTE); /* EmfPlusPathPointType */
+        size *= data->PathPointCount;
+    }
+
+    if (data_size < size)
+        return InvalidParameter;
+
+    status = GdipCreatePath(FillModeAlternate, path);
+    if (status != Ok)
+        return status;
+
+    (*path)->pathdata.Count = data->PathPointCount;
+    (*path)->pathdata.Points = GdipAlloc(data->PathPointCount * sizeof(*(*path)->pathdata.Points));
+    (*path)->pathdata.Types = GdipAlloc(data->PathPointCount * sizeof(*(*path)->pathdata.Types));
+    (*path)->datalen = (*path)->pathdata.Count;
+
+    if (!(*path)->pathdata.Points || !(*path)->pathdata.Types)
+    {
+        GdipDeletePath(*path);
+        return OutOfMemory;
+    }
+
+    if (data->PathPointFlags & 0x4000) /* C */
+    {
+        EmfPlusPoint *points = (EmfPlusPoint *)data->data;
+        for (i = 0; i < data->PathPointCount; i++)
+        {
+            (*path)->pathdata.Points[i].X = points[i].X;
+            (*path)->pathdata.Points[i].Y = points[i].Y;
+        }
+        types = (BYTE *)(points + i);
+    }
+    else
+    {
+        EmfPlusPointF *points = (EmfPlusPointF *)data->data;
+        memcpy((*path)->pathdata.Points, points, sizeof(*points) * data->PathPointCount);
+        types = (BYTE *)(points + data->PathPointCount);
+    }
+
+    memcpy((*path)->pathdata.Types, types, sizeof(*types) * data->PathPointCount);
+
+    return Ok;
+}
+
 static GpStatus metafile_deserialize_brush(const BYTE *record_data, UINT data_size, GpBrush **brush)
 {
     static const UINT header_size = FIELD_OFFSET(EmfPlusBrush, BrushData);
@@ -1614,6 +1686,9 @@ static GpStatus METAFILE_PlaybackObject(GpMetafile *metafile, UINT flags, UINT d
     case ObjectTypeBrush:
         status = metafile_deserialize_brush(record_data, data_size, (GpBrush **)&object);
         break;
+    case ObjectTypePath:
+        status = metafile_deserialize_path(record_data, data_size, (GpPath **)&object);
+        break;
     case ObjectTypeImage:
         status = metafile_deserialize_image(record_data, data_size, (GpImage **)&object);
         break;




More information about the wine-cvs mailing list