]>
git.saurik.com Git - wxWidgets.git/blob - src/gtk/bitmap.cpp
1d8a6b5767de404c7d61089e46ee8ba4970d1816
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/bitmap.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  13 #include "wx/bitmap.h" 
  18     #include "wx/colour.h" 
  21 #include "wx/rawbmp.h" 
  23 #include "wx/gtk/private/object.h" 
  24 #include "wx/gtk/private.h" 
  28 extern GtkWidget 
*wxGetRootWindow(); 
  31 static void PixmapToPixbuf(GdkPixmap
* pixmap
, GdkPixbuf
* pixbuf
, int w
, int h
) 
  33     gdk_pixbuf_get_from_drawable(pixbuf
, pixmap
, NULL
, 0, 0, 0, 0, w
, h
); 
  34     if (gdk_drawable_get_depth(pixmap
) == 1) 
  36         // invert to match XBM convention 
  37         guchar
* p 
= gdk_pixbuf_get_pixels(pixbuf
); 
  38         const int inc 
= 3 + int(gdk_pixbuf_get_has_alpha(pixbuf
) != 0); 
  39         const int rowpad 
= gdk_pixbuf_get_rowstride(pixbuf
) - w 
* inc
; 
  40         for (int y 
= h
; y
; y
--, p 
+= rowpad
) 
  41             for (int x 
= w
; x
; x
--, p 
+= inc
) 
  43                 // pixels are either (0,0,0) or (0xff,0xff,0xff) 
  51 static void MaskToAlpha(GdkPixmap
* mask
, GdkPixbuf
* pixbuf
, int w
, int h
) 
  53     GdkPixbuf
* mask_pixbuf 
= gdk_pixbuf_get_from_drawable( 
  54         NULL
, mask
, NULL
, 0, 0, 0, 0, w
, h
); 
  55     guchar
* p 
= gdk_pixbuf_get_pixels(pixbuf
) + 3; 
  56     const guchar
* mask_data 
= gdk_pixbuf_get_pixels(mask_pixbuf
); 
  57     const int rowpad 
= gdk_pixbuf_get_rowstride(pixbuf
) - w 
* 4; 
  58     const int mask_rowpad 
= gdk_pixbuf_get_rowstride(mask_pixbuf
) - w 
* 3; 
  59     for (int y 
= h
; y
; y
--, p 
+= rowpad
, mask_data 
+= mask_rowpad
) 
  61         for (int x 
= w
; x
; x
--, p 
+= 4, mask_data 
+= 3) 
  64             // no need to test all 3 components, 
  65             //   pixels are either (0,0,0) or (0xff,0xff,0xff) 
  66             if (mask_data
[0] == 0) 
  70     g_object_unref(mask_pixbuf
); 
  74 //----------------------------------------------------------------------------- 
  76 //----------------------------------------------------------------------------- 
  78 IMPLEMENT_DYNAMIC_CLASS(wxMask
, wxMaskBase
) 
  85 wxMask::wxMask(const wxMask
& mask
) 
  91         const int w 
= cairo_image_surface_get_width(mask
.m_bitmap
); 
  92         const int h 
= cairo_image_surface_get_height(mask
.m_bitmap
); 
  93         m_bitmap 
= cairo_image_surface_create(CAIRO_FORMAT_A8
, w
, h
); 
  94         const guchar
* src 
= cairo_image_surface_get_data(mask
.m_bitmap
); 
  95         guchar
* dst 
= cairo_image_surface_get_data(m_bitmap
); 
  96         const int stride 
= cairo_image_surface_get_stride(m_bitmap
); 
  97         wxASSERT(stride 
== cairo_image_surface_get_stride(mask
.m_bitmap
)); 
  98         memcpy(dst
, src
, stride 
* h
); 
  99         cairo_surface_mark_dirty(m_bitmap
); 
 102     if ( !mask
.m_bitmap 
) 
 108     // create a copy of an existing mask 
 110     gdk_drawable_get_size(mask
.m_bitmap
, &w
, &h
); 
 111     m_bitmap 
= gdk_pixmap_new(mask
.m_bitmap
, w
, h
, 1); 
 113     wxGtkObject
<GdkGC
> gc(gdk_gc_new(m_bitmap
)); 
 114     gdk_draw_drawable(m_bitmap
, gc
, mask
.m_bitmap
, 0, 0, 0, 0, -1, -1); 
 118 wxMask::wxMask( const wxBitmap
& bitmap
, const wxColour
& colour 
) 
 121     InitFromColour(bitmap
, colour
); 
 125 wxMask::wxMask( const wxBitmap
& bitmap
, int paletteIndex 
) 
 128     Create( bitmap
, paletteIndex 
); 
 130 #endif // wxUSE_PALETTE 
 132 wxMask::wxMask( const wxBitmap
& bitmap 
) 
 135     InitFromMonoBitmap(bitmap
); 
 139 wxMask::wxMask(cairo_surface_t
* bitmap
) 
 141 wxMask::wxMask(GdkPixmap
* bitmap
) 
 152         cairo_surface_destroy(m_bitmap
); 
 154         g_object_unref (m_bitmap
); 
 159 void wxMask::FreeData() 
 164         cairo_surface_destroy(m_bitmap
); 
 166         g_object_unref (m_bitmap
); 
 172 bool wxMask::InitFromColour(const wxBitmap
& bitmap
, const wxColour
& colour
) 
 174     const int w 
= bitmap
.GetWidth(); 
 175     const int h 
= bitmap
.GetHeight(); 
 178     m_bitmap 
= cairo_image_surface_create(CAIRO_FORMAT_A8
, w
, h
); 
 179     GdkPixbuf
* pixbuf 
= bitmap
.GetPixbufNoMask(); 
 180     const guchar
* src 
= gdk_pixbuf_get_pixels(pixbuf
); 
 181     guchar
* dst 
= cairo_image_surface_get_data(m_bitmap
); 
 182     const int stride_src 
= gdk_pixbuf_get_rowstride(pixbuf
); 
 183     const int stride_dst 
= cairo_image_surface_get_stride(m_bitmap
); 
 184     const int src_inc 
= gdk_pixbuf_get_n_channels(pixbuf
); 
 185     const guchar r 
= colour
.Red(); 
 186     const guchar g 
= colour
.Green(); 
 187     const guchar b 
= colour
.Blue(); 
 188     for (int j 
= 0; j 
< h
; j
++, src 
+= stride_src
, dst 
+= stride_dst
) 
 190         const guchar
* s 
= src
; 
 191         for (int i 
= 0; i 
< w
; i
++, s 
+= src_inc
) 
 194             if (s
[0] == r 
&& s
[1] == g 
&& s
[2] == b
) 
 198     cairo_surface_mark_dirty(m_bitmap
); 
 200     // create mask as XBM format bitmap 
 202     // one bit per pixel, each row starts on a byte boundary 
 203     const size_t out_size 
= size_t((w 
+ 7) / 8) * unsigned(h
); 
 204     wxByte
* out 
= new wxByte
[out_size
]; 
 205     // set bits are unmasked 
 206     memset(out
, 0xff, out_size
); 
 207     unsigned bit_index 
= 0; 
 208     if (bitmap
.HasPixbuf()) 
 210         const wxByte r_mask 
