[3/5] gdiplus: Add initial GdipGetMetafileHeaderFromEmf implementation.

Vincent Povirk madewokherd at gmail.com
Fri Oct 30 15:07:29 CDT 2015


-------------- next part --------------
From 79a4740aeafac68ea1c2685fa9ce49516595aa9c Mon Sep 17 00:00:00 2001
From: Vincent Povirk <vincent at codeweavers.com>
Date: Fri, 30 Oct 2015 13:54:05 -0500
Subject: [PATCH 3/5] gdiplus: Add initial GdipGetMetafileHeaderFromEmf
 implementation.

Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
---
 dlls/gdiplus/metafile.c       | 81 +++++++++++++++++++++++++++++++++++++++----
 dlls/gdiplus/tests/metafile.c | 40 ++++++++++-----------
 2 files changed, 95 insertions(+), 26 deletions(-)

diff --git a/dlls/gdiplus/metafile.c b/dlls/gdiplus/metafile.c
index c46be76..20b8e20 100644
--- a/dlls/gdiplus/metafile.c
+++ b/dlls/gdiplus/metafile.c
@@ -941,18 +941,87 @@ GpStatus WINGDIPAPI GdipGetMetafileHeaderFromMetafile(GpMetafile * metafile,
     return Ok;
 }
 
-GpStatus WINGDIPAPI GdipGetMetafileHeaderFromEmf(HENHMETAFILE hEmf,
+static int CALLBACK get_emfplus_header_proc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR,
+    int nObj, LPARAM lpData)
+{
+    EmfPlusHeader *dst_header = (EmfPlusHeader*)lpData;
+
+    if (lpEMFR->iType == EMR_GDICOMMENT)
+    {
+        const EMRGDICOMMENT *comment = (const EMRGDICOMMENT*)lpEMFR;
+
+        if (comment->cbData >= 4 && memcmp(comment->Data, "EMF+", 4) == 0)
+        {
+            const EmfPlusRecordHeader *header = (const EmfPlusRecordHeader*)&comment->Data[4];
+
+            if (4 + sizeof(EmfPlusHeader) <= comment->cbData &&
+                header->Type == EmfPlusRecordTypeHeader)
+            {
+                memcpy(dst_header, header, sizeof(*dst_header));
+            }
+        }
+    }
+    else if (lpEMFR->iType == EMR_HEADER)
+        return TRUE;
+
+    return FALSE;
+}
+
+GpStatus WINGDIPAPI GdipGetMetafileHeaderFromEmf(HENHMETAFILE hemf,
     MetafileHeader *header)
 {
-    static int calls;
+    ENHMETAHEADER3 emfheader;
+    EmfPlusHeader emfplusheader;
+    MetafileType metafile_type;
+
+    TRACE("(%p,%p)\n", hemf, header);
 
-    if(!hEmf || !header)
+    if(!hemf || !header)
         return InvalidParameter;
 
-    if(!(calls++))
-        FIXME("not implemented\n");
+    if (GetEnhMetaFileHeader(hemf, sizeof(emfheader), (ENHMETAHEADER*)&emfheader) == 0)
+        return GenericError;
 
-    memset(header, 0, sizeof(MetafileHeader));
+    emfplusheader.Header.Type = 0;
+
+    EnumEnhMetaFile(NULL, hemf, get_emfplus_header_proc, &emfplusheader, NULL);
+
+    if (emfplusheader.Header.Type == EmfPlusRecordTypeHeader)
+    {
+        if ((emfplusheader.Header.Flags & 1) == 1)
+            metafile_type = MetafileTypeEmfPlusDual;
+        else
+            metafile_type = MetafileTypeEmfPlusOnly;
+    }
+    else
+        metafile_type = MetafileTypeEmf;
+
+    header->Type = metafile_type;
+    header->Size = emfheader.nBytes;
+    header->DpiX = (REAL)emfheader.szlDevice.cx * 25.4 / emfheader.szlMillimeters.cx;
+    header->DpiY = (REAL)emfheader.szlDevice.cy * 25.4 / emfheader.szlMillimeters.cy;
+    header->X = gdip_round((REAL)emfheader.rclFrame.left / 2540.0 * header->DpiX);
+    header->Y = gdip_round((REAL)emfheader.rclFrame.top / 2540.0 * header->DpiY);
+    header->Width = gdip_round((REAL)(emfheader.rclFrame.right - emfheader.rclFrame.left) / 2540.0 * header->DpiX);
+    header->Height = gdip_round((REAL)(emfheader.rclFrame.bottom - emfheader.rclFrame.top) / 2540.0 * header->DpiY);
+    header->EmfHeader = emfheader;
+
+    if (metafile_type == MetafileTypeEmfPlusDual || metafile_type == MetafileTypeEmfPlusOnly)
+    {
+        header->Version = emfplusheader.Version;
+        header->EmfPlusFlags = emfplusheader.EmfPlusFlags;
+        header->EmfPlusHeaderSize = emfplusheader.Header.Size;
+        header->LogicalDpiX = emfplusheader.LogicalDpiX;
+        header->LogicalDpiY = emfplusheader.LogicalDpiY;
+    }
+    else
+    {
+        header->Version = emfheader.nVersion;
+        header->EmfPlusFlags = 0;
+        header->EmfPlusHeaderSize = 0;
+        header->LogicalDpiX = 0;
+        header->LogicalDpiY = 0;
+    }
 
     return Ok;
 }
