[3/3] gdiplus: Implement EMR_SETWORLDTRANSFORM playback.

Vincent Povirk madewokherd at gmail.com
Fri Oct 7 16:03:44 CDT 2016


From: Vincent Povirk <vincent at codeweavers.com>

Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
---
 dlls/gdiplus/gdiplus_private.h |  1 +
 dlls/gdiplus/metafile.c        | 50 +++++++++++++++++++++++++++++-------------
 dlls/gdiplus/tests/metafile.c  |  2 +-
 3 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index 86a29a0..340e9bd 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -374,6 +374,7 @@ struct GpMetafile{
     GpRectF src_rect;
     HANDLETABLE *handle_table;
     int handle_count;
+    XFORM gdiworldtransform;
     GpMatrix *world_transform;
     GpUnit page_unit;
     REAL page_scale;
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c
index 803384a..a3fdb34 100644
--- a/dlls/gdiplus/metafile.c
+++ b/dlls/gdiplus/metafile.c
@@ -1040,6 +1040,30 @@ GpStatus WINGDIPAPI GdipGetHemfFromMetafile(GpMetafile *metafile, HENHMETAFILE *
     return Ok;
 }
 
+static GpStatus METAFILE_PlaybackUpdateGdiTransform(GpMetafile *metafile)
+{
+    XFORM combined, final;
+    const GpRectF *rect;
+    const GpPointF *pt;
+
+    /* This transforms metafile device space to output points. */
+    rect = &metafile->src_rect;
+    pt = metafile->playback_points;
+    final.eM11 = (pt[1].X - pt[0].X) / rect->Width;
+    final.eM21 = (pt[2].X - pt[0].X) / rect->Height;
+    final.eDx = pt[0].X - final.eM11 * rect->X - final.eM21 * rect->Y;
+    final.eM12 = (pt[1].Y - pt[0].Y) / rect->Width;
+    final.eM22 = (pt[2].Y - pt[0].Y) / rect->Height;
+    final.eDy = pt[0].Y - final.eM12 * rect->X - final.eM22 * rect->Y;
+
+    CombineTransform(&combined, &metafile->gdiworldtransform, &final);
+
+    SetGraphicsMode(metafile->playback_dc, GM_ADVANCED);
+    SetWorldTransform(metafile->playback_dc, &combined);
+
+    return Ok;
+}
+
 static GpStatus METAFILE_PlaybackGetDC(GpMetafile *metafile)
 {
     GpStatus stat = Ok;
@@ -1048,20 +1072,10 @@ static GpStatus METAFILE_PlaybackGetDC(GpMetafile *metafile)
 
     if (stat == Ok)
     {
-        /* The result of GdipGetDC always expects device co-ordinates, but the
-         * device co-ordinates of the source metafile do not correspond to
-         * device co-ordinates of the destination. Therefore, we set up the DC
-         * so that the metafile's bounds map to the destination points where we
-         * are drawing this metafile. */
-        SetMapMode(metafile->playback_dc, MM_ANISOTROPIC);
-
-        SetWindowOrgEx(metafile->playback_dc, metafile->bounds.X, metafile->bounds.Y, NULL);
-        SetWindowExtEx(metafile->playback_dc, metafile->bounds.Width, metafile->bounds.Height, NULL);
-
-        SetViewportOrgEx(metafile->playback_dc, metafile->playback_points[0].X, metafile->playback_points[0].Y, NULL);
-        SetViewportExtEx(metafile->playback_dc,
-            metafile->playback_points[1].X - metafile->playback_points[0].X,
-            metafile->playback_points[2].Y - metafile->playback_points[0].Y, NULL);
+        static const XFORM identity = {1, 0, 0, 1, 0, 0};
+
+        metafile->gdiworldtransform = identity;
+        METAFILE_PlaybackUpdateGdiTransform(metafile);
     }
 
     return stat;
@@ -1141,12 +1155,18 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
             case EMR_SETVIEWPORTORGEX:
             case EMR_SETVIEWPORTEXTEX:
             case EMR_EXTSELECTCLIPRGN:
-            case EMR_SETWORLDTRANSFORM:
             case EMR_SCALEVIEWPORTEXTEX:
             case EMR_SCALEWINDOWEXTEX:
             case EMR_MODIFYWORLDTRANSFORM:
                 FIXME("not implemented for record type %x\n", recordType);
                 break;
+            case EMR_SETWORLDTRANSFORM:
+            {
+                const XFORM* xform = (void*)data;
+                real_metafile->gdiworldtransform = *xform;
+                METAFILE_PlaybackUpdateGdiTransform(real_metafile);
+                break;
+            }
             default:
                 break;
             }
diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c
index 8531ce5..0646c7a 100644
--- a/dlls/gdiplus/tests/metafile.c
+++ b/dlls/gdiplus/tests/metafile.c
@@ -2260,7 +2260,7 @@ static void test_gditransform(void)
 
     stat = GdipBitmapGetPixel(bitmap, 30, 30, &color);
     expect(Ok, stat);
-    todo_wine expect(0x00000000, color);
+    expect(0x00000000, color);
 
     stat = GdipDeleteGraphics(graphics);
     expect(Ok, stat);
-- 
2.7.4




More information about the wine-patches mailing list