= colour
.Red(); 
 211         const wxByte g_mask 
= colour
.Green(); 
 212         const wxByte b_mask 
= colour
.Blue(); 
 213         GdkPixbuf
* pixbuf 
= bitmap
.GetPixbuf(); 
 214         const wxByte
* in 
= gdk_pixbuf_get_pixels(pixbuf
); 
 215         const int inc 
= 3 + int(gdk_pixbuf_get_has_alpha(pixbuf
) != 0); 
 216         const int rowpadding 
= gdk_pixbuf_get_rowstride(pixbuf
) - inc 
* w
; 
 217         for (int y 
= 0; y 
< h
; y
++, in 
+= rowpadding
) 
 219             for (int x 
= 0; x 
< w
; x
++, in 
+= inc
, bit_index
++) 
 220                 if (in
[0] == r_mask 
&& in
[1] == g_mask 
&& in
[2] == b_mask
) 
 221                     out
[bit_index 
>> 3] ^= 1 << (bit_index 
& 7); 
 222             // move index to next byte boundary 
 223             bit_index 
= (bit_index 
+ 7) & ~7u; 
 228         GdkImage
* image 
= gdk_drawable_get_image(bitmap
.GetPixmap(), 0, 0, w
, h
); 
 229         GdkColormap
* colormap 
= gdk_image_get_colormap(image
); 
 231         if (colormap 
== NULL
) 
 232             // mono bitmap, white is pixel value 0 
 233             mask_pixel 
= guint32(colour
.Red() != 255 || colour
.Green() != 255 || colour
.Blue() != 255); 
 237             c
.CalcPixel(colormap
); 
 238             mask_pixel 
= c
.GetPixel(); 
 240         for (int y 
= 0; y 
< h
; y
++) 
 242             for (int x 
= 0; x 
< w
; x
++, bit_index
++) 
 243                 if (gdk_image_get_pixel(image
, x
, y
) == mask_pixel
) 
 244                     out
[bit_index 
>> 3] ^= 1 << (bit_index 
& 7); 
 245             bit_index 
= (bit_index 
+ 7) & ~7u; 
 247         g_object_unref(image
); 
 249     m_bitmap 
= gdk_bitmap_create_from_data(wxGetRootWindow()->window
, (char*)out
, w
, h
); 
 255 bool wxMask::InitFromMonoBitmap(const wxBitmap
& bitmap
) 
 257     if (!bitmap
.IsOk()) return false; 
 259     wxCHECK_MSG( bitmap
.GetDepth() == 1, false, wxT("Cannot create mask from colour bitmap") ); 
 262     InitFromColour(bitmap
, *wxBLACK
); 
 264     m_bitmap 
= gdk_pixmap_new( wxGetRootWindow()->window
, bitmap
.GetWidth(), bitmap
.GetHeight(), 1 ); 
 266     if (!m_bitmap
) return false; 
 268     wxGtkObject
<GdkGC
> gc(gdk_gc_new( m_bitmap 
)); 
 269     gdk_gc_set_function(gc
, GDK_COPY_INVERT
); 
 270     gdk_draw_drawable(m_bitmap
, gc
, bitmap
.GetPixmap(), 0, 0, 0, 0, bitmap
.GetWidth(), bitmap
.GetHeight()); 
 276 wxBitmap 
wxMask::GetBitmap() const 
 282         cairo_surface_t
* mask 
= m_bitmap
; 
 283         const int w 
= cairo_image_surface_get_width(mask
); 
 284         const int h 
= cairo_image_surface_get_height(mask
); 
 285         GdkPixbuf
* pixbuf 
= gdk_pixbuf_new(GDK_COLORSPACE_RGB
, false, 8, w
, h
); 
 286         const guchar
* src 
= cairo_image_surface_get_data(mask
); 
 287         guchar
* dst 
= gdk_pixbuf_get_pixels(pixbuf
); 
 288         const int stride_src 
= cairo_image_surface_get_stride(mask
); 
 289         const int stride_dst 
= gdk_pixbuf_get_rowstride(pixbuf
); 
 290         for (int j 
= 0; j 
< h
; j
++, src 
+= stride_src
, dst 
+= stride_dst
) 
 293             for (int i 
= 0; i 
< w
; i
++, d 
+= 3) 
 300         bitmap 
= wxBitmap(pixbuf
, 1); 
 302         GdkPixmap
* mask 
= m_bitmap
; 
 304         gdk_drawable_get_size(mask
, &w
, &h
); 
 305         GdkPixmap
* pixmap 
= gdk_pixmap_new(mask
, w
, h
, -1); 
 306         GdkGC
* gc 
= gdk_gc_new(pixmap
); 
 307         gdk_gc_set_function(gc
, GDK_COPY_INVERT
); 
 308         gdk_draw_drawable(pixmap
, gc
, mask
, 0, 0, 0, 0, w
, h
); 
 310         bitmap 
= wxBitmap(pixmap
); 
 317 wxMask::operator cairo_surface_t
*() const 
 319 wxMask::operator GdkPixmap
*() const 
 325 //----------------------------------------------------------------------------- 
 327 //----------------------------------------------------------------------------- 
 329 class wxBitmapRefData
: public wxGDIRefData
 
 332     wxBitmapRefData(int width
, int height
, int depth
); 
 333     virtual ~wxBitmapRefData(); 
 335     virtual bool IsOk() const; 
 338     GdkPixbuf
* m_pixbufMask
; 
 339     GdkPixbuf
* m_pixbufNoMask
; 
 340     cairo_surface_t
* m_surface
; 
 350     bool m_alphaRequested
; 
 353     // We don't provide a copy ctor as copying m_pixmap and m_pixbuf properly 
 354     // is expensive and we don't want to do it implicitly (and possibly 
 355     // accidentally). wxBitmap::CloneGDIRefData() which does need to do it does 
 356     // it explicitly itself. 
 357     wxDECLARE_NO_COPY_CLASS(wxBitmapRefData
); 
 360 wxBitmapRefData::wxBitmapRefData(int width
, int height
, int depth
) 
 364     m_pixbufNoMask 
= NULL
; 
 375     if (m_bpp 
!= 1 && m_bpp 
!= 32) 
 379         m_bpp 
= gdk_drawable_get_depth(wxGetRootWindow()->window
); 
 380     m_alphaRequested 
= depth 
== 32; 
 384 wxBitmapRefData::~wxBitmapRefData() 
 388         g_object_unref(m_pixbufMask
); 
 390         g_object_unref(m_pixbufNoMask
); 
 392         cairo_surface_destroy(m_surface
); 
 395         g_object_unref (m_pixmap
); 
 397         g_object_unref (m_pixbuf
); 
 402 bool wxBitmapRefData::IsOk() const 
 407 //----------------------------------------------------------------------------- 
 409 //----------------------------------------------------------------------------- 
 411 #define M_BMPDATA static_cast<wxBitmapRefData*>(m_refData) 
 413 IMPLEMENT_DYNAMIC_CLASS(wxBitmap
,wxGDIObject
) 
 415 wxBitmap::wxBitmap(const wxString 
&filename
, wxBitmapType type
) 
 417     LoadFile(filename
, type
); 
 420 wxBitmap::wxBitmap(const char bits
[], int width
, int height
, int depth
) 
 422     wxASSERT(depth 
== 1); 
 423     if (width 
> 0 && height 
> 0 && depth 
== 1) 
 425         m_refData 
