added alpha channel support to wxGTK2's wxBitmap

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@28850 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík
2004-08-21 22:42:06 +00:00
parent 4fab71288e
commit feac79373c
7 changed files with 1641 additions and 1146 deletions

View File

@@ -249,6 +249,7 @@ wxGTK:
- implemented wxTopLevel::IsMaximized() for GTK+2 and WMs that implement
freedesktop.org's wm-spec (Mart Raudsepp)
- wxEVT_CONTEXT_MENU is now generated for right mouse press, not release
- implemented alpha channel support in wxBitmap
wxMotif:

View File

@@ -21,6 +21,10 @@
#include "wx/palette.h"
#include "wx/gdiobj.h"
#ifdef __WXGTK20__
typedef struct _GdkPixbuf GdkPixbuf;
#endif
//-----------------------------------------------------------------------------
// classes
//-----------------------------------------------------------------------------
@@ -109,9 +113,17 @@ public:
void SetDepth( int depth );
void SetPixmap( GdkPixmap *pixmap );
void SetBitmap( GdkBitmap *bitmap );
#ifdef __WXGTK20__
void SetPixbuf(GdkPixbuf *pixbuf);
#endif
GdkPixmap *GetPixmap() const;
GdkBitmap *GetBitmap() const;
bool HasPixmap() const;
#ifdef __WXGTK20__
bool HasPixbuf() const;
GdkPixbuf *GetPixbuf() const;
#endif
// Basically, this corresponds to Win32 StretchBlt()
wxBitmap Rescale( int clipx, int clipy, int clipwidth, int clipheight, int width, int height );
@@ -120,6 +132,25 @@ protected:
bool CreateFromImage(const wxImage& image, int depth);
private:
// to be called from CreateFromImage only!
bool CreateFromImageAsBitmap(const wxImage& image);
bool CreateFromImageAsPixmap(const wxImage& image);
#ifdef __WXGTK20__
bool CreateFromImageAsPixbuf(const wxImage& image);
enum Representation
{
Pixmap,
Pixbuf
};
// removes other representations from memory, keeping only 'keep'
// (wxBitmap may keep same bitmap e.g. as both pixmap and pixbuf):
void PurgeOtherRepresentations(Representation keep);
friend class wxMemoryDC;
#endif
DECLARE_DYNAMIC_CLASS(wxBitmap)
};

View File

@@ -21,6 +21,10 @@
#include "wx/palette.h"
#include "wx/gdiobj.h"
#ifdef __WXGTK20__
typedef struct _GdkPixbuf GdkPixbuf;
#endif
//-----------------------------------------------------------------------------
// classes
//-----------------------------------------------------------------------------
@@ -109,9 +113,17 @@ public:
void SetDepth( int depth );
void SetPixmap( GdkPixmap *pixmap );
void SetBitmap( GdkBitmap *bitmap );
#ifdef __WXGTK20__
void SetPixbuf(GdkPixbuf *pixbuf);
#endif
GdkPixmap *GetPixmap() const;
GdkBitmap *GetBitmap() const;
bool HasPixmap() const;
#ifdef __WXGTK20__
bool HasPixbuf() const;
GdkPixbuf *GetPixbuf() const;
#endif
// Basically, this corresponds to Win32 StretchBlt()
wxBitmap Rescale( int clipx, int clipy, int clipwidth, int clipheight, int width, int height );
@@ -120,6 +132,25 @@ protected:
bool CreateFromImage(const wxImage& image, int depth);
private:
// to be called from CreateFromImage only!
bool CreateFromImageAsBitmap(const wxImage& image);
bool CreateFromImageAsPixmap(const wxImage& image);
#ifdef __WXGTK20__
bool CreateFromImageAsPixbuf(const wxImage& image);
enum Representation
{
Pixmap,
Pixbuf
};
// removes other representations from memory, keeping only 'keep'
// (wxBitmap may keep same bitmap e.g. as both pixmap and pixbuf):
void PurgeOtherRepresentations(Representation keep);
friend class wxMemoryDC;
#endif
DECLARE_DYNAMIC_CLASS(wxBitmap)
};

View File

