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
This commit is contained in:
Vadim Zeitlin
2011-10-09 22:07:22 +00:00
parent 12493a5fb8
commit 0a470e5ea5
8 changed files with 439 additions and 8 deletions

View 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);