]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/dc.cpp
Several corrections to wxDocManager fields documentation.
[wxWidgets.git] / src / msw / dc.cpp
index e0e1ec6523475415acc22f3a6de4b47c28ff85d7..4420abf53a3725da8a5d35fc39e2bb2795662a76 100644 (file)
@@ -34,6 +34,7 @@
     #include "wx/bitmap.h"
     #include "wx/dcmemory.h"
     #include "wx/log.h"
+    #include "wx/math.h"
     #include "wx/icon.h"
     #include "wx/dcprint.h"
     #include "wx/module.h"
@@ -82,7 +83,9 @@ IMPLEMENT_ABSTRACT_CLASS(wxMSWDCImpl, wxDCImpl)
 // constants
 // ---------------------------------------------------------------------------
 
-static const int VIEWPORT_EXTENT = 1024;
+// The device space in Win32 GDI measures 2^27*2^27 , so we use 2^27-1 as the
+// maximal possible view port extent.
+static const int VIEWPORT_EXTENT = 134217727;
 
 // ROPs which don't have standard names (see "Ternary Raster Operations" in the
 // MSDN docs for how this and other numbers in wxDC::Blit() are obtained)
@@ -1959,6 +1962,31 @@ bool wxMSWDCImpl::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widt
     return true;
 }
 
+namespace
+{
+
+void ApplyEffectiveScale(double scale, int sign, int *device, int *logical)
+{
+    // To reduce rounding errors as much as possible, we try to use the largest
+    // possible extent (2^27-1) for the device space but we must also avoid
+    // overflowing the int range i.e. ensure that logical extents are less than
+    // 2^31 in magnitude. So the minimal scale we can use is 1/16 as for
+    // anything smaller VIEWPORT_EXTENT/scale would overflow the int range.
+    static const double MIN_LOGICAL_SCALE = 1./16;
+
+    double physExtent = VIEWPORT_EXTENT;
+    if ( scale < MIN_LOGICAL_SCALE )
+    {
+        physExtent *= scale/MIN_LOGICAL_SCALE;
+        scale = MIN_LOGICAL_SCALE;
+    }
+
+    *device = wxRound(physExtent);
+    *logical = sign*wxRound(VIEWPORT_EXTENT/scale);
+}
+
+} // anonymous namespace
+
 void wxMSWDCImpl::RealizeScaleAndOrigin()
 {
     // although it may seem wasteful to always use MM_ANISOTROPIC here instead
@@ -1969,34 +1997,13 @@ void wxMSWDCImpl::RealizeScaleAndOrigin()
 
     // 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.
+    // actually specify the extents that we use so compute them here.
+
     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;
-    }
+    ApplyEffectiveScale(m_scaleX, m_signX, &devExtX, &logExtX);
+    ApplyEffectiveScale(m_scaleY, m_signY, &devExtY, &logExtY);
 
     ::SetViewportExtEx(GetHdc(), devExtX, devExtY, NULL);
     ::SetWindowExtEx(GetHdc(), logExtX, logExtY, NULL);