From a892b6801667fc3aa213c7c15027e1919308877c Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Tue, 18 Jul 2017 18:59:48 +0200 Subject: [PATCH] gdiplus: Add write_path_data helper to create EMF+ path object. Signed-off-by: Piotr Caban Signed-off-by: Vincent Povirk Signed-off-by: Alexandre Julliard --- 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 d6806cc94a9..762aa135a75 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 e19053214f6..05c79825660 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; ipathdata.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 d53c85f6bc2..c3895edffaf 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; ipathdata.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; ipathdata.Count; i++) - types[i] = path->pathdata.Types[i]; + write_path_data(path, &object_record->ObjectData.path); return Ok; }