[3/3] gdi32: Make generated EMFs fully match Windows ones

Dmitry Timoshkov dmitry at codeweavers.com
Sun May 25 07:32:31 CDT 2008


Hello,

all this patch does is adds saving/restoring clipping region, and removes
saving/restoring current font on MF/EMF playing, doesn't write an original
metafile as a GDI comment EMF record if mapping mode is MM_TEXT, adds
saving/restoring current palette on old metafile creation (as the generated
EMFs show).

I had to change indentation of some parts of the code, and that makes
the patch look large.

As a result no compare_emf_bits() calls have the todo parameter set to TRUE.
I decided to not remove the todo parameter altogether to allow adding new
tests with possibly incompatible with Wine EMF structure.

Changelog:
    gdi32: Make generated EMFs fully match Windows ones.
---
 dlls/gdi32/enhmetafile.c    |   89 +++++++++++++++++++++++-------------------
 dlls/gdi32/metafile.c       |   19 ++++++++-
 dlls/gdi32/tests/metafile.c |   10 ++--
 3 files changed, 70 insertions(+), 48 deletions(-)

diff --git a/dlls/gdi32/enhmetafile.c b/dlls/gdi32/enhmetafile.c
index 1041594..b20f442 100644
--- a/dlls/gdi32/enhmetafile.c
+++ b/dlls/gdi32/enhmetafile.c
@@ -2257,6 +2257,7 @@ BOOL WINAPI EnumEnhMetaFile(
     HPEN hPen = NULL;
     HBRUSH hBrush = NULL;
     HFONT hFont = NULL;
+    HRGN hRgn = NULL;
     enum_emh_data *info;
     SIZE vp_size, win_size;
     POINT vp_org, win_org;
@@ -2311,11 +2312,18 @@ BOOL WINAPI EnumEnhMetaFile(
         GetWindowOrgEx(hdc, &win_org);
         mapMode = GetMapMode(hdc);
 
-	/* save the current pen, brush and font */
+	/* save DC */
 	hPen = GetCurrentObject(hdc, OBJ_PEN);
 	hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
 	hFont = GetCurrentObject(hdc, OBJ_FONT);
 
+        hRgn = CreateRectRgn(0, 0, 0, 0);
+        if (!GetClipRgn(hdc, hRgn))
+        {
+            DeleteObject(hRgn);
+            hRgn = 0;
+        }
+
         old_text_color = SetTextColor(hdc, RGB(0,0,0));
         old_bk_color = SetBkColor(hdc, RGB(0xff, 0xff, 0xff));
         old_align = SetTextAlign(hdc, 0);
@@ -2410,10 +2418,12 @@ BOOL WINAPI EnumEnhMetaFile(
         SetBkColor(hdc, old_bk_color);
         SetTextColor(hdc, old_text_color);
 
-	/* restore pen, brush and font */
+	/* restore DC */
 	SelectObject(hdc, hBrush);
 	SelectObject(hdc, hPen);
 	SelectObject(hdc, hFont);
+        ExtSelectClipRgn(hdc, hRgn, RGN_COPY);
+        DeleteObject(hRgn);
 
 	SetWorldTransform(hdc, &savedXform);
 	if (savedMode)
@@ -2673,9 +2683,8 @@ HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer,
     HENHMETAFILE ret = NULL;
     HDC hdc = NULL, hdcdisp = NULL;
     RECT rc, *prcFrame = NULL;
-    gdi_mf_comment *mfcomment;
-    UINT mfcomment_size;
     LONG mm, xExt, yExt;
+    INT horzsize, vertsize, horzres, vertres;
 
     TRACE("(%d, %p, %p, %p)\n", cbBuffer, lpbBuffer, hdcRef, lpmfp);
 
@@ -2736,49 +2745,49 @@ HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer,
      * Write the original METAFILE into the enhanced metafile.
      * It is encapsulated in a GDICOMMENT_WINDOWS_METAFILE record.
      */
-    mfcomment_size = sizeof (gdi_mf_comment) + cbBuffer;
-    mfcomment = HeapAlloc(GetProcessHeap(), 0, mfcomment_size);
-    if(mfcomment)
-    {
-        mfcomment->ident = GDICOMMENT_IDENTIFIER;
-        mfcomment->iComment = GDICOMMENT_WINDOWS_METAFILE;
-        mfcomment->nVersion = 0x00000300;
-        mfcomment->nChecksum = 0; /* FIXME */
-        mfcomment->fFlags = 0;
-        mfcomment->cbWinMetaFile = cbBuffer;
-        memcpy(&mfcomment[1], lpbBuffer, cbBuffer);
-        GdiComment(hdc, mfcomment_size, (BYTE*) mfcomment);
-        HeapFree(GetProcessHeap(), 0, mfcomment);
-    }
-
     if (mm != MM_TEXT)
-        SetMapMode(hdc, mm);
-
-    if (mm == MM_ISOTROPIC || mm == MM_ANISOTROPIC)
     {
-        INT horzsize, vertsize, horzres, vertres;
+        gdi_mf_comment *mfcomment;
+        UINT mfcomment_size;
 
-        horzsize = GetDeviceCaps(hdcRef, HORZSIZE);
-        vertsize = GetDeviceCaps(hdcRef, VERTSIZE);
-        horzres = GetDeviceCaps(hdcRef, HORZRES);
-        vertres = GetDeviceCaps(hdcRef, VERTRES);
-
-        if (!xExt || !yExt)
+        mfcomment_size = sizeof (gdi_mf_comment) + cbBuffer;
+        mfcomment = HeapAlloc(GetProcessHeap(), 0, mfcomment_size);
+        if (mfcomment)
         {
-            /* Use the whole device surface */
-           xExt = horzres;
-           yExt = vertres;
-        }
-        else
-        {
-            xExt = MulDiv(xExt, horzres, 100 * horzsize);
-            yExt = MulDiv(yExt, vertres, 100 * vertsize);
+            mfcomment->ident = GDICOMMENT_IDENTIFIER;
+            mfcomment->iComment = GDICOMMENT_WINDOWS_METAFILE;
+            mfcomment->nVersion = 0x00000300;
+            mfcomment->nChecksum = 0; /* FIXME */
+            mfcomment->fFlags = 0;
+            mfcomment->cbWinMetaFile = cbBuffer;
+            memcpy(&mfcomment[1], lpbBuffer, cbBuffer);
+            GdiComment(hdc, mfcomment_size, (BYTE*) mfcomment);
+            HeapFree(GetProcessHeap(), 0, mfcomment);
         }
+        SetMapMode(hdc, mm);
+    }
 
-        /* set the initial viewport:window ratio as 1:1 */
-        SetViewportExtEx(hdc, xExt, yExt, NULL);
-        SetWindowExtEx(hdc,   xExt, yExt, NULL);
+
+    horzsize = GetDeviceCaps(hdcRef, HORZSIZE);
+    vertsize = GetDeviceCaps(hdcRef, VERTSIZE);
+    horzres = GetDeviceCaps(hdcRef, HORZRES);
+    vertres = GetDeviceCaps(hdcRef, VERTRES);
+
+    if (!xExt || !yExt)
+    {
+        /* Use the whole device surface */
+       xExt = horzres;
+       yExt = vertres;
     }
+    else
+    {
+        xExt = MulDiv(xExt, horzres, 100 * horzsize);
+        yExt = MulDiv(yExt, vertres, 100 * vertsize);
+    }
+
+    /* set the initial viewport:window ratio as 1:1 */
+    SetViewportExtEx(hdc, xExt, yExt, NULL);
+    SetWindowExtEx(hdc,   xExt, yExt, NULL);
 
     PlayMetaFile(hdc, hmf);
 
diff --git a/dlls/gdi32/metafile.c b/dlls/gdi32/metafile.c
index 56404a0..68ec203 100644
--- a/dlls/gdi32/metafile.c
+++ b/dlls/gdi32/metafile.c
@@ -396,6 +396,8 @@ BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
     HPEN hPen;
     HBRUSH hBrush;
     HFONT hFont;
+    HPALETTE hPal;
+    HRGN hRgn;
     BOOL loaded = FALSE;
 
     if (!mh) return FALSE;
@@ -405,10 +407,18 @@ BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
 	loaded = TRUE;
     }
 
-    /* save the current pen, brush and font */
+    /* save DC */
     hPen = GetCurrentObject(hdc, OBJ_PEN);
     hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
     hFont = GetCurrentObject(hdc, OBJ_FONT);
+    hPal = GetCurrentObject(hdc, OBJ_PAL);
+
+    hRgn = CreateRectRgn(0, 0, 0, 0);
+    if (!GetClipRgn(hdc, hRgn))
+    {
+        DeleteObject(hRgn);
+        hRgn = 0;
+    }
 
     /* create the handle table */
     ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
@@ -436,9 +446,12 @@ BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
 	PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects );
     }
 
