Michael Kaufmann : gdi: Fixes for the isotropic mapping mode.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Jan 31 06:04:29 CST 2006


Module: wine
Branch: refs/heads/master
Commit: 5c6301a5c948e87b714e09db4e771a3070e15b32
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=5c6301a5c948e87b714e09db4e771a3070e15b32

Author: Michael Kaufmann <hallo at michael-kaufmann.ch>
Date:   Tue Jan 31 12:56:57 2006 +0100

gdi: Fixes for the isotropic mapping mode.
- Isotropic mapping mode: Adjust the viewport extension in
  SetWindowExtEx, handle negative extents.
- Support the isotropic mapping mode in the enhanced metafile driver.
- New tests.

---

 dlls/gdi/enhmetafile.c   |   37 +++++++++++++++--
 dlls/gdi/mapping.c       |   24 +++++++----
 dlls/gdi/tests/mapping.c |  101 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 149 insertions(+), 13 deletions(-)

diff --git a/dlls/gdi/enhmetafile.c b/dlls/gdi/enhmetafile.c
index c97e4ca..8725f9b 100644
--- a/dlls/gdi/enhmetafile.c
+++ b/dlls/gdi/enhmetafile.c
@@ -595,6 +595,33 @@ static void EMF_SetMapMode(HDC hdc, enum
     }
 }
 
