From c64c9cd3ba5c5aa5d1cc0b59e9b78fd66650bc58 Mon Sep 17 00:00:00 2001 From: Kevin Ollivier Date: Sun, 29 Oct 2006 05:29:04 +0000 Subject: [PATCH] Added wxDC::GetAsBitmap, and implemented wxWindowDC::DoGetAsBitmap on OS X, in order to restore the ability to blit the contents of those DCs. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@42604 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/dc.h | 7 +++++ include/wx/mac/carbon/dcclient.h | 1 + src/common/dcgraph.cpp | 33 +++++++++++++++------ src/mac/carbon/dcclient.cpp | 49 ++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 8 deletions(-) diff --git a/include/wx/dc.h b/include/wx/dc.h index d6bfafdc61..ebf665a580 100644 --- a/include/wx/dc.h +++ b/include/wx/dc.h @@ -313,6 +313,11 @@ public: return DoBlit(destPt.x, destPt.y, sz.x, sz.y, source, srcPt.x, srcPt.y, rop, useMask, srcPtMask.x, srcPtMask.y); } + + wxBitmap GetAsBitmap() + { + return DoGetAsBitmap(); + } #if wxUSE_SPLINES // TODO: this API needs fixing (wxPointList, why (!const) "wxList *"?) @@ -712,6 +717,8 @@ protected: wxDC *source, wxCoord xsrc, wxCoord ysrc, int rop = wxCOPY, bool useMask = false, wxCoord xsrcMask = wxDefaultCoord, wxCoord ysrcMask = wxDefaultCoord) = 0; + virtual wxBitmap DoGetAsBitmap() const { return wxNullBitmap; } + virtual void DoGetSize(int *width, int *height) const = 0; virtual void DoGetSizeMM(int* width, int* height) const = 0; diff --git a/include/wx/mac/carbon/dcclient.h b/include/wx/mac/carbon/dcclient.h index 4fc84defdd..2817c20a9a 100644 --- a/include/wx/mac/carbon/dcclient.h +++ b/include/wx/mac/carbon/dcclient.h @@ -35,6 +35,7 @@ class WXDLLEXPORT wxWindowDC: public wxDC wxWindow *GetWindow() const { return m_window; } protected : virtual void DoGetSize( int *width, int *height ) const; + virtual wxBitmap DoGetAsBitmap() const; wxWindow *m_window; #if wxMAC_USE_CORE_GRAPHICS bool m_release; diff --git a/src/common/dcgraph.cpp b/src/common/dcgraph.cpp index 4234c0ccbe..0819d2f919 100644 --- a/src/common/dcgraph.cpp +++ b/src/common/dcgraph.cpp @@ -854,9 +854,14 @@ bool wxGCDC::DoBlit( { wxCHECK_MSG( Ok(), false, wxT("wxGCDC(cg)::DoBlit - invalid DC") ); wxCHECK_MSG( source->Ok(), false, wxT("wxGCDC(cg)::DoBlit - invalid source DC") ); - + if ( logical_func == wxNO_OP ) return true; + else if ( logical_func != wxCOPY ) + { + wxFAIL_MSG( wxT("Blitting is only supported with wxCOPY logical operation.") ); + return false; + } if (xsrcMask == -1 && ysrcMask == -1) { @@ -874,10 +879,11 @@ bool wxGCDC::DoBlit( wxCoord wwdest = LogicalToDeviceXRel(width); wxCoord hhdest = LogicalToDeviceYRel(height); + wxBitmap blit; wxMemoryDC* memdc = wxDynamicCast(source,wxMemoryDC); - if ( memdc && logical_func == wxCOPY ) + if ( memdc ) { - wxBitmap blit = memdc->GetSelectedBitmap(); + blit = memdc->GetSelectedBitmap(); wxASSERT_MSG( blit.Ok() , wxT("Invalid bitmap for blitting") ); @@ -908,15 +914,26 @@ bool wxGCDC::DoBlit( blit = wxNullBitmap; } } - - if ( blit.Ok() ) - { - m_graphicContext->DrawBitmap( blit, xxdest , yydest , wwdest , hhdest ); + } + else + { + wxWindowDC* windc = wxDynamicCast(source,wxWindowDC); + if (windc) + { + wxBitmap bmp; + bmp = windc->GetAsBitmap(); + if (bmp.IsOk()) + blit = bmp.GetSubBitmap( wxRect(xsrc, ysrc, width, height ) ); } } + + if ( blit.Ok() ) + { + m_graphicContext->DrawBitmap( blit, xxdest , yydest , wwdest , hhdest ); + } else { - wxFAIL_MSG( wxT("Blitting is only supported from bitmap contexts, and only with wxCOPY logical operation.") ); + wxFAIL_MSG( wxT("Cannot Blit. Unable to get contents of DC as bitmap.") ); return false; } diff --git a/src/mac/carbon/dcclient.cpp b/src/mac/carbon/dcclient.cpp index 73d0d4d301..970370092b 100644 --- a/src/mac/carbon/dcclient.cpp +++ b/src/mac/carbon/dcclient.cpp @@ -24,6 +24,7 @@ #endif #include "wx/graphics.h" +#include "wx/rawbmp.h" #include "wx/mac/private.h" //----------------------------------------------------------------------------- @@ -187,6 +188,54 @@ void wxWindowDC::DoGetSize( int* width, int* height ) const #endif } +wxBitmap wxWindowDC::DoGetAsBitmap() const +{ + ControlRef handle = (ControlRef) m_window->GetHandle(); + if ( !handle ) + return wxNullBitmap; + + HIRect rect; + CGImageRef image; + CGContextRef context; + void* data; + + size_t bytesPerRow; + + HIViewCreateOffscreenImage( handle, 0, &rect, &image); + + int width = rect.size.width; + int height = rect.size.height; + + bytesPerRow = ( ( width * 8 * 4 + 7 ) / 8 ); + + data = calloc( 1, bytesPerRow * height ); + context = CGBitmapContextCreate( data, width, height, 8, bytesPerRow, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedFirst ); + + CGContextDrawImage( context, rect, image ); + + unsigned char* buffer = (unsigned char*) data; + wxBitmap bmp = wxBitmap(width, height, 32); + wxAlphaPixelData pixData(bmp, wxPoint(0,0), wxSize(width, height)); + + pixData.UseAlpha(); + wxAlphaPixelData::Iterator p(pixData); + for (int y=0; y