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