+/***********************************************************************
+ *           EMF_FixIsotropic
+ *
+ * Fix viewport extensions for isotropic mode.
+ */
+
+static void EMF_FixIsotropic(HDC hdc, enum_emh_data *info)
+{
+    double xdim = fabs((double)info->vportExtX * GetDeviceCaps( hdc, HORZSIZE ) /
+                  (GetDeviceCaps( hdc, HORZRES ) * info->wndExtX));
+    double ydim = fabs((double)info->vportExtY * GetDeviceCaps( hdc, VERTSIZE ) /
+                  (GetDeviceCaps( hdc, VERTRES ) * info->wndExtY));
+
+    if (xdim > ydim)
+    {
+        INT mincx = (info->vportExtX >= 0) ? 1 : -1;
+        info->vportExtX = floor(info->vportExtX * ydim / xdim + 0.5);
+        if (!info->vportExtX) info->vportExtX = mincx;
+    }
+    else
+    {
+        INT mincy = (info->vportExtY >= 0) ? 1 : -1;
+        info->vportExtY = floor(info->vportExtY * xdim / ydim + 0.5);
+        if (!info->vportExtY) info->vportExtY = mincy;
+    }
+}
+
 /*****************************************************************************
  *       emr_produces_output
  *
@@ -829,6 +856,8 @@ BOOL WINAPI PlayEnhMetaFileRecord(
 	    break;
         info->wndExtX = pSetWindowExtEx->szlExtent.cx;
         info->wndExtY = pSetWindowExtEx->szlExtent.cy;
+        if (info->mode == MM_ISOTROPIC)
+            EMF_FixIsotropic(hdc, info);
 
         TRACE("SetWindowExtEx: %d,%d\n",info->wndExtX,info->wndExtY);
 	break;
@@ -852,6 +881,8 @@ BOOL WINAPI PlayEnhMetaFileRecord(
 	    break;
         info->vportExtX = pSetViewportExtEx->szlExtent.cx;
         info->vportExtY = pSetViewportExtEx->szlExtent.cy;
+        if (info->mode == MM_ISOTROPIC)
+            EMF_FixIsotropic(hdc, info);
         TRACE("SetViewportExtEx: %d,%d\n",info->vportExtX,info->vportExtY);
 	break;
       }
@@ -1316,8 +1347,7 @@ BOOL WINAPI PlayEnhMetaFileRecord(
         if (info->vportExtX == 0) info->vportExtX = 1;
         if (info->vportExtY == 0) info->vportExtY = 1;
         if (info->mode == MM_ISOTROPIC)
-            FIXME("EMRSCALEVIEWPORTEXTEX MM_ISOTROPIC mapping\n");
-            /* MAPPING_FixIsotropic( dc ); */
+            EMF_FixIsotropic(hdc, info);
 
         TRACE("EMRSCALEVIEWPORTEXTEX %ld/%ld %ld/%ld\n",
              lpScaleViewportExtEx->xNum,lpScaleViewportExtEx->xDenom,
@@ -1342,8 +1372,7 @@ BOOL WINAPI PlayEnhMetaFileRecord(
         if (info->wndExtX == 0) info->wndExtX = 1;
         if (info->wndExtY == 0) info->wndExtY = 1;
         if (info->mode == MM_ISOTROPIC)
-            FIXME("EMRSCALEWINDOWEXTEX MM_ISOTROPIC mapping\n");
-            /* MAPPING_FixIsotropic( dc ); */
+            EMF_FixIsotropic(hdc, info);
 
         TRACE("EMRSCALEWINDOWEXTEX %ld/%ld %ld/%ld\n",
              lpScaleWindowExtEx->xNum,lpScaleWindowExtEx->xDenom,
diff --git a/dlls/gdi/mapping.c b/dlls/gdi/mapping.c
index 507c789..7a1b947 100644
--- a/dlls/gdi/mapping.c
+++ b/dlls/gdi/mapping.c
@@ -33,19 +33,22 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdi);
  */
 void MAPPING_FixIsotropic( DC * dc )
 {
-    double xdim = (double)dc->vportExtX * GetDeviceCaps( dc->hSelf, HORZSIZE ) /
-                  (GetDeviceCaps( dc->hSelf, HORZRES ) * dc->wndExtX);
-    double ydim = (double)dc->vportExtY * GetDeviceCaps( dc->hSelf, VERTSIZE ) /
-                  (GetDeviceCaps( dc->hSelf, VERTRES ) * dc->wndExtY);
+    double xdim = fabs((double)dc->vportExtX * GetDeviceCaps( dc->hSelf, HORZSIZE ) /
+                  (GetDeviceCaps( dc->hSelf, HORZRES ) * dc->wndExtX));
+    double ydim = fabs((double)dc->vportExtY * GetDeviceCaps( dc->hSelf, VERTSIZE ) /
+                  (GetDeviceCaps( dc->hSelf, VERTRES ) * dc->wndExtY));
+
     if (xdim > ydim)
     {
-	dc->vportExtX = floor(dc->vportExtX * fabs( ydim / xdim ) + 0.5);
-	if (!dc->vportExtX) dc->vportExtX = 1;
+        INT mincx = (dc->vportExtX >= 0) ? 1 : -1;
+        dc->vportExtX = floor(dc->vportExtX * ydim / xdim + 0.5);
+        if (!dc->vportExtX) dc->vportExtX = mincx;
     }
     else
     {
-	dc->vportExtY = floor(dc->vportExtY * fabs( xdim / ydim ) + 0.5);
-	if (!dc->vportExtY) dc->vportExtY = 1;
+        INT mincy = (dc->vportExtY >= 0) ? 1 : -1;
+        dc->vportExtY = floor(dc->vportExtY * xdim / ydim + 0.5);
+        if (!dc->vportExtY) dc->vportExtY = mincy;
     }
 }
 
@@ -326,7 +329,10 @@ BOOL WINAPI SetWindowExtEx( HDC hdc, INT
     }
     dc->wndExtX = x;
     dc->wndExtY = y;
-    /* Windows fixes MM_ISOTROPIC mode only in SetViewportExtEx() */
+    /* The API docs say that you should call SetWindowExtEx before
+       SetViewportExtEx. This advice does not imply that Windows
+       doesn't ensure the isotropic mapping after SetWindowExtEx! */
+    if (dc->MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
     DC_UpdateXforms( dc );
  done:
     GDI_ReleaseObj( hdc );
diff --git a/dlls/gdi/tests/mapping.c b/dlls/gdi/tests/mapping.c
index a7fdda9..0dbc89a 100644
--- a/dlls/gdi/tests/mapping.c
+++ b/dlls/gdi/tests/mapping.c
@@ -53,7 +53,108 @@ void test_modify_world_transform(void)
     ReleaseDC(0, hdc);
 }
 
+void test_SetWindowExt(HDC hdc, LONG cx, LONG cy, LONG expected_vp_cx, LONG expected_vp_cy)
+{
+    SIZE windowExt, viewportExt;
+    POINT windowOrg, windowOrgAfter, viewportOrg, viewportOrgAfter;
+
+    GetWindowOrgEx(hdc, &windowOrg);
+    GetViewportOrgEx(hdc, &viewportOrg);
+
+    SetWindowExtEx(hdc, cx, cy, NULL);
+    GetWindowExtEx(hdc, &windowExt);
+    ok(windowExt.cx == cx && windowExt.cy == cy,
+       "Window extension: Expected %ldx%ld, got %ldx%ld\n",
+       cx, cy, windowExt.cx, windowExt.cy);
+
+    GetViewportExtEx(hdc, &viewportExt);
+    ok(viewportExt.cx == expected_vp_cx && viewportExt.cy == expected_vp_cy,
+        "Viewport extents have not been properly adjusted: Expected %ldx%ld, got %ldx%ld\n",
+        expected_vp_cx, expected_vp_cy, viewportExt.cx, viewportExt.cy);
+
+    GetWindowOrgEx(hdc, &windowOrgAfter);
+    ok(windowOrg.x == windowOrgAfter.x && windowOrg.y == windowOrgAfter.y,
+        "Window origin changed from (%ld,%ld) to (%ld,%ld)\n",
+        windowOrg.x, windowOrg.y, windowOrgAfter.x, windowOrgAfter.y);
+
+    GetViewportOrgEx(hdc, &viewportOrgAfter);
+    ok(viewportOrg.x == viewportOrgAfter.x && viewportOrg.y == viewportOrgAfter.y,
+        "Viewport origin changed from (%ld,%ld) to (%ld,%ld)\n",
+        viewportOrg.x, viewportOrg.y, viewportOrgAfter.x, viewportOrgAfter.y);
+}
+
+void test_SetViewportExt(HDC hdc, LONG cx, LONG cy, LONG expected_vp_cx, LONG expected_vp_cy)
+{
+    SIZE windowExt, windowExtAfter, viewportExt;
+    POINT windowOrg, windowOrgAfter, viewportOrg, viewportOrgAfter;
+
+    GetWindowOrgEx(hdc, &windowOrg);
+    GetViewportOrgEx(hdc, &viewportOrg);
+    GetWindowExtEx(hdc, &windowExt);
+
+    SetViewportExtEx(hdc, cx, cy, NULL);
+    GetViewportExtEx(hdc, &viewportExt);
+    ok(viewportExt.cx == expected_vp_cx && viewportExt.cy == expected_vp_cy,
+        "Viewport extents have not been properly adjusted: Expected %ldx%ld, got %ldx%ld\n",
+        expected_vp_cx, expected_vp_cy, viewportExt.cx, viewportExt.cy);
+
+    GetWindowExtEx(hdc, &windowExtAfter);
+    ok(windowExt.cx == windowExtAfter.cx && windowExt.cy == windowExtAfter.cy,
+       "Window extension changed from %ldx%ld to %ldx%ld\n",
+       windowExt.cx, windowExt.cy, windowExtAfter.cx, windowExtAfter.cy);
+
+    GetWindowOrgEx(hdc, &windowOrgAfter);
+    ok(windowOrg.x == windowOrgAfter.x && windowOrg.y == windowOrgAfter.y,
+        "Window origin changed from (%ld,%ld) to (%ld,%ld)\n",
+        windowOrg.x, windowOrg.y, windowOrgAfter.x, windowOrgAfter.y);
+
+    GetViewportOrgEx(hdc, &viewportOrgAfter);
+    ok(viewportOrg.x == viewportOrgAfter.x && viewportOrg.y == viewportOrgAfter.y,
+        "Viewport origin changed from (%ld,%ld) to (%ld,%ld)\n",
+        viewportOrg.x, viewportOrg.y, viewportOrgAfter.x, viewportOrgAfter.y);
+}
+
+void test_isotropic_mapping(void)
+{
+    SIZE win, vp;
+    HDC hdc = GetDC(0);
+    
+    SetMapMode(hdc, MM_ISOTROPIC);
+    
+    /* MM_ISOTROPIC is set up like MM_LOMETRIC.
+       Initial values after SetMapMode():
+       (1 inch = 25.4 mm)
+       
+                       Windows 9x:               Windows NT:
+       Window Ext:     254 x -254                HORZSIZE*10 x VERTSIZE*10
+       Viewport Ext:   LOGPIXELSX x LOGPIXELSY   HORZRES x -VERTRES
+       
+       To test without rounding errors, we have to use multiples of
+       these values!
+     */
+    
+    GetWindowExtEx(hdc, &win);
+    GetViewportExtEx(hdc, &vp);
+    
+    test_SetViewportExt(hdc, 10 * vp.cx, 10 * vp.cy, 10 * vp.cx, 10 * vp.cy);
+    test_SetWindowExt(hdc, win.cx, win.cy, 10 * vp.cx, 10 * vp.cy);
+    test_SetWindowExt(hdc, 2 * win.cx, win.cy, 10 * vp.cx, 5 * vp.cy);
+    test_SetWindowExt(hdc, win.cx, win.cy, 5 * vp.cx, 5 * vp.cy);
+    test_SetViewportExt(hdc, 4 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy);
+    test_SetViewportExt(hdc, vp.cx, 2 * vp.cy, vp.cx, vp.cy);
+    test_SetViewportExt(hdc, 2 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy);
+    test_SetViewportExt(hdc, 4 * vp.cx, 2 * vp.cy, 2 * vp.cx, 2 * vp.cy);
+    test_SetWindowExt(hdc, 4 * win.cx, 2 * win.cy, 2 * vp.cx, vp.cy);
+    test_SetViewportExt(hdc, -2 * vp.cx, -4 * vp.cy, -2 * vp.cx, -vp.cy);
+    test_SetViewportExt(hdc, -2 * vp.cx, -1 * vp.cy, -2 * vp.cx, -vp.cy);    
+    test_SetWindowExt(hdc, -4 * win.cx, -2 * win.cy, -2 * vp.cx, -vp.cy);
+    test_SetWindowExt(hdc, 4 * win.cx, -4 * win.cy, -vp.cx, -vp.cy);
+    
+    ReleaseDC(0, hdc);
+}
+
 START_TEST(mapping)
 {
     test_modify_world_transform();
+    test_isotropic_mapping();
 }




More information about the wine-cvs mailing list