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