]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/dc.cpp
More small fixes
[wxWidgets.git] / src / msw / dc.cpp
index 90433d392f8ed5887b35c637dbe6e8ae6239866b..f0135c90d9355870cf44aaaf4d35860ca6f39da7 100644 (file)
@@ -40,6 +40,7 @@
     #include "wx/icon.h"
 #endif
 
     #include "wx/icon.h"
 #endif
 
+#include "wx/settings.h"
 #include "wx/dcprint.h"
 
 #include <string.h>
 #include "wx/dcprint.h"
 
 #include <string.h>
@@ -183,23 +184,34 @@ wxDC::wxDC()
 
     m_windowExtX = VIEWPORT_EXTENT;
     m_windowExtY = VIEWPORT_EXTENT;
 
     m_windowExtX = VIEWPORT_EXTENT;
     m_windowExtY = VIEWPORT_EXTENT;
-
-    m_hDCCount = 0;
 }
 
 
 wxDC::~wxDC()
 {
 }
 
 
 wxDC::~wxDC()
 {
-    if ( m_hDC != 0 ) {
+    if ( m_hDC != 0 )
+    {
         SelectOldObjects(m_hDC);
         SelectOldObjects(m_hDC);
-        if ( m_bOwnsDC ) {
-            if ( m_canvas == NULL )
-                ::DeleteDC(GetHdc());
+
+        // if we own the HDC, we delete it, otherwise we just release it
+
+        if ( m_bOwnsDC )
+        {
+            ::DeleteDC(GetHdc());
+        }
+        else // we don't own our HDC
+        {
+            if (m_canvas)
+            {
+                ::ReleaseDC(GetHwndOf(m_canvas), GetHdc());
+            }
             else
             else
-                ::ReleaseDC((HWND)m_canvas->GetHWND(), GetHdc());
+            {
+                // Must have been a wxScreenDC
+                ::ReleaseDC((HWND) NULL, GetHdc());
+            }
         }
     }
         }
     }
-
 }
 
 // This will select current objects out of the DC,
 }
 
 // This will select current objects out of the DC,
@@ -252,39 +264,57 @@ void wxDC::SelectOldObjects(WXHDC dc)
 // clipping
 // ---------------------------------------------------------------------------
 
 // clipping
 // ---------------------------------------------------------------------------
 
-#define DO_SET_CLIPPING_BOX()                   \
-{                                               \
-    RECT rect;                                  \
-                                                \
-    GetClipBox(GetHdc(), &rect);                \
-                                                \
-    m_clipX1 = (wxCoord) XDEV2LOG(rect.left);   \
-    m_clipY1 = (wxCoord) YDEV2LOG(rect.top);    \
-    m_clipX2 = (wxCoord) XDEV2LOG(rect.right);  \
-    m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom); \
+void wxDC::UpdateClipBox()
+{
+    RECT rect;
+    GetClipBox(GetHdc(), &rect);
+
+    m_clipX1 = (wxCoord) XDEV2LOG(rect.left);
+    m_clipY1 = (wxCoord) YDEV2LOG(rect.top);
+    m_clipX2 = (wxCoord) XDEV2LOG(rect.right);
+    m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom);
 }
 
 }
 
