From: Alexander Kochetkov Subject: [PATCH] gdi32/enhmfdrv: Fix scaling factors for EMR_EXTTEXTOUTW Message-Id: Date: Sat, 19 Feb 2011 02:09:57 +0300 The patch fixes one problem related to bug #22996. From c39646418c896fd2b4d29135a4e9744f61d2e857 Mon Sep 17 00:00:00 2001 From: Alexander Kochetkov 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