From 0a470e5ea537237f0562c3b2182ee293dec36eb3 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 9 Oct 2011 22:07:22 +0000 Subject: [PATCH] Allow creating wxGraphicsBitmap and wxGraphicsContext from wxImage. Provide a way to use wxGraphicsContext to draw on wxImage. This is implemented internally by drawing on wxGraphicsBitmap which can be now also created from wxImage. Add a test of the new functionality to the image sample. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@69358 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + include/wx/graphics.h | 17 ++++++ interface/wx/graphics.h | 57 ++++++++++++++++-- samples/image/image.cpp | 91 ++++++++++++++++++++++++++++ src/common/graphcmn.cpp | 14 +++++ src/generic/graphicc.cpp | 77 +++++++++++++++++++++++- src/msw/graphics.cpp | 115 ++++++++++++++++++++++++++++++++++++ src/osx/carbon/graphics.cpp | 75 +++++++++++++++++++++++ 8 files changed, 439 insertions(+), 8 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 407c69925a..b0e4dbaae3 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -473,6 +473,7 @@ All (GUI): - Added wxPersistentSplitter. - Derive wxAuiNotebook from wxBookCtrlBase (Steven Lamerton). - Fix tooltips in wxSearchCtrl and other composite controls (Catalin Raceanu). +- Allow converting to and from wxGraphicsBitmap and wxImage directly. OSX: diff --git a/include/wx/graphics.h b/include/wx/graphics.h index a612258a7a..398df5a4e4 100644 --- a/include/wx/graphics.h +++ b/include/wx/graphics.h @@ -434,6 +434,13 @@ public: static wxGraphicsContext* Create( wxWindow* window ); +#if wxUSE_IMAGE + // Create a context for drawing onto a wxImage. The image life time must be + // greater than that of the context itself as when the context is destroyed + // it will copy its contents to the specified image. + static wxGraphicsContext* Create(wxImage& image); +#endif // wxUSE_IMAGE + // create a context that can be used for measuring texts only, no drawing allowed static wxGraphicsContext * Create(); @@ -488,6 +495,9 @@ public: // create a native bitmap representation virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) const; +#if wxUSE_IMAGE + wxGraphicsBitmap CreateBitmapFromImage(const wxImage& image) const; +#endif // wxUSE_IMAGE // create a native bitmap representation virtual wxGraphicsBitmap CreateSubBitmap( const wxGraphicsBitmap &bitmap, wxDouble x, wxDouble y, wxDouble w, wxDouble h ) const; @@ -781,6 +791,10 @@ public: virtual wxGraphicsContext * CreateContext( wxWindow* window ) = 0; +#if wxUSE_IMAGE + virtual wxGraphicsContext * CreateContextFromImage(wxImage& image) = 0; +#endif // wxUSE_IMAGE + // create a context that can be used for measuring texts only, no drawing allowed virtual wxGraphicsContext * CreateMeasuringContext() = 0; @@ -818,6 +832,9 @@ public: // create a native bitmap representation virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) = 0; +#if wxUSE_IMAGE + virtual wxGraphicsBitmap CreateBitmapFromImage(const wxImage& image) = 0; +#endif // wxUSE_IMAGE // create a graphics bitmap from a native bitmap virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap( void* bitmap ) = 0; diff --git a/interface/wx/graphics.h b/interface/wx/graphics.h index 971df3c422..15cbefcde9 100644 --- a/interface/wx/graphics.h +++ b/interface/wx/graphics.h @@ -269,11 +269,11 @@ enum wxCompositionMode Represents a bitmap. The objects of this class are not created directly but only via - wxGraphicsContext or wxGraphicsRenderer CreateBitmap() and - CreateSubBitmap() methods. They can subsequently be used with - wxGraphicsContext::DrawBitmap(). The only other operation is testing for - the bitmap validity which can be performed using IsNull() method inherited - from the base class. + wxGraphicsContext or wxGraphicsRenderer CreateBitmap(), + CreateBitmapFromImage() or CreateSubBitmap() methods. They can subsequently + be used with wxGraphicsContext::DrawBitmap(). The only other operation is + testing for the bitmap validity which can be performed using IsNull() + method inherited from the base class. */ class wxGraphicsBitmap : public wxGraphicsObject { @@ -384,6 +384,19 @@ public: */ static wxGraphicsContext* Create(const wxEnhMetaFileDC& dc); + /** + Creates a wxGraphicsContext associated with a wxImage. + + The image specifies the size of the context as well as whether alpha is + supported (if wxImage::HasAlpha()) or not and the initial contents of + the context. The @a image object must have a life time greater than + that of the new context as the context copies its contents back to the + image when it is destroyed. + + @since 2.9.3 + */ + static wxGraphicsContext* Create(wxImage& image); + /** Clips drawings to the specified region. */ @@ -407,6 +420,18 @@ public: */ virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) = 0; + /** + Creates wxGraphicsBitmap from an existing wxImage. + + This method is more efficient than converting wxImage to wxBitmap first + and then calling CreateBitmap() but otherwise has the same effect. + + Returns an invalid wxNullGraphicsBitmap on failure. + + @since 2.9.3 + */ + virtual wxGraphicsBitmap CreateBitmapFromImage(const wxImage& image); + /** Extracts a sub-bitmap from an existing bitmap. @@ -914,6 +939,18 @@ public: */ virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) = 0; + /** + Creates wxGraphicsBitmap from an existing wxImage. + + This method is more efficient than converting wxImage to wxBitmap first + and then calling CreateBitmap() but otherwise has the same effect. + + Returns an invalid wxNullGraphicsBitmap on failure. + + @since 2.9.3 + */ + virtual wxGraphicsBitmap CreateBitmapFromImage(const wxImage& image) = 0; + /** Creates wxGraphicsBitmap from a native bitmap handle. @@ -951,6 +988,16 @@ public: */ virtual wxGraphicsContext* CreateContext(const wxEnhMetaFileDC& dc) = 0; + /** + Creates a wxGraphicsContext associated with a wxImage. + + This function is used by wxContext::CreateFromImage() and is not + normally called directly. + + @since 2.9.3 + */ + static wxGraphicsContext* CreateContextFromImage(wxImage& image); + /** Creates a native brush from a wxBrush. */ diff --git a/samples/image/image.cpp b/samples/image/image.cpp index 7fa9637561..c35f991737 100644 --- a/samples/image/image.cpp +++ b/samples/image/image.cpp @@ -24,9 +24,11 @@ #include "wx/image.h" #include "wx/file.h" #include "wx/filename.h" +#include "wx/graphics.h" #include "wx/mstream.h" #include "wx/wfstream.h" #include "wx/quantize.h" +#include "wx/scopedptr.h" #include "wx/stopwatch.h" #include "wx/versioninfo.h" @@ -83,6 +85,9 @@ public: #ifdef wxHAVE_RAW_BITMAP void OnTestRawBitmap( wxCommandEvent &event ); #endif // wxHAVE_RAW_BITMAP +#if wxUSE_GRAPHICS_CONTEXT + void OnTestGraphics(wxCommandEvent& event); +#endif // wxUSE_GRAPHICS_CONTEXT void OnQuit( wxCommandEvent &event ); #if wxUSE_CLIPBOARD @@ -617,6 +622,7 @@ enum ID_NEW = 100, ID_INFO, ID_SHOWRAW, + ID_GRAPHICS, ID_SHOWTHUMBNAIL }; @@ -630,6 +636,9 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) #ifdef wxHAVE_RAW_BITMAP EVT_MENU (ID_SHOWRAW, MyFrame::OnTestRawBitmap) #endif +#if wxUSE_GRAPHICS_CONTEXT + EVT_MENU (ID_GRAPHICS, MyFrame::OnTestGraphics) +#endif // wxUSE_GRAPHICS_CONTEXT #if wxUSE_CLIPBOARD EVT_MENU(wxID_COPY, MyFrame::OnCopy) EVT_MENU(wxID_PASTE, MyFrame::OnPaste) @@ -651,6 +660,10 @@ MyFrame::MyFrame() menuImage->AppendSeparator(); menuImage->Append( ID_SHOWRAW, wxT("Test &raw bitmap...\tCtrl-R")); #endif +#if wxUSE_GRAPHICS_CONTEXT + menuImage->AppendSeparator(); + menuImage->Append(ID_GRAPHICS, "Test &graphics context...\tCtrl-G"); +#endif // wxUSE_GRAPHICS_CONTEXT menuImage->AppendSeparator(); menuImage->Append( ID_SHOWTHUMBNAIL, wxT("Test &thumbnail...\tCtrl-T"), "Test scaling the image during load (try with JPEG)"); @@ -796,6 +809,84 @@ void MyFrame::OnTestRawBitmap( wxCommandEvent &WXUNUSED(event) ) #endif // wxHAVE_RAW_BITMAP +#if wxUSE_GRAPHICS_CONTEXT + +class MyGraphicsFrame : public wxFrame +{ +public: + enum + { + WIDTH = 256, + HEIGHT = 90 + }; + + MyGraphicsFrame(wxWindow* parent) : + wxFrame(parent, wxID_ANY, "Graphics context test"), + m_image(WIDTH, HEIGHT, false) + { + // Create a test image: it has 3 horizontal primary colour bands with + // alpha increasing from left to right. + m_image.SetAlpha(); + unsigned char* alpha = m_image.GetAlpha(); + unsigned char* data = m_image.GetData(); + + for ( int y = 0; y < HEIGHT; y++ ) + { + unsigned char r = 0, + g = 0, + b = 0; + if ( y < HEIGHT/3 ) + r = 0xff; + else if ( y < (2*HEIGHT)/3 ) + g = 0xff; + else + b = 0xff; + + for ( int x = 0; x < WIDTH; x++ ) + { + *alpha++ = x; + *data++ = r; + *data++ = g; + *data++ = b; + } + } + + m_bitmap = wxBitmap(m_image); + + Connect(wxEVT_PAINT, wxPaintEventHandler(MyGraphicsFrame::OnPaint)); + + Show(); + } + +private: + void OnPaint(wxPaintEvent& WXUNUSED(event)) + { + wxPaintDC dc(this); + wxScopedPtr gc(wxGraphicsContext::Create(dc)); + wxGraphicsBitmap gb(gc->CreateBitmapFromImage(m_image)); + + gc->SetFont(*wxNORMAL_FONT, *wxBLACK); + + gc->DrawText("Bitmap", 0, HEIGHT/2); + gc->DrawBitmap(m_bitmap, 0, 0, WIDTH, HEIGHT); + + gc->DrawText("Graphics bitmap", 0, (3*HEIGHT)/2); + gc->DrawBitmap(gb, 0, HEIGHT, WIDTH, HEIGHT); + } + + wxImage m_image; + wxBitmap m_bitmap; + + wxDECLARE_NO_COPY_CLASS(MyGraphicsFrame); +}; + +void MyFrame::OnTestGraphics(wxCommandEvent& WXUNUSED(event)) +{ + new MyGraphicsFrame(this); +} + +#endif // wxUSE_GRAPHICS_CONTEXT + #if wxUSE_CLIPBOARD void MyFrame::OnCopy(wxCommandEvent& WXUNUSED(event)) diff --git a/src/common/graphcmn.cpp b/src/common/graphcmn.cpp index 8536a68762..a312abf312 100644 --- a/src/common/graphcmn.cpp +++ b/src/common/graphcmn.cpp @@ -848,6 +848,13 @@ wxGraphicsBitmap wxGraphicsContext::CreateBitmap( const wxBitmap& bmp ) const return GetRenderer()->CreateBitmap(bmp); } +#if wxUSE_IMAGE +wxGraphicsBitmap wxGraphicsContext::CreateBitmapFromImage(const wxImage& image) const +{ + return GetRenderer()->CreateBitmapFromImage(image); +} +#endif // wxUSE_IMAGE + wxGraphicsBitmap wxGraphicsContext::CreateSubBitmap( const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h ) const { return GetRenderer()->CreateSubBitmap(bmp,x,y,w,h); @@ -894,6 +901,13 @@ wxGraphicsContext* wxGraphicsContext::Create( wxWindow* window ) return wxGraphicsRenderer::GetDefaultRenderer()->CreateContext(window); } +#if wxUSE_IMAGE +/* static */ wxGraphicsContext* wxGraphicsContext::Create(wxImage& image) +{ + return wxGraphicsRenderer::GetDefaultRenderer()->CreateContextFromImage(image); +} +#endif // wxUSE_IMAGE + wxGraphicsContext* wxGraphicsContext::Create() { return wxGraphicsRenderer::GetDefaultRenderer()->CreateMeasuringContext(); diff --git a/src/generic/graphicc.cpp b/src/generic/graphicc.cpp index 9635a86bfe..b9be59fe38 100644 --- a/src/generic/graphicc.cpp +++ b/src/generic/graphicc.cpp @@ -311,6 +311,9 @@ class wxCairoBitmapData : public wxGraphicsObjectRefData { public: wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitmap& bmp ); +#if wxUSE_IMAGE + wxCairoBitmapData(wxGraphicsRenderer* renderer, const wxImage& image); +#endif // wxUSE_IMAGE wxCairoBitmapData( wxGraphicsRenderer* renderer, cairo_surface_t* bitmap ); ~wxCairoBitmapData(); @@ -427,9 +430,9 @@ public: protected: virtual void DoDrawText( const wxString &str, wxDouble x, wxDouble y ); -private: void Init(cairo_t *context); +private: cairo_t* m_context; wxVector m_layerOpacities; @@ -437,6 +440,35 @@ private: wxDECLARE_NO_COPY_CLASS(wxCairoContext); }; +#if wxUSE_IMAGE +// ---------------------------------------------------------------------------- +// wxCairoImageContext: context associated with a wxImage. +// ---------------------------------------------------------------------------- + +class wxCairoImageContext : public wxCairoContext +{ +public: + wxCairoImageContext(wxGraphicsRenderer* renderer, wxImage& image) : + wxCairoContext(renderer), + m_image(image), + m_data(renderer, image) + { + Init(cairo_create(m_data.GetCairoSurface())); + } + + virtual ~wxCairoImageContext() + { + m_image = m_data.ConvertToImage(); + } + +private: + wxImage& m_image; + wxCairoBitmapData m_data; + + wxDECLARE_NO_COPY_CLASS(wxCairoImageContext); +}; +#endif // wxUSE_IMAGE + //----------------------------------------------------------------------------- // wxCairoPenData implementation //----------------------------------------------------------------------------- @@ -1283,7 +1315,7 @@ wxCairoBitmapData::wxCairoBitmapData(wxGraphicsRenderer* renderer, ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24; - InitBuffer(image.GetWidth(), image.GetHeight(), bufferFormat); + int stride = InitBuffer(image.GetWidth(), image.GetHeight(), bufferFormat); // Copy wxImage data into the buffer. Notice that we work with wxUint32 // values and not bytes becase Cairo always works with buffers in native @@ -1297,6 +1329,8 @@ wxCairoBitmapData::wxCairoBitmapData(wxGraphicsRenderer* renderer, for ( int y = 0; y < m_height; y++ ) { + wxUint32* const rowStartDst = dst; + for ( int x = 0; x < m_width; x++ ) { const unsigned char a = *alpha++; @@ -1307,12 +1341,16 @@ wxCairoBitmapData::wxCairoBitmapData(wxGraphicsRenderer* renderer, Premultiply(a, src[2]); src += 3; } + + dst = rowStartDst + stride / 4; } } else // RGB { for ( int y = 0; y < m_height; y++ ) { + wxUint32* const rowStartDst = dst; + for ( int x = 0; x < m_width; x++ ) { *dst++ = src[0] << 16 | @@ -1320,10 +1358,12 @@ wxCairoBitmapData::wxCairoBitmapData(wxGraphicsRenderer* renderer, src[2]; src += 3; } + + dst = rowStartDst + stride / 4; } } - InitSurface(bufferFormat); + InitSurface(bufferFormat, stride); } wxImage wxCairoBitmapData::ConvertToImage() const @@ -2108,6 +2148,9 @@ public : virtual wxGraphicsContext * CreateContextFromNativeContext( void * context ); virtual wxGraphicsContext * CreateContextFromNativeWindow( void * window ); +#if wxUSE_IMAGE + virtual wxGraphicsContext * CreateContextFromImage(wxImage& image); +#endif // wxUSE_IMAGE virtual wxGraphicsContext * CreateContext( wxWindow* window ); @@ -2147,6 +2190,9 @@ public : // create a native bitmap representation virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ); +#if wxUSE_IMAGE + virtual wxGraphicsBitmap CreateBitmapFromImage(const wxImage& image); +#endif // wxUSE_IMAGE // create a graphics bitmap from a native bitmap virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap( void* bitmap ); @@ -2257,6 +2303,13 @@ wxGraphicsContext * wxCairoRenderer::CreateContextFromNativeWindow( void * windo #endif } +#if wxUSE_IMAGE +wxGraphicsContext * wxCairoRenderer::CreateContextFromImage(wxImage& image) +{ + return new wxCairoImageContext(this, image); +} +#endif // wxUSE_IMAGE + wxGraphicsContext * wxCairoRenderer::CreateMeasuringContext() { ENSURE_LOADED_OR_RETURN(NULL); @@ -2377,6 +2430,24 @@ wxGraphicsBitmap wxCairoRenderer::CreateBitmap( const wxBitmap& bmp ) return wxNullGraphicsBitmap; } +#if wxUSE_IMAGE + +wxGraphicsBitmap wxCairoRenderer::CreateBitmapFromImage(const wxImage& image) +{ + wxGraphicsBitmap bmp; + + ENSURE_LOADED_OR_RETURN(bmp); + + if ( image.IsOk() ) + { + bmp.SetRefData(new wxCairoBitmapData(this, image)); + } + + return bmp; +} + +#endif // wxUSE_IMAGE + wxGraphicsBitmap wxCairoRenderer::CreateBitmapFromNativeBitmap( void* bitmap ) { ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap); diff --git a/src/msw/graphics.cpp b/src/msw/graphics.cpp index 42c0b21746..77fa96e6b2 100644 --- a/src/msw/graphics.cpp +++ b/src/msw/graphics.cpp @@ -281,6 +281,10 @@ public: virtual Bitmap* GetGDIPlusBitmap() { return m_bitmap; } +#if wxUSE_IMAGE + wxImage ConvertToImage() const; +#endif // wxUSE_IMAGE + private : Bitmap* m_bitmap; Bitmap* m_helper; @@ -404,6 +408,38 @@ private: wxDECLARE_NO_COPY_CLASS(wxGDIPlusContext); }; +#if wxUSE_IMAGE + +class wxGDIPlusImageContext : public wxGDIPlusContext +{ +public: + wxGDIPlusImageContext(wxGraphicsRenderer* renderer, wxImage& image) : + wxGDIPlusContext(renderer), + m_image(image), + m_bitmap(renderer, image) + { + Init + ( + new Graphics(m_bitmap.GetGDIPlusBitmap()), + image.GetWidth(), + image.GetHeight() + ); + } + + virtual ~wxGDIPlusImageContext() + { + m_image = m_bitmap.ConvertToImage(); + } + +private: + wxImage& m_image; + wxGDIPlusBitmapData m_bitmap; + + wxDECLARE_NO_COPY_CLASS(wxGDIPlusImageContext); +}; + +#endif // wxUSE_IMAGE + class wxGDIPlusMeasuringContext : public wxGDIPlusContext { public: @@ -469,6 +505,10 @@ public : virtual wxGraphicsContext * CreateContext( wxWindow* window ); +#if wxUSE_IMAGE + virtual wxGraphicsContext * CreateContextFromImage(wxImage& image); +#endif // wxUSE_IMAGE + virtual wxGraphicsContext * CreateMeasuringContext(); // Path @@ -498,6 +538,9 @@ public : // create a native bitmap representation virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ); +#if wxUSE_IMAGE + virtual wxGraphicsBitmap CreateBitmapFromImage(const wxImage& image); +#endif // wxUSE_IMAGE // stub: should not be called directly virtual wxGraphicsFont CreateFont( const wxFont& WXUNUSED(font), @@ -1013,12 +1056,50 @@ wxGDIPlusBitmapData::wxGDIPlusBitmapData( wxGraphicsRenderer* renderer, m_bitmap = image; } +#if wxUSE_IMAGE + +wxImage wxGDIPlusBitmapData::ConvertToImage() const +{ + // We could use Bitmap::LockBits() and convert to wxImage directly but + // passing by wxBitmap is easier. It would be nice to measure performance + // of the two methods but for this the second one would need to be written + // first... + HBITMAP hbmp; + if ( m_bitmap->GetHBITMAP(Color(0xffffffff), &hbmp) != Gdiplus::Ok ) + return wxNullImage; + + wxBitmap bmp; + bmp.SetWidth(m_bitmap->GetWidth()); + bmp.SetHeight(m_bitmap->GetHeight()); + bmp.SetHBITMAP(hbmp); + bmp.SetDepth(IsAlphaPixelFormat(m_bitmap->GetPixelFormat()) ? 32 : 24); + return bmp.ConvertToImage(); +} + +#endif // wxUSE_IMAGE + wxGDIPlusBitmapData::~wxGDIPlusBitmapData() { delete m_bitmap; delete m_helper; } +// ---------------------------------------------------------------------------- +// wxGraphicsBitmap implementation +// ---------------------------------------------------------------------------- + +#if wxUSE_IMAGE + +wxImage wxGraphicsBitmap::ConvertToImage() const +{ + const wxGDIPlusBitmapData* const + data = static_cast(GetGraphicsData()); + + return data ? data->ConvertToImage() : wxNullImage; +} + +#endif // wxUSE_IMAGE + //----------------------------------------------------------------------------- // wxGDIPlusPath implementation //----------------------------------------------------------------------------- @@ -1939,6 +2020,17 @@ wxGraphicsContext * wxGDIPlusRenderer::CreateContext( const wxMemoryDC& dc) return context; } +#if wxUSE_IMAGE +wxGraphicsContext * wxGDIPlusRenderer::CreateContextFromImage(wxImage& image) +{ + ENSURE_LOADED_OR_RETURN(NULL); + wxGDIPlusContext* context = new wxGDIPlusImageContext(this, image); + context->EnableOffset(true); + return context; +} + +#endif // wxUSE_IMAGE + wxGraphicsContext * wxGDIPlusRenderer::CreateMeasuringContext() { ENSURE_LOADED_OR_RETURN(NULL); @@ -2071,6 +2163,29 @@ wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmap( const wxBitmap &bitmap ) return wxNullGraphicsBitmap; } +#if wxUSE_IMAGE + +wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmapFromImage(const wxImage& image) +{ + ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap); + if ( image.IsOk() ) + { + // Notice that we rely on conversion from wxImage to wxBitmap here but + // we could probably do it more efficiently by converting from wxImage + // to GDI+ Bitmap directly, i.e. copying wxImage pixels to the buffer + // returned by Bitmap::LockBits(). However this would require writing + // code specific for this task while like this we can reuse existing + // code (see also wxGDIPlusBitmapData::ConvertToImage()). + wxGraphicsBitmap gb; + gb.SetRefData(new wxGDIPlusBitmapData(this, image)); + return gb; + } + else + return wxNullGraphicsBitmap; +} + +#endif // wxUSE_IMAGE + wxGraphicsBitmap wxGDIPlusRenderer::CreateBitmapFromNativeBitmap( void *bitmap ) { ENSURE_LOADED_OR_RETURN(wxNullGraphicsBitmap); diff --git a/src/osx/carbon/graphics.cpp b/src/osx/carbon/graphics.cpp index e481253450..067b3750b7 100644 --- a/src/osx/carbon/graphics.cpp +++ b/src/osx/carbon/graphics.cpp @@ -2724,6 +2724,49 @@ wxGraphicsMatrix wxMacCoreGraphicsContext::GetTransform() const return m; } + +#if wxUSE_IMAGE + +// ---------------------------------------------------------------------------- +// wxMacCoreGraphicsImageContext +// ---------------------------------------------------------------------------- + +// This is a GC that can be used to draw on wxImage. In this implementation we +// simply draw on a wxBitmap using wxMemoryDC and then convert it to wxImage in +// the end so it's not especially interesting and exists mainly for +// compatibility with the other platforms. +class wxMacCoreGraphicsImageContext : public wxMacCoreGraphicsContext +{ +public: + wxMacCoreGraphicsImageContext(wxGraphicsRenderer* renderer, + wxImage& image) : + wxMacCoreGraphicsContext(renderer), + m_image(image), + m_bitmap(image), + m_memDC(m_bitmap) + { + SetNativeContext + ( + (CGContextRef)(m_memDC.GetGraphicsContext()->GetNativeContext()) + ); + m_width = image.GetWidth(); + m_height = image.GetHeight(); + } + + virtual ~wxMacCoreGraphicsImageContext() + { + m_memDC.SelectObject(wxNullBitmap); + m_image = m_bitmap.ConvertToImage(); + } + +private: + wxImage& m_image; + wxBitmap m_bitmap; + wxMemoryDC m_memDC; +}; + +#endif // wxUSE_IMAGE + // // Renderer // @@ -2753,6 +2796,10 @@ public : virtual wxGraphicsContext * CreateContext( wxWindow* window ); +#if wxUSE_IMAGE + virtual wxGraphicsContext * CreateContextFromImage(wxImage& image); +#endif // wxUSE_IMAGE + virtual wxGraphicsContext * CreateMeasuringContext(); // Path @@ -2786,6 +2833,10 @@ public : // create a native bitmap representation virtual wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) ; +#if wxUSE_IMAGE + virtual wxGraphicsBitmap CreateBitmapFromImage(const wxImage& image); +#endif // wxUSE_IMAGE + // create a graphics bitmap from a native bitmap virtual wxGraphicsBitmap CreateBitmapFromNativeBitmap( void* bitmap ); @@ -2895,6 +2946,16 @@ wxGraphicsContext * wxMacCoreGraphicsRenderer::CreateMeasuringContext() return new wxMacCoreGraphicsContext(this); } +#if wxUSE_IMAGE + +wxGraphicsContext* +wxMacCoreGraphicsRenderer::CreateContextFromImage(wxImage& image) +{ + return new wxMacCoreGraphicsImageContext(this, image); +} + +#endif // wxUSE_IMAGE + // Path wxGraphicsPath wxMacCoreGraphicsRenderer::CreatePath() @@ -2953,6 +3014,20 @@ wxGraphicsBitmap wxMacCoreGraphicsRenderer::CreateBitmap( const wxBitmap& bmp ) return wxNullGraphicsBitmap; } +#if wxUSE_IMAGE + +wxGraphicsBitmap +wxMacCoreGraphicsRenderer::CreateBitmapFromImage(const wxImage& image) +{ + // We don't have any direct way to convert wxImage to CGImage so pass by + // wxBitmap. This makes this function pretty useless in this implementation + // but it allows to have the same API as with Cairo backend where we can + // convert wxImage to a Cairo surface directly, bypassing wxBitmap. + return CreateBitmap(wxBitmap(image)); +} + +#endif // wxUSE_IMAGE + wxGraphicsBitmap wxMacCoreGraphicsRenderer::CreateBitmapFromNativeBitmap( void* bitmap ) { if ( bitmap != NULL ) -- 2.45.2