]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/bitmap.cpp
[ 1487463 ] XRC handler for wxOwnerDrawnComboBox.
[wxWidgets.git] / src / gtk / bitmap.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
0b04c4e0 2// Name: src/gtk/bitmap.cpp
c801d85f
KB
3// Purpose:
4// Author: Robert Roebling
6f65e337 5// RCS-ID: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling
65571936 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
14f355c2
VS
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
559a723c
WS
13#include "wx/bitmap.h"
14
93763ad5
WS
15#ifndef WX_PRECOMP
16 #include "wx/app.h"
f38924e8 17 #include "wx/dcmemory.h"
559a723c 18 #include "wx/palette.h"
923d28da 19 #include "wx/icon.h"
18680f86 20 #include "wx/math.h"
93763ad5 21#endif
22bd9387 22
fd0eed64 23#include "wx/filefn.h"
83624f79
RR
24#include "wx/image.h"
25
5696ebb3 26#include "wx/rawbmp.h"
9e691f46
VZ
27 // need this to get gdk_image_new_bitmap()
28 #define GDK_ENABLE_BROKEN
9e691f46 29
20e05ffb 30#include <gdk/gdk.h>
d76fe38b 31#include <gtk/gtk.h>
b5f01ae0
VS
32#include <gdk/gdkx.h>
33
68567a96 34#include <gdk/gdkimage.h>
13111b2a 35
f6bcfd97
BP
36extern void gdk_wx_draw_bitmap (GdkDrawable *drawable,
37 GdkGC *gc,
38 GdkDrawable *src,
39 gint xsrc,
40 gint ysrc,
41 gint xdest,
42 gint ydest,
43 gint width,
44 gint height);
45
d76fe38b
RR
46//-----------------------------------------------------------------------------
47// data
48//-----------------------------------------------------------------------------
49
c2fa61e8 50extern GtkWidget *wxGetRootWindow();
c801d85f
KB
51
52//-----------------------------------------------------------------------------
53// wxMask
54//-----------------------------------------------------------------------------
55
56IMPLEMENT_DYNAMIC_CLASS(wxMask,wxObject)
57
8bbe427f 58wxMask::wxMask()
c801d85f 59{
fd0eed64 60 m_bitmap = (GdkBitmap *) NULL;
ff7b1510 61}
c801d85f 62
91b8de8d 63wxMask::wxMask( const wxBitmap& bitmap, const wxColour& colour )
c801d85f 64{
72a7edf0 65 m_bitmap = (GdkBitmap *) NULL;
91b8de8d 66 Create( bitmap, colour );
ff7b1510 67}
c801d85f 68
0b04c4e0 69#if wxUSE_PALETTE
91b8de8d 70wxMask::wxMask( const wxBitmap& bitmap, int paletteIndex )
c801d85f 71{
72a7edf0 72 m_bitmap = (GdkBitmap *) NULL;
91b8de8d 73 Create( bitmap, paletteIndex );
ff7b1510 74}
0b04c4e0 75#endif // wxUSE_PALETTE
c801d85f 76
91b8de8d 77wxMask::wxMask( const wxBitmap& bitmap )
c801d85f 78{
72a7edf0 79 m_bitmap = (GdkBitmap *) NULL;
91b8de8d 80 Create( bitmap );
ff7b1510 81}
c801d85f 82
8bbe427f 83wxMask::~wxMask()
c801d85f 84{
13111b2a 85 if (m_bitmap)
3fe39b0c 86 g_object_unref (m_bitmap);
ff7b1510 87}
c801d85f 88
1fb4de31
RR
89bool wxMask::Create( const wxBitmap& bitmap,
90 const wxColour& colour )
91b8de8d
RR
91{
92 if (m_bitmap)
284b4c88 93 {
3fe39b0c 94 g_object_unref (m_bitmap);
284b4c88 95 m_bitmap = (GdkBitmap*) NULL;
91b8de8d 96 }
13111b2a 97
368d59f0 98 wxImage image = bitmap.ConvertToImage();
902725ee 99 if (!image.Ok()) return false;
13111b2a 100
c2fa61e8 101 m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, image.GetWidth(), image.GetHeight(), 1 );
f9ee644e 102 GdkGC *gc = gdk_gc_new( m_bitmap );
13111b2a 103
f9ee644e
RR
104 GdkColor color;
105 color.red = 65000;
106 color.green = 65000;
107 color.blue = 65000;
108 color.pixel = 1;
109 gdk_gc_set_foreground( gc, &color );
110 gdk_gc_set_fill( gc, GDK_SOLID );
111 gdk_draw_rectangle( m_bitmap, gc, TRUE, 0, 0, image.GetWidth(), image.GetHeight() );
13111b2a 112
1fb4de31
RR
113 unsigned char *data = image.GetData();
114 int index = 0;
13111b2a 115
1fb4de31
RR
116 unsigned char red = colour.Red();
117 unsigned char green = colour.Green();
118 unsigned char blue = colour.Blue();
13111b2a 119
005f5d18 120 GdkVisual *visual = wxTheApp->GetGdkVisual();
c2fa61e8 121
1fb4de31 122 int bpp = visual->depth;
2eefae6e
VZ
123 if ((bpp == 16) && (visual->red_mask != 0xf800))
124 bpp = 15;
1fb4de31
RR
125 if (bpp == 15)
126 {
127 red = red & 0xf8;
1fb4de31 128 green = green & 0xf8;
f6bcfd97 129 blue = blue & 0xf8;
2eefae6e
VZ
130 }
131 else if (bpp == 16)
1fb4de31
RR
132 {
133 red = red & 0xf8;
f6bcfd97
BP
134 green = green & 0xfc;
135 blue = blue & 0xf8;
2eefae6e
VZ
136 }
137 else if (bpp == 12)
005f5d18
RR
138 {
139 red = red & 0xf0;
140 green = green & 0xf0;
141 blue = blue & 0xf0;
1fb4de31 142 }
13111b2a 143
f9ee644e
RR
144 color.red = 0;
145 color.green = 0;
146 color.blue = 0;
147 color.pixel = 0;
148 gdk_gc_set_foreground( gc, &color );
13111b2a 149
1fb4de31 150 for (int j = 0; j < image.GetHeight(); j++)
f9ee644e 151 {
f2593d0d
RR
152 int start_x = -1;
153 int i;
154 for (i = 0; i < image.GetWidth(); i++)
1fb4de31 155 {
13111b2a
VZ
156 if ((data[index] == red) &&
157 (data[index+1] == green) &&
158 (data[index+2] == blue))
159 {
160 if (start_x == -1)
161 start_x = i;
162 }
163 else
164 {
165 if (start_x != -1)
166 {
167 gdk_draw_line( m_bitmap, gc, start_x, j, i-1, j );
168 start_x = -1;
169 }
f9ee644e
RR
170 }
171 index += 3;
172 }
173 if (start_x != -1)
174 gdk_draw_line( m_bitmap, gc, start_x, j, i, j );
175 }
1fb4de31 176
3fe39b0c 177 g_object_unref (gc);
1fb4de31 178
902725ee 179 return true;
91b8de8d
RR
180}
181
0b04c4e0 182#if wxUSE_PALETTE
b5f01ae0 183bool wxMask::Create( const wxBitmap& bitmap, int paletteIndex )
91b8de8d 184{
b5f01ae0
VS
185 unsigned char r,g,b;
186 wxPalette *pal = bitmap.GetPalette();
284b4c88 187
902725ee 188 wxCHECK_MSG( pal, false, wxT("Cannot create mask from bitmap without palette") );
c2fa61e8 189
b5f01ae0 190 pal->GetRGB(paletteIndex, &r, &g, &b);
284b4c88 191
b5f01ae0 192 return Create(bitmap, wxColour(r, g, b));
91b8de8d 193}
0b04c4e0 194#endif // wxUSE_PALETTE
91b8de8d
RR
195
196bool wxMask::Create( const wxBitmap& bitmap )
197{
198 if (m_bitmap)
284b4c88 199 {
3fe39b0c 200 g_object_unref (m_bitmap);
284b4c88 201 m_bitmap = (GdkBitmap*) NULL;
91b8de8d 202 }
284b4c88 203
902725ee 204 if (!bitmap.Ok()) return false;
284b4c88 205
b85229d1 206 wxCHECK_MSG( bitmap.GetDepth() == 1, false, wxT("Cannot create mask from colour bitmap") );
284b4c88 207
c2fa61e8 208 m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, bitmap.GetWidth(), bitmap.GetHeight(), 1 );
284b4c88 209
902725ee 210 if (!m_bitmap) return false;
284b4c88 211
91b8de8d 212 GdkGC *gc = gdk_gc_new( m_bitmap );
284b4c88 213
b85229d1 214 gdk_wx_draw_bitmap( m_bitmap, gc, bitmap.GetPixmap(), 0, 0, 0, 0, bitmap.GetWidth(), bitmap.GetHeight() );
284b4c88 215
3fe39b0c 216 g_object_unref (gc);
284b4c88 217
902725ee 218 return true;
91b8de8d
RR
219}
220
221GdkBitmap *wxMask::GetBitmap() const
c801d85f 222{
fd0eed64 223 return m_bitmap;
ff7b1510 224}
8bbe427f 225
c801d85f
KB
226//-----------------------------------------------------------------------------
227// wxBitmap
228//-----------------------------------------------------------------------------
229
230class wxBitmapRefData: public wxObjectRefData
231{
fd0eed64 232public:
f2593d0d
RR
233 wxBitmapRefData();
234 ~wxBitmapRefData();
235
236 GdkPixmap *m_pixmap;
feac7937 237 GdkPixbuf *m_pixbuf;
f2593d0d
RR
238 wxMask *m_mask;
239 int m_width;
240 int m_height;
241 int m_bpp;
242 wxPalette *m_palette;
c801d85f
KB
243};
244
8bbe427f 245wxBitmapRefData::wxBitmapRefData()
c801d85f 246{
fd0eed64 247 m_pixmap = (GdkPixmap *) NULL;
feac7937 248 m_pixbuf = (GdkPixbuf *) NULL;
fd0eed64
RR
249 m_mask = (wxMask *) NULL;
250 m_width = 0;
251 m_height = 0;
252 m_bpp = 0;
253 m_palette = (wxPalette *) NULL;
ff7b1510 254}
c801d85f 255
8bbe427f 256wxBitmapRefData::~wxBitmapRefData()
c801d85f 257{
3ebcd89d 258 if (m_pixmap)
3fe39b0c 259 g_object_unref (m_pixmap);
feac7937 260 if (m_pixbuf)
3fe39b0c 261 g_object_unref (m_pixbuf);
3ebcd89d 262 delete m_mask;
0b04c4e0 263#if wxUSE_PALETTE
3ebcd89d 264 delete m_palette;
0b04c4e0 265#endif // wxUSE_PALETTE
ff7b1510 266}
c801d85f
KB
267
268//-----------------------------------------------------------------------------
269
b85229d1 270#define M_BMPDATA wx_static_cast(wxBitmapRefData*, m_refData)
c801d85f
KB
271
272IMPLEMENT_DYNAMIC_CLASS(wxBitmap,wxGDIObject)
273
8bbe427f 274wxBitmap::wxBitmap()
c801d85f 275{
ff7b1510 276}
8bbe427f 277
debe6624 278wxBitmap::wxBitmap( int width, int height, int depth )
c801d85f 279{
c826213d 280 Create( width, height, depth );
c826213d
RR
281}
282
283bool wxBitmap::Create( int width, int height, int depth )
284{
285 UnRef();
286
3ebcd89d
VZ
287 if ( width <= 0 || height <= 0 )
288 {
289 return false;
290 }
284b4c88 291
005f5d18 292 GdkVisual *visual = wxTheApp->GetGdkVisual();
284b4c88 293
3ebcd89d
VZ
294 if (depth == -1)
295 depth = visual->depth;
103aab26 296
902725ee 297 wxCHECK_MSG( (depth == visual->depth) || (depth == 1) || (depth == 32), false,
637b7e4f 298 wxT("invalid bitmap depth") );
8bbe427f 299
eefa26be 300 m_refData = new wxBitmapRefData();
fd0eed64 301 M_BMPDATA->m_mask = (wxMask *) NULL;
fd0eed64
RR
302 M_BMPDATA->m_width = width;
303 M_BMPDATA->m_height = height;
b85229d1
PC
304 M_BMPDATA->m_bpp = depth;
305 if (depth == 32)
284f2b59
RR
306 {
307 M_BMPDATA->m_pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB, true,
308 8, width, height);
284f2b59 309 }
eefa26be
RR
310 else
311 {
c2fa61e8 312 M_BMPDATA->m_pixmap = gdk_pixmap_new( wxGetRootWindow()->window, width, height, depth );
eefa26be 313 }
8bbe427f 314
c826213d 315 return Ok();
ff7b1510 316}
b5f01ae0 317
e838cc14 318bool wxBitmap::CreateFromXpm( const char **bits )
e52f60e6 319{
a11672a4
RR
320 UnRef();
321
637b7e4f 322 wxCHECK_MSG( bits != NULL, false, wxT("invalid bitmap data") );
8bbe427f 323
005f5d18 324 GdkVisual *visual = wxTheApp->GetGdkVisual();
c2fa61e8 325
e52f60e6
RR
326 m_refData = new wxBitmapRefData();
327
328 GdkBitmap *mask = (GdkBitmap*) NULL;
8bbe427f 329
c2fa61e8 330 M_BMPDATA->m_pixmap = gdk_pixmap_create_from_xpm_d( wxGetRootWindow()->window, &mask, NULL, (gchar **) bits );
8bbe427f 331
902725ee 332 wxCHECK_MSG( M_BMPDATA->m_pixmap, false, wxT("couldn't create pixmap") );
8bbe427f 333
fd0eed64
RR
334 if (mask)
335 {
336 M_BMPDATA->m_mask = new wxMask();
337 M_BMPDATA->m_mask->m_bitmap = mask;
338 }
8bbe427f 339
791d7ea2 340 gdk_drawable_get_size( M_BMPDATA->m_pixmap, &(M_BMPDATA->m_width), &(M_BMPDATA->m_height) );
2eefae6e 341
8cce8940 342 M_BMPDATA->m_bpp = visual->depth; // Can we get a different depth from create_from_xpm_d() ?
c2fa61e8 343
902725ee 344 return true;
ff7b1510 345}
b5f01ae0 346
783da845
RR
347wxBitmap wxBitmap::Rescale( int clipx, int clipy, int clipwidth, int clipheight, int newx, int newy )
348{
349 wxCHECK_MSG( Ok(), wxNullBitmap, wxT("invalid bitmap") );
350
351 if (newy==M_BMPDATA->m_width && newy==M_BMPDATA->m_height)
352 return *this;
902725ee 353
783da845
RR
354 int width = wxMax(newx, 1);
355 int height = wxMax(newy, 1);
356 width = wxMin(width, clipwidth);
357 height = wxMin(height, clipheight);
902725ee 358
feac7937 359 wxBitmap bmp;
783da845 360
feac7937 361 if (HasPixbuf())
783da845 362 {
feac7937
VS
363 bmp.SetWidth(width);
364 bmp.SetHeight(height);
365 bmp.SetDepth(GetDepth());
6db34764
VS
366 bmp.SetPixbuf(gdk_pixbuf_new(GDK_COLORSPACE_RGB,
367 gdk_pixbuf_get_has_alpha(GetPixbuf()),
feac7937 368 8, width, height));
6db34764 369 gdk_pixbuf_scale(GetPixbuf(), bmp.GetPixbuf(),
feac7937 370 0, 0, width, height,
902725ee 371 clipx, clipy,
feac7937
VS
372 (double)newx/GetWidth(), (double)newy/GetHeight(),
373 GDK_INTERP_BILINEAR);
783da845 374 }
feac7937 375 else
783da845 376 {
feac7937
VS
377 GdkImage *img = (GdkImage*) NULL;
378 if (GetPixmap())
379 img = gdk_image_get( GetPixmap(), 0, 0, GetWidth(), GetHeight() );
feac7937
VS
380 else
381 wxFAIL_MSG( wxT("Ill-formed bitmap") );
382
383 wxCHECK_MSG( img, wxNullBitmap, wxT("couldn't create image") );
783da845 384
feac7937
VS
385 int bpp = -1;
386
902725ee 387
feac7937
VS
388 GdkGC *gc = NULL;
389 GdkPixmap *dstpix = NULL;
b85229d1 390 if (GetDepth() != 1)
783da845 391 {
22a3bce4 392 GdkVisual *visual = gdk_drawable_get_visual( GetPixmap() );
feac7937
VS
393 if (visual == NULL)
394 visual = wxTheApp->GetGdkVisual();
395
396 bpp = visual->depth;
397 bmp = wxBitmap(width,height,bpp);
398 dstpix = bmp.GetPixmap();
399 gc = gdk_gc_new( dstpix );
783da845 400 }
783da845 401
feac7937
VS
402 char *dst = NULL;
403 long dstbyteperline = 0;
902725ee 404
b85229d1 405 if (GetDepth() == 1)
feac7937
VS
406 {
407 bpp = 1;
408 dstbyteperline = width/8*M_BMPDATA->m_bpp;
409 if (width*M_BMPDATA->m_bpp % 8 != 0)
410 dstbyteperline++;
411 dst = (char*) malloc(dstbyteperline*height);
412 }
902725ee 413
feac7937
VS
414 // be careful to use the right scaling factor
415 float scx = (float)M_BMPDATA->m_width/(float)newx;
416 float scy = (float)M_BMPDATA->m_height/(float)newy;
417 // prepare accel-tables
418 int *tablex = (int *)calloc(width,sizeof(int));
419 int *tabley = (int *)calloc(height,sizeof(int));
420
421 // accel table filled with clipped values
422 for (int x = 0; x < width; x++)
423 tablex[x] = (int) (scx * (x+clipx));
424 for (int y = 0; y < height; y++)
425 tabley[y] = (int) (scy * (y+clipy));
783da845 426
feac7937 427 // Main rescaling routine starts here
783da845
RR
428 for (int h = 0; h < height; h++)
429 {
430 char outbyte = 0;
f9ebac93 431 int old_x = -1;
b63b07a8 432 guint32 old_pixval = 0;
feac7937 433
f9ebac93 434 for (int w = 0; w < width; w++)
783da845 435 {
f9ebac93
RR
436 guint32 pixval;
437 int x = tablex[w];
438 if (x == old_x)
439 pixval = old_pixval;
440 else
441 {
442 pixval = gdk_image_get_pixel( img, x, tabley[h] );
443 old_pixval = pixval;
444 old_x = x;
445 }
902725ee 446
ce46daf9 447 if ( dst )
783da845 448 {
feac7937
VS
449 if (!pixval)
450 {
451 char bit=1;
d0ee33f5 452 char shift = bit << (w % 8);
feac7937
VS
453 outbyte |= shift;
454 }
902725ee 455
feac7937
VS
456 if ((w+1)%8==0)
457 {
458 dst[h*dstbyteperline+w/8] = outbyte;
459 outbyte = 0;
460 }
783da845 461 }
feac7937 462 else
783da845 463 {
feac7937
VS
464 GdkColor col;
465 col.pixel = pixval;
466 gdk_gc_set_foreground( gc, &col );
467 gdk_draw_point( dstpix, gc, w, h);
783da845
RR
468 }
469 }
902725ee 470
783da845 471 // do not forget the last byte
ce46daf9 472 if ( dst && (width % 8 != 0) )
f9ebac93 473 dst[h*dstbyteperline+width/8] = outbyte;
783da845 474 }
902725ee 475
3fe39b0c
MR
476 g_object_unref (img);
477 if (gc) g_object_unref (gc);
feac7937 478
ce46daf9 479 if ( dst )
feac7937
VS
480 {
481 bmp = wxBitmap( (const char *)dst, width, height, 1 );
482 free( dst );
483 }
902725ee 484
feac7937
VS
485 if (GetMask())
486 {
487 dstbyteperline = width/8;
488 if (width % 8 != 0)
489 dstbyteperline++;
490 dst = (char*) malloc(dstbyteperline*height);
491 img = gdk_image_get( GetMask()->GetBitmap(), 0, 0, GetWidth(), GetHeight() );
783da845 492
feac7937
VS
493 for (int h = 0; h < height; h++)
494 {
495 char outbyte = 0;
496 int old_x = -1;
497 guint32 old_pixval = 0;
902725ee 498
feac7937
VS
499 for (int w = 0; w < width; w++)
500 {
501 guint32 pixval;
502 int x = tablex[w];
503 if (x == old_x)
504 pixval = old_pixval;
505 else
506 {
507 pixval = gdk_image_get_pixel( img, x, tabley[h] );
508 old_pixval = pixval;
509 old_x = x;
510 }
902725ee 511
feac7937
VS
512 if (pixval)
513 {
514 char bit=1;
d0ee33f5 515 char shift = bit << (w % 8);
feac7937
VS
516 outbyte |= shift;
517 }
902725ee 518
feac7937
VS
519 if ((w+1)%8 == 0)
520 {
521 dst[h*dstbyteperline+w/8] = outbyte;
522 outbyte = 0;
523 }
524 }
902725ee 525
feac7937
VS
526 // do not forget the last byte
527 if (width % 8 != 0)
528 dst[h*dstbyteperline+width/8] = outbyte;
529 }
530 wxMask* mask = new wxMask;
531 mask->m_bitmap = gdk_bitmap_create_from_data( wxGetRootWindow()->window, (gchar *) dst, width, height );
532 bmp.SetMask(mask);
533
534 free( dst );
3fe39b0c 535 g_object_unref (img);
feac7937
VS
536 }
537
538 free( tablex );
539 free( tabley );
540 }
902725ee
WS
541
542 return bmp;
783da845
RR
543}
544
feac7937 545bool wxBitmap::CreateFromImage(const wxImage& image, int depth)
b5f01ae0 546{
a11672a4
RR
547 UnRef();
548
637b7e4f
VZ
549 wxCHECK_MSG( image.Ok(), false, wxT("invalid image") );
550 wxCHECK_MSG( depth == -1 || depth == 1, false, wxT("invalid bitmap depth") );
b5f01ae0 551
feac7937
VS
552 if (image.GetWidth() <= 0 || image.GetHeight() <= 0)
553 return false;
902725ee 554
feac7937 555 m_refData = new wxBitmapRefData();
3ebcd89d 556
feac7937 557 if (depth == 1)
3ebcd89d 558 {
feac7937 559 return CreateFromImageAsBitmap(image);
3ebcd89d 560 }
feac7937
VS
561 else
562 {
feac7937
VS
563 if (image.HasAlpha())
564 return CreateFromImageAsPixbuf(image);
68567a96 565
feac7937
VS
566 return CreateFromImageAsPixmap(image);
567 }
568}
3ebcd89d 569
feac7937
VS
570// conversion to mono bitmap:
571bool wxBitmap::CreateFromImageAsBitmap(const wxImage& img)
572{
573 // convert alpha channel to mask, if it is present:
574 wxImage image(img);
575 image.ConvertAlphaToMask();
902725ee 576
feac7937
VS
577 int width = image.GetWidth();
578 int height = image.GetHeight();
c2fa61e8 579
3ebcd89d
VZ
580 SetHeight( height );
581 SetWidth( width );
582
b85229d1 583 SetPixmap( gdk_pixmap_new( wxGetRootWindow()->window, width, height, 1 ) );
b5f01ae0 584
feac7937 585 SetDepth( 1 );
2eefae6e 586
feac7937 587 GdkVisual *visual = wxTheApp->GetGdkVisual();
b5f01ae0 588
feac7937 589 // Create picture image
b5f01ae0 590
feac7937 591 unsigned char *data_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
b5f01ae0 592
feac7937
VS
593 GdkImage *data_image =
594 gdk_image_new_bitmap( visual, data_data, width, height );
b5f01ae0 595
feac7937 596 // Create mask image
b5f01ae0 597
feac7937 598 GdkImage *mask_image = (GdkImage*) NULL;
b5f01ae0 599
feac7937
VS
600 if (image.HasMask())
601 {
602 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
b5f01ae0 603
feac7937 604 mask_image = gdk_image_new_bitmap( visual, mask_data, width, height );
b5f01ae0 605
feac7937
VS
606 wxMask *mask = new wxMask();
607 mask->m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, width, height, 1 );
b5f01ae0 608
feac7937
VS
609 SetMask( mask );
610 }
b5f01ae0 611
feac7937
VS
612 int r_mask = image.GetMaskRed();
613 int g_mask = image.GetMaskGreen();
614 int b_mask = image.GetMaskBlue();
b5f01ae0 615
feac7937 616 unsigned char* data = image.GetData();
b5f01ae0 617
feac7937
VS
618 int index = 0;
619 for (int y = 0; y < height; y++)
620 {
621 for (int x = 0; x < width; x++)
b5f01ae0 622 {
feac7937
VS
623 int r = data[index];
624 index++;
625 int g = data[index];
626 index++;
627 int b = data[index];
628 index++;
629
630 if (image.HasMask())
b5f01ae0 631 {
feac7937
VS
632 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
633 gdk_image_put_pixel( mask_image, x, y, 1 );
b5f01ae0 634 else
feac7937
VS
635 gdk_image_put_pixel( mask_image, x, y, 0 );
636 }
b5f01ae0 637
feac7937
VS
638 if ((r == 255) && (b == 255) && (g == 255))
639 gdk_image_put_pixel( data_image, x, y, 1 );
640 else
641 gdk_image_put_pixel( data_image, x, y, 0 );
b5f01ae0 642
feac7937
VS
643 } // for
644 } // for
b5f01ae0 645
feac7937 646 // Blit picture
b5f01ae0 647
b85229d1 648 GdkGC *data_gc = gdk_gc_new( GetPixmap() );
b5f01ae0 649
b85229d1 650 gdk_draw_image( GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
b5f01ae0 651
3fe39b0c
MR
652 g_object_unref (data_image);
653 g_object_unref (data_gc);
b5f01ae0 654
feac7937 655 // Blit mask
b5f01ae0 656
feac7937
VS
657 if (image.HasMask())
658 {
659 GdkGC *mask_gc = gdk_gc_new( GetMask()->GetBitmap() );
b5f01ae0 660
feac7937
VS
661 gdk_draw_image( GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
662
3fe39b0c
MR
663 g_object_unref (mask_image);
664 g_object_unref (mask_gc);
b5f01ae0 665 }
c2fa61e8 666
feac7937
VS
667 return true;
668}
902725ee 669
feac7937
VS
670// conversion to colour bitmap:
671bool wxBitmap::CreateFromImageAsPixmap(const wxImage& img)
672{
673 // convert alpha channel to mask, if it is present:
674 wxImage image(img);
675 image.ConvertAlphaToMask();
902725ee 676
feac7937
VS
677 int width = image.GetWidth();
678 int height = image.GetHeight();
679
680 SetHeight( height );
681 SetWidth( width );
682
683 SetPixmap( gdk_pixmap_new( wxGetRootWindow()->window, width, height, -1 ) );
b5f01ae0 684
feac7937 685 GdkVisual *visual = wxTheApp->GetGdkVisual();
b5f01ae0 686
feac7937 687 int bpp = visual->depth;
b5f01ae0 688
feac7937 689 SetDepth( bpp );
b5f01ae0 690
0006b9a5 691 GdkGC *gc = gdk_gc_new( GetPixmap() );
b5f01ae0 692
0006b9a5
PC
693 gdk_draw_rgb_image( GetPixmap(),
694 gc,
695 0, 0,
696 width, height,
697 GDK_RGB_DITHER_NONE,
698 image.GetData(),
699 width*3 );
b5f01ae0 700
0006b9a5 701 g_object_unref (gc);
b5f01ae0 702
feac7937 703 // Create mask image
b5f01ae0 704
feac7937 705 GdkImage *mask_image = (GdkImage*) NULL;
b5f01ae0 706
0006b9a5
PC
707 if (!image.HasMask())
708 return true;
b5f01ae0 709
0006b9a5 710 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
b5f01ae0 711
0006b9a5 712 mask_image = gdk_image_new_bitmap( visual, mask_data, width, height );
b5f01ae0 713
0006b9a5
PC
714 wxMask *mask = new wxMask();
715 mask->m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, width, height, 1 );
b5f01ae0 716
0006b9a5 717 SetMask( mask );
b5f01ae0 718
feac7937
VS
719 int r_mask = image.GetMaskRed();
720 int g_mask = image.GetMaskGreen();
721 int b_mask = image.GetMaskBlue();
b5f01ae0 722
feac7937 723 unsigned char* data = image.GetData();
b5f01ae0 724
feac7937
VS
725 int index = 0;
726 for (int y = 0; y < height; y++)
727 {
728 for (int x = 0; x < width; x++)
b5f01ae0 729 {
feac7937
VS
730 int r = data[index];
731 index++;
732 int g = data[index];
733 index++;
734 int b = data[index];
735 index++;
736
0006b9a5
PC
737 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
738 gdk_image_put_pixel( mask_image, x, y, 1 );
739 else
740 gdk_image_put_pixel( mask_image, x, y, 0 );
feac7937
VS
741 } // for
742 } // for
b5f01ae0 743
feac7937 744 // Blit mask
b5f01ae0 745
0006b9a5 746 GdkGC *mask_gc = gdk_gc_new( GetMask()->GetBitmap() );
b5f01ae0 747
0006b9a5 748 gdk_draw_image( GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
b5f01ae0 749
0006b9a5
PC
750 g_object_unref (mask_image);
751 g_object_unref (mask_gc);
b5f01ae0 752
feac7937 753 return true;
b5f01ae0
VS
754}
755
feac7937 756bool wxBitmap::CreateFromImageAsPixbuf(const wxImage& image)
b5f01ae0 757{
feac7937
VS
758 int width = image.GetWidth();
759 int height = image.GetHeight();
2eefae6e 760
feac7937
VS
761 GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
762 image.HasAlpha(),
763 8 /* bits per sample */,
764 width, height);
765 if (!pixbuf)
766 return false;
c2fa61e8 767
6db34764 768 wxASSERT( image.HasAlpha() ); // for now
feac7937
VS
769 wxASSERT( gdk_pixbuf_get_n_channels(pixbuf) == 4 );
770 wxASSERT( gdk_pixbuf_get_width(pixbuf) == width );
771 wxASSERT( gdk_pixbuf_get_height(pixbuf) == height );
902725ee 772
feac7937
VS
773 M_BMPDATA->m_pixbuf = pixbuf;
774 SetHeight(height);
775 SetWidth(width);
776 SetDepth(wxTheApp->GetGdkVisual()->depth);
902725ee 777
feac7937
VS
778 // Copy the data:
779 unsigned char *in = image.GetData();
780 unsigned char *out = gdk_pixbuf_get_pixels(pixbuf);
781 unsigned char *alpha = image.GetAlpha();
902725ee 782
feac7937 783 int rowinc = gdk_pixbuf_get_rowstride(pixbuf) - 4 * width;
b5f01ae0 784
feac7937 785 for (int y = 0; y < height; y++, out += rowinc)
b5f01ae0 786 {
feac7937
VS
787 for (int x = 0; x < width; x++, alpha++, out += 4, in += 3)
788 {
789 out[0] = in[0];
790 out[1] = in[1];
791 out[2] = in[2];
792 out[3] = *alpha;
793 }
b5f01ae0 794 }
902725ee 795
feac7937
VS
796 return true;
797}
b5f01ae0 798
feac7937
VS
799wxImage wxBitmap::ConvertToImage() const
800{
801 wxImage image;
c2fa61e8 802
feac7937 803 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
902725ee 804
feac7937
VS
805 image.Create(GetWidth(), GetHeight());
806 unsigned char *data = image.GetData();
2eefae6e 807
b5f01ae0
VS
808 if (!data)
809 {
b5f01ae0
VS
810 wxFAIL_MSG( wxT("couldn't create image") );
811 return wxNullImage;
812 }
813
feac7937 814 if (HasPixbuf())
b5f01ae0 815 {
feac7937
VS
816 GdkPixbuf *pixbuf = GetPixbuf();
817 wxASSERT( gdk_pixbuf_get_has_alpha(pixbuf) );
902725ee 818
feac7937
VS
819 int w = GetWidth();
820 int h = GetHeight();
902725ee 821
feac7937 822 image.SetAlpha();
b5f01ae0 823
feac7937
VS
824 unsigned char *alpha = image.GetAlpha();
825 unsigned char *in = gdk_pixbuf_get_pixels(pixbuf);
826 unsigned char *out = data;
827 int rowinc = gdk_pixbuf_get_rowstride(pixbuf) - 4 * w;
b5f01ae0 828
feac7937
VS
829 for (int y = 0; y < h; y++, in += rowinc)
830 {
831 for (int x = 0; x < w; x++, in += 4, out += 3, alpha++)
832 {
833 out[0] = in[0];
834 out[1] = in[1];
835 out[2] = in[2];
836 *alpha = in[3];
837 }
838 }
b5f01ae0 839 }
feac7937 840 else
b5f01ae0 841 {
feac7937
VS
842 // the colour used as transparent one in wxImage and the one it is
843 // replaced with when it really occurs in the bitmap
844 static const int MASK_RED = 1;
845 static const int MASK_GREEN = 2;
846 static const int MASK_BLUE = 3;
847 static const int MASK_BLUE_REPLACEMENT = 2;
b5f01ae0 848
feac7937 849 GdkImage *gdk_image = (GdkImage*) NULL;
b5f01ae0 850
feac7937
VS
851 if (HasPixmap())
852 {
853 gdk_image = gdk_image_get( GetPixmap(),
854 0, 0,
855 GetWidth(), GetHeight() );
856 }
feac7937
VS
857 else
858 {
859 wxFAIL_MSG( wxT("Ill-formed bitmap") );
860 }
b5f01ae0 861
feac7937
VS
862 wxCHECK_MSG( gdk_image, wxNullImage, wxT("couldn't create image") );
863
864 GdkImage *gdk_image_mask = (GdkImage*) NULL;
865 if (GetMask())
b5f01ae0 866 {
feac7937
VS
867 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
868 0, 0,
869 GetWidth(), GetHeight() );
870
871 image.SetMaskColour( MASK_RED, MASK_GREEN, MASK_BLUE );
872 }
873
874 int bpp = -1;
875 int red_shift_right = 0;
876 int green_shift_right = 0;
877 int blue_shift_right = 0;
878 int red_shift_left = 0;
879 int green_shift_left = 0;
880 int blue_shift_left = 0;
902725ee 881 bool use_shift = false;
feac7937 882
b85229d1 883 if (GetDepth() != 1)
feac7937 884 {
22a3bce4 885 GdkVisual *visual = gdk_drawable_get_visual( GetPixmap() );
feac7937
VS
886 if (visual == NULL)
887 visual = wxTheApp->GetGdkVisual();
888
889 bpp = visual->depth;
890 if (bpp == 16)
891 bpp = visual->red_prec + visual->green_prec + visual->blue_prec;
892 red_shift_right = visual->red_shift;
893 red_shift_left = 8-visual->red_prec;
894 green_shift_right = visual->green_shift;
895 green_shift_left = 8-visual->green_prec;
896 blue_shift_right = visual->blue_shift;
897 blue_shift_left = 8-visual->blue_prec;
898
899 use_shift = (visual->type == GDK_VISUAL_TRUE_COLOR) || (visual->type == GDK_VISUAL_DIRECT_COLOR);
900 }
b85229d1 901 else
feac7937
VS
902 {
903 bpp = 1;
904 }
905
906
907 GdkColormap *cmap = gtk_widget_get_default_colormap();
908
909 long pos = 0;
910 for (int j = 0; j < GetHeight(); j++)
911 {
912 for (int i = 0; i < GetWidth(); i++)
8ab696e0 913 {
feac7937
VS
914 wxUint32 pixel = gdk_image_get_pixel( gdk_image, i, j );
915 if (bpp == 1)
b5f01ae0 916 {
feac7937
VS
917 if (pixel == 0)
918 {
919 data[pos] = 0;
920 data[pos+1] = 0;
921 data[pos+2] = 0;
922 }
923 else
924 {
925 data[pos] = 255;
926 data[pos+1] = 255;
927 data[pos+2] = 255;
928 }
8ab696e0 929 }
feac7937 930 else if (use_shift)
8ab696e0 931 {
feac7937
VS
932 data[pos] = (pixel >> red_shift_right) << red_shift_left;
933 data[pos+1] = (pixel >> green_shift_right) << green_shift_left;
934 data[pos+2] = (pixel >> blue_shift_right) << blue_shift_left;
8ab696e0 935 }
feac7937 936 else if (cmap->colors)
b5f01ae0 937 {
feac7937
VS
938 data[pos] = cmap->colors[pixel].red >> 8;
939 data[pos+1] = cmap->colors[pixel].green >> 8;
940 data[pos+2] = cmap->colors[pixel].blue >> 8;
2eefae6e 941 }
feac7937 942 else
2eefae6e 943 {
feac7937 944 wxFAIL_MSG( wxT("Image conversion failed. Unknown visual type.") );
b5f01ae0 945 }
b5f01ae0 946
feac7937
VS
947 if (gdk_image_mask)
948 {
949 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
950 if (mask_pixel == 0)
951 {
952 data[pos] = MASK_RED;
953 data[pos+1] = MASK_GREEN;
954 data[pos+2] = MASK_BLUE;
955 }
956 else if ( data[pos] == MASK_RED &&
957 data[pos+1] == MASK_GREEN &&
958 data[pos+2] == MASK_BLUE )
959 {
960 data[pos+2] = MASK_BLUE_REPLACEMENT;
961 }
962 }
963
964 pos += 3;
965 }
b5f01ae0 966 }
b5f01ae0 967
3fe39b0c
MR
968 g_object_unref (gdk_image);
969 if (gdk_image_mask) g_object_unref (gdk_image_mask);
feac7937 970 }
b5f01ae0
VS
971
972 return image;
973}
974
4611dd06 975wxBitmap::wxBitmap( const wxString &filename, wxBitmapType type )
c801d85f 976{
fd0eed64 977 LoadFile( filename, type );
ff7b1510 978}
c801d85f 979
debe6624 980wxBitmap::wxBitmap( const char bits[], int width, int height, int WXUNUSED(depth))
6f65e337 981{
3ebcd89d
VZ
982 if ( width > 0 && height > 0 )
983 {
984 m_refData = new wxBitmapRefData();
6f65e337 985
3ebcd89d 986 M_BMPDATA->m_mask = (wxMask *) NULL;
b85229d1 987 M_BMPDATA->m_pixmap = gdk_bitmap_create_from_data
3ebcd89d
VZ
988 (
989 wxGetRootWindow()->window,
990 (gchar *) bits,
991 width,
992 height
993 );
994 M_BMPDATA->m_width = width;
995 M_BMPDATA->m_height = height;
996 M_BMPDATA->m_bpp = 1;
6f65e337 997
b85229d1 998 wxASSERT_MSG( M_BMPDATA->m_pixmap, wxT("couldn't create bitmap") );
3ebcd89d 999 }
6f65e337 1000}
8bbe427f
VZ
1001
1002wxBitmap::~wxBitmap()
c801d85f 1003{
ff7b1510 1004}
8bbe427f 1005
f6bcfd97 1006bool wxBitmap::operator == ( const wxBitmap& bmp ) const
c801d85f 1007{
8bbe427f 1008 return m_refData == bmp.m_refData;
ff7b1510 1009}
8bbe427f 1010
f6bcfd97 1011bool wxBitmap::operator != ( const wxBitmap& bmp ) const
c801d85f 1012{
8bbe427f 1013 return m_refData != bmp.m_refData;
ff7b1510 1014}
8bbe427f 1015
91b8de8d 1016bool wxBitmap::Ok() const
c801d85f 1017{
902725ee 1018 return (m_refData != NULL) &&
feac7937 1019 (
feac7937 1020 M_BMPDATA->m_pixbuf ||
b85229d1 1021 M_BMPDATA->m_pixmap
feac7937 1022 );
ff7b1510 1023}
8bbe427f 1024
91b8de8d 1025int wxBitmap::GetHeight() const
c801d85f 1026{
223d09f6 1027 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
e55ad60e 1028
fd0eed64 1029 return M_BMPDATA->m_height;
ff7b1510 1030}
c801d85f 1031
91b8de8d 1032int wxBitmap::GetWidth() const
c801d85f 1033{
223d09f6 1034 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
8bbe427f 1035
fd0eed64 1036 return M_BMPDATA->m_width;
ff7b1510 1037}
c801d85f 1038
91b8de8d 1039int wxBitmap::GetDepth() const
c801d85f 1040{
223d09f6 1041 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
8bbe427f 1042
fd0eed64 1043 return M_BMPDATA->m_bpp;
ff7b1510 1044}
c801d85f 1045
91b8de8d 1046wxMask *wxBitmap::GetMask() const
c801d85f 1047{
223d09f6 1048 wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") );
8bbe427f 1049
fd0eed64 1050 return M_BMPDATA->m_mask;
ff7b1510 1051}
c801d85f
KB
1052
1053void wxBitmap::SetMask( wxMask *mask )
1054{
223d09f6 1055 wxCHECK_RET( Ok(), wxT("invalid bitmap") );
8bbe427f 1056
fd0eed64 1057 if (M_BMPDATA->m_mask) delete M_BMPDATA->m_mask;
8bbe427f 1058
fd0eed64 1059 M_BMPDATA->m_mask = mask;
ff7b1510 1060}
c801d85f 1061
db0aec83
VS
1062bool wxBitmap::CopyFromIcon(const wxIcon& icon)
1063{
1064 *this = icon;
902725ee 1065 return true;
db0aec83
VS
1066}
1067
17bec151
RR
1068wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
1069{
1070 wxCHECK_MSG( Ok() &&
13111b2a
VZ
1071 (rect.x >= 0) && (rect.y >= 0) &&
1072 (rect.x+rect.width <= M_BMPDATA->m_width) && (rect.y+rect.height <= M_BMPDATA->m_height),
17bec151 1073 wxNullBitmap, wxT("invalid bitmap or bitmap region") );
13111b2a 1074
17bec151
RR
1075 wxBitmap ret( rect.width, rect.height, M_BMPDATA->m_bpp );
1076 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
13111b2a 1077
feac7937 1078 if (HasPixbuf())
17bec151 1079 {
feac7937 1080 GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
6db34764 1081 gdk_pixbuf_get_has_alpha(GetPixbuf()),
17f504ec 1082 8, rect.width, rect.height);
feac7937 1083 ret.SetPixbuf(pixbuf);
6db34764 1084 gdk_pixbuf_copy_area(GetPixbuf(),
feac7937
VS
1085 rect.x, rect.y, rect.width, rect.height,
1086 pixbuf, 0, 0);
17bec151
RR
1087 }
1088 else
1089 {
b85229d1 1090 if (ret.GetDepth() != 1)
feac7937
VS
1091 {
1092 GdkGC *gc = gdk_gc_new( ret.GetPixmap() );
15f0ad70 1093 gdk_draw_drawable( ret.GetPixmap(), gc, GetPixmap(), rect.x, rect.y, 0, 0, rect.width, rect.height );
3fe39b0c 1094 g_object_unref (gc);
feac7937
VS
1095 }
1096 else
1097 {
b85229d1 1098 GdkGC *gc = gdk_gc_new( ret.GetPixmap() );
feac7937
VS
1099 GdkColor col;
1100 col.pixel = 0xFFFFFF;
1101 gdk_gc_set_foreground( gc, &col );
1102 col.pixel = 0;
1103 gdk_gc_set_background( gc, &col );
b85229d1 1104 gdk_wx_draw_bitmap( ret.GetPixmap(), gc, GetPixmap(), rect.x, rect.y, 0, 0, rect.width, rect.height );
3fe39b0c 1105 g_object_unref (gc);
feac7937 1106 }
17bec151 1107 }
13111b2a 1108
17bec151
RR
1109 if (GetMask())
1110 {
1111 wxMask *mask = new wxMask;
c2fa61e8 1112 mask->m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, rect.width, rect.height, 1 );
13111b2a 1113
17bec151 1114 GdkGC *gc = gdk_gc_new( mask->m_bitmap );
f9ebac93
RR
1115 GdkColor col;
1116 col.pixel = 0xFFFFFF;
1117 gdk_gc_set_foreground( gc, &col );
1118 col.pixel = 0;
1119 gdk_gc_set_background( gc, &col );
1120 gdk_wx_draw_bitmap( mask->m_bitmap, gc, M_BMPDATA->m_mask->m_bitmap, rect.x, rect.y, 0, 0, rect.width, rect.height );
3fe39b0c 1121 g_object_unref (gc);
13111b2a
VZ
1122
1123 ret.SetMask( mask );
17bec151 1124 }
13111b2a 1125
17bec151
RR
1126 return ret;
1127}
1128
4611dd06 1129bool wxBitmap::SaveFile( const wxString &name, wxBitmapType type, const wxPalette *WXUNUSED(palette) ) const
c801d85f 1130{
902725ee 1131 wxCHECK_MSG( Ok(), false, wxT("invalid bitmap") );
8bbe427f 1132
b75dd496 1133 // Try to save the bitmap via wxImage handlers:
fd0eed64 1134 {
368d59f0 1135 wxImage image = ConvertToImage();
284b4c88 1136 if (image.Ok()) return image.SaveFile( name, type );
fd0eed64 1137 }
8bbe427f 1138
902725ee 1139 return false;
ff7b1510 1140}
c801d85f 1141
4611dd06 1142bool wxBitmap::LoadFile( const wxString &name, wxBitmapType type )
c801d85f 1143{
fd0eed64 1144 UnRef();
8bbe427f 1145
3ebcd89d 1146 if (!wxFileExists(name))
902725ee 1147 return false;
8bbe427f 1148
005f5d18 1149 GdkVisual *visual = wxTheApp->GetGdkVisual();
c2fa61e8 1150
fd0eed64
RR
1151 if (type == wxBITMAP_TYPE_XPM)
1152 {
1153 m_refData = new wxBitmapRefData();
8bbe427f 1154
fd0eed64 1155 GdkBitmap *mask = (GdkBitmap*) NULL;
8bbe427f 1156
3ebcd89d
VZ
1157 M_BMPDATA->m_pixmap = gdk_pixmap_create_from_xpm
1158 (
1159 wxGetRootWindow()->window,
1160 &mask,
1161 NULL,
1162 name.fn_str()
1163 );
8bbe427f 1164
fd0eed64
RR
1165 if (mask)
1166 {
1167 M_BMPDATA->m_mask = new wxMask();
1168 M_BMPDATA->m_mask->m_bitmap = mask;
1169 }
8bbe427f 1170
791d7ea2 1171 gdk_drawable_get_size( M_BMPDATA->m_pixmap, &(M_BMPDATA->m_width), &(M_BMPDATA->m_height) );
c2fa61e8 1172
103aab26 1173 M_BMPDATA->m_bpp = visual->depth;
fd0eed64 1174 }
b75dd496 1175 else // try if wxImage can load it
fd0eed64
RR
1176 {
1177 wxImage image;
3ebcd89d 1178 if ( !image.LoadFile( name, type ) || !image.Ok() )
902725ee 1179 return false;
3ebcd89d
VZ
1180
1181 *this = wxBitmap(image);
fd0eed64 1182 }
8bbe427f 1183
902725ee 1184 return true;
ff7b1510 1185}
8bbe427f 1186
0b04c4e0 1187#if wxUSE_PALETTE
91b8de8d 1188wxPalette *wxBitmap::GetPalette() const
c801d85f 1189{
3ebcd89d
VZ
1190 if (!Ok())
1191 return (wxPalette *) NULL;
8bbe427f 1192
fd0eed64 1193 return M_BMPDATA->m_palette;
ff7b1510 1194}
c801d85f 1195
4611dd06
RR
1196void wxBitmap::SetPalette(const wxPalette& WXUNUSED(palette))
1197{
1198 // TODO
1199}
0b04c4e0 1200#endif // wxUSE_PALETTE
4611dd06 1201
4bc67cc5
RR
1202void wxBitmap::SetHeight( int height )
1203{
3ebcd89d
VZ
1204 if (!m_refData)
1205 m_refData = new wxBitmapRefData();
4bc67cc5
RR
1206
1207 M_BMPDATA->m_height = height;
1208}
1209
1210void wxBitmap::SetWidth( int width )
1211{
3ebcd89d
VZ
1212 if (!m_refData)
1213 m_refData = new wxBitmapRefData();
4bc67cc5
RR
1214
1215 M_BMPDATA->m_width = width;
1216}
1217
1218void wxBitmap::SetDepth( int depth )
1219{
3ebcd89d
VZ
1220 if (!m_refData)
1221 m_refData = new wxBitmapRefData();
4bc67cc5
RR
1222
1223 M_BMPDATA->m_bpp = depth;
1224}
1225
1226void wxBitmap::SetPixmap( GdkPixmap *pixmap )
1227{
3ebcd89d
VZ
1228 if (!m_refData)
1229 m_refData = new wxBitmapRefData();
4bc67cc5
RR
1230
1231 M_BMPDATA->m_pixmap = pixmap;
6db34764 1232 PurgeOtherRepresentations(Pixmap);
4bc67cc5
RR
1233}
1234
91b8de8d 1235GdkPixmap *wxBitmap::GetPixmap() const
c801d85f 1236{
223d09f6 1237 wxCHECK_MSG( Ok(), (GdkPixmap *) NULL, wxT("invalid bitmap") );
8bbe427f 1238
feac7937
VS
1239 // create the pixmap on the fly if we use Pixbuf representation:
1240 if (HasPixbuf() && !HasPixmap())
1241 {
70dcce79
VS
1242 delete M_BMPDATA->m_mask;
1243 M_BMPDATA->m_mask = new wxMask();
feac7937
VS
1244 gdk_pixbuf_render_pixmap_and_mask(M_BMPDATA->m_pixbuf,
1245 &M_BMPDATA->m_pixmap,
70dcce79 1246 &M_BMPDATA->m_mask->m_bitmap,
feac7937
VS
1247 128 /*threshold*/);
1248 }
feac7937 1249
fd0eed64 1250 return M_BMPDATA->m_pixmap;
ff7b1510 1251}
8bbe427f 1252
feac7937
VS
1253bool wxBitmap::HasPixmap() const
1254{
1255 wxCHECK_MSG( Ok(), false, wxT("invalid bitmap") );
1256
1257 return M_BMPDATA->m_pixmap != NULL;
1258}
1259
feac7937
VS
1260GdkPixbuf *wxBitmap::GetPixbuf() const
1261{
1262 wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
1263
6db34764
VS
1264 if (HasPixmap() && !HasPixbuf())
1265 {
1266 int width = GetWidth();
1267 int height = GetHeight();
902725ee 1268
6db34764
VS
1269 GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
1270 GetMask() != NULL,
1271 8, width, height);
902725ee 1272 M_BMPDATA->m_pixbuf =
6db34764
VS
1273 gdk_pixbuf_get_from_drawable(pixbuf, M_BMPDATA->m_pixmap, NULL,
1274 0, 0, 0, 0, width, height);
902725ee 1275
6db34764
VS
1276 // apply the mask to created pixbuf:
1277 if (M_BMPDATA->m_pixbuf && M_BMPDATA->m_mask)
1278 {
902725ee 1279 GdkPixbuf *pmask =
6db34764
VS
1280 gdk_pixbuf_get_from_drawable(NULL,
1281 M_BMPDATA->m_mask->GetBitmap(),
1282 NULL,
1283 0, 0, 0, 0, width, height);
1284 if (pmask)
1285 {
1286 guchar *bmp = gdk_pixbuf_get_pixels(pixbuf);
1287 guchar *mask = gdk_pixbuf_get_pixels(pmask);
1288 int bmprowinc = gdk_pixbuf_get_rowstride(pixbuf) - 4 * width;
1289 int maskrowinc = gdk_pixbuf_get_rowstride(pmask) - 3 * width;
1290
1291 for (int y = 0; y < height;
1292 y++, bmp += bmprowinc, mask += maskrowinc)
1293 {
1294 for (int x = 0; x < width; x++, bmp += 4, mask += 3)
1295 {
1296 if (mask[0] == 0 /*black pixel*/)
1297 bmp[3] = 0;
1298 }
1299 }
902725ee 1300
3fe39b0c 1301 g_object_unref (pmask);
6db34764
VS
1302 }
1303 }
1304 }
1305
feac7937
VS
1306 return M_BMPDATA->m_pixbuf;
1307}
1308
1309bool wxBitmap::HasPixbuf() const
1310{
1311 wxCHECK_MSG( Ok(), false, wxT("invalid bitmap") );
1312
1313 return M_BMPDATA->m_pixbuf != NULL;
1314}
1315
1316void wxBitmap::SetPixbuf( GdkPixbuf *pixbuf )
1317{
1318 if (!m_refData)
1319 m_refData = new wxBitmapRefData();
1320
1321 M_BMPDATA->m_pixbuf = pixbuf;
6db34764 1322 PurgeOtherRepresentations(Pixbuf);
feac7937
VS
1323}
1324
1325void wxBitmap::PurgeOtherRepresentations(wxBitmap::Representation keep)
1326{
1327 if (keep == Pixmap && HasPixbuf())
1328 {
3fe39b0c 1329 g_object_unref (M_BMPDATA->m_pixbuf);
feac7937
VS
1330 M_BMPDATA->m_pixbuf = NULL;
1331 }
1332 if (keep == Pixbuf && HasPixmap())
1333 {
3fe39b0c 1334 g_object_unref (M_BMPDATA->m_pixmap);
feac7937
VS
1335 M_BMPDATA->m_pixmap = NULL;
1336 }
1337}
1338
284f2b59
RR
1339void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp)
1340{
284f2b59
RR
1341 if (bpp != 32)
1342 return NULL;
902725ee 1343
284f2b59
RR
1344 GdkPixbuf *pixbuf = GetPixbuf();
1345 if (!pixbuf)
1346 return NULL;
1347
902725ee 1348#if 0
284f2b59
RR
1349 if (gdk_pixbuf_get_has_alpha( pixbuf ))
1350 wxPrintf( wxT("Has alpha\n") );
1351 else
1352 wxPrintf( wxT("No alpha.\n") );
1353#endif
1354
902725ee
WS
1355 data.m_height = gdk_pixbuf_get_height( pixbuf );
1356 data.m_width = gdk_pixbuf_get_width( pixbuf );
1357 data.m_stride = gdk_pixbuf_get_rowstride( pixbuf );
1358
284f2b59 1359 return gdk_pixbuf_get_pixels( pixbuf );
284f2b59
RR
1360}
1361
17a1ebd1 1362void wxBitmap::UngetRawData(wxPixelDataBase& WXUNUSED(data))
284f2b59
RR
1363{
1364}
1365
0ff2a74d 1366
902725ee 1367bool wxBitmap::HasAlpha() const
0ff2a74d 1368{
0ff2a74d 1369 return HasPixbuf();
0ff2a74d
RR
1370}
1371
1372void wxBitmap::UseAlpha()
902725ee 1373{
0ff2a74d 1374 GetPixbuf();
0ff2a74d
RR
1375}
1376
4b61c88d
RR
1377//-----------------------------------------------------------------------------
1378// wxBitmapHandler
1379//-----------------------------------------------------------------------------
1380
1381IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler,wxBitmapHandlerBase)
1382
1383wxBitmapHandler::~wxBitmapHandler()
1384{
1385}
1386
17a1ebd1
VZ
1387bool wxBitmapHandler::Create(wxBitmap * WXUNUSED(bitmap),
1388 void * WXUNUSED(data),
1389 long WXUNUSED(type),
1390 int WXUNUSED(width),
1391 int WXUNUSED(height),
1392 int WXUNUSED(depth))
4b61c88d 1393{
17a1ebd1
VZ
1394 wxFAIL_MSG( _T("not implemented") );
1395
902725ee 1396 return false;
4b61c88d
RR
1397}
1398
17a1ebd1
VZ
1399bool wxBitmapHandler::LoadFile(wxBitmap * WXUNUSED(bitmap),
1400 const wxString& WXUNUSED(name),
1401 long WXUNUSED(flags),
1402 int WXUNUSED(desiredWidth),
1403 int WXUNUSED(desiredHeight))
4b61c88d 1404{
17a1ebd1
VZ
1405 wxFAIL_MSG( _T("not implemented") );
1406
902725ee 1407 return false;
4b61c88d
RR
1408}
1409
17a1ebd1
VZ
1410bool wxBitmapHandler::SaveFile(const wxBitmap * WXUNUSED(bitmap),
1411 const wxString& WXUNUSED(name),
1412 int WXUNUSED(type),
1413 const wxPalette * WXUNUSED(palette))
4b61c88d 1414{
17a1ebd1
VZ
1415 wxFAIL_MSG( _T("not implemented") );
1416
902725ee 1417 return false;
4b61c88d
RR
1418}
1419
1420/* static */ void wxBitmap::InitStandardHandlers()
1421{
1422 // TODO: Insert handler based on GdkPixbufs handler later
1423}