Vincent Povirk : gdiplus: Implement BeginContainer metafile record.

Alexandre Julliard julliard at winehq.org
Mon Sep 19 10:32:12 CDT 2016


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

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

gdiplus: Implement BeginContainer metafile record.

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        |  2 +-
 dlls/gdiplus/metafile.c        | 89 ++++++++++++++++++++++++++++++++++++++++++
 dlls/gdiplus/tests/metafile.c  | 44 +++++++++++++++++++++
 4 files changed, 136 insertions(+), 1 deletion(-)

diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index 216dd4a..86a29a0 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -101,6 +101,8 @@ extern GpStatus METAFILE_MultiplyWorldTransform(GpMetafile* metafile, GDIPCONST
 extern GpStatus METAFILE_RotateWorldTransform(GpMetafile* metafile, REAL angle, MatrixOrder order) DECLSPEC_HIDDEN;
 extern GpStatus METAFILE_TranslateWorldTransform(GpMetafile* metafile, REAL dx, REAL dy, MatrixOrder order) DECLSPEC_HIDDEN;
 extern GpStatus METAFILE_ResetWorldTransform(GpMetafile* metafile) DECLSPEC_HIDDEN;
+extern GpStatus METAFILE_BeginContainer(GpMetafile* metafile, GDIPCONST GpRectF *dstrect,
+    GDIPCONST GpRectF *srcrect, GpUnit unit, DWORD StackIndex) DECLSPEC_HIDDEN;
 extern GpStatus METAFILE_BeginContainerNoParams(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN;
 extern GpStatus METAFILE_EndContainer(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN;
 extern GpStatus METAFILE_SaveGraphics(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN;
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 06a0c95..4ae1f48 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -5236,7 +5236,7 @@ GpStatus WINGDIPAPI GdipBeginContainer(GpGraphics *graphics, GDIPCONST GpRectF *
     GdipMultiplyMatrix(&graphics->worldtrans, &transform, MatrixOrderPrepend);
 
     if (graphics->image && graphics->image->type == ImageTypeMetafile) {
-        FIXME("Write to metafile\n");
+        METAFILE_BeginContainer((GpMetafile*)graphics->image, dstrect, srcrect, unit, container->contid);
     }
 
     return Ok;
diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c
index c0e799c..9de584c 100644
--- a/dlls/gdiplus/metafile.c
+++ b/dlls/gdiplus/metafile.c
@@ -122,6 +122,14 @@ typedef struct EmfPlusTranslateWorldTransform
     REAL dy;
 } EmfPlusTranslateWorldTransform;
 
+typedef struct EmfPlusBeginContainer
+{
+    EmfPlusRecordHeader Header;
+    GpRectF DestRect;
+    GpRectF SrcRect;
+    DWORD StackIndex;
+} EmfPlusBeginContainer;
+
 typedef struct EmfPlusContainerRecord
 {
     EmfPlusRecordHeader Header;
@@ -782,6 +790,30 @@ GpStatus METAFILE_ResetWorldTransform(GpMetafile* metafile)
     return Ok;
 }
 
+GpStatus METAFILE_BeginContainer(GpMetafile* metafile, GDIPCONST GpRectF *dstrect,
+    GDIPCONST GpRectF *srcrect, GpUnit unit, DWORD StackIndex)
+{
+    if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual)
+    {
+        EmfPlusBeginContainer *record;
+        GpStatus stat;
+
+        stat = METAFILE_AllocateRecord(metafile, sizeof(*record), (void**)&record);
+        if (stat != Ok)
+            return stat;
+
+        record->Header.Type = EmfPlusRecordTypeBeginContainer;
+        record->Header.Flags = unit & 0xff;
+        record->DestRect = *dstrect;
+        record->SrcRect = *srcrect;
+        record->StackIndex = StackIndex;
+
+        METAFILE_WriteRecords(metafile);
+    }
+
+    return Ok;
+}
+
 GpStatus METAFILE_BeginContainerNoParams(GpMetafile* metafile, DWORD StackIndex)
 {
     if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual)
@@ -1309,6 +1341,63 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
 
             return METAFILE_PlaybackUpdateWorldTransform(real_metafile);
         }
+        case EmfPlusRecordTypeBeginContainer:
+        {
+            EmfPlusBeginContainer *record = (EmfPlusBeginContainer*)header;
+            container* cont;
+            GpUnit unit;
+            REAL scale_x, scale_y;
+            GpRectF scaled_srcrect;
+            GpMatrix transform;
+
+            cont = heap_alloc_zero(sizeof(*cont));
+            if (!cont)
+                return OutOfMemory;
+
+            stat = GdipCloneRegion(metafile->clip, &cont->clip);
+            if (stat != Ok)
+            {
+                heap_free(cont);
+                return stat;
+            }
+
+            GdipBeginContainer2(metafile->playback_graphics, &cont->state);
+
+            if (stat != Ok)
+            {
+                GdipDeleteRegion(cont->clip);
+                heap_free(cont);
+                return stat;
+            }
+
+            cont->id = record->StackIndex;
+            cont->type = BEGIN_CONTAINER;
+            cont->world_transform = *metafile->world_transform;
+            cont->page_unit = metafile->page_unit;
+            cont->page_scale = metafile->page_scale;
+            list_add_head(&real_metafile->containers, &cont->entry);
+
+            unit = record->Header.Flags & 0xff;
+
+            scale_x = units_to_pixels(1.0, unit, metafile->image.xres);
+            scale_y = units_to_pixels(1.0, unit, metafile->image.yres);
+
+            scaled_srcrect.X = scale_x * record->SrcRect.X;
+            scaled_srcrect.Y = scale_y * record->SrcRect.Y;
+            scaled_srcrect.Width = scale_x * record->SrcRect.Width;
+            scaled_srcrect.Height = scale_y * record->SrcRect.Height;
+
+            transform.matrix[0] = record->DestRect.Width / scaled_srcrect.Width;
+            transform.matrix[1] = 0.0;
+            transform.matrix[2] = 0.0;
+            transform.matrix[3] = record->DestRect.Height / scaled_srcrect.Height;
+            transform.matrix[4] = record->DestRect.X - scaled_srcrect.X;
+            transform.matrix[5] = record->DestRect.Y - scaled_srcrect.Y;
+
+            GdipMultiplyMatrix(real_metafile->world_transform, &transform, MatrixOrderPrepend);
+
+            return METAFILE_PlaybackUpdateWorldTransform(real_metafile);
+        }
         case EmfPlusRecordTypeBeginContainerNoParams:
         case EmfPlusRecordTypeSave:
         {
diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c
index 6a21afa..60890d9 100644
--- a/dlls/gdiplus/tests/metafile.c
+++ b/dlls/gdiplus/tests/metafile.c
@@ -1846,6 +1846,9 @@ static const emfplus_record container_records[] = {
     {0, EmfPlusRecordTypeBeginContainerNoParams},
     {0, EmfPlusRecordTypeEndContainer},
     {0, EmfPlusRecordTypeFillRects},
+    {0, EmfPlusRecordTypeBeginContainer},
+    {0, EmfPlusRecordTypeFillRects},
+    {0, EmfPlusRecordTypeEndContainer},
     {0, EmfPlusRecordTypeBeginContainerNoParams},
     {0, EmfPlusRecordTypeEndOfFile},
     {0, EMR_EOF},
@@ -1865,6 +1868,8 @@ static void test_containers(void)
     static const GpPointF dst_points[3] = {{0.0,0.0},{100.0,0.0},{0.0,100.0}};
     static const WCHAR description[] = {'w','i','n','e','t','e','s','t',0};
     GraphicsContainer state1, state2;
+    GpRectF srcrect, dstrect;
+    REAL dpix, dpiy;
 
     hdc = CreateCompatibleDC(0);
 
@@ -1938,6 +1943,41 @@ static void test_containers(void)
     stat = GdipFillRectangle(graphics, brush, 20.0, 20.0, 5.0, 5.0);
     expect(Ok, stat);
 
+    stat = GdipDeleteBrush(brush);
+    expect(Ok, stat);
+
+    /* With transform applied */
+    stat = GdipGetDpiX(graphics, &dpix);
+    expect(Ok, stat);
+
+    stat = GdipGetDpiY(graphics, &dpiy);
+    expect(Ok, stat);
+
+    srcrect.X = 0.0;
+    srcrect.Y = 0.0;
+    srcrect.Width = 1.0;
+    srcrect.Height = 1.0;
+
+    dstrect.X = 25.0;
+    dstrect.Y = 0.0;
+    dstrect.Width = 5.0;
+    dstrect.Height = 5.0;
+
+    stat = GdipBeginContainer(graphics, &dstrect, &srcrect, UnitInch, &state1);
+    expect(Ok, stat);
+
+    stat = GdipCreateSolidFill((ARGB)0xff00ffff, (GpSolidFill**)&brush);
+    expect(Ok, stat);
+
+    stat = GdipFillRectangle(graphics, brush, 0.0, 0.0, dpix, dpiy);
+    expect(Ok, stat);
+
+    stat = GdipDeleteBrush(brush);
+    expect(Ok, stat);
+
+    stat = GdipEndContainer(graphics, state1);
+    expect(Ok, stat);
+
     /* Restoring an invalid state seems to break the graphics object? */
     if (0) {
         stat = GdipEndContainer(graphics, state1);
@@ -1979,6 +2019,10 @@ static void test_containers(void)
     expect(Ok, stat);
     expect(0xff00ff00, color);
 
+    stat = GdipBitmapGetPixel(bitmap, 55, 5, &color);
+    expect(Ok, stat);
+    expect(0xff00ffff, color);
+
     stat = GdipDeleteGraphics(graphics);
     expect(Ok, stat);
 




More information about the wine-cvs mailing list