[PATCH] gdi32/enhmfdrv: Fix scaling factors for EMR_EXTTEXTOUTW

Alexander Kochetkov al.kochet at gmail.com
Fri Feb 18 17:09:57 CST 2011


The patch fixes one problem related to bug #22996.
-------------- next part --------------
From c39646418c896fd2b4d29135a4e9744f61d2e857 Mon Sep 17 00:00:00 2001
From: Alexander Kochetkov <al.kochet at gmail.com>
Date: Sat, 19 Feb 2011 01:56:01 +0300
Subject: [PATCH] gdi32/enhmfdrv: Fix scaling factors for EMR_EXTTEXTOUTW

---
 dlls/gdi32/enhmfdrv/graphics.c |   30 ++++++++-
 dlls/gdi32/tests/metafile.c    |  136 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 162 insertions(+), 4 deletions(-)

diff --git a/dlls/gdi32/enhmfdrv/graphics.c b/dlls/gdi32/enhmfdrv/graphics.c
index e066d0d..95a8353 100644
--- a/dlls/gdi32/enhmfdrv/graphics.c
+++ b/dlls/gdi32/enhmfdrv/graphics.c
@@ -728,6 +728,8 @@ BOOL CDECL EMFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
     int textHeight = 0;
     int textWidth = 0;
     const UINT textAlign = GetTextAlign(physDev->hdc);
+    const INT graphicsMode = GetGraphicsMode(physDev->hdc);
+    FLOAT exScale, eyScale;
 
     nSize = sizeof(*pemr) + ((count+1) & ~1) * sizeof(WCHAR) + count * sizeof(INT);
 
@@ -735,12 +737,32 @@ BOOL CDECL EMFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
            wine_dbgstr_rect(lprect), count, nSize);
     pemr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nSize);
 
+    if (graphicsMode == GM_COMPATIBLE)
+    {
+        const INT horzSize = GetDeviceCaps(physDev->hdc, HORZSIZE);
+        const INT horzRes  = GetDeviceCaps(physDev->hdc, HORZRES);
+        const INT vertSize = GetDeviceCaps(physDev->hdc, VERTSIZE);
+        const INT vertRes  = GetDeviceCaps(physDev->hdc, VERTRES);
+        SIZE wndext, vportext;
+
+        GetViewportExtEx(physDev->hdc, &vportext);
+        GetWindowExtEx(physDev->hdc, &wndext);
+        exScale = 100.0 * ((FLOAT)horzSize  / (FLOAT)horzRes) /
+                          ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
+        eyScale = 100.0 * ((FLOAT)vertSize  / (FLOAT)vertRes) /
+                          ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
+    }
+    else
+    {
+        exScale = 0.0;
+        eyScale = 0.0;
+    }
+
     pemr->emr.iType = EMR_EXTTEXTOUTW;
     pemr->emr.nSize = nSize;
-
-    pemr->iGraphicsMode = GetGraphicsMode(physDev->hdc);
-    pemr->exScale = pemr->eyScale = 1.0; /* FIXME */
-
+    pemr->iGraphicsMode = graphicsMode;
+    pemr->exScale = exScale;
+    pemr->eyScale = eyScale;
     pemr->emrtext.ptlReference.x = x;
     pemr->emrtext.ptlReference.y = y;
     pemr->emrtext.nChars = count;
diff --git a/dlls/gdi32/tests/metafile.c b/dlls/gdi32/tests/metafile.c
index a4630f1..9ccb9ce 100644
--- a/dlls/gdi32/tests/metafile.c
+++ b/dlls/gdi32/tests/metafile.c
@@ -264,6 +264,141 @@ static void test_ExtTextOut(void)
     DestroyWindow(hwnd);
 }
 
