diff --git a/src/generic/graphicc.cpp b/src/generic/graphicc.cpp index 5155bf8e28..6cd1645857 100644 --- a/src/generic/graphicc.cpp +++ b/src/generic/graphicc.cpp @@ -301,6 +301,23 @@ private : double m_alpha; }; +class wxCairoBitmapData : public wxGraphicsObjectRefData +{ +public: + wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitmap& bmp ); + ~wxCairoBitmapData(); + + virtual cairo_surface_t* GetCairoSurface() { return m_surface; } + virtual cairo_pattern_t* GetCairoPattern() { return m_pattern; } + virtual wxSize GetSize() { return wxSize(m_width, m_height); } +private : + cairo_surface_t* m_surface; + cairo_pattern_t* m_pattern; + int m_width; + int m_height; + unsigned char* m_buffer; +}; + class WXDLLIMPEXP_CORE wxCairoContext : public wxGraphicsContext { DECLARE_NO_COPY_CLASS(wxCairoContext) @@ -341,7 +358,7 @@ public: // gets the matrix of this context virtual wxGraphicsMatrix GetTransform() const; - void DrawGraphicsBitmapInternal( const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h ) {} + void DrawGraphicsBitmapInternal( const wxGraphicsBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h ); virtual void DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h ); virtual void DrawIcon( const wxIcon &icon, wxDouble x, wxDouble y, wxDouble w, wxDouble h ); virtual void PushState(); @@ -962,6 +979,90 @@ void * wxCairoMatrixData::GetNativeMatrix() const return (void*) &m_matrix; } +//----------------------------------------------------------------------------- +// wxCairoBitmap implementation +//----------------------------------------------------------------------------- + +wxCairoBitmapData::wxCairoBitmapData( wxGraphicsRenderer* renderer, const wxBitmap& bmp ) : wxGraphicsObjectRefData( renderer ) +{ + wxCHECK_RET( bmp.IsOk(), wxT("Invalid bitmap in wxCairoContext::DrawBitmap")); + + int bw = m_width = bmp.GetWidth(); + int bh = m_height = bmp.GetHeight(); + wxBitmap bmpSource = bmp; // we need a non-const instance + m_buffer = new unsigned char[bw*bh*4]; + wxUint32* data = (wxUint32*)m_buffer; + + // Create a surface object and copy the bitmap pixel data to it. if the + // image has alpha (or a mask represented as alpha) then we'll use a + // different format and iterator than if it doesn't... + if (bmpSource.HasAlpha() || bmpSource.GetMask()) + { + m_surface = cairo_image_surface_create_for_data( + m_buffer, CAIRO_FORMAT_ARGB32, bw, bh, bw*4); + wxAlphaPixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh)); + wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data.")); + + wxAlphaPixelData::Iterator p(pixData); + for (int y=0; y(this)->DrawGraphicsBitmapInternal(bmp, x, y, w, h); } void wxCairoContext::DrawBitmap( const wxBitmap &bmp, wxDouble x, wxDouble y, wxDouble w, wxDouble h ) { - wxCHECK_RET( bmp.IsOk(), wxT("Invalid bitmap in wxCairoContext::DrawBitmap")); + wxGraphicsBitmap bitmap = GetRenderer()->CreateBitmap(bmp); + DrawGraphicsBitmapInternal(bitmap, x, y, w, h); +} - cairo_surface_t* surface; - int bw = bmp.GetWidth(); - int bh = bmp.GetHeight(); - wxBitmap bmpSource = bmp; // we need a non-const instance - unsigned char* buffer = new unsigned char[bw*bh*4]; - wxUint32* data = (wxUint32*)buffer; - - // Create a surface object and copy the bitmap pixel data to it. if the - // image has alpha (or a mask represented as alpha) then we'll use a - // different format and iterator than if it doesn't... - if (bmpSource.HasAlpha() || bmpSource.GetMask()) - { - surface = cairo_image_surface_create_for_data( - buffer, CAIRO_FORMAT_ARGB32, bw, bh, bw*4); - wxAlphaPixelData pixData(bmpSource, wxPoint(0,0), wxSize(bw, bh)); - wxCHECK_RET( pixData, wxT("Failed to gain raw access to bitmap data.")); - - wxAlphaPixelData::Iterator p(pixData); - for (int y=0; y(bmp.GetRefData()); + cairo_pattern_t* pattern = data->GetCairoPattern(); + wxSize size = data->GetSize(); PushState(); // In case we're scaling the image by using a width and height different // than the bitmap's size create a pattern transformation on the surface and // draw the transformed pattern. - cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface); - wxDouble scaleX = w / bw; - wxDouble scaleY = h / bh; + wxDouble scaleX = w / size.GetWidth(); + wxDouble scaleY = h / size.GetHeight(); cairo_scale(m_context, scaleX, scaleY); // prepare to draw the image cairo_translate(m_context, x, y); cairo_set_source(m_context, pattern); // use the original size here since the context is scaled already... - cairo_rectangle(m_context, 0, 0, bw, bh); + cairo_rectangle(m_context, 0, 0, size.GetWidth(), size.GetHeight()); // fill the rectangle using the pattern cairo_fill(m_context); // clean up - cairo_pattern_destroy(pattern); - cairo_surface_destroy(surface); - delete [] buffer; PopState(); } @@ -1378,7 +1414,7 @@ public : // sets the font virtual wxGraphicsFont CreateFont( const wxFont &font , const wxColour &col = *wxBLACK ) ; - wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) { return wxGraphicsBitmap(); } + wxGraphicsBitmap CreateBitmap( const wxBitmap &bitmap ) ; private : DECLARE_DYNAMIC_CLASS_NO_COPY(wxCairoRenderer) @@ -1520,4 +1556,16 @@ wxGraphicsFont wxCairoRenderer::CreateFont( const wxFont &font , const wxColour return wxNullGraphicsFont; } +wxGraphicsBitmap wxGraphicsRenderer::CreateBitmap( const wxBitmap& bmp ) +{ + if ( bmp.Ok() ) + { + wxGraphicsBitmap p; + p.SetRefData(new wxCairoBitmapData( this , bmp )); + return p; + } + else + return wxNullGraphicsBitmap; +} + #endif // wxUSE_GRAPHICS_CONTEXT