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:
@@ -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:
|
||||
|
||||
|
@@ -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)
|
||||
};
|
||||
|
||||
|
@@ -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)
|
||||
};
|
||||
|
||||
|
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
// ------
|
||||
// conversion to colour bitmap:
|
||||
// ------
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// conversion to colour bitmap:
|
||||
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;
|
||||
}
|
||||
|
||||
#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;
|
||||
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__
|
||||
|
@@ -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
|
||||
|
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
// ------
|
||||
// conversion to colour bitmap:
|
||||
// ------
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// conversion to colour bitmap:
|
||||
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;
|
||||
}
|
||||
|
||||
#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;
|
||||
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__
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user