-void wxDC::DoSetClippingRegion(wxCoord cx, wxCoord cy, wxCoord cw, wxCoord ch)
+void wxDC::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
 {
     m_clipping = TRUE;
 {
     m_clipping = TRUE;
-    IntersectClipRect(GetHdc(), XLOG2DEV(cx), YLOG2DEV(cy),
-                                XLOG2DEV(cx + cw), YLOG2DEV(cy + ch));
-    DO_SET_CLIPPING_BOX()
+
+    // the region coords are always the device ones, so do the translation
+    // manually
+    //
+    // FIXME: possible +/-1 error here, to check!
+    HRGN hrgn = ::CreateRectRgn(LogicalToDeviceX(x),
+                                LogicalToDeviceY(y),
+                                LogicalToDeviceX(x + w),
+                                LogicalToDeviceY(y + h));
+    if ( !hrgn )
+    {
+        wxLogLastError(_T("CreateRectRgn"));
+    }
+    else
+    {
+        if ( ::SelectClipRgn(GetHdc(), hrgn) == ERROR )
+        {
+            wxLogLastError(_T("SelectClipRgn"));
+        }
+
+        UpdateClipBox();
+    }
 }
 
 void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region)
 {
 }
 
 void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region)
 {
-    wxCHECK_RET( region.GetHRGN(), wxT("invalid clipping region") );
+    wxCHECK_RET( GetHrgnOf(region), wxT("invalid clipping region") );
 
     m_clipping = TRUE;
 
 #ifdef __WIN16__
 
     m_clipping = TRUE;
 
 #ifdef __WIN16__
-    SelectClipRgn(GetHdc(), (HRGN) region.GetHRGN());
-#else
-    ExtSelectClipRgn(GetHdc(), (HRGN) region.GetHRGN(), RGN_AND);
-#endif
+    SelectClipRgn(GetHdc(), GetHrgnOf(region));
+#else // Win32
+    ExtSelectClipRgn(GetHdc(), GetHrgnOf(region), RGN_AND);
+#endif // Win16/32
 
 
-    DO_SET_CLIPPING_BOX()
+    UpdateClipBox();
 }
 
 void wxDC::DestroyClippingRegion()
 }
 
 void wxDC::DestroyClippingRegion()
@@ -298,6 +328,7 @@ void wxDC::DestroyClippingRegion()
         SelectClipRgn(GetHdc(), rgn);
         DeleteObject(rgn);
     }
         SelectClipRgn(GetHdc(), rgn);
         DeleteObject(rgn);
     }
+
     m_clipping = FALSE;
 }
 
     m_clipping = FALSE;
 }
 
@@ -757,16 +788,23 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask
     if ( useMask )
     {
 #ifdef __WIN32__
     if ( useMask )
     {
 #ifdef __WIN32__
-        HDC hdcMem = ::CreateCompatibleDC(GetHdc());
-        ::SelectObject(hdcMem, GetHbitmapOf(bmp));
-
         // use MaskBlt() with ROP which doesn't do anything to dst in the mask
         // points
         // use MaskBlt() with ROP which doesn't do anything to dst in the mask
         // points
-        bool ok = ::MaskBlt(GetHdc(), x, y, width, height,
+        // On some systems, MaskBlt succeeds yet is much much slower
+        // than the wxWindows fall-back implementation. So we need
+        // to be able to switch this on and off at runtime.
+        bool ok = FALSE;
+        if (wxSystemSettings::GetOptionInt(wxT("no-maskblt")) == 0)
+        {
+            HDC hdcMem = ::CreateCompatibleDC(GetHdc());
+            ::SelectObject(hdcMem, GetHbitmapOf(bmp));
+
+            ok = ::MaskBlt(GetHdc(), x, y, width, height,
                             hdcMem, 0, 0,
                             hbmpMask, 0, 0,
                             MAKEROP4(SRCCOPY, DSTCOPY)) != 0;
                             hdcMem, 0, 0,
                             hbmpMask, 0, 0,
                             MAKEROP4(SRCCOPY, DSTCOPY)) != 0;
-        ::DeleteDC(hdcMem);
+            ::DeleteDC(hdcMem);
+        }
 
         if ( !ok )
 #endif // Win32
 
         if ( !ok )
 #endif // Win32
@@ -1160,7 +1198,7 @@ void wxDC::SetRop(WXHDC dc)
     SetROP2(GetHdc(), rop);
 }
 
     SetROP2(GetHdc(), rop);
 }
 