-    SelectObject(hdc, hBrush);
+    /* restore DC */
     SelectObject(hdc, hPen);
-    SelectObject(hdc, hFont);
+    SelectObject(hdc, hBrush);
+    SelectPalette(hdc, hPal, FALSE);
+    ExtSelectClipRgn(hdc, hRgn, RGN_COPY);
+    DeleteObject(hRgn);
 
     /* free objects in handle table */
     for(i = 0; i < mh->mtNoObjects; i++)
diff --git a/dlls/gdi32/tests/metafile.c b/dlls/gdi32/tests/metafile.c
index 40c7445..5f295bb 100644
--- a/dlls/gdi32/tests/metafile.c
+++ b/dlls/gdi32/tests/metafile.c
@@ -1480,7 +1480,7 @@ static void test_emf_ExtTextOut_on_path(void)
      * are there, but their contents don't match for different reasons.
      */
     if (compare_emf_bits(hMetafile, EMF_TEXTOUT_ON_PATH_BITS, sizeof(EMF_TEXTOUT_ON_PATH_BITS),
-        "emf_TextOut_on_path", FALSE, TRUE) != 0)
+        "emf_TextOut_on_path", FALSE, FALSE) != 0)
     {
         dump_emf_bits(hMetafile, "emf_TextOut_on_path");
         dump_emf_records(hMetafile, "emf_TextOut_on_path");
@@ -1676,7 +1676,7 @@ static void test_emf_clipping(void)
     ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
 
     if (compare_emf_bits(hemf, EMF_CLIPPING, sizeof(EMF_CLIPPING),
-        "emf_clipping", FALSE, TRUE) != 0)
+        "emf_clipping", FALSE, FALSE) != 0)
     {
         dump_emf_bits(hemf, "emf_clipping");
         dump_emf_records(hemf, "emf_clipping");
@@ -1785,7 +1785,7 @@ static void test_mf_conversions(void)
         hemf = create_converted_emf(&mfp);
 
         if (compare_emf_bits(hemf, EMF_LINETO_MM_ANISOTROPIC_BITS, sizeof(EMF_LINETO_MM_ANISOTROPIC_BITS),
-                             "emf_LineTo MM_ANISOTROPIC", TRUE, TRUE) != 0)
+                             "emf_LineTo MM_ANISOTROPIC", TRUE, FALSE) != 0)
         {
             dump_emf_bits(hemf, "emf_LineTo MM_ANISOTROPIC");
             dump_emf_records(hemf, "emf_LineTo MM_ANISOTROPIC");
@@ -1810,7 +1810,7 @@ static void test_mf_conversions(void)
         hemf = create_converted_emf(&mfp);
 
         if (compare_emf_bits(hemf, EMF_LINETO_MM_TEXT_BITS, sizeof(EMF_LINETO_MM_TEXT_BITS),
-                             "emf_LineTo MM_TEXT", TRUE, TRUE) != 0)
+                             "emf_LineTo MM_TEXT", TRUE, FALSE) != 0)
         {
             dump_emf_bits(hemf, "emf_LineTo MM_TEXT");
             dump_emf_records(hemf, "emf_LineTo MM_TEXT");
@@ -1830,7 +1830,7 @@ static void test_mf_conversions(void)
         hemf = create_converted_emf(NULL);
 
         if (compare_emf_bits(hemf, EMF_LINETO_BITS, sizeof(EMF_LINETO_BITS),
-                             "emf_LineTo NULL", TRUE, TRUE) != 0)
+                             "emf_LineTo NULL", TRUE, FALSE) != 0)
         {
             dump_emf_bits(hemf, "emf_LineTo NULL");
             dump_emf_records(hemf, "emf_LineTo NULL");
-- 
1.5.5.1






More information about the wine-patches mailing list