+struct eto_scale_test_record
+{
+    INT graphics_mode;
+    INT map_mode;
+    double ex_scale;
+    double ey_scale;
+    BOOL processed;
+};
+
+static int CALLBACK eto_scale_enum_proc(HDC hdc, HANDLETABLE *handle_table,
+    const ENHMETARECORD *emr, int n_objs, LPARAM param)
+{
+    struct eto_scale_test_record *test = (struct eto_scale_test_record*)param;
+
+    if (emr->iType == EMR_EXTTEXTOUTW)
+    {
+        const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)emr;
+        trace("gm %d, mm %d, scale %f, %f, expected %f, %f\n",
+              test->graphics_mode, test->map_mode,
+              pExtTextOutW->exScale, pExtTextOutW->eyScale,
+              test->ex_scale, test->ey_scale);
+        ok(fabs(test->ex_scale - pExtTextOutW->exScale) < 0.001,
+           "Got exScale %f, expected %f\n", pExtTextOutW->exScale, test->ex_scale);
+        ok(fabs(test->ey_scale - pExtTextOutW->eyScale) < 0.001,
+           "Got eyScale %f, expected %f\n", pExtTextOutW->eyScale, test->ey_scale);
+        test->processed = TRUE;
+    }
+
+    return 1;
+}
+
+static void test_ExtTextOutScale(void)
+{
+    const RECT rc = { 0, 0, 100, 100 };
+    const WCHAR str[] = {'a',0 };
+    struct eto_scale_test_record test;
+    HDC hdcDisplay, hdcMetafile;
+    HENHMETAFILE hMetafile;
+    HWND hwnd;
+    SIZE wndext, vportext;
+    int horzSize, vertSize, horzRes, vertRes;
+    int ret;
+    int i;
+
+    hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
+                           0, 0, 200, 200, 0, 0, 0, NULL);
+    ok(hwnd != 0, "CreateWindowExA failed\n");
+
+    hdcDisplay = GetDC(hwnd);
+    ok(hdcDisplay != 0, "GetDC failed\n");
+
+    horzSize = GetDeviceCaps(hdcDisplay, HORZSIZE);
+    horzRes  = GetDeviceCaps(hdcDisplay, HORZRES);
+    vertSize = GetDeviceCaps(hdcDisplay, VERTSIZE);
+    vertRes  = GetDeviceCaps(hdcDisplay, VERTRES);
+    ok(horzSize && horzRes && vertSize && vertRes, "GetDeviceCaps failed\n");
+
+    for (i = 0; i < 16; i++)
+    {
+        test.graphics_mode = i / 8 + 1;
+        test.map_mode      = i % 8 + 1;
+
+        ret = SetGraphicsMode(hdcDisplay, test.graphics_mode);
+        ok(ret, "SetGraphicsMode failed\n");
+        ret = SetMapMode(hdcDisplay, test.map_mode);
+        ok(ret, "SetMapMode failed\n");
+
+        if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
+        {
+            ret = SetWindowExtEx(hdcDisplay, 1, 1, NULL);
+            ok(ret, "SetWindowExtEx failed\n");
+            ret = SetViewportExtEx(hdcDisplay, -20, -10, NULL);
+            ok(ret, "SetViewportExtEx failed\n");
+        }
+
+        ret = GetViewportExtEx(hdcDisplay, &vportext);
+        ok(ret, "GetViewportExtEx failed\n");
+        ret = GetWindowExtEx(hdcDisplay, &wndext);
+        ok(ret, "GetWindowExtEx failed\n");
+
+        trace("gm %d, mm %d, wnd %d,%d, vp %d,%d horz %d,%d vert %d,%d\n",
+               test.graphics_mode, test.map_mode,
+               wndext.cx, wndext.cy, vportext.cx, vportext.cy,
+               horzSize, horzRes, vertSize, vertRes);
+
+        if (test.graphics_mode == GM_COMPATIBLE)
+        {
+            test.ex_scale = 100.0 * ((FLOAT)horzSize  / (FLOAT)horzRes) /
+                                    ((FLOAT)wndext.cx / (FLOAT)vportext.cx);
+            test.ey_scale = 100.0 * ((FLOAT)vertSize  / (FLOAT)vertRes) /
+                                    ((FLOAT)wndext.cy / (FLOAT)vportext.cy);
+        }
+        else
+        {
+            test.ex_scale = 0.0;
+            test.ey_scale = 0.0;
+        }
+
+        hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
+        ok(hdcMetafile != 0, "CreateEnhMetaFileA failed\n");
+
+        ret = SetGraphicsMode(hdcMetafile, test.graphics_mode);
+        ok(ret, "SetGraphicsMode failed\n");
+        ret = SetMapMode(hdcMetafile, test.map_mode);
+        ok(ret, "SetMapMode failed\n");
+
+        if ((test.map_mode == MM_ISOTROPIC) || (test.map_mode == MM_ANISOTROPIC))
+        {
+            ret = SetWindowExtEx(hdcMetafile, 1, 1, NULL);
+            ok(ret, "SetWindowExtEx failed\n");
+            ret = SetViewportExtEx(hdcMetafile, -20, -10, NULL);
+            ok(ret, "SetViewportExtEx failed\n");
+        }
+
+        ret = ExtTextOutW(hdcMetafile, 0, 0, 0, 0, str, 1, NULL);
+        ok(ret, "ExtTextOutW failed\n");
+
+        hMetafile = CloseEnhMetaFile(hdcMetafile);
+        ok(hMetafile != 0, "CloseEnhMetaFile failed\n");
+
+        test.processed = 0;
+        ret = EnumEnhMetaFile(hdcDisplay, hMetafile, eto_scale_enum_proc, &test, &rc);
+        ok(ret, "EnumEnhMetaFile failed\n");
+        ok(test.processed, "EnumEnhMetaFile couldn't find EMR_EXTTEXTOUTW record\n");
+
+        ret = DeleteEnhMetaFile(hMetafile);
+        ok(ret, "DeleteEnhMetaFile failed\n");
+    }
+
+    ret = ReleaseDC(hwnd, hdcDisplay);
+    ok(ret, "ReleaseDC failed\n");
+    DestroyWindow(hwnd);
+}
+
+
 static void check_dc_state(HDC hdc, int restore_no,
                            int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
                            int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
@@ -2779,6 +2914,7 @@ START_TEST(metafile)
 
     /* For enhanced metafiles (enhmfdrv) */
     test_ExtTextOut();
+    test_ExtTextOutScale();
     test_SaveDC();
     test_emf_BitBlt();
 
-- 
1.7.0.4


More information about the wine-patches mailing list