-bool wxDC::StartDoc(const wxString& message)
+bool wxDC::StartDoc(const wxString& WXUNUSED(message))
 {
     // We might be previewing, so return TRUE to let it continue.
     return TRUE;
 {
     // We might be previewing, so return TRUE to let it continue.
     return TRUE;
@@ -1202,22 +1240,35 @@ wxCoord wxDC::GetCharWidth() const
 
 void wxDC::DoGetTextExtent(const wxString& string, wxCoord *x, wxCoord *y,
                            wxCoord *descent, wxCoord *externalLeading,
 
 void wxDC::DoGetTextExtent(const wxString& string, wxCoord *x, wxCoord *y,
                            wxCoord *descent, wxCoord *externalLeading,
-                           wxFont *theFont) const
+                           wxFont *font) const
 {
 {
-    wxFont *fontToUse = (wxFont*) theFont;
-    if (!fontToUse)
-        fontToUse = (wxFont*) &m_font;
+    HFONT hfontOld;
+    if ( font )
+    {
+        wxASSERT_MSG( font->Ok(), _T("invalid font in wxDC::GetTextExtent") );
+
+        hfontOld = (HFONT)::SelectObject(GetHdc(), GetHfontOf(*font));
+    }
+    else // don't change the font
+    {
+        hfontOld = 0;
+    }
 
     SIZE sizeRect;
     TEXTMETRIC tm;
 
 
     SIZE sizeRect;
     TEXTMETRIC tm;
 
-    GetTextExtentPoint(GetHdc(), WXSTRINGCAST string, wxStrlen(WXSTRINGCAST string), &sizeRect);
+    GetTextExtentPoint(GetHdc(), string, string.length(), &sizeRect);
     GetTextMetrics(GetHdc(), &tm);
 
     if (x) *x = XDEV2LOGREL(sizeRect.cx);
     if (y) *y = YDEV2LOGREL(sizeRect.cy);
     if (descent) *descent = tm.tmDescent;
     if (externalLeading) *externalLeading = tm.tmExternalLeading;
     GetTextMetrics(GetHdc(), &tm);
 
     if (x) *x = XDEV2LOGREL(sizeRect.cx);
     if (y) *y = YDEV2LOGREL(sizeRect.cy);
     if (descent) *descent = tm.tmDescent;
     if (externalLeading) *externalLeading = tm.tmExternalLeading;
+
+    if ( hfontOld )
+    {
+        ::SelectObject(GetHdc(), hfontOld);
+    }
 }
 
 void wxDC::SetMapMode(int mode)
 }
 
 void wxDC::SetMapMode(int mode)
@@ -1434,7 +1485,7 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
            return FALSE;
     }
 
            return FALSE;
     }
 
-    bool success;
+    bool success = FALSE;
 
     if (useMask)
     {
 
     if (useMask)
     {
@@ -1443,10 +1494,17 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest,
         // transparent, so use "DSTCOPY" ROP for the mask points (the usual
         // meaning of fg and bg is inverted which corresponds to wxWin notion
         // of the mask which is also contrary to the Windows one)
         // transparent, so use "DSTCOPY" ROP for the mask points (the usual
         // meaning of fg and bg is inverted which corresponds to wxWin notion
         // of the mask which is also contrary to the Windows one)
-        success = ::MaskBlt(GetHdc(), xdest, ydest, width, height,
+
+        // On some systems, MaskBlt succeeds yet is much much slower
+        // than the wxWindows fall-back implementation. So we need
+        // to be able to switch this on and off at runtime.
+        if (wxSystemSettings::GetOptionInt(wxT("no-maskblt")) == 0)
+        {
+           success = ::MaskBlt(GetHdc(), xdest, ydest, width, height,
                             GetHdcOf(*source), xsrc, ysrc,
                             (HBITMAP)mask->GetMaskBitmap(), xsrc, ysrc,
                             MAKEROP4(dwRop, DSTCOPY)) != 0;
                             GetHdcOf(*source), xsrc, ysrc,
                             (HBITMAP)mask->GetMaskBitmap(), xsrc, ysrc,
                             MAKEROP4(dwRop, DSTCOPY)) != 0;
+        }
 
         if ( !success )
 #endif // Win32
 
         if ( !success )
 #endif // Win32