Vincent Povirk : gdiplus: Implement recording/ playback for MultiplyWorldTransform.

Alexandre Julliard julliard at winehq.org
Mon Aug 8 11:09:28 CDT 2016


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

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Fri Aug  5 16:14:37 2016 -0500

gdiplus: Implement recording/playback for MultiplyWorldTransform.

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/graphics.c        |  7 +++++++
 dlls/gdiplus/metafile.c        | 44 ++++++++++++++++++++++++++++++++++++++++++
 dlls/gdiplus/tests/metafile.c  | 34 ++++++++++++++++++++++++++++++++
 4 files changed, 86 insertions(+)

diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index 3eebaed..65135f8 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -91,6 +91,7 @@ extern GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush,
     GDIPCONST GpRectF* rects, INT count) DECLSPEC_HIDDEN;
 extern GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) DECLSPEC_HIDDEN;
 extern GpStatus METAFILE_ScaleWorldTransform(GpMetafile* metafile, REAL sx, REAL sy, MatrixOrder order) DECLSPEC_HIDDEN;
+extern GpStatus METAFILE_MultiplyWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* matrix, MatrixOrder order) DECLSPEC_HIDDEN;
 extern GpStatus METAFILE_ResetWorldTransform(GpMetafile* metafile) DECLSPEC_HIDDEN;
 extern GpStatus METAFILE_GraphicsDeleted(GpMetafile* metafile) DECLSPEC_HIDDEN;
 
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 6003a19..9b0d9b5 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -5744,6 +5744,13 @@ GpStatus WINGDIPAPI GdipMultiplyWorldTransform(GpGraphics *graphics, GDIPCONST G
     if(graphics->busy)
         return ObjectBusy;
 
+    if (graphics->image && graphics->image->type == ImageTypeMetafile) {
+        ret = METAFILE_MultiplyWorldTransform((GpMetafile*)graphics->image, matrix, order);
+
+        if (ret != Ok)
+            return ret;
+    }
+
     m = graphics->worldtrans;
 
     ret = GdipMultiplyMatrix(&m, matrix, order);
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c
index f869b90..8d4002c 100644
--- a/dlls/gdiplus/metafile.c
+++ b/dlls/gdiplus/metafile.c
@@ -91,6 +91,12 @@ typedef struct EmfPlusScaleWorldTransform
     REAL Sy;
 } EmfPlusScaleWorldTransform;
 
+typedef struct EmfPlusMultiplyWorldTransform
+{
+    EmfPlusRecordHeader Header;
+    REAL MatrixData[6];
+} EmfPlusMultiplyWorldTransform;
+
 static GpStatus METAFILE_AllocateRecord(GpMetafile *metafile, DWORD size, void **result)
 {
     DWORD size_needed;
@@ -586,6 +592,29 @@ GpStatus METAFILE_ScaleWorldTransform(GpMetafile* metafile, REAL sx, REAL sy, Ma
     return Ok;
 }
 
+GpStatus METAFILE_MultiplyWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* matrix, MatrixOrder order)
+{
+    if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual)
+    {
+        EmfPlusMultiplyWorldTransform *record;
+        GpStatus stat;
+
+        stat = METAFILE_AllocateRecord(metafile,
+            sizeof(EmfPlusMultiplyWorldTransform),
+            (void**)&record);
+        if (stat != Ok)
+            return stat;
+
+        record->Header.Type = EmfPlusRecordTypeMultiplyWorldTransform;
+        record->Header.Flags = (order == MatrixOrderAppend ? 0x2000 : 0);
+        memcpy(record->MatrixData, matrix->matrix, sizeof(record->MatrixData));
+
+        METAFILE_WriteRecords(metafile);
+    }
+
+    return Ok;
+}
+
 GpStatus METAFILE_ResetWorldTransform(GpMetafile* metafile)
 {
     if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual)
@@ -957,6 +986,21 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
 
             return METAFILE_PlaybackUpdateWorldTransform(real_metafile);
         }
+        case EmfPlusRecordTypeMultiplyWorldTransform:
+        {
+            EmfPlusMultiplyWorldTransform *record = (EmfPlusMultiplyWorldTransform*)header;
+            MatrixOrder order = (flags & 0x2000) ? MatrixOrderAppend : MatrixOrderPrepend;
+            GpMatrix matrix;
+
+            if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(EmfPlusMultiplyWorldTransform))
+                return InvalidParameter;
+
+            memcpy(matrix.matrix, record->MatrixData, sizeof(matrix.matrix));
+
+            GdipMultiplyMatrix(real_metafile->world_transform, &matrix, order);
+
+            return METAFILE_PlaybackUpdateWorldTransform(real_metafile);
+        }
         case EmfPlusRecordTypeResetWorldTransform:
         {
             GdipSetMatrixElements(real_metafile->world_transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c
index a8fc67e..98b3f3e 100644
--- a/dlls/gdiplus/tests/metafile.c
+++ b/dlls/gdiplus/tests/metafile.c
@@ -1292,6 +1292,8 @@ static const emfplus_record worldtransform_records[] = {
     {0, EmfPlusRecordTypeFillRects},
     {0, EmfPlusRecordTypeResetWorldTransform},
     {0, EmfPlusRecordTypeFillRects},
+    {0, EmfPlusRecordTypeMultiplyWorldTransform},
+    {0, EmfPlusRecordTypeFillRects},
     {0, EmfPlusRecordTypeEndOfFile},
     {0, EMR_EOF},
     {0}
@@ -1391,6 +1393,34 @@ static void test_worldtransform(void)
     stat = GdipDeleteBrush(brush);
     expect(Ok, stat);
 
+    /* multiply transform */
+    stat = GdipSetMatrixElements(transform, 2.0, 0.0, 0.0, 1.0, 0.0, 0.0);
+    expect(Ok, stat);
+
+    stat = GdipMultiplyWorldTransform(graphics, transform, MatrixOrderPrepend);
+    expect(Ok, stat);
+
+    stat = GdipGetWorldTransform(graphics, transform);
+    expect(Ok, stat);
+
+    stat = GdipGetMatrixElements(transform, elements);
+    expect(Ok, stat);
+    expectf(2.0, elements[0]);
+    expectf(0.0, elements[1]);
+    expectf(0.0, elements[2]);
+    expectf(1.0, elements[3]);
+    expectf(0.0, elements[4]);
+    expectf(0.0, elements[5]);
+
+    stat = GdipCreateSolidFill((ARGB)0xffff0000, (GpSolidFill**)&brush);
+    expect(Ok, stat);
+
+    stat = GdipFillRectangle(graphics, brush, 1.0, 1.0, 0.5, 1.0);
+    expect(Ok, stat);
+
+    stat = GdipDeleteBrush(brush);
+    expect(Ok, stat);
+
     stat = GdipDeleteMatrix(transform);
     expect(Ok, stat);
 
@@ -1425,6 +1455,10 @@ static void test_worldtransform(void)
     expect(Ok, stat);
     expect(0xff00ffff, color);
 
+    stat = GdipBitmapGetPixel(bitmap, 50, 30, &color);
+    expect(Ok, stat);
+    expect(0xffff0000, color);
+
     stat = GdipDeleteGraphics(graphics);
     expect(Ok, stat);
 




More information about the wine-cvs mailing list