Piotr Caban : gdiplus: Add write_path_data helper to create EMF+ path object.

Alexandre Julliard julliard at winehq.org
Wed Jul 19 16:05:33 CDT 2017


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Tue Jul 18 18:59:48 2017 +0200

gdiplus: Add write_path_data helper to create EMF+ path object.

Signed-off-by: Piotr Caban <piotr 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 |  2 ++
 dlls/gdiplus/graphicspath.c    | 74 ++++++++++++++++++++++++++++++++++++++++++
 dlls/gdiplus/metafile.c        | 27 +++------------
 3 files changed, 80 insertions(+), 23 deletions(-)

diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index d6806cc..762aa13 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -124,6 +124,8 @@ extern void free_installed_fonts(void) DECLSPEC_HIDDEN;
 
 extern BOOL lengthen_path(GpPath *path, INT len) DECLSPEC_HIDDEN;
 
+extern DWORD write_path_data(GpPath *path, void *data) DECLSPEC_HIDDEN;
+
 extern GpStatus trace_path(GpGraphics *graphics, GpPath *path) DECLSPEC_HIDDEN;
 
 typedef struct region_element region_element;
diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c
index e190532..05c7982 100644
--- a/dlls/gdiplus/graphicspath.c
+++ b/dlls/gdiplus/graphicspath.c
@@ -2454,3 +2454,77 @@ GpStatus WINGDIPAPI GdipWindingModeOutline(GpPath *path, GpMatrix *matrix, REAL
    FIXME("stub: %p, %p, %.2f\n", path, matrix, flatness);
    return NotImplemented;
 }
+
+#define FLAGS_INTPATH 0x4000
+
+struct path_header
+{
+    DWORD version;
+    DWORD count;
+    DWORD flags;
+};
+
+/* 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++)
+    {
+        short x, y;
+        x = gdip_round(path->pathdata.Points[i].X);
+        y = gdip_round(path->pathdata.Points[i].Y);
+        if (path->pathdata.Points[i].X != (REAL)x || path->pathdata.Points[i].Y != (REAL)y)
+            return FALSE;
+    }
+    return TRUE;
+}
+
+DWORD write_path_data(GpPath *path, void *data)
+{
+    struct path_header *header = data;
+    BOOL integer_path = is_integer_path(path);
+    DWORD i, size;
+    BYTE *types;
+
+    size = sizeof(struct path_header) + path->pathdata.Count;
+    if (integer_path)
+        size += sizeof(short[2]) * path->pathdata.Count;
+    else
+        size += sizeof(float[2]) * path->pathdata.Count;
+    size = (size + 3) & ~3;
+
+    if (!data) return size;
+
+    header->version = VERSION_MAGIC2;
+    header->count = path->pathdata.Count;
+    header->flags = integer_path ? FLAGS_INTPATH : 0;
+
+    if (integer_path)
+    {
+        short *points = (short*)(header + 1);
+        for (i = 0; i < path->pathdata.Count; i++)
+        {
+            points[2*i] = path->pathdata.Points[i].X;
+            points[2*i + 1] = path->pathdata.Points[i].Y;
+        }
+        types = (BYTE*)(points + 2*i);
+    }
+    else
+    {
+        float *points = (float*)(header + 1);
+        for (i = 0; i < path->pathdata.Count; i++)
+        {
+            points[2*i]  = path->pathdata.Points[i].X;
+            points[2*i + 1] = path->pathdata.Points[i].Y;
+        }
+        types = (BYTE*)(points + 2*i);
+    }
+
+    for (i=0; i<path->pathdata.Count; i++)
+        types[i] = path->pathdata.Types[i];
+    memset(types + i, 0, ((path->pathdata.Count + 3) & ~3) - path->pathdata.Count);
+    return size;
+}
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c
index d53c85f..c3895ed 100644
--- a/dlls/gdiplus/metafile.c
+++ b/dlls/gdiplus/metafile.c
@@ -2698,42 +2698,23 @@ GpStatus METAFILE_AddSimpleProperty(GpMetafile *metafile, SHORT prop, SHORT val)
 static GpStatus METAFILE_AddPathObject(GpMetafile *metafile, GpPath *path, DWORD *id)
 {
     EmfPlusObject *object_record;
-    EmfPlusPointF *points;
-    BYTE *types;
     GpStatus stat;
-    DWORD i, size;
+    DWORD size;
 
     *id = -1;
     if (metafile->metafile_type != MetafileTypeEmfPlusOnly && metafile->metafile_type != MetafileTypeEmfPlusDual)
         return Ok;
 
-    /* TODO: Add support for more point formats */
-    size = sizeof(EmfPlusPointF)*path->pathdata.Count + path->pathdata.Count;
-    size = (size + 3) & ~3;
-
+    size = write_path_data(path, NULL);
     stat = METAFILE_AllocateRecord(metafile,
-            FIELD_OFFSET(EmfPlusObject, ObjectData.path.data[size]),
+            FIELD_OFFSET(EmfPlusObject, ObjectData.path) + size,
             (void**)&object_record);
     if (stat != Ok) return stat;
 
     *id = METAFILE_AddObjectId(metafile);
     object_record->Header.Type = EmfPlusRecordTypeObject;
     object_record->Header.Flags = *id | ObjectTypePath << 8;
-
-    object_record->ObjectData.path.Version = 0xDBC01002;
-    object_record->ObjectData.path.PathPointCount = path->pathdata.Count;
-    object_record->ObjectData.path.PathPointFlags = 0;
-
-    points = (EmfPlusPointF*)object_record->ObjectData.path.data;
-    for (i=0; i<path->pathdata.Count; i++)
-    {
-        points[i].X = path->pathdata.Points[i].X;
-        points[i].Y = path->pathdata.Points[i].Y;
-    }
-
-    types = (BYTE*)(points + path->pathdata.Count);
-    for (i=0; i<path->pathdata.Count; i++)
-        types[i] = path->pathdata.Types[i];
+    write_path_data(path, &object_record->ObjectData.path);
     return Ok;
 }
 




More information about the wine-cvs mailing list