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