Piotr Caban : gdiplus: Support GdipSetClipRegion in metafiles.

Alexandre Julliard julliard at winehq.org
Sat Aug 12 07:19:31 CDT 2017


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Thu Aug 10 20:56:19 2017 +0200

gdiplus: Support GdipSetClipRegion in metafiles.

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/graphics.c        |  7 ++++++
 dlls/gdiplus/metafile.c        | 55 ++++++++++++++++++++++++++++++++++++++++++
 dlls/gdiplus/region.c          |  2 +-
 dlls/gdiplus/tests/metafile.c  | 12 +++++++++
 5 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index 762aa13..3396676 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -93,6 +93,7 @@ extern GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush,
     GDIPCONST GpRectF* rects, INT count) DECLSPEC_HIDDEN;
 extern GpStatus METAFILE_SetClipRect(GpMetafile* metafile,
     REAL x, REAL y, REAL width, REAL height, CombineMode mode) DECLSPEC_HIDDEN;
+extern GpStatus METAFILE_SetClipRegion(GpMetafile* metafile, GpRegion* region, CombineMode mode) DECLSPEC_HIDDEN;
 extern GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) DECLSPEC_HIDDEN;
 extern GpStatus METAFILE_SetWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* transform) DECLSPEC_HIDDEN;
 extern GpStatus METAFILE_ScaleWorldTransform(GpMetafile* metafile, REAL sx, REAL sy, MatrixOrder order) DECLSPEC_HIDDEN;
@@ -124,6 +125,7 @@ extern void free_installed_fonts(void) DECLSPEC_HIDDEN;
 
 extern BOOL lengthen_path(GpPath *path, INT len) DECLSPEC_HIDDEN;
 
+extern DWORD write_region_data(const GpRegion *region, void *data) DECLSPEC_HIDDEN;
 extern DWORD write_path_data(GpPath *path, void *data) DECLSPEC_HIDDEN;
 
 extern GpStatus trace_path(GpGraphics *graphics, GpPath *path) DECLSPEC_HIDDEN;
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 4b2ae49..e45618e 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -6269,6 +6269,13 @@ GpStatus WINGDIPAPI GdipSetClipRegion(GpGraphics *graphics, GpRegion *region,
     if(graphics->busy)
         return ObjectBusy;
 
+    if (graphics->image && graphics->image->type == ImageTypeMetafile)
+    {
+        status = METAFILE_SetClipRegion((GpMetafile*)graphics->image, region, mode);
+        if (status != Ok)
+            return status;
+    }
+
     status = GdipCloneRegion(region, &clip);
     if (status == Ok)
     {
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c
index 99e5483..41355bc 100644
--- a/dlls/gdiplus/metafile.c
+++ b/dlls/gdiplus/metafile.c
@@ -239,6 +239,13 @@ typedef struct EmfPlusPath
     BYTE data[1];
 } EmfPlusPath;
 
+typedef struct EmfPlusRegion
+{
+    DWORD Version;
+    DWORD RegionNodeCount;
+    BYTE RegionNode[1];
+} EmfPlusRegion;
+
 typedef enum
 {
     BitmapDataTypePixel,
@@ -312,6 +319,7 @@ typedef struct EmfPlusObject
         EmfPlusBrush brush;
         EmfPlusPen pen;
         EmfPlusPath path;
+        EmfPlusRegion region;
         EmfPlusImage image;
         EmfPlusImageAttributes image_attributes;
     } ObjectData;
@@ -847,6 +855,53 @@ GpStatus METAFILE_SetClipRect(GpMetafile* metafile, REAL x, REAL y, REAL width,
     return Ok;
 }
 
+static GpStatus METAFILE_AddRegionObject(GpMetafile *metafile, GpRegion *region, DWORD *id)
+{
+    EmfPlusObject *object_record;
+    DWORD size;
+    GpStatus stat;
+
+    *id = -1;
+    if (metafile->metafile_type != MetafileTypeEmfPlusOnly && metafile->metafile_type != MetafileTypeEmfPlusDual)
+        return Ok;
+
+    size = write_region_data(region, NULL);
+    stat = METAFILE_AllocateRecord(metafile,
+            FIELD_OFFSET(EmfPlusObject, ObjectData.region) + size, (void**)&object_record);
+    if (stat != Ok) return stat;
+
+    *id = METAFILE_AddObjectId(metafile);
+    object_record->Header.Type = EmfPlusRecordTypeObject;
+    object_record->Header.Flags = *id | ObjectTypeRegion << 8;
+    write_region_data(region, &object_record->ObjectData.region);
+    return Ok;
+}
+
+GpStatus METAFILE_SetClipRegion(GpMetafile* metafile, GpRegion* region, CombineMode mode)
+{
+    EmfPlusRecordHeader *record;
+    DWORD region_id;
+    GpStatus stat;
+
+    if (metafile->metafile_type == MetafileTypeEmf)
+    {
+        FIXME("stub!\n");
+        return NotImplemented;
+    }
+
+    stat = METAFILE_AddRegionObject(metafile, region, &region_id);
+    if (stat != Ok) return stat;
+
+    stat = METAFILE_AllocateRecord(metafile, sizeof(*record), (void**)&record);
+    if (stat != Ok) return stat;
+
+    record->Type = EmfPlusRecordTypeSetClipRegion;
+    record->Flags = region_id | mode << 8;
+
+    METAFILE_WriteRecords(metafile);
+    return Ok;
+}
+
 GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale)
 {
     if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual)
diff --git a/dlls/gdiplus/region.c b/dlls/gdiplus/region.c
index d133afa..015b677 100644
--- a/dlls/gdiplus/region.c
+++ b/dlls/gdiplus/region.c
@@ -699,7 +699,7 @@ static void write_element(const region_element* element, DWORD *buffer,
     }
 }
 
-static DWORD write_region_data(const GpRegion *region, void *data)
+DWORD write_region_data(const GpRegion *region, void *data)
 {
     struct region_header *header = data;
     INT filled = 0;
diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c
index 26716c4..1d36d9e 100644
--- a/dlls/gdiplus/tests/metafile.c
+++ b/dlls/gdiplus/tests/metafile.c
@@ -2154,6 +2154,8 @@ static const emfplus_record clipping_records[] = {
     {0, EmfPlusRecordTypeRestore},
     {0, EmfPlusRecordTypeSetClipRect},
     {0, EmfPlusRecordTypeFillRects},
+    {0, EmfPlusRecordTypeObject, 1},
+    {0, EmfPlusRecordTypeSetClipRegion, 1},
     {0, EmfPlusRecordTypeEndOfFile},
     {0, EMR_EOF},
     {0}
@@ -2165,6 +2167,7 @@ static void test_clipping(void)
     GpMetafile *metafile;
     GpGraphics *graphics;
     GpBitmap *bitmap;
+    GpRegion *region;
     GpBrush *brush;
     GpRectF rect;
     ARGB color;
@@ -2231,6 +2234,15 @@ static void test_clipping(void)
     stat = GdipDeleteBrush(brush);
     expect(Ok, stat);
 
+    stat = GdipCreateRegionRect(&rect, &region);
+    expect(Ok, stat);
+
+    stat = GdipSetClipRegion(graphics, region, CombineModeIntersect);
+    expect(Ok, stat);
+
+    stat = GdipDeleteRegion(region);
+    expect(Ok, stat);
+
     stat = GdipDeleteGraphics(graphics);
     expect(Ok, stat);
 




More information about the wine-cvs mailing list