@@ -239,6 +239,9 @@ public:
GdkPixmap *m_pixmap;
GdkBitmap *m_bitmap;
#ifdef __WXGTK20__
GdkPixbuf *m_pixbuf;
#endif
wxMask *m_mask;
int m_width;
int m_height;
@@ -250,6 +253,9 @@ wxBitmapRefData::wxBitmapRefData()
{
m_pixmap = (GdkPixmap *) NULL;
m_bitmap = (GdkBitmap *) NULL;
#ifdef __WXGTK20__
m_pixbuf = (GdkPixbuf *) NULL;
#endif
m_mask = (wxMask *) NULL;
m_width = 0;
m_height = 0;
@@ -263,6 +269,10 @@ wxBitmapRefData::~wxBitmapRefData()
gdk_pixmap_unref( m_pixmap );
if (m_bitmap)
gdk_bitmap_unref( m_bitmap );
#ifdef __WXGTK20__
if (m_pixbuf)
gdk_pixbuf_unref( m_pixbuf );
#endif
delete m_mask;
delete m_palette;
}
@@ -353,6 +363,30 @@ wxBitmap wxBitmap::Rescale( int clipx, int clipy, int clipwidth, int clipheight,
if (newy==M_BMPDATA->m_width && newy==M_BMPDATA->m_height)
return *this;
int width = wxMax(newx, 1);
int height = wxMax(newy, 1);
width = wxMin(width, clipwidth);
height = wxMin(height, clipheight);
wxBitmap bmp;
#ifdef __WXGTK20__
if (HasPixbuf())
{
bmp.SetWidth(width);
bmp.SetHeight(height);
bmp.SetDepth(GetDepth());
bmp.SetPixbuf(gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE/*has_alpha*/,
8, width, height));
gdk_pixbuf_scale(M_BMPDATA->m_pixbuf, bmp.GetPixbuf(),
0, 0, width, height,
clipx, clipy,
(double)newx/GetWidth(), (double)newy/GetHeight(),
GDK_INTERP_BILINEAR);
}
else
#endif // __WXGTK20__
{
GdkImage *img = (GdkImage*) NULL;
if (GetPixmap())
img = gdk_image_get( GetPixmap(), 0, 0, GetWidth(), GetHeight() );
@@ -363,13 +397,8 @@ wxBitmap wxBitmap::Rescale( int clipx, int clipy, int clipwidth, int clipheight,
wxCHECK_MSG( img, wxNullBitmap, wxT("couldn't create image") );
wxBitmap bmp;
int bpp = -1;
int width = wxMax(newx, 1);
int height = wxMax(newy, 1);
width = wxMin(width, clipwidth);
height = wxMin(height, clipheight);
GdkGC *gc = NULL;
GdkPixmap *dstpix = NULL;
@@ -523,40 +552,50 @@ wxBitmap wxBitmap::Rescale( int clipx, int clipy, int clipwidth, int clipheight,
free( tablex );
free( tabley );
}
return bmp;
}
bool wxBitmap::CreateFromImage( const wxImage& img, int depth )
bool wxBitmap::CreateFromImage(const wxImage& image, int depth)
{
UnRef();
wxCHECK_MSG( img.Ok(), FALSE, wxT("invalid image") )
wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") )
wxCHECK_MSG( depth == -1 || depth == 1, FALSE, wxT("invalid bitmap depth") )
// NB: wxGTK doesn't yet support alpha channel in bitmaps. The best we can
// do is to convert alpha channel to mask, if it is present:
if (image.GetWidth() <= 0 || image.GetHeight() <= 0)
return false;
m_refData = new wxBitmapRefData();
if (depth == 1)
{
return CreateFromImageAsBitmap(image);
}
else
{
#ifdef __WXGTK20__
if (image.HasAlpha())
return CreateFromImageAsPixbuf(image);
#endif
return CreateFromImageAsPixmap(image);
}
}
// conversion to mono bitmap:
bool wxBitmap::CreateFromImageAsBitmap(const wxImage& img)
{
// convert alpha channel to mask, if it is present:
wxImage image(img);
image.ConvertAlphaToMask();
int width = image.GetWidth();
int height = image.GetHeight();
if ( width <= 0 || height <= 0 )
{
return false;
}
m_refData = new wxBitmapRefData();
SetHeight( height );
SetWidth( width );
// ------
// conversion to mono bitmap:
// ------
if (depth == 1)
{
SetBitmap( gdk_pixmap_new( wxGetRootWindow()->window, width, height, 1 ) );
SetDepth( 1 );
@@ -640,13 +679,23 @@ bool wxBitmap::CreateFromImage( const wxImage& img, int depth )
gdk_image_destroy( mask_image );
gdk_gc_unref( mask_gc );
}
return true;
}
// ------
// conversion to colour bitmap:
// ------
else
bool wxBitmap::CreateFromImageAsPixmap(const wxImage& img)
{
// convert alpha channel to mask, if it is present:
wxImage image(img);
image.ConvertAlphaToMask();
int width = image.GetWidth();
int height = image.GetHeight();
SetHeight( height );
SetWidth( width );
SetPixmap( gdk_pixmap_new( wxGetRootWindow()->window, width, height, -1 ) );
GdkVisual *visual = wxTheApp->GetGdkVisual();
@@ -869,26 +918,110 @@ bool wxBitmap::CreateFromImage( const wxImage& img, int depth )
gdk_image_destroy( mask_image );
gdk_gc_unref( mask_gc );
}
return true;
}
return TRUE;
#ifdef __WXGTK20__
bool wxBitmap::CreateFromImageAsPixbuf(const wxImage& image)
{
int width = image.GetWidth();
int height = image.GetHeight();
GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
image.HasAlpha(),
8 /* bits per sample */,
width, height);
if (!pixbuf)
return false;
wxASSERT( gdk_pixbuf_get_n_channels(pixbuf) == 4 );
wxASSERT( gdk_pixbuf_get_width(pixbuf) == width );
wxASSERT( gdk_pixbuf_get_height(pixbuf) == height );
M_BMPDATA->m_pixbuf = pixbuf;
SetHeight(height);
SetWidth(width);
SetDepth(wxTheApp->GetGdkVisual()->depth);
// Copy the data:
unsigned char *in = image.GetData();
unsigned char *out = gdk_pixbuf_get_pixels(pixbuf);
unsigned char *alpha = image.GetAlpha();
int rowinc = gdk_pixbuf_get_rowstride(pixbuf) - 4 * width;
for (int y = 0; y < height; y++, out += rowinc)
{
for (int x = 0; x < width; x++, alpha++, out += 4, in += 3)
{
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
out[3] = *alpha;
}
}
return true;
}
#endif // __WXGTK20__
wxImage wxBitmap::ConvertToImage() const
{
// the colour used as transparent one in wxImage and the one it is replaced
// with when it really occurs in the bitmap
wxImage image;
wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
image.Create(GetWidth(), GetHeight());
unsigned char *data = image.GetData();
if (!data)
{
wxFAIL_MSG( wxT("couldn't create image") );
return wxNullImage;
}
#ifdef __WXGTK20__
if (HasPixbuf())
{
GdkPixbuf *pixbuf = GetPixbuf();
wxASSERT( gdk_pixbuf_get_has_alpha(pixbuf) );
int w = GetWidth();
int h = GetHeight();
image.SetAlpha();
unsigned char *alpha = image.GetAlpha();
unsigned char *in = gdk_pixbuf_get_pixels(pixbuf);
unsigned char *out = data;
int rowinc = gdk_pixbuf_get_rowstride(pixbuf) - 4 * w;
for (int y = 0; y < h; y++, in += rowinc)
{
for (int x = 0; x < w; x++, in += 4, out += 3, alpha++)
{
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
*alpha = in[3];
}
}
}
else
#endif // __WXGTK20__
{
// the colour used as transparent one in wxImage and the one it is
// replaced with when it really occurs in the bitmap
static const int MASK_RED = 1;
static const int MASK_GREEN = 2;
static const int MASK_BLUE = 3;
static const int MASK_BLUE_REPLACEMENT = 2;
wxImage image;
wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
GdkImage *gdk_image = (GdkImage*) NULL;
if (GetPixmap())
if (HasPixmap())
{
gdk_image = gdk_image_get( GetPixmap(),
0, 0,
@@ -907,16 +1040,6 @@ wxImage wxBitmap::ConvertToImage() const
wxCHECK_MSG( gdk_image, wxNullImage, wxT("couldn't create image") );
image.Create( GetWidth(), GetHeight() );
char unsigned *data = image.GetData();
if (!data)
{
gdk_image_destroy( gdk_image );
wxFAIL_MSG( wxT("couldn't create image") );
return wxNullImage;
}
GdkImage *gdk_image_mask = (GdkImage*) NULL;
if (GetMask())
{
@@ -1023,6 +1146,7 @@ wxImage wxBitmap::ConvertToImage() const
gdk_image_destroy( gdk_image );
if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
}
return image;
}
@@ -1084,7 +1208,13 @@ bool wxBitmap::operator != ( const wxBitmap& bmp ) const
bool wxBitmap::Ok() const
{
return (m_refData != NULL) && (M_BMPDATA->m_bitmap || M_BMPDATA->m_pixmap);
return (m_refData != NULL) &&
(
#ifdef __WXGTK20__
M_BMPDATA->m_pixbuf ||
#endif
M_BMPDATA->m_bitmap || M_BMPDATA->m_pixmap
);
}
int wxBitmap::GetHeight() const
@@ -1140,6 +1270,20 @@ wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
wxBitmap ret( rect.width, rect.height, M_BMPDATA->m_bpp );
wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
#ifdef __WXGTK20__
if (HasPixbuf())
{
GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
TRUE/*has_alpha*/,
8, GetWidth(), GetHeight());
ret.SetPixbuf(pixbuf);
gdk_pixbuf_copy_area(M_BMPDATA->m_pixbuf,
rect.x, rect.y, rect.width, rect.height,
pixbuf, 0, 0);
}
else
#endif // __WXGTK20__
{
if (ret.GetPixmap())
{
GdkGC *gc = gdk_gc_new( ret.GetPixmap() );
@@ -1157,6 +1301,7 @@ wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
gdk_wx_draw_bitmap( ret.GetBitmap(), gc, GetBitmap(), rect.x, rect.y, 0, 0, rect.width, rect.height );
gdk_gc_destroy( gc );
}
}
if (GetMask())
{
@@ -1288,12 +1433,69 @@ GdkPixmap *wxBitmap::GetPixmap() const
{
wxCHECK_MSG( Ok(), (GdkPixmap *) NULL, wxT("invalid bitmap") );
#ifdef __WXGTK20__
// create the pixmap on the fly if we use Pixbuf representation:
if (HasPixbuf() && !HasPixmap())
{
gdk_pixbuf_render_pixmap_and_mask(M_BMPDATA->m_pixbuf,
&M_BMPDATA->m_pixmap,
NULL /*mask*/,
128 /*threshold*/);
}
#endif // __WXGTK20__
return M_BMPDATA->m_pixmap;
}
bool wxBitmap::HasPixmap() const
{
wxCHECK_MSG( Ok(), false, wxT("invalid bitmap") );
return M_BMPDATA->m_pixmap != NULL;
}
GdkBitmap *wxBitmap::GetBitmap() const
{
wxCHECK_MSG( Ok(), (GdkBitmap *) NULL, wxT("invalid bitmap") );
return M_BMPDATA->m_bitmap;
}
#ifdef __WXGTK20__
GdkPixbuf *wxBitmap::GetPixbuf() const
{
wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
return M_BMPDATA->m_pixbuf;
}
bool wxBitmap::HasPixbuf() const
{
wxCHECK_MSG( Ok(), false, wxT("invalid bitmap") );
return M_BMPDATA->m_pixbuf != NULL;
}
void wxBitmap::SetPixbuf( GdkPixbuf *pixbuf )
{
if (!m_refData)
m_refData = new wxBitmapRefData();
M_BMPDATA->m_pixbuf = pixbuf;
}
void wxBitmap::PurgeOtherRepresentations(wxBitmap::Representation keep)
{
if (keep == Pixmap && HasPixbuf())
{
gdk_pixbuf_unref( M_BMPDATA->m_pixbuf );
M_BMPDATA->m_pixbuf = NULL;
}
if (keep == Pixbuf && HasPixmap())
{
gdk_pixmap_unref( M_BMPDATA->m_pixmap );
M_BMPDATA->m_pixmap = NULL;
}
}
#endif // __WXGTK20__

View File

@@ -1147,7 +1147,21 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
}
else
{
gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
#if GTK_CHECK_VERSION(2,2,0)
if (use_bitmap.HasPixbuf())
{
gdk_draw_pixbuf(m_window, m_penGC,
use_bitmap.GetPixbuf(),
0, 0, xx, yy, -1, -1,
GDK_RGB_DITHER_NORMAL, xx, yy);
}
else
#endif
{
gdk_draw_pixmap(m_window, m_penGC,
use_bitmap.GetPixmap(),
0, 0, xx, yy, -1, -1);
}
}
// remove mask again if any

View File

@@ -239,6 +239,9 @@ public:
GdkPixmap *m_pixmap;
GdkBitmap *m_bitmap;
#ifdef __WXGTK20__
GdkPixbuf *m_pixbuf;
#endif
wxMask *m_mask;
int m_width;
int m_height;
@@ -250,6 +253,9 @@ wxBitmapRefData::wxBitmapRefData()
{
m_pixmap = (GdkPixmap *) NULL;
m_bitmap = (GdkBitmap *) NULL;
#ifdef __WXGTK20__
m_pixbuf = (GdkPixbuf *) NULL;
#endif
m_mask = (wxMask *) NULL;
m_width = 0;
m_height = 0;
@@ -263,6 +269,10 @@ wxBitmapRefData::~wxBitmapRefData()
gdk_pixmap_unref( m_pixmap );
if (m_bitmap)
gdk_bitmap_unref( m_bitmap );
#ifdef __WXGTK20__
if (m_pixbuf)
gdk_pixbuf_unref( m_pixbuf );
#endif
delete m_mask;
delete m_palette;
}
@@ -353,6 +363,30 @@ wxBitmap wxBitmap::Rescale( int clipx, int clipy, int clipwidth, int clipheight,
if (newy==M_BMPDATA->m_width && newy==M_BMPDATA->m_height)
return *this;
int width = wxMax(newx, 1);
int height = wxMax(newy, 1);
width = wxMin(width, clipwidth);
height = wxMin(height, clipheight);
wxBitmap bmp;
#ifdef __WXGTK20__
if (HasPixbuf())
{
bmp.SetWidth(width);
bmp.SetHeight(height);
bmp.SetDepth(GetDepth());
bmp.SetPixbuf(gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE/*has_alpha*/,
8, width, height));
gdk_pixbuf_scale(M_BMPDATA->m_pixbuf, bmp.GetPixbuf(),
0, 0, width, height,
clipx, clipy,
(double)newx/GetWidth(), (double)newy/GetHeight(),
GDK_INTERP_BILINEAR);
}
else
#endif // __WXGTK20__
{
GdkImage *img = (GdkImage*) NULL;
if (GetPixmap())
img = gdk_image_get( GetPixmap(), 0, 0, GetWidth(), GetHeight() );
@@ -363,13 +397,8 @@ wxBitmap wxBitmap::Rescale( int clipx, int clipy, int clipwidth, int clipheight,
wxCHECK_MSG( img, wxNullBitmap, wxT("couldn't create image") );
wxBitmap bmp;
int bpp = -1;
int width = wxMax(newx, 1);
int height = wxMax(newy, 1);
width = wxMin(width, clipwidth);
height = wxMin(height, clipheight);
GdkGC *gc = NULL;
GdkPixmap *dstpix = NULL;
@@ -523,40 +552,50 @@ wxBitmap wxBitmap::Rescale( int clipx, int clipy, int clipwidth, int clipheight,
free( tablex );
free( tabley );
}
return bmp;
}
bool wxBitmap::CreateFromImage( const wxImage& img, int depth )
bool wxBitmap::CreateFromImage(const wxImage& image, int depth)
{
UnRef();
wxCHECK_MSG( img.Ok(), FALSE, wxT("invalid image") )
wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") )
wxCHECK_MSG( depth == -1 || depth == 1, FALSE, wxT("invalid bitmap depth") )
// NB: wxGTK doesn't yet support alpha channel in bitmaps. The best we can
// do is to convert alpha channel to mask, if it is present:
if (image.GetWidth() <= 0 || image.GetHeight() <= 0)
return false;
m_refData = new wxBitmapRefData();
if (depth == 1)
{
return CreateFromImageAsBitmap(image);
}
else
{
#ifdef __WXGTK20__
if (image.HasAlpha())
return CreateFromImageAsPixbuf(image);
#endif
return CreateFromImageAsPixmap(image);
}
}
// conversion to mono bitmap:
bool wxBitmap::CreateFromImageAsBitmap(const wxImage& img)
{
// convert alpha channel to mask, if it is present:
wxImage image(img);
image.ConvertAlphaToMask();
int width = image.GetWidth();
int height = image.GetHeight();
if ( width <= 0 || height <= 0 )
{
return false;
}
m_refData = new wxBitmapRefData();
SetHeight( height );
SetWidth( width );
// ------
// conversion to mono bitmap:
// ------
if (depth == 1)
{
SetBitmap( gdk_pixmap_new( wxGetRootWindow()->window, width, height, 1 ) );
SetDepth( 1 );
@@ -640,13 +679,23 @@ bool wxBitmap::CreateFromImage( const wxImage& img, int depth )
gdk_image_destroy( mask_image );
gdk_gc_unref( mask_gc );
}
return true;
}
// ------
// conversion to colour bitmap:
// ------
else
bool wxBitmap::CreateFromImageAsPixmap(const wxImage& img)
{
// convert alpha channel to mask, if it is present:
wxImage image(img);
image.ConvertAlphaToMask();
int width = image.GetWidth();
int height = image.GetHeight();
SetHeight( height );
SetWidth( width );
SetPixmap( gdk_pixmap_new( wxGetRootWindow()->window, width, height, -1 ) );
GdkVisual *visual = wxTheApp->GetGdkVisual();
@@ -869,26 +918,110 @@ bool wxBitmap::CreateFromImage( const wxImage& img, int depth )
gdk_image_destroy( mask_image );
gdk_gc_unref( mask_gc );
}
return true;
}
return TRUE;
#ifdef __WXGTK20__
bool wxBitmap::CreateFromImageAsPixbuf(const wxImage& image)
{
int width = image.GetWidth();
int height = image.GetHeight();
GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
image.HasAlpha(),
8 /* bits per sample */,
width, height);
if (!pixbuf)
return false;
wxASSERT( gdk_pixbuf_get_n_channels(pixbuf) == 4 );
wxASSERT( gdk_pixbuf_get_width(pixbuf) == width );
wxASSERT( gdk_pixbuf_get_height(pixbuf) == height );
M_BMPDATA->m_pixbuf = pixbuf;
SetHeight(height);
SetWidth(width);
SetDepth(wxTheApp->GetGdkVisual()->depth);
// Copy the data:
unsigned char *in = image.GetData();
unsigned char *out = gdk_pixbuf_get_pixels(pixbuf);
unsigned char *alpha = image.GetAlpha();
int rowinc = gdk_pixbuf_get_rowstride(pixbuf) - 4 * width;
for (int y = 0; y < height; y++, out += rowinc)
{
for (int x = 0; x < width; x++, alpha++, out += 4, in += 3)
{
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
out[3] = *alpha;
}
}
return true;
}
#endif // __WXGTK20__
wxImage wxBitmap::ConvertToImage() const
{
// the colour used as transparent one in wxImage and the one it is replaced
// with when it really occurs in the bitmap
wxImage image;
wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
image.Create(GetWidth(), GetHeight());
unsigned char *data = image.GetData();
if (!data)
{
wxFAIL_MSG( wxT("couldn't create image") );
return wxNullImage;
}
#ifdef __WXGTK20__
if (HasPixbuf())
{
GdkPixbuf *pixbuf = GetPixbuf();
wxASSERT( gdk_pixbuf_get_has_alpha(pixbuf) );
int w = GetWidth();
int h = GetHeight();
image.SetAlpha();
unsigned char *alpha = image.GetAlpha();
unsigned char *in = gdk_pixbuf_get_pixels(pixbuf);
unsigned char *out = data;
int rowinc = gdk_pixbuf_get_rowstride(pixbuf) - 4 * w;
for (int y = 0; y < h; y++, in += rowinc)
{
for (int x = 0; x < w; x++, in += 4, out += 3, alpha++)
{
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
*alpha = in[3];
}
}
}
else
#endif // __WXGTK20__
{
// the colour used as transparent one in wxImage and the one it is
// replaced with when it really occurs in the bitmap
static const int MASK_RED = 1;
static const int MASK_GREEN = 2;
static const int MASK_BLUE = 3;
static const int MASK_BLUE_REPLACEMENT = 2;
wxImage image;
wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
GdkImage *gdk_image = (GdkImage*) NULL;
if (GetPixmap())
if (HasPixmap())
{
gdk_image = gdk_image_get( GetPixmap(),
0, 0,
@@ -907,16 +1040,6 @@ wxImage wxBitmap::ConvertToImage() const
wxCHECK_MSG( gdk_image, wxNullImage, wxT("couldn't create image") );
image.Create( GetWidth(), GetHeight() );
char unsigned *data = image.GetData();
if (!data)
{
gdk_image_destroy( gdk_image );
wxFAIL_MSG( wxT("couldn't create image") );
return wxNullImage;
}
GdkImage *gdk_image_mask = (GdkImage*) NULL;
if (GetMask())
{
@@ -1023,6 +1146,7 @@ wxImage wxBitmap::ConvertToImage() const
gdk_image_destroy( gdk_image );
if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
}
return image;
}
@@ -1084,7 +1208,13 @@ bool wxBitmap::operator != ( const wxBitmap& bmp ) const
bool wxBitmap::Ok() const
{
return (m_refData != NULL) && (M_BMPDATA->m_bitmap || M_BMPDATA->m_pixmap);
return (m_refData != NULL) &&
(
#ifdef __WXGTK20__
M_BMPDATA->m_pixbuf ||
#endif
M_BMPDATA->m_bitmap || M_BMPDATA->m_pixmap
);
}
int wxBitmap::GetHeight() const
@@ -1140,6 +1270,20 @@ wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
wxBitmap ret( rect.width, rect.height, M_BMPDATA->m_bpp );
wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
#ifdef __WXGTK20__
if (HasPixbuf())
{
GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
TRUE/*has_alpha*/,
8, GetWidth(), GetHeight());
ret.SetPixbuf(pixbuf);
gdk_pixbuf_copy_area(M_BMPDATA->m_pixbuf,
rect.x, rect.y, rect.width, rect.height,
pixbuf, 0, 0);
}
else
#endif // __WXGTK20__
{
if (ret.GetPixmap())
{
GdkGC *gc = gdk_gc_new( ret.GetPixmap() );
@@ -1157,6 +1301,7 @@ wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
gdk_wx_draw_bitmap( ret.GetBitmap(), gc, GetBitmap(), rect.x, rect.y, 0, 0, rect.width, rect.height );
gdk_gc_destroy( gc );
}
}
if (GetMask())
{
@@ -1288,12 +1433,69 @@ GdkPixmap *wxBitmap::GetPixmap() const
{
wxCHECK_MSG( Ok(), (GdkPixmap *) NULL, wxT("invalid bitmap") );
#ifdef __WXGTK20__
// create the pixmap on the fly if we use Pixbuf representation:
if (HasPixbuf() && !HasPixmap())
{
gdk_pixbuf_render_pixmap_and_mask(M_BMPDATA->m_pixbuf,
&M_BMPDATA->m_pixmap,
NULL /*mask*/,
128 /*threshold*/);
}
#endif // __WXGTK20__
return M_BMPDATA->m_pixmap;
}
bool wxBitmap::HasPixmap() const
{
wxCHECK_MSG( Ok(), false, wxT("invalid bitmap") );
return M_BMPDATA->m_pixmap != NULL;
}
GdkBitmap *wxBitmap::GetBitmap() const
{
wxCHECK_MSG( Ok(), (GdkBitmap *) NULL, wxT("invalid bitmap") );
return M_BMPDATA->m_bitmap;
}
#ifdef __WXGTK20__
GdkPixbuf *wxBitmap::GetPixbuf() const
{
wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
return M_BMPDATA->m_pixbuf;
}
bool wxBitmap::HasPixbuf() const
{
wxCHECK_MSG( Ok(), false, wxT("invalid bitmap") );
return M_BMPDATA->m_pixbuf != NULL;
}
void wxBitmap::SetPixbuf( GdkPixbuf *pixbuf )
{
if (!m_refData)
m_refData = new wxBitmapRefData();
M_BMPDATA->m_pixbuf = pixbuf;
}
void wxBitmap::PurgeOtherRepresentations(wxBitmap::Representation keep)
{
if (keep == Pixmap && HasPixbuf())
{
gdk_pixbuf_unref( M_BMPDATA->m_pixbuf );
M_BMPDATA->m_pixbuf = NULL;
}
if (keep == Pixbuf && HasPixmap())
{
gdk_pixmap_unref( M_BMPDATA->m_pixmap );
M_BMPDATA->m_pixmap = NULL;
}
}
#endif // __WXGTK20__

View File

@@ -1147,7 +1147,21 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
}
else
{
gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
#if GTK_CHECK_VERSION(2,2,0)
if (use_bitmap.HasPixbuf())
{
gdk_draw_pixbuf(m_window, m_penGC,
use_bitmap.GetPixbuf(),
0, 0, xx, yy, -1, -1,
GDK_RGB_DITHER_NORMAL, xx, yy);
}
else
#endif
{
gdk_draw_pixmap(m_window, m_penGC,
use_bitmap.GetPixmap(),
0, 0, xx, yy, -1, -1);
}
}
// remove mask again if any