]> git.saurik.com Git - wxWidgets.git/commitdiff
Fix drawing of bitmaps with masks in mirrored wxDC.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 9 Feb 2013 00:35:49 +0000 (00:35 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 9 Feb 2013 00:35:49 +0000 (00:35 +0000)
The mask must be mirrored in the same way as the main bitmap itself (currently
it's not mirrored at all but this could change in the future), so create the
temporary memory HDC with the same layout as is used by the main HDC.

Closes #3995.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@73484 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/msw/dc.cpp

index 22bf7df908e09d36be647ac236edd9a7663b57f7..494561562484bfa98f3f095003329cf0d75dfde7 100644 (file)
@@ -149,6 +149,22 @@ wxAlphaBlend(HDC hdcDst, int xDst, int yDst,
 
 #endif // wxHAS_RAW_BITMAP
 
+namespace wxMSW
+{
+
+// Wrappers for the dynamically loaded {Set,Get}Layout() functions. They work
+// in exactly the same way as the standard functions and return GDI_ERROR if
+// they're not actually available.
+DWORD GetLayout(HDC hdc);
+DWORD SetLayout(HDC hdc, DWORD dwLayout);
+
+// Create a compatible HDC and copy the layout of the source DC to it. This is
+// necessary in order to draw bitmaps (which are usually blitted from a
+// temporary compatible memory DC to the real target DC) using the same layout.
+HDC CreateCompatibleDCWithLayout(HDC hdc);
+
+} // namespace wxMSW
+
 // ----------------------------------------------------------------------------
 // private classes
 // ----------------------------------------------------------------------------
@@ -1326,7 +1342,7 @@ void wxMSWDCImpl::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool
 #endif // wxUSE_SYSTEM_OPTIONS
         {
             HDC cdc = GetHdc();
-            HDC hdcMem = ::CreateCompatibleDC(GetHdc());
+            HDC hdcMem = wxMSW::CreateCompatibleDCWithLayout(cdc);
             HGDIOBJ hOldBitmap = ::SelectObject(hdcMem, GetHbitmapOf(bmp));
 #if wxUSE_PALETTE
             wxPalette *pal = bmp.GetPalette();
@@ -1358,17 +1374,16 @@ void wxMSWDCImpl::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool
             // level
             wxMemoryDC memDC;
 
+            memDC.SetLayoutDirection(GetLayoutDirection());
             memDC.SelectObjectAsSource(bmp);
 
             GetOwner()->Blit(x, y, width, height, &memDC, 0, 0, wxCOPY, useMask);
-
-            memDC.SelectObject(wxNullBitmap);
         }
     }
     else // no mask, just use BitBlt()
     {
         HDC cdc = GetHdc();
-        HDC memdc = ::CreateCompatibleDC( cdc );
+        HDC memdc = wxMSW::CreateCompatibleDCWithLayout( cdc );
         HBITMAP hbitmap = (HBITMAP) bmp.GetHBITMAP( );
 
         wxASSERT_MSG( hbitmap, wxT("bitmap is ok but HBITMAP is NULL?") );
@@ -2267,8 +2282,8 @@ bool wxMSWDCImpl::DoStretchBlit(wxCoord xdest, wxCoord ydest,
             buffer_bmap = (HBITMAP) bitmapCacheEntry->m_bitmap;
 #else // !wxUSE_DC_CACHEING
             // create a temp buffer bitmap and DCs to access it and the mask
-            dc_mask = ::CreateCompatibleDC(hdcSrc);
-            dc_buffer = ::CreateCompatibleDC(GetHdc());
+            dc_mask = wxMSW::CreateCompatibleDCWithLayout(hdcSrc);
+            dc_buffer = wxMSW::CreateCompatibleDCWithLayout(GetHdc());
             buffer_bmap = ::CreateCompatibleBitmap(GetHdc(), dstWidth, dstHeight);
 #endif // wxUSE_DC_CACHEING/!wxUSE_DC_CACHEING
             HGDIOBJ hOldMaskBitmap = ::SelectObject(dc_mask, (HBITMAP) mask->GetMaskBitmap());
@@ -2581,7 +2596,7 @@ wxDCCacheEntry* wxMSWDCImpl::FindDCInCache(wxDCCacheEntry* notThis, WXHDC dc)
 
         node = node->GetNext();
     }
-    WXHDC hDC = (WXHDC) ::CreateCompatibleDC((HDC) dc);
+    WXHDC hDC = (WXHDC) wxMSW::CreateCompatibleDCWithLayout((HDC) dc);
     if ( !hDC)
     {
         wxLogLastError(wxT("CreateCompatibleDC"));
@@ -2813,20 +2828,47 @@ void wxMSWDCImpl::DoGradientFillLinear (const wxRect& rect,
 
 #if wxUSE_DYNLIB_CLASS
 
-static DWORD wxGetDCLayout(HDC hdc)
+namespace wxMSW
+{
+
+DWORD GetLayout(HDC hdc)
 {
     typedef DWORD (WINAPI *GetLayout_t)(HDC);
     static GetLayout_t
         wxDL_INIT_FUNC(s_pfn, GetLayout, wxDynamicLibrary(wxT("gdi32.dll")));
 
-    return s_pfnGetLayout ? s_pfnGetLayout(hdc) : (DWORD)-1;
+    return s_pfnGetLayout ? s_pfnGetLayout(hdc) : GDI_ERROR;
+}
+
+DWORD SetLayout(HDC hdc, DWORD dwLayout)
+{
+    typedef DWORD (WINAPI *SetLayout_t)(HDC, DWORD);
+    static SetLayout_t
+        wxDL_INIT_FUNC(s_pfn, SetLayout, wxDynamicLibrary(wxT("gdi32.dll")));
+
+    return s_pfnSetLayout ? s_pfnSetLayout(hdc, dwLayout) : GDI_ERROR;
+}
+
+HDC CreateCompatibleDCWithLayout(HDC hdc)
+{
+    HDC hdcNew = ::CreateCompatibleDC(hdc);
+    if ( hdcNew )
+    {
+        DWORD dwLayout = wxMSW::GetLayout(hdc);
+        if ( dwLayout != GDI_ERROR )
+            wxMSW::SetLayout(hdcNew, dwLayout);
+    }
+
+    return hdcNew;
 }
 
+} // namespace wxMSW
+
 wxLayoutDirection wxMSWDCImpl::GetLayoutDirection() const
 {
-    DWORD layout = wxGetDCLayout(GetHdc());
+    DWORD layout = wxMSW::GetLayout(GetHdc());
 
-    if ( layout == (DWORD)-1 )
+    if ( layout == GDI_ERROR )
         return wxLayout_Default;
 
     return layout & LAYOUT_RTL ? wxLayout_RightToLeft : wxLayout_LeftToRight;
@@ -2834,12 +2876,6 @@ wxLayoutDirection wxMSWDCImpl::GetLayoutDirection() const
 
 void wxMSWDCImpl::SetLayoutDirection(wxLayoutDirection dir)
 {
-    typedef DWORD (WINAPI *SetLayout_t)(HDC, DWORD);
-    static SetLayout_t
-        wxDL_INIT_FUNC(s_pfn, SetLayout, wxDynamicLibrary(wxT("gdi32.dll")));
-    if ( !s_pfnSetLayout )
-        return;
-
     if ( dir == wxLayout_Default )
     {
         dir = wxTheApp->GetLayoutDirection();
@@ -2847,17 +2883,41 @@ void wxMSWDCImpl::SetLayoutDirection(wxLayoutDirection dir)
             return;
     }
 
-    DWORD layout = wxGetDCLayout(GetHdc());
+    DWORD layout = GetLayout(GetHdc());
+    if ( layout == GDI_ERROR )
+        return;
+
     if ( dir == wxLayout_RightToLeft )
         layout |= LAYOUT_RTL;
     else
         layout &= ~LAYOUT_RTL;
 
-    s_pfnSetLayout(GetHdc(), layout);
+    wxMSW::SetLayout(GetHdc(), layout);
 }
 
 #else // !wxUSE_DYNLIB_CLASS
 
+// Provide stubs to avoid ifdefs in the code using these functions.
+namespace wxMSW
+{
+
+DWORD GetLayout(HDC WXUNUSED(hdc))
+{
+    return GDI_ERROR;
+}
+
+DWORD SetLayout(HDC WXUNUSED(hdc), DWORD WXUNUSED(dwLayout))
+{
+    return GDI_ERROR;
+}
+
+HDC CreateCompatibleDCWithLayout(HDC hdc)
+{
+    return ::CreateCompatibleDC(hdc);
+}
+
+} // namespace wxMSW
+
 // we can't provide RTL support without dynamic loading, so stub it out
 wxLayoutDirection wxMSWDCImpl::GetLayoutDirection() const
 {