From a152f137f6c21cd47d74df0e7a98cdb55e4ca178 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 26 Apr 2011 22:57:42 +0000 Subject: [PATCH] Avoid rounding errors in wxMSW wxDC scaling code. Multiply by scale factor when it's > 1 and divide by it when it's < 1 to avoid rounding errors. By choosing whether to increase the viewport or window extents we increase precisions without any apparent negative effects (at least under Windows NT where the coordinates in 2^27 range are supported, but even under Windows 9x it's not clear if the old code was better as while we never overflowed the viewport extents, we could overflow the window ones easily for small zoom factors). Closes #9554. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@67623 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/msw/dc.cpp | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 5079795653..17ffaae9bf 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -1967,11 +1967,39 @@ void wxMSWDCImpl::RealizeScaleAndOrigin() #ifndef __WXWINCE__ ::SetMapMode(GetHdc(), MM_ANISOTROPIC); - int width = DeviceToLogicalXRel(VIEWPORT_EXTENT)*m_signX, - height = DeviceToLogicalYRel(VIEWPORT_EXTENT)*m_signY; + // wxWidgets API assumes that the coordinate space is "infinite" (i.e. only + // limited by 2^32 range of the integer coordinates) but in MSW API we must + // actually specify the extents that we use. So we more or less arbitrarily + // decide to use "base" VIEWPORT_EXTENT and adjust it depending on scale. + // + // To avoid rounding errors we prefer to multiply by the scale if it's > 1 + // and to divide by it if it's < 1. + int devExtX, devExtY, // Viewport, i.e. device space, extents. + logExtX, logExtY; // Window, i.e. logical coordinate space, extents. + if ( m_scaleX >= 1 ) + { + devExtX = VIEWPORT_EXTENT*m_scaleX; + logExtX = m_signX*VIEWPORT_EXTENT; + } + else + { + devExtX = VIEWPORT_EXTENT; + logExtX = m_signX*VIEWPORT_EXTENT/m_scaleX; + } + + if ( m_scaleY >= 1 ) + { + devExtY = VIEWPORT_EXTENT*m_scaleY; + logExtY = m_signY*VIEWPORT_EXTENT; + } + else + { + devExtY = VIEWPORT_EXTENT; + logExtY = m_signY*VIEWPORT_EXTENT/m_scaleY; + } - ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL); - ::SetWindowExtEx(GetHdc(), width, height, NULL); + ::SetViewportExtEx(GetHdc(), devExtX, devExtY, NULL); + ::SetWindowExtEx(GetHdc(), logExtX, logExtY, NULL); ::SetViewportOrgEx(GetHdc(), m_deviceOriginX, m_deviceOriginY, NULL); ::SetWindowOrgEx(GetHdc(), m_logicalOriginX, m_logicalOriginY, NULL); -- 2.45.2