]> git.saurik.com Git - wxWidgets.git/commitdiff
Allow creating wxGraphicsBitmap and wxGraphicsContext from wxImage.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 9 Oct 2011 22:07:22 +0000 (22:07 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 9 Oct 2011 22:07:22 +0000 (22:07 +0000)
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
include/wx/graphics.h
interface/wx/graphics.h
samples/image/image.cpp
src/common/graphcmn.cpp
src/generic/graphicc.cpp
src/msw/graphics.cpp
src/osx/carbon/graphics.cpp

index 407c69925a412ed134243bb3ca786ac3a86ae23d..b0e4dbaae38dfbe673d7785bdd9a10939af572a8 100644 (file)
@@ -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:
 
index a612258a7a37cbdd8084e3a0fe79306cdcdc09cf..398df5a4e4c72ffd4434c943a99acef49bee8b74 100644 (file)
@@ -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;
index 971df3c422207d3d1fc39bebf4ece2fa791c63c3..15cbefcde9026065ca98d1e49f1ff88622230c45 100644 (file)
@@ -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.
     */
index 7fa96375616b914f52a072c63af1ebe8f2903671..c35f99173776637527929e7c2fb5630ca70731d4 100644 (file)
 #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<wxGraphicsContext> 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))
index 8536a68762f3afbe930c6573bea7f41b34e1179c..a312abf3123fe3f1d50fa3895d8935a0621b3d54 100644 (file)
@@ -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();
index 9635a86bfef6e1a1dc6d5a80f40d4c78c284b314..b9be59fe38f14408878b9ba1fc9fe9ea951b69fe 100644 (file)
@@ -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<float> 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);
index 42c0b21746291585079ac7072d15b44e5df56d56..77fa96e6b2177f1342d1e8d37a4d26035e8d6b25 100644 (file)
@@ -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<wxGDIPlusBitmapData*>(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);
index e481253450ef46011e308be4dbeb7d5335d566dd..067b3750b73ea6d641b15bb860a6ff46c15dfb30 100644 (file)
@@ -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 )