X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4314ec480ecfdd8c0d170e570978d6d2134fc8be..6e7ce6246c2952fd844f6b3f05f25719d82e0584:/src/msw/dc.cpp diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 7031bf7bd9..d6be602027 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -23,6 +23,7 @@ // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" +#include "wx/msw/private.h" // needs to be before #include #ifdef __BORLANDC__ #pragma hdrstop @@ -56,11 +57,7 @@ #include #endif -#include "wx/msw/private.h" - -#if !USE_SHARED_LIBRARY IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject) -#endif // --------------------------------------------------------------------------- // constants @@ -601,27 +598,85 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask { if (!bmp.Ok()) return; - + + bool needsPixelCopy = FALSE ; + bool isPrinter = FALSE ; + if (IsKindOf(CLASSINFO(wxPrinterDC)) ) + { + isPrinter = TRUE ; + if ( ::GetDeviceCaps((HDC) m_hDC, RASTERCAPS) & RC_STRETCHDIB ) + { + } + else + { + needsPixelCopy = TRUE ; + } + } // If we're not drawing transparently, and not drawing to a printer, // optimize this function to use Windows functions. - if (!useMask && !IsKindOf(CLASSINFO(wxPrinterDC))) + if (!useMask && !needsPixelCopy) { - HDC cdc = GetHdc(); - HDC memdc = ::CreateCompatibleDC( cdc ); - HBITMAP hbitmap = (HBITMAP) bmp.GetHBITMAP( ); + if ( isPrinter ) + { + BITMAPINFO *info = (BITMAPINFO *) malloc( sizeof( BITMAPINFOHEADER ) + 256 * sizeof(RGBQUAD ) ) ; + int iBitsSize = ((bmp.GetWidth() + 3 ) & ~3 ) * bmp.GetHeight() ; + + void* bits = malloc( iBitsSize ) ; + + memset( info , 0 , sizeof( BITMAPINFOHEADER ) ) ; + + info->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ) ; + info->bmiHeader.biWidth = bmp.GetWidth() ; + info->bmiHeader.biHeight = bmp.GetHeight() ; + info->bmiHeader.biPlanes = 1 ; + info->bmiHeader.biBitCount = 8 ; + info->bmiHeader.biCompression = BI_RGB ; + + HDC display = GetDC( NULL ) ; + if ( GetDIBits( display , (HBITMAP) bmp.GetHBITMAP( ) , 0 , bmp.GetHeight() , bits , info , DIB_RGB_COLORS ) ) + { + StretchDIBits( (HDC) m_hDC, + x, y, bmp.GetWidth(), bmp.GetHeight() , + 0 , 0 ,bmp.GetWidth(), bmp.GetHeight() , + bits , info , DIB_RGB_COLORS , SRCCOPY ) ; + } + ReleaseDC( NULL , display ) ; + free ( bits ) ; + free( info ) ; + } + else + { + HDC cdc = GetHdc(); + HDC memdc = ::CreateCompatibleDC( cdc ); + HBITMAP hbitmap = (HBITMAP) bmp.GetHBITMAP( ); + + wxASSERT_MSG( hbitmap, wxT("bitmap is ok but HBITMAP is NULL?") ); + + COLORREF old_textground = ::GetTextColor(GetHdc()); + COLORREF old_background = ::GetBkColor(GetHdc()); + if (m_textForegroundColour.Ok()) + { + ::SetTextColor(GetHdc(), m_textForegroundColour.GetPixel() ); + } + if (m_textBackgroundColour.Ok()) + { + ::SetBkColor(GetHdc(), m_textBackgroundColour.GetPixel() ); + } - wxASSERT_MSG( hbitmap, wxT("bitmap is ok but HBITMAP is NULL?") ); + ::SelectObject( memdc, hbitmap ); + ::BitBlt( cdc, x, y, bmp.GetWidth(), bmp.GetHeight(), memdc, 0, 0, SRCCOPY); + ::DeleteDC( memdc ); - ::SelectObject( memdc, hbitmap ); - ::BitBlt( cdc, x, y, bmp.GetWidth(), bmp.GetHeight(), memdc, 0, 0, SRCCOPY); - ::DeleteDC( memdc ); + ::SetTextColor(GetHdc(), old_textground); + ::SetBkColor(GetHdc(), old_background); + } } else { // Rather than reproduce wxDC::Blit, let's do it at the wxWin API level wxMemoryDC memDC; memDC.SelectObject(bmp); - + /* Not sure if we need this. The mask should leave the * masked areas as per the original background of this DC. */ @@ -631,9 +686,9 @@ void wxDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask memDC.SetBackground(* GetBackground()); memDC.Clear(); */ - + Blit(x, y, bmp.GetWidth(), bmp.GetHeight(), & memDC, 0, 0, wxCOPY, useMask); - + memDC.SelectObject(wxNullBitmap); } } @@ -666,7 +721,7 @@ void wxDC::DrawAnyText(const wxString& text, wxCoord x, wxCoord y) : OPAQUE); if ( ::TextOut(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), - text.c_str(), text.length()) != 0 ) + text.c_str(), text.length()) == 0 ) { wxLogLastError("TextOut"); } @@ -684,28 +739,39 @@ void wxDC::DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y, double angle) { - if ( angle == 0.0 ) + // we test that we have some font because otherwise we should still use the + // "else" part below to avoid that DrawRotatedText(angle = 180) and + // DrawRotatedText(angle = 0) use different fonts (we can't use the default + // font for drawing rotated fonts unfortunately) + if ( (angle == 0.0) && m_font.Ok() ) { DoDrawText(text, x, y); } else { + // NB: don't take DEFAULT_GUI_FONT because it's not TrueType and so + // can't have non zero orientation/escapement + wxFont font = m_font.Ok() ? m_font : *wxNORMAL_FONT; + HFONT hfont = (HFONT)font.GetResourceHandle(); LOGFONT lf; - wxFillLogFont(&lf, &m_font); + if ( ::GetObject(hfont, sizeof(lf), &lf) == 0 ) + { + wxLogLastError("GetObject(hfont)"); + } // GDI wants the angle in tenth of degree long angle10 = (long)(angle * 10); lf.lfEscapement = angle10; lf. lfOrientation = angle10; - HFONT hfont = ::CreateFontIndirect(&lf); + hfont = ::CreateFontIndirect(&lf); if ( !hfont ) { wxLogLastError("CreateFont"); } else { - HFONT hfontOld = ::SelectObject(GetHdc(), hfont); + HFONT hfontOld = (HFONT)::SelectObject(GetHdc(), hfont); DrawAnyText(text, x, y); @@ -723,7 +789,6 @@ void wxDC::DoDrawRotatedText(const wxString& text, // "upper left" and "upper right" CalcBoundingBox(x, y); CalcBoundingBox(x + w*cos(rad), y - h*sin(rad)); - CalcBoundingBox(x + h*sin(rad), y + h*cos(rad)); // "bottom left" and "bottom right" x += (wxCoord)(h*sin(rad)); @@ -1180,8 +1245,6 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, wxCoord xsrc1 = xsrc; wxCoord ysrc1 = ysrc; - // Chris Breeze 18/5/98: use text foreground/background colours - // when blitting from 1-bit bitmaps COLORREF old_textground = ::GetTextColor(GetHdc()); COLORREF old_background = ::GetBkColor(GetHdc()); if (m_textForegroundColour.Ok()) @@ -1208,7 +1271,27 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, SRCCOPY; bool success = TRUE; - if (useMask && source->m_selectedBitmap.Ok() && source->m_selectedBitmap.GetMask()) + bool needsPixelCopy = FALSE ; + bool isPrinter = FALSE ; + + if (IsKindOf(CLASSINFO(wxPrinterDC)) ) + { + isPrinter = TRUE ; + if ( ::GetDeviceCaps((HDC) m_hDC, RASTERCAPS) & RC_STRETCHDIB ) + { + } + else + { + needsPixelCopy = TRUE ; + } + } + if (useMask && !source->m_selectedBitmap.Ok()) + return FALSE; + + if (useMask && !source->m_selectedBitmap.GetMask()) + useMask = FALSE; + + if (useMask) { #if 0 // __WIN32__ @@ -1222,21 +1305,10 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, else #endif { - // Old code -#if 0 - HDC dc_mask = CreateCompatibleDC((HDC) source->m_hDC); - ::SelectObject(dc_mask, (HBITMAP) source->m_selectedBitmap.GetMask()->GetMaskBitmap()); - success = (BitBlt(GetHdc(), xdest1, ydest1, (int)width, (int)height, - dc_mask, xsrc1, ysrc1, 0x00220326 /* NOTSRCAND */) != 0); - success = (BitBlt(GetHdc(), xdest1, ydest1, (int)width, (int)height, - (HDC) source->m_hDC, xsrc1, ysrc1, SRCPAINT) != 0); - ::SelectObject(dc_mask, 0); - ::DeleteDC(dc_mask); -#endif // New code from Chris Breeze, 15/7/98 // Blit bitmap with mask - if (IsKindOf(CLASSINFO(wxPrinterDC))) + if (isPrinter) { // If we are printing source colours are screen colours // not printer colours and so we need copy the bitmap @@ -1308,32 +1380,77 @@ bool wxDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, } } } - else + else if (needsPixelCopy) // not masked, but we need pixel copy. Only true if it's a printer { - if (IsKindOf(CLASSINFO(wxPrinterDC))) + // If we are printing, source colours are screen colours + // not printer colours and so we need copy the bitmap + // pixel by pixel. + if (isPrinter) { - // If we are printing, source colours are screen colours - // not printer colours and so we need copy the bitmap - // pixel by pixel. HDC dc_src = (HDC) source->m_hDC; - RECT rect; - for (int x = 0; x < width; x++) - { - for (int y = 0; y < height; y++) - { - HBRUSH brush = ::CreateSolidBrush(::GetPixel(dc_src, x, y)); - rect.left = xdest1 + x; rect.right = rect.left + 1; - rect.top = ydest1 + y; rect.bottom = rect.top + 1; - ::FillRect(GetHdc(), &rect, brush); - ::DeleteObject(brush); + RECT rect; + for (int y = 0; y < height; y++) + { + // This is Stefan Csomor's optimisation, where + // identical adjacent pixels are drawn together. + for (int x = 0; x < width; x++) + { + COLORREF col = ::GetPixel(dc_src, x, y) ; + HBRUSH brush = ::CreateSolidBrush( col ); + + rect.left = xdest1 + x; + rect.top = ydest1 + y; + while( (x + 1 < width) && (::GetPixel(dc_src, x + 1, y) == col ) ) + { + ++x ; + } + rect.right = xdest1 + x + 1; + rect.bottom = rect.top + 1; + ::FillRect((HDC) m_hDC, &rect, brush); + ::DeleteObject(brush); } - } - } + } + } else { - success = (BitBlt(GetHdc(), xdest1, ydest1, (int)width, (int)height, (HDC) source->m_hDC, - xsrc1, ysrc1, dwRop) != 0); + wxFAIL_MSG( "If needsPixelCopy is true, isPrinter should be true also." ); + } + } + else if (isPrinter) // not masked, not pixel copy + { + wxBitmap& bmp = source->m_selectedBitmap ; + BITMAPINFO *info = (BITMAPINFO *) malloc( sizeof( BITMAPINFOHEADER ) + 256 * sizeof(RGBQUAD ) ) ; + int iBitsSize = ((bmp.GetWidth() + 3 ) & ~3 ) * bmp.GetHeight() ; + + void* bits = malloc( iBitsSize ) ; + + memset( info , 0 , sizeof( BITMAPINFOHEADER ) ) ; + + info->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ) ; + info->bmiHeader.biWidth = bmp.GetWidth() ; + info->bmiHeader.biHeight = bmp.GetHeight() ; + info->bmiHeader.biPlanes = 1 ; + info->bmiHeader.biBitCount = 8 ; + info->bmiHeader.biCompression = BI_RGB ; + + HDC display = GetDC( NULL ) ; + if ( GetDIBits( display , (HBITMAP) bmp.GetHBITMAP( ) , 0 , bmp.GetHeight() , bits , info , DIB_RGB_COLORS ) ) + { + success = (GDI_ERROR != StretchDIBits( (HDC) m_hDC, + xdest1, ydest1, bmp.GetWidth(), bmp.GetHeight() , + xsrc1 , ysrc1 ,bmp.GetWidth(), bmp.GetHeight() , + bits , info , DIB_RGB_COLORS , SRCCOPY )) ; } + else + success = FALSE; + ReleaseDC( NULL , display ) ; + free ( bits ) ; + free( info ) ; + } + else // Not masked, not printer, not pixel copy + { + success = (BitBlt(GetHdc(), xdest1, ydest1, (int)width, (int)height, (HDC) source->m_hDC, + xsrc1, ysrc1, dwRop) != 0); } ::SetTextColor(GetHdc(), old_textground); ::SetBkColor(GetHdc(), old_background);