= new wxBitmapRefData(width
, height
, 1); 
 427         GdkPixbuf
* pixbuf 
= gdk_pixbuf_new(GDK_COLORSPACE_RGB
, false, 8, width
, height
); 
 428         M_BMPDATA
->m_pixbufNoMask 
= pixbuf
; 
 429         const char* src 
= bits
; 
 430         guchar
* dst 
= gdk_pixbuf_get_pixels(pixbuf
); 
 431         const int stride_src 
= (width 
+ 7) / 8; 
 432         const int rowinc_dst 
= gdk_pixbuf_get_rowstride(pixbuf
) - 3 * width
; 
 433         for (int j 
= 0; j 
< width
; j
++, src 
+= stride_src
, dst 
+= rowinc_dst
) 
 435             for (int i 
= 0; i 
< height
; i
++) 
 438                 if (src
[i 
>> 3] & (1 << (i 
& 7))) 
 446         M_BMPDATA
->m_pixmap 
= gdk_bitmap_create_from_data( 
 447             wxGetRootWindow()->window
, bits
, width
, height
); 
 452 wxBitmap::wxBitmap(const char* const* bits
) 
 454     wxCHECK2_MSG(bits 
!= NULL
, return, wxT("invalid bitmap data")); 
 457     *this = wxBitmap(wxImage(bits
)); 
 458 #elif defined __WXGTK3__ 
 459     GdkPixbuf
* pixbuf 
= gdk_pixbuf_new_from_xpm_data(const_cast<const char**>(bits
)); 
 462         m_refData 
= new wxBitmapRefData( 
 463             gdk_pixbuf_get_width(pixbuf
), gdk_pixbuf_get_height(pixbuf
), 
 464             gdk_pixbuf_get_n_channels(pixbuf
) * 8); 
 465         M_BMPDATA
->m_pixbufNoMask 
= pixbuf
; 
 466         wxASSERT(M_BMPDATA
->m_bpp 
== 32 || !gdk_pixbuf_get_has_alpha(M_BMPDATA
->m_pixbufNoMask
)); 
 469     GdkBitmap
* mask 
= NULL
; 
 470     GdkPixmap
* pixmap 
= gdk_pixmap_create_from_xpm_d(wxGetRootWindow()->window
, &mask
, NULL
, const_cast<char**>(bits
)); 
 474         gdk_drawable_get_size(pixmap
, &width
, &height
); 
 475         m_refData 
= new wxBitmapRefData(width
, height
, -1); 
 476         M_BMPDATA
->m_pixmap 
= pixmap
; 
 479             M_BMPDATA
->m_mask 
= new wxMask(mask
); 
 485 wxBitmap::wxBitmap(GdkPixbuf
* pixbuf
, int depth
) 
 490             depth 
= gdk_pixbuf_get_n_channels(pixbuf
) * 8; 
 491         wxBitmapRefData