diff --git a/dlls/gdiplus/tests/metafile.c b/dlls/gdiplus/tests/metafile.c
index ae4c713..82e803d 100644
--- a/dlls/gdiplus/tests/metafile.c
+++ b/dlls/gdiplus/tests/metafile.c
@@ -369,26 +369,26 @@ static void test_empty(void)
     memset(&header, 0xaa, sizeof(header));
     stat = GdipGetMetafileHeaderFromEmf(hemf, &header);
     expect(Ok, stat);
-    todo_wine expect(MetafileTypeEmfPlusOnly, header.Type);
+    expect(MetafileTypeEmfPlusOnly, header.Type);
     expect(U(header).EmfHeader.nBytes, header.Size);
-    todo_wine ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
-    todo_wine expect(1, header.EmfPlusFlags); /* reference device was display, not printer */
+    ok(header.Version == 0xdbc01001 || header.Version == 0xdbc01002, "Unexpected version %x\n", header.Version);
+    expect(1, header.EmfPlusFlags); /* reference device was display, not printer */
     todo_wine expectf(xres, header.DpiX);
     todo_wine expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
     todo_wine expectf(yres, header.DpiY);
     todo_wine expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
     expect(0, header.X);
     expect(0, header.Y);
-    todo_wine expect(100, header.Width);
-    todo_wine expect(100, header.Height);
-    todo_wine expect(28, header.EmfPlusHeaderSize);
-    todo_wine expect(96, header.LogicalDpiX);
-    todo_wine expect(96, header.LogicalDpiX);
-    todo_wine expect(EMR_HEADER, U(header).EmfHeader.iType);
+    expect(100, header.Width);
+    expect(100, header.Height);
+    expect(28, header.EmfPlusHeaderSize);
+    expect(96, header.LogicalDpiX);
+    expect(96, header.LogicalDpiX);
+    expect(EMR_HEADER, U(header).EmfHeader.iType);
     expect(0, U(header).EmfHeader.rclBounds.left);
     expect(0, U(header).EmfHeader.rclBounds.top);
-    todo_wine expect(-1, U(header).EmfHeader.rclBounds.right);
-    todo_wine expect(-1, U(header).EmfHeader.rclBounds.bottom);
+    expect(-1, U(header).EmfHeader.rclBounds.right);
+    expect(-1, U(header).EmfHeader.rclBounds.bottom);
     expect(0, U(header).EmfHeader.rclFrame.left);
     expect(0, U(header).EmfHeader.rclFrame.top);
     todo_wine expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
@@ -716,9 +716,9 @@ static void test_emfonly(void)
     memset(&header, 0xaa, sizeof(header));
     stat = GdipGetMetafileHeaderFromEmf(hemf, &header);
     expect(Ok, stat);
-    todo_wine expect(MetafileTypeEmf, header.Type);
+    expect(MetafileTypeEmf, header.Type);
     expect(U(header).EmfHeader.nBytes, header.Size);
-    todo_wine expect(0x10000, header.Version);
+    expect(0x10000, header.Version);
     expect(0, header.EmfPlusFlags);
     todo_wine expectf(xres, header.DpiX);
     todo_wine expectf(xres, U(header).EmfHeader.szlDevice.cx / (REAL)U(header).EmfHeader.szlMillimeters.cx * 25.4);
@@ -726,16 +726,16 @@ static void test_emfonly(void)
     todo_wine expectf(yres, U(header).EmfHeader.szlDevice.cy / (REAL)U(header).EmfHeader.szlMillimeters.cy * 25.4);
     expect(0, header.X);
     expect(0, header.Y);
-    todo_wine expect(100, header.Width);
-    todo_wine expect(100, header.Height);
+    expect(100, header.Width);
+    expect(100, header.Height);
     expect(0, header.EmfPlusHeaderSize);
     expect(0, header.LogicalDpiX);
     expect(0, header.LogicalDpiX);
-    todo_wine expect(EMR_HEADER, U(header).EmfHeader.iType);
-    todo_wine expect(25, U(header).EmfHeader.rclBounds.left);
-    todo_wine expect(25, U(header).EmfHeader.rclBounds.top);
-    todo_wine expect(74, U(header).EmfHeader.rclBounds.right);
-    todo_wine expect(74, U(header).EmfHeader.rclBounds.bottom);
+    expect(EMR_HEADER, U(header).EmfHeader.iType);
+    expect(25, U(header).EmfHeader.rclBounds.left);
+    expect(25, U(header).EmfHeader.rclBounds.top);
+    expect(74, U(header).EmfHeader.rclBounds.right);
+    expect(74, U(header).EmfHeader.rclBounds.bottom);
     expect(0, U(header).EmfHeader.rclFrame.left);
     expect(0, U(header).EmfHeader.rclFrame.top);
     todo_wine expectf_(100.0, U(header).EmfHeader.rclFrame.right * xres / 2540.0, 2.0);
-- 
2.1.4



More information about the wine-patches mailing list