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
This commit is contained in:
Vadim Zeitlin
2011-04-26 22:57:42 +00:00
parent 42604e44be
commit a152f137f6

View File

@@ -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;
}
::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
::SetWindowExtEx(GetHdc(), width, height, NULL);
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(), devExtX, devExtY, NULL);
::SetWindowExtEx(GetHdc(), logExtX, logExtY, NULL);
::SetViewportOrgEx(GetHdc(), m_deviceOriginX, m_deviceOriginY, NULL);
::SetWindowOrgEx(GetHdc(), m_logicalOriginX, m_logicalOriginY, NULL);