* bmpData 
= new wxBitmapRefData( 
 492             gdk_pixbuf_get_width(pixbuf
), gdk_pixbuf_get_height(pixbuf
), 
 496         bmpData
->m_pixbufNoMask 
= pixbuf
; 
 498         bmpData
->m_pixbuf 
= pixbuf
; 
 504 wxBitmap::wxBitmap(GdkPixmap
* pixmap
) 
 509         gdk_drawable_get_size(pixmap
, &w
, &h
); 
 510         wxBitmapRefData
* bmpData 
= 
 511             new wxBitmapRefData(w
, h
, gdk_drawable_get_depth(pixmap
)); 
 513         bmpData
->m_pixmap 
= pixmap
; 
 518 wxBitmap::~wxBitmap() 
 522 bool wxBitmap::Create( int width
, int height
, int depth 
) 
 525     wxCHECK_MSG(width 
>= 0 && height 
>= 0, false, "invalid bitmap size"); 
 526     m_refData 
= new wxBitmapRefData(width
, height
, depth
); 
 531 static void CopyImageData( 
 532     guchar
* dst
, int dstChannels
, int dstStride
, 
 533     const guchar
* src
, int srcChannels
, int srcStride
, 
 536     if (dstChannels 
== srcChannels
) 
 538         if (dstStride 
== srcStride
) 
 539             memcpy(dst
, src
, size_t(dstStride
) * h
); 
 542             const int stride 
= dstStride 
< srcStride 
? dstStride 
: srcStride
; 
 543             for (int j 
= 0; j 
< h
; j
++, src 
+= srcStride
, dst 
+= dstStride
) 
 544                 memcpy(dst
, src
, stride
); 
 549         for (int j 
= 0; j 
< h
; j
++, src 
+= srcStride
, dst 
+= dstStride
) 
 552             const guchar
* s 
= src
; 
 553             if (dstChannels 
== 4) 
 555                 for (int i 
= 0; i 
< w
; i
++, d 
+= 4, s 
+= 3) 
 565                 for (int i 
= 0; i 
< w
; i
++, d 
+= 3, s 
+= 4) 
 579 wxBitmap::wxBitmap(const wxImage
& image
, int depth
) 
 581     wxCHECK_RET(image
.IsOk(), "invalid image"); 
 583     const int w 
= image
.GetWidth(); 
 584     const int h 
= image
.GetHeight(); 
 585     const guchar
* alpha 
= image
.GetAlpha(); 
 587         depth 
= alpha 
? 32 : 24; 
 588     else if (depth 
!= 1 && depth 
!= 32) 
 590     wxBitmapRefData
* bmpData 
= new wxBitmapRefData(w
, h
, depth
); 
 592     GdkPixbuf
* pixbuf_dst 
= gdk_pixbuf_new(GDK_COLORSPACE_RGB
, depth 
== 32, 8, w
, h
); 
 593     bmpData
->m_pixbufNoMask 
= pixbuf_dst
; 
 594     wxASSERT(bmpData
->m_bpp 
== 32 || !gdk_pixbuf_get_has_alpha(bmpData
->m_pixbufNoMask
)); 
 595     const guchar
* src 
= image
.GetData(); 
 597     guchar
* dst 
= gdk_pixbuf_get_pixels(pixbuf_dst
); 
 598     const int dstStride 
= gdk_pixbuf_get_rowstride(pixbuf_dst
); 
 599     CopyImageData(dst
, gdk_pixbuf_get_n_channels(pixbuf_dst
), dstStride
, src
, 3, 3 * w
, w
, h
); 
 601     if (depth 
== 32 && alpha
) 
 603         for (int j 
= 0; j 
< h
; j
++, dst 
+= dstStride
) 
 604             for (int i 
= 0; i 
< w
; i
++) 
 605                 dst
[i 
* 4 + 3] = *alpha
++; 
 609         const guchar r 
= image
.GetMaskRed(); 
 610         const guchar g 
= image
.GetMaskGreen(); 
 611         const guchar b 
= image
.GetMaskBlue(); 
 612         cairo_surface_t
* surface 
= cairo_image_surface_create(CAIRO_FORMAT_A8
, w
, h
); 
 613         const int stride 
= cairo_image_surface_get_stride(surface
); 
 614         dst 
= cairo_image_surface_get_data(surface
); 
 615         memset(dst
, 0xff, stride 
* h
); 
 616         for (int j 
= 0; j 
< h
; j
++, dst 
+= stride
) 
 617             for (int i 
= 0; i 
< w
; i
++, src 
+= 3) 
 618                 if (src
[0] == r 
&& src
[1] == g 
&& src
[2] == b
) 
 620         cairo_surface_mark_dirty(surface
); 
 621         bmpData
->m_mask 
= new wxMask(surface
); 
 625 wxBitmap::wxBitmap(const wxImage
& image
, int depth
) 
 627     wxCHECK_RET(image
.IsOk(), "invalid image"); 
 629     if (depth 
== 32 || (depth 
== -1 && image
.HasAlpha())) 
 630         CreateFromImageAsPixbuf(image
); 
 632         // otherwise create pixmap, if alpha is present it will be converted to mask 
 633         CreateFromImageAsPixmap(image
, depth
); 
 636 bool wxBitmap::CreateFromImageAsPixmap(const wxImage
& image
, int depth
) 
 638     const int w 
= image
.GetWidth(); 
 639     const int h 
= image
.GetHeight(); 
 642         // create XBM format bitmap 
 644         // one bit per pixel, each row starts on a byte boundary 
 645         const size_t out_size 
= size_t((w 
+ 7) / 8) * unsigned(h
); 
 646         wxByte
* out 
= new wxByte
[out_size
]; 
 647         // set bits are black 
 648         memset(out
, 0xff, out_size
); 
 649         const wxByte
* in 
= image
.GetData(); 
 650         unsigned bit_index 
= 0; 
 651         for (int y 
= 0; y 
< h
; y
++) 
 653             for (int x 
= 0; x 
< w
; x
++, in 
+= 3, bit_index
++) 
 654                 if (in
[0] == 255 && in
[1] == 255 && in
[2] == 255) 
 655                     out
[bit_index 
>> 3] ^= 1 << (bit_index 
& 7); 
 656             // move index to next byte boundary 
 657             bit_index 
= (bit_index 
+ 7) & ~7u; 
 659         SetPixmap(gdk_bitmap_create_from_data(wxGetRootWindow()->window
, (char*)out
, w
, h
)); 
 662         if (!M_BMPDATA
)     // SetPixmap may have failed 
 667         SetPixmap(gdk_pixmap_new(wxGetRootWindow()->window
, w
, h
, depth
)); 
 671         wxGtkObject
<GdkGC
> gc(gdk_gc_new(M_BMPDATA
->m_pixmap
)); 
 673             M_BMPDATA
->m_pixmap
, gc
, 
 675             GDK_RGB_DITHER_NONE
, image
.GetData(), w 
* 3); 
 678     const wxByte
* alpha 
= image
.GetAlpha(); 
 679     if (alpha 
!= NULL 
|| image
.HasMask()) 
 681         // create mask as XBM format bitmap 
 683         const size_t out_size 
= size_t((w 
+ 7) / 8) * unsigned(h
); 
 684         wxByte
* out 
= new wxByte
[out_size
]; 
 685         memset(out
, 0xff, out_size
); 
 686         unsigned bit_index 
= 0; 
 689             for (int y 
= 0; y 
< h
; y
++) 
 691                 for (int x 
= 0; x 
< w
; x
++, bit_index
++) 
 692                     if (*alpha
++ < wxIMAGE_ALPHA_THRESHOLD
) 
 693                         out
[bit_index 
>> 3] ^= 1 << (bit_index 
& 7); 
 694                 bit_index 
= (bit_index 
+ 7) & ~7u; 
 699             const wxByte r_mask 
= image
.GetMaskRed(); 
 700             const wxByte g_mask 
= image
.GetMaskGreen(); 
 701             const wxByte b_mask 
= image
.GetMaskBlue(); 
 702             const wxByte
* in 
= image
.GetData(); 
 703             for (int y 
= 0; y 
< h
; y
++) 
 705                 for (int x 
= 0; x 
< w
; x
++, in 
+= 3, bit_index
++) 
 706                     if (in
[0] == r_mask 
&& in
[1] == g_mask 
&& in
[2] == b_mask
) 
 707                         out
[bit_index 
>> 3] ^= 1 << (bit_index 
& 7); 
 708                 bit_index 
= (bit_index 
+ 7) & ~7u; 
 711         SetMask(new wxMask(gdk_bitmap_create_from_data(M_BMPDATA
->m_pixmap
, (char*)out
, w
, h
))); 
 717 bool wxBitmap::CreateFromImageAsPixbuf(const wxImage
& image
) 
 719     int width 
= image
.GetWidth(); 
 720     int height 
= image
.GetHeight(); 
 722     Create(width
, height
, 32); 
 723     GdkPixbuf
* pixbuf 
= GetPixbuf(); 
 728     const unsigned char* in 
= image
.GetData(); 
 729     unsigned char *out 
= gdk_pixbuf_get_pixels(pixbuf
); 
 730     unsigned char *alpha 
= image
.GetAlpha(); 
 732     int rowpad 
= gdk_pixbuf_get_rowstride(pixbuf
) - 4 * width
; 
 734     for (int y 
= 0; y 
< height
; y
++, out 
+= rowpad
) 
 736         for (int x 
= 0; x 
< width
; x
++, out 
+= 4, in 
+= 3) 
 750 wxImage 
wxBitmap::ConvertToImage() const 
 754     wxCHECK_MSG(IsOk(), image
, "invalid bitmap"); 
 755     wxBitmapRefData
* bmpData 
= M_BMPDATA
; 
 756     const int w 
= bmpData
->m_width
; 
 757     const int h 
= bmpData
->m_height
; 
 758     image
.Create(w
, h
, false); 
 759     guchar
* dst 
= image
.GetData(); 
 760     GdkPixbuf
* pixbuf_src 
= NULL
; 
 761     if (bmpData
->m_pixbufNoMask
) 
 762         pixbuf_src 
= bmpData
->m_pixbufNoMask
; 
 763     else if (bmpData
->m_surface
) 
 765         pixbuf_src 
= gdk_pixbuf_get_from_surface(bmpData
->m_surface
, 0, 0, w
, h
); 
 766         bmpData
->m_pixbufNoMask 
= pixbuf_src
; 
 767         wxASSERT(bmpData
->m_bpp 
== 32 || !gdk_pixbuf_get_has_alpha(bmpData
->m_pixbufNoMask
)); 
 771         const guchar
* src 
= gdk_pixbuf_get_pixels(pixbuf_src
); 
 772         const int srcStride 
= gdk_pixbuf_get_rowstride(pixbuf_src
); 
 773         const int srcChannels 
= gdk_pixbuf_get_n_channels(pixbuf_src
); 
 774         CopyImageData(dst
, 3, 3 * w
, src
, srcChannels
, srcStride
, w
, h
); 
 776         if (srcChannels 
== 4) 
 779             guchar
* alpha 
= image
.GetAlpha(); 
 780             for (int j 
= 0; j 
< h
; j
++, src 
+= srcStride
) 
 782                 const guchar
* s 
= src
; 
 783                 for (int i 
= 0; i 
< w
; i
++, s 
+= 4) 
 788     cairo_surface_t
* maskSurf 
= NULL
; 
 790         maskSurf 
= *bmpData
->m_mask
; 
 796         image
.SetMaskColour(r
, g
, b
); 
 797         wxASSERT(cairo_image_surface_get_format(maskSurf
) == CAIRO_FORMAT_A8
); 
 798         const int stride 
= cairo_image_surface_get_stride(maskSurf
); 
 799         const guchar
* src 
= cairo_image_surface_get_data(maskSurf
); 
 800         for (int j 
= 0; j 
< h
; j
++, src 
+= stride
) 
 802             for (int i 
= 0; i 
< w
; i
++, dst 
+= 3) 
 809                 else if (dst
[0] == r 
&& dst
[1] == g 
&& dst
[2] == b
) 
 814     wxCHECK_MSG( IsOk(), wxNullImage
, wxT("invalid bitmap") ); 
 816     const int w 
= GetWidth(); 
 817     const int h 
= GetHeight(); 
 818     wxImage 
image(w
, h
, false); 
 819     unsigned char *data 
= image
.GetData(); 
 821     wxCHECK_MSG(data 
!= NULL
, wxNullImage
, wxT("couldn't create image") ); 
 823     // prefer pixbuf if available, it will preserve alpha and should be quicker 
 826         GdkPixbuf 
*pixbuf 
= GetPixbuf(); 
 827         unsigned char* alpha 
= NULL
; 
 828         if (gdk_pixbuf_get_has_alpha(pixbuf
)) 
 831             alpha 
= image
.GetAlpha(); 
 833         const unsigned char* in 
= gdk_pixbuf_get_pixels(pixbuf
); 
 834         unsigned char *out 
= data
; 
 835         const int inc 
= 3 + int(alpha 
!= NULL
); 
 836         const int rowpad 
= gdk_pixbuf_get_rowstride(pixbuf
) - inc 
* w
; 
 838         for (int y 
= 0; y 
< h
; y
++, in 
+= rowpad
) 
 840             for (int x 
= 0; x 
< w
; x
++, in 
+= inc
, out 
+= 3) 
 852         GdkPixmap
* pixmap 
= GetPixmap(); 
 853         GdkPixmap
* pixmap_invert 
= NULL
; 
 856             // mono bitmaps are inverted, i.e. 0 is white 
 857             pixmap_invert 
= gdk_pixmap_new(pixmap
, w
, h
, 1); 
 858             wxGtkObject
<GdkGC
> gc(gdk_gc_new(pixmap_invert
)); 
 859             gdk_gc_set_function(gc
, GDK_COPY_INVERT
); 
 860             gdk_draw_drawable(pixmap_invert
, gc
, pixmap
, 0, 0, 0, 0, w
, h
); 
 861             pixmap 
= pixmap_invert
; 
 863         // create a pixbuf which shares data with the wxImage 
 864         GdkPixbuf
* pixbuf 
= gdk_pixbuf_new_from_data( 
 865             data
, GDK_COLORSPACE_RGB
, false, 8, w
, h
, 3 * w
, NULL
, NULL
); 
 867         gdk_pixbuf_get_from_drawable(pixbuf
, pixmap
, NULL
, 0, 0, 0, 0, w
, h
); 
 869         g_object_unref(pixbuf
); 
 870         if (pixmap_invert 
!= NULL
) 
 871             g_object_unref(pixmap_invert
); 
 873     // convert mask, unless there is already alpha 
 874     if (GetMask() && !image
.HasAlpha()) 
 876         // we hard code the mask colour for now but we could also make an 
 877         // effort (and waste time) to choose a colour not present in the 
 878         // image already to avoid having to fudge the pixels below -- 
 879         // whether it's worth to do it is unclear however 
 880         const int MASK_RED 
= 1; 
 881         const int MASK_GREEN 
= 2; 
 882         const int MASK_BLUE 
= 3; 
 883         const int MASK_BLUE_REPLACEMENT 
= 2; 
 885         image
.SetMaskColour(MASK_RED
, MASK_GREEN
, MASK_BLUE
); 
 886         GdkImage
* image_mask 
= gdk_drawable_get_image(*GetMask(), 0, 0, w
, h
); 
 888         for (int y 
= 0; y 
< h
; y
++) 
 890             for (int x 
= 0; x 
< w
; x
++, data 
+= 3) 
 892                 if (gdk_image_get_pixel(image_mask
, x
, y
) == 0) 
 895                     data
[1] = MASK_GREEN
; 
 898                 else if (data
[0] == MASK_RED 
&& data
[1] == MASK_GREEN 
&& data
[2] == MASK_BLUE
) 
 900                     // we have to fudge the colour a bit to prevent 
 901                     // this pixel from appearing transparent 
 902                     data
[2] = MASK_BLUE_REPLACEMENT
; 
 906         g_object_unref(image_mask
); 
 913 #endif // wxUSE_IMAGE 
 915 int wxBitmap::GetHeight() const 
 917     wxCHECK_MSG( IsOk(), -1, wxT("invalid bitmap") ); 
 919     return M_BMPDATA
->m_height
; 
 922 int wxBitmap::GetWidth() const 
 924     wxCHECK_MSG( IsOk(), -1, wxT("invalid bitmap") ); 
 926     return M_BMPDATA
->m_width
; 
 929 int wxBitmap::GetDepth() const 
 931     wxCHECK_MSG( IsOk(), -1, wxT("invalid bitmap") ); 
 933     return M_BMPDATA
->m_bpp
; 
 936 wxMask 
*wxBitmap::GetMask() const 
 938     wxCHECK_MSG( IsOk(), NULL
, wxT("invalid bitmap") ); 
 940     return M_BMPDATA
->m_mask
; 
 943 void wxBitmap::SetMask( wxMask 
*mask 
) 
 945     wxCHECK_RET( IsOk(), wxT("invalid bitmap") ); 
 948     delete M_BMPDATA
->m_mask
; 
 949     M_BMPDATA
->m_mask 
= mask
; 
 952 bool wxBitmap::CopyFromIcon(const wxIcon
& icon
) 
 959 static cairo_surface_t
* GetSubSurface(cairo_surface_t
* surface
, const wxRect
& rect
) 
 961     cairo_surface_flush(surface
); 
 962     const cairo_format_t format 
= cairo_image_surface_get_format(surface
); 
 964     if (format 
!= CAIRO_FORMAT_A8
) 
 966     cairo_surface_t
* subSurface 
= cairo_image_surface_create(format
, rect
.width
, rect
.height
); 
 967     const int srcStride 
= cairo_image_surface_get_stride(surface
); 
 968     const int dstStride 
= cairo_image_surface_get_stride(subSurface
); 
 969     const guchar
* src 
= cairo_image_surface_get_data(surface
) + rect
.y 
* srcStride 
+ x
; 
 970     guchar
* dst 
= cairo_image_surface_get_data(subSurface
); 
 971     for (int j 
= 0; j 
< rect
.height
; j
++, src 
+= srcStride
, dst 
+= dstStride
) 
 972         memcpy(dst
, src
, dstStride
); 
 973     cairo_surface_mark_dirty(subSurface
); 
 978 wxBitmap 
wxBitmap::GetSubBitmap( const wxRect
& rect
) const 
 982     wxCHECK_MSG(IsOk(), ret
, wxT("invalid bitmap")); 
 984     const int w 
= rect
.width
; 
 985     const int h 
= rect
.height
; 
 986     const wxBitmapRefData
* bmpData 
= M_BMPDATA
; 
 988     wxCHECK_MSG(rect
.x 
>= 0 && rect
.y 
>= 0 && 
 989                 rect
.x 
+ w 
<= bmpData
->m_width 
&& 
 990                 rect
.y 
+ h 
<= bmpData
->m_height
, 
 991                 ret
, wxT("invalid bitmap region")); 
 993     wxBitmapRefData 
* const newRef 
= new wxBitmapRefData(w
, h
, bmpData
->m_bpp
); 
 994     ret
.m_refData 
= newRef
; 
 997     if (bmpData
->m_pixbufNoMask
) 
 999         GdkPixbuf
* pixbuf 
= gdk_pixbuf_new_subpixbuf(bmpData
->m_pixbufNoMask
, rect
.x
, rect
.y
, w
, h
); 
1000         newRef
->m_pixbufNoMask 
= gdk_pixbuf_copy(pixbuf
); 
1001         wxASSERT(newRef
->m_bpp 
== 32 || !gdk_pixbuf_get_has_alpha(newRef
->m_pixbufNoMask
)); 
1002         g_object_unref(pixbuf
); 
1004     else if (bmpData
->m_surface
) 
1005         newRef
->m_surface 
= GetSubSurface(bmpData
->m_surface
, rect
); 
1007     cairo_surface_t
* maskSurf 
= NULL
; 
1008     if (bmpData
->m_mask
) 
1009         maskSurf 
= *bmpData
->m_mask
; 
1012         newRef
->m_mask 
= new wxMask(GetSubSurface(maskSurf
, rect
)); 
1015     if (bmpData
->m_pixbuf
) 
1018             gdk_pixbuf_new_subpixbuf(bmpData
->m_pixbuf
, rect
.x
, rect
.y
, w
, h
); 
1019         newRef
->m_pixbuf 
= gdk_pixbuf_copy(pixbuf
); 
1020         g_object_unref(pixbuf
); 
1022     if (bmpData
->m_pixmap
) 
1024         newRef
->m_pixmap 
= gdk_pixmap_new(bmpData
->m_pixmap
, w
, h
, -1); 
1025         GdkGC
* gc 
= gdk_gc_new(newRef
->m_pixmap
); 
1027             newRef
->m_pixmap
, gc
, bmpData
->m_pixmap
, rect
.x
, rect
.y
, 0, 0, w
, h
); 
1030     GdkPixmap
* mask 
= NULL
; 
1031     if (bmpData
->m_mask
) 
1032         mask 
= *bmpData
->m_mask
; 
1035         GdkPixmap
* sub_mask 
= gdk_pixmap_new(mask
, w
, h
, 1); 
1036         newRef
->m_mask 
= new wxMask(sub_mask
); 
1037         GdkGC
* gc 
= gdk_gc_new(sub_mask
); 
1039             sub_mask
, gc
, mask
, rect
.x
, rect
.y
, 0, 0, w
, h
); 
1047 bool wxBitmap::SaveFile( const wxString 
&name
, wxBitmapType type
, const wxPalette 
*WXUNUSED(palette
) ) const 
1049     wxCHECK_MSG( IsOk(), false, wxT("invalid bitmap") ); 
1052     wxImage image 
= ConvertToImage(); 
1053     if (image
.IsOk() && image
.SaveFile(name
, type
)) 
1056     const char* type_name 
= NULL
; 
1059         case wxBITMAP_TYPE_BMP
:  type_name 
= "bmp";  break; 
1060         case wxBITMAP_TYPE_ICO
:  type_name 
= "ico";  break; 
1061         case wxBITMAP_TYPE_JPEG
: type_name 
= "jpeg"; break; 
1062         case wxBITMAP_TYPE_PNG
:  type_name 
= "png";  break; 
1066         gdk_pixbuf_save(GetPixbuf(), wxGTK_CONV_FN(name
), type_name
, NULL
, NULL
); 
1069 bool wxBitmap::LoadFile( const wxString 
&name
, wxBitmapType type 
) 
1073     if (image
.LoadFile(name
, type
) && image
.IsOk()) 
1074         *this = wxBitmap(image
); 
1078         wxUnusedVar(type
); // The type is detected automatically by GDK. 
1080         *this = wxBitmap(gdk_pixbuf_new_from_file(wxGTK_CONV_FN(name
), NULL
)); 
1087 wxPalette 
*wxBitmap::GetPalette() const 
1092 void wxBitmap::SetPalette(const wxPalette
& WXUNUSED(palette
)) 
1096 #endif // wxUSE_PALETTE 
1098 void wxBitmap::SetHeight( int height 
) 
1101     M_BMPDATA
->m_height 
= height
; 
1104 void wxBitmap::SetWidth( int width 
) 
1107     M_BMPDATA
->m_width 
= width
; 
1110 void wxBitmap::SetDepth( int depth 
) 
1113     M_BMPDATA
->m_bpp 
= depth
; 
1117 void wxBitmap::SetPixmap( GdkPixmap 
*pixmap 
) 
1125     gdk_drawable_get_size(pixmap
, &w
, &h
); 
1126     wxBitmapRefData
* bmpData 
= new wxBitmapRefData(w
, h
, 0); 
1127     m_refData 
= bmpData
; 
1128     bmpData
->m_pixmap 
= pixmap
; 
1129     bmpData
->m_bpp 
= gdk_drawable_get_depth(pixmap
); 
1132 GdkPixmap 
*wxBitmap::GetPixmap() const 
1134     wxCHECK_MSG( IsOk(), NULL
, wxT("invalid bitmap") ); 
1136     wxBitmapRefData
* bmpData 
= M_BMPDATA
; 
1137     if (bmpData
->m_pixmap
) 
1138         return bmpData
->m_pixmap
; 
1140     if (bmpData
->m_pixbuf
) 
1142         GdkPixmap
* pixmap 
= NULL
; 
1143         GdkPixmap
** mask_pixmap 
= NULL
; 
1144         if (gdk_pixbuf_get_has_alpha(bmpData
->m_pixbuf
)) 
1146             // make new mask from alpha 
1147             mask_pixmap 
= &pixmap
; 
1149         gdk_pixbuf_render_pixmap_and_mask( 
1150             bmpData
->m_pixbuf
, &bmpData
->m_pixmap
, mask_pixmap
, 128); 
1153             delete bmpData
->m_mask
; 
1154             bmpData
->m_mask 
= new wxMask(pixmap
); 
1159         bmpData
->m_pixmap 
= gdk_pixmap_new(wxGetRootWindow()->window
, 
1160             bmpData
->m_width
, bmpData
->m_height
, bmpData
->m_bpp 
== 1 ? 1 : -1); 
1162     return bmpData
->m_pixmap
; 
1165 bool wxBitmap::HasPixmap() const 
1167     wxCHECK_MSG( IsOk(), false, wxT("invalid bitmap") ); 
1169     return M_BMPDATA
->m_pixmap 
!= NULL
; 
1174 GdkPixbuf
* wxBitmap::GetPixbufNoMask() const 
1176     wxCHECK_MSG(IsOk(), NULL
, "invalid bitmap"); 
1178     wxBitmapRefData
* bmpData 
= M_BMPDATA
; 
1179     GdkPixbuf
* pixbuf 
= bmpData
->m_pixbufNoMask
; 
1183     const int w 
= bmpData
->m_width
; 
1184     const int h 
= bmpData
->m_height
; 
1185     if (bmpData
->m_surface
) 
1186         pixbuf 
= gdk_pixbuf_get_from_surface(bmpData
->m_surface
, 0, 0, w
, h
); 
1188         pixbuf 
= gdk_pixbuf_new(GDK_COLORSPACE_RGB
, bmpData
->m_bpp 
== 32, 8, w
, h
); 
1189     bmpData
->m_pixbufNoMask 
= pixbuf
; 
1190     wxASSERT(bmpData
->m_bpp 
== 32 || !gdk_pixbuf_get_has_alpha(bmpData
->m_pixbufNoMask
)); 
1195 // helper to set up a simulated depth 1 surface 
1196 static void SetSourceSurface1(const wxBitmapRefData
* bmpData
, cairo_t
* cr
, int x
, int y
, const wxColour
* fg
, const wxColour
* bg
) 
1198     GdkPixbuf
* pixbuf 
= gdk_pixbuf_copy(bmpData
->m_pixbufNoMask
); 
1199     const int w 
= bmpData
->m_width
; 
1200     const int h 
= bmpData
->m_height
; 
1201     const int stride 
= gdk_pixbuf_get_rowstride(pixbuf
); 
1202     const int channels 
= gdk_pixbuf_get_n_channels(pixbuf
); 
1203     guchar
* dst 
= gdk_pixbuf_get_pixels(pixbuf
); 
1204     guchar fg_r 
= 0, fg_g 
= 0, fg_b 
= 0; 
1205     if (fg 
&& fg
->IsOk()) 
1211     guchar bg_r 
= 255, bg_g 
= 255, bg_b 
= 255; 
1212     if (bg 
&& bg
->IsOk()) 
1218     for (int j 
= 0; j 
< h
; j
++, dst 
+= stride
) 
1221         for (int i 
= 0; i 
< w
; i
++, d 
+= channels
) 
1235     gdk_cairo_set_source_pixbuf(cr
, pixbuf
, x
, y
); 
1236     g_object_unref(pixbuf
); 
1239 void wxBitmap::SetSourceSurface(cairo_t
* cr
, int x
, int y
, const wxColour
* fg
, const wxColour
* bg
) const 
1241     wxBitmapRefData
* bmpData 
= M_BMPDATA
; 
1242     if (bmpData
->m_surface
) 
1244         cairo_set_source_surface(cr
, bmpData
->m_surface
, x
, y
); 
1247     wxCHECK_RET(bmpData
->m_pixbufNoMask
, "no bitmap data"); 
1248     if (bmpData
->m_bpp 
== 1) 
1249         SetSourceSurface1(bmpData
, cr
, x
, y
, fg
, bg
); 
1252         gdk_cairo_set_source_pixbuf(cr
, bmpData
->m_pixbufNoMask
, x
, y
); 
1253         cairo_pattern_get_surface(cairo_get_source(cr
), &bmpData
->m_surface
); 
1254         cairo_surface_reference(bmpData
->m_surface
); 
1258 cairo_t
* wxBitmap::CairoCreate() const 
1260     wxCHECK_MSG(IsOk(), NULL
, "invalid bitmap"); 
1262     wxBitmapRefData
* bmpData 
= M_BMPDATA
; 
1264     if (bmpData
->m_surface
) 
1265         cr 
= cairo_create(bmpData
->m_surface
); 
1268         GdkPixbuf
* pixbuf 
= bmpData
->m_pixbufNoMask
; 
1269         const bool useAlpha 
= bmpData
->m_bpp 
== 32 || (pixbuf 
&& gdk_pixbuf_get_has_alpha(pixbuf
)); 
1270         bmpData
->m_surface 
= cairo_image_surface_create( 
1271             useAlpha 
? CAIRO_FORMAT_ARGB32 
: CAIRO_FORMAT_RGB24
, 
1272             bmpData
->m_width
, bmpData
->m_height
); 
1273         cr 
= cairo_create(bmpData
->m_surface
); 
1276             gdk_cairo_set_source_pixbuf(cr
, pixbuf
, 0, 0); 
1278             cairo_set_source_rgb(cr
, 0, 0, 0); 
1281     if (bmpData
->m_pixbufNoMask
) 
1283         g_object_unref(bmpData
->m_pixbufNoMask
); 
1284         bmpData
->m_pixbufNoMask 
= NULL
; 
1286     if (bmpData
->m_pixbufMask
) 
1288         g_object_unref(bmpData
->m_pixbufMask
); 
1289         bmpData
->m_pixbufMask 
= NULL
; 
1291     wxASSERT(cr 
&& cairo_status(cr
) == 0); 
1295 void wxBitmap::Draw(cairo_t
* cr
, int x
, int y
, bool useMask
, const wxColour
* fg
, const wxColour
* bg
) const 
1297     wxCHECK_RET(IsOk(), "invalid bitmap"); 
1299     wxBitmapRefData
* bmpData 
= M_BMPDATA
; 
1300     SetSourceSurface(cr
, x
, y
, fg
, bg
); 
1301     cairo_pattern_set_filter(cairo_get_source(cr
), CAIRO_FILTER_NEAREST
); 
1302     cairo_surface_t
* mask 
= NULL
; 
1303     if (useMask 
&& bmpData
->m_mask
) 
1304         mask 
= *bmpData
->m_mask
; 
1306         cairo_mask_surface(cr
, mask
, x
, y
); 
1312 GdkPixbuf 
*wxBitmap::GetPixbuf() const 
1314     wxCHECK_MSG( IsOk(), NULL
, wxT("invalid bitmap") ); 
1316     wxBitmapRefData
* bmpData 
= M_BMPDATA
; 
1318     if (bmpData
->m_pixbufMask
) 
1319         return bmpData
->m_pixbufMask
; 
1321     if (bmpData
->m_pixbufNoMask 
== NULL
) 
1323     cairo_surface_t
* mask 
= NULL
; 
1324     if (bmpData
->m_mask
) 
1325         mask 
= *bmpData
->m_mask
; 
1327         return bmpData
->m_pixbufNoMask
; 
1329     const int w 
= bmpData
->m_width
; 
1330     const int h 
= bmpData
->m_height
; 
1331     bmpData
->m_pixbufMask 
= gdk_pixbuf_new(GDK_COLORSPACE_RGB
, true, 8, w
, h
); 
1333     guchar
* dst 
= gdk_pixbuf_get_pixels(bmpData
->m_pixbufMask
); 
1334     const int dstStride 
= gdk_pixbuf_get_rowstride(bmpData
->m_pixbufMask
); 
1335     CopyImageData(dst
, 4, dstStride
, 
1336         gdk_pixbuf_get_pixels(bmpData
->m_pixbufNoMask
), 
1337         gdk_pixbuf_get_n_channels(bmpData
->m_pixbufNoMask
), 
1338         gdk_pixbuf_get_rowstride(bmpData
->m_pixbufNoMask
), 
1341     const guchar
* src 
= cairo_image_surface_get_data(mask
); 
1342     const int srcStride 
= cairo_image_surface_get_stride(mask
); 
1343     for (int j 
= 0; j 
< h
; j
++, src 
+= srcStride
, dst 
+= dstStride
) 
1344         for (int i 
= 0; i 
< w
; i
++) 
1348     return bmpData
->m_pixbufMask
; 
1350     if (bmpData
->m_pixbuf
) 
1351         return bmpData
->m_pixbuf
; 
1353     const int w 
= bmpData
->m_width
; 
1354     const int h 
= bmpData
->m_height
; 
1355     GdkPixmap
* mask 
= NULL
; 
1356     if (bmpData
->m_mask
) 
1357         mask 
= *bmpData
->m_mask
; 
1358     const bool useAlpha 
= bmpData
->m_alphaRequested 
|| mask
; 
1359     bmpData
->m_pixbuf 
= gdk_pixbuf_new(GDK_COLORSPACE_RGB
, useAlpha
, 8, w
, h
); 
1360     if (bmpData
->m_pixmap
) 
1361         PixmapToPixbuf(bmpData
->m_pixmap
, bmpData
->m_pixbuf
, w
, h
); 
1363         MaskToAlpha(mask
, bmpData
->m_pixbuf
, w
, h
); 
1364     return bmpData
->m_pixbuf
; 
1369 bool wxBitmap::HasPixbuf() const 
1371     wxCHECK_MSG( IsOk(), false, wxT("invalid bitmap") ); 
1373     return M_BMPDATA
->m_pixbuf 
!= NULL
; 
1376 void wxBitmap::PurgeOtherRepresentations(wxBitmap::Representation keep
) 
1378     if (keep 
== Pixmap 
&& HasPixbuf()) 
1380         g_object_unref (M_BMPDATA
->m_pixbuf
); 
1381         M_BMPDATA
->m_pixbuf 
= NULL
; 
1383     if (keep 
== Pixbuf 
&& HasPixmap()) 
1385         g_object_unref (M_BMPDATA
->m_pixmap
); 
1386         M_BMPDATA
->m_pixmap 
= NULL
; 
1391 #ifdef wxHAS_RAW_BITMAP 
1392 void *wxBitmap::GetRawData(wxPixelDataBase
& data
, int bpp
) 
1396     GdkPixbuf
* pixbuf 
= GetPixbufNoMask(); 
1397     if ((bpp 
== 32) == (gdk_pixbuf_get_has_alpha(pixbuf
) != 0)) 
1399         bits 
= gdk_pixbuf_get_pixels(pixbuf
); 
1400         wxBitmapRefData
* bmpData 
= M_BMPDATA
; 
1401         data
.m_width 
= bmpData
->m_width
; 
1402         data
.m_height 
= bmpData
->m_height
; 
1403         data
.m_stride 
= gdk_pixbuf_get_rowstride(pixbuf
); 
1404         if (bmpData
->m_pixbufMask
) 
1406             g_object_unref(bmpData
->m_pixbufMask
); 
1407             bmpData
->m_pixbufMask 
= NULL
; 
1409         if (bmpData
->m_surface
) 
1411             cairo_surface_destroy(bmpData
->m_surface
); 
1412             bmpData
->m_surface 
= NULL
; 
1416     GdkPixbuf 
*pixbuf 
= GetPixbuf(); 
1417     const bool hasAlpha 
= HasAlpha(); 
1419     // allow access if bpp is valid and matches existence of alpha 
1420     if ( pixbuf 
&& ((bpp 
== 24 && !hasAlpha
) || (bpp 
== 32 && hasAlpha
)) ) 
1422         data
.m_height 
= gdk_pixbuf_get_height( pixbuf 
); 
1423         data
.m_width 
= gdk_pixbuf_get_width( pixbuf 
); 
1424         data
.m_stride 
= gdk_pixbuf_get_rowstride( pixbuf 
); 
1425         bits 
= gdk_pixbuf_get_pixels(pixbuf
); 
1431 void wxBitmap::UngetRawData(wxPixelDataBase
& WXUNUSED(data
)) 
1434 #endif // wxHAS_RAW_BITMAP 
1436 bool wxBitmap::HasAlpha() const 
1438     const wxBitmapRefData
* bmpData 
= M_BMPDATA
; 
1440     return bmpData 
&& bmpData
->m_bpp 
== 32; 
1442     return bmpData 
&& (bmpData
->m_alphaRequested 
|| 
1443         (bmpData
->m_pixbuf 
&& gdk_pixbuf_get_has_alpha(bmpData
->m_pixbuf
))); 
1447 wxGDIRefData
* wxBitmap::CreateGDIRefData() const 
1449     return new wxBitmapRefData(0, 0, 0); 
1452 wxGDIRefData
* wxBitmap::CloneGDIRefData(const wxGDIRefData
* data
) const 
1454     const wxBitmapRefData
* oldRef 
= static_cast<const wxBitmapRefData
*>(data
); 
1455     wxBitmapRefData 
* const newRef 
= new wxBitmapRefData(oldRef
->m_width
, 
1459     if (oldRef
->m_pixbufNoMask
) 
1460         newRef
->m_pixbufNoMask 
= gdk_pixbuf_copy(oldRef
->m_pixbufNoMask
); 
1461     if (oldRef
->m_surface
) 
1463         const int w 
= oldRef
->m_width
; 
1464         const int h 
= oldRef
->m_height
; 
1465         cairo_surface_t
* surface 
= cairo_image_surface_create( 
1466             cairo_image_surface_get_format(oldRef
->m_surface
), w
, h
); 
1467         newRef
->m_surface 
= surface
; 
1468         cairo_surface_flush(oldRef
->m_surface
); 
1469         const guchar
* src 
= cairo_image_surface_get_data(oldRef
->m_surface
); 
1470         guchar
* dst 
= cairo_image_surface_get_data(surface
); 
1471         const int stride 
= cairo_image_surface_get_stride(surface
); 
1472         wxASSERT(stride 
== cairo_image_surface_get_stride(oldRef
->m_surface
)); 
1473         memcpy(dst
, src
, stride 
* h
); 
1474         cairo_surface_mark_dirty(surface
); 
1477     if (oldRef
->m_pixmap 
!= NULL
) 
1479         newRef
->m_pixmap 
= gdk_pixmap_new( 
1480             oldRef
->m_pixmap
, oldRef
->m_width
, oldRef
->m_height
, 
1481             // use pixmap depth, m_bpp may not match 
1482             gdk_drawable_get_depth(oldRef
->m_pixmap
)); 
1483         wxGtkObject
<GdkGC
> gc(gdk_gc_new(newRef
->m_pixmap
)); 
1485             newRef
->m_pixmap
, gc
, oldRef
->m_pixmap
, 0, 0, 0, 0, -1, -1); 
1487     if (oldRef
->m_pixbuf 
!= NULL
) 
1489         newRef
->m_pixbuf 
= gdk_pixbuf_copy(oldRef
->m_pixbuf
); 
1492     if (oldRef
->m_mask 
!= NULL
) 
1494         newRef
->m_mask 
= new wxMask(*oldRef
->m_mask
); 
1500 /* static */ void wxBitmap::InitStandardHandlers() 
1502     // TODO: Insert handler based on GdkPixbufs handler later