]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/bitmap.cpp
linking fixes
[wxWidgets.git] / src / gtk / bitmap.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: bitmap.cpp
3// Purpose:
4// Author: Robert Roebling
6f65e337 5// RCS-ID: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling
8bbe427f 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
11#pragma implementation "bitmap.h"
12#endif
13
14#include "wx/bitmap.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
25#if (GTK_MINOR_VERSION > 0)
26#include <gdk/gdkrgb.h>
27#endif
13111b2a 28
f6bcfd97
BP
29extern void gdk_wx_draw_bitmap (GdkDrawable *drawable,
30 GdkGC *gc,
31 GdkDrawable *src,
32 gint xsrc,
33 gint ysrc,
34 gint xdest,
35 gint ydest,
36 gint width,
37 gint height);
38
d76fe38b
RR
39//-----------------------------------------------------------------------------
40// data
41//-----------------------------------------------------------------------------
42
c2fa61e8 43extern GtkWidget *wxGetRootWindow();
c801d85f
KB
44
45//-----------------------------------------------------------------------------
46// wxMask
47//-----------------------------------------------------------------------------
48
49IMPLEMENT_DYNAMIC_CLASS(wxMask,wxObject)
50
8bbe427f 51wxMask::wxMask()
c801d85f 52{
fd0eed64 53 m_bitmap = (GdkBitmap *) NULL;
ff7b1510 54}
c801d85f 55
91b8de8d 56wxMask::wxMask( const wxBitmap& bitmap, const wxColour& colour )
c801d85f 57{
72a7edf0 58 m_bitmap = (GdkBitmap *) NULL;
91b8de8d 59 Create( bitmap, colour );
ff7b1510 60}
c801d85f 61
91b8de8d 62wxMask::wxMask( const wxBitmap& bitmap, int paletteIndex )
c801d85f 63{
72a7edf0 64 m_bitmap = (GdkBitmap *) NULL;
91b8de8d 65 Create( bitmap, paletteIndex );
ff7b1510 66}
c801d85f 67
91b8de8d 68wxMask::wxMask( const wxBitmap& bitmap )
c801d85f 69{
72a7edf0 70 m_bitmap = (GdkBitmap *) NULL;
91b8de8d 71 Create( bitmap );
ff7b1510 72}
c801d85f 73
8bbe427f 74wxMask::~wxMask()
c801d85f 75{
13111b2a 76 if (m_bitmap)
72a7edf0 77 gdk_bitmap_unref( m_bitmap );
ff7b1510 78}
c801d85f 79
1fb4de31
RR
80bool wxMask::Create( const wxBitmap& bitmap,
81 const wxColour& colour )
91b8de8d
RR
82{
83 if (m_bitmap)
284b4c88 84 {
91b8de8d 85 gdk_bitmap_unref( m_bitmap );
284b4c88 86 m_bitmap = (GdkBitmap*) NULL;
91b8de8d 87 }
13111b2a 88
1fb4de31
RR
89 wxImage image( bitmap );
90 if (!image.Ok()) return FALSE;
13111b2a 91
c2fa61e8 92 m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, image.GetWidth(), image.GetHeight(), 1 );
f9ee644e 93 GdkGC *gc = gdk_gc_new( m_bitmap );
13111b2a 94
f9ee644e
RR
95 GdkColor color;
96 color.red = 65000;
97 color.green = 65000;
98 color.blue = 65000;
99 color.pixel = 1;
100 gdk_gc_set_foreground( gc, &color );
101 gdk_gc_set_fill( gc, GDK_SOLID );
102 gdk_draw_rectangle( m_bitmap, gc, TRUE, 0, 0, image.GetWidth(), image.GetHeight() );
13111b2a 103
1fb4de31
RR
104 unsigned char *data = image.GetData();
105 int index = 0;
13111b2a 106
1fb4de31
RR
107 unsigned char red = colour.Red();
108 unsigned char green = colour.Green();
109 unsigned char blue = colour.Blue();
13111b2a 110
c2fa61e8 111 GdkVisual *visual = gdk_window_get_visual( wxGetRootWindow()->window );
103aab26 112 wxASSERT( visual );
c2fa61e8 113
1fb4de31
RR
114 int bpp = visual->depth;
115 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
116 if (bpp == 15)
117 {
118 red = red & 0xf8;
1fb4de31 119 green = green & 0xf8;
f6bcfd97 120 blue = blue & 0xf8;
1fb4de31
RR
121 }
122 if (bpp == 16)
123 {
124 red = red & 0xf8;
f6bcfd97
BP
125 green = green & 0xfc;
126 blue = blue & 0xf8;
1fb4de31 127 }
13111b2a 128
f9ee644e
RR
129 color.red = 0;
130 color.green = 0;
131 color.blue = 0;
132 color.pixel = 0;
133 gdk_gc_set_foreground( gc, &color );
13111b2a 134
1fb4de31 135 for (int j = 0; j < image.GetHeight(); j++)
f9ee644e 136 {
f2593d0d
RR
137 int start_x = -1;
138 int i;
139 for (i = 0; i < image.GetWidth(); i++)
1fb4de31 140 {
13111b2a
VZ
141 if ((data[index] == red) &&
142 (data[index+1] == green) &&
143 (data[index+2] == blue))
144 {
145 if (start_x == -1)
146 start_x = i;
147 }
148 else
149 {
150 if (start_x != -1)
151 {
152 gdk_draw_line( m_bitmap, gc, start_x, j, i-1, j );
153 start_x = -1;
154 }
f9ee644e
RR
155 }
156 index += 3;
157 }
158 if (start_x != -1)
159 gdk_draw_line( m_bitmap, gc, start_x, j, i, j );
160 }
1fb4de31 161
f9ee644e 162 gdk_gc_unref( gc );
1fb4de31 163
f9ee644e 164 return TRUE;
91b8de8d
RR
165}
166
b5f01ae0 167bool wxMask::Create( const wxBitmap& bitmap, int paletteIndex )
91b8de8d 168{
b5f01ae0
VS
169 unsigned char r,g,b;
170 wxPalette *pal = bitmap.GetPalette();
284b4c88 171
b5f01ae0 172 wxCHECK_MSG( pal, FALSE, wxT("Cannot create mask from bitmap without palette") );
c2fa61e8 173
b5f01ae0 174 pal->GetRGB(paletteIndex, &r, &g, &b);
284b4c88 175
b5f01ae0 176 return Create(bitmap, wxColour(r, g, b));
91b8de8d
RR
177}
178
179bool wxMask::Create( const wxBitmap& bitmap )
180{
181 if (m_bitmap)
284b4c88 182 {
91b8de8d 183 gdk_bitmap_unref( m_bitmap );
284b4c88 184 m_bitmap = (GdkBitmap*) NULL;
91b8de8d 185 }
284b4c88 186
91b8de8d 187 if (!bitmap.Ok()) return FALSE;
284b4c88 188
223d09f6 189 wxCHECK_MSG( bitmap.GetBitmap(), FALSE, wxT("Cannot create mask from colour bitmap") );
284b4c88 190
c2fa61e8 191 m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, bitmap.GetWidth(), bitmap.GetHeight(), 1 );
284b4c88 192
91b8de8d 193 if (!m_bitmap) return FALSE;
284b4c88 194
91b8de8d 195 GdkGC *gc = gdk_gc_new( m_bitmap );
284b4c88 196
f6bcfd97 197 gdk_wx_draw_bitmap( m_bitmap, gc, bitmap.GetBitmap(), 0, 0, 0, 0, bitmap.GetWidth(), bitmap.GetHeight() );
284b4c88 198
91b8de8d 199 gdk_gc_unref( gc );
284b4c88 200
91b8de8d
RR
201 return TRUE;
202}
203
204GdkBitmap *wxMask::GetBitmap() const
c801d85f 205{
fd0eed64 206 return m_bitmap;
ff7b1510 207}
8bbe427f 208
c801d85f
KB
209//-----------------------------------------------------------------------------
210// wxBitmap
211//-----------------------------------------------------------------------------
212
213class wxBitmapRefData: public wxObjectRefData
214{
fd0eed64 215public:
f2593d0d
RR
216 wxBitmapRefData();
217 ~wxBitmapRefData();
218
219 GdkPixmap *m_pixmap;
220 GdkBitmap *m_bitmap;
221 wxMask *m_mask;
222 int m_width;
223 int m_height;
224 int m_bpp;
225 wxPalette *m_palette;
c801d85f
KB
226};
227
8bbe427f 228wxBitmapRefData::wxBitmapRefData()
c801d85f 229{
fd0eed64
RR
230 m_pixmap = (GdkPixmap *) NULL;
231 m_bitmap = (GdkBitmap *) NULL;
232 m_mask = (wxMask *) NULL;
233 m_width = 0;
234 m_height = 0;
235 m_bpp = 0;
236 m_palette = (wxPalette *) NULL;
ff7b1510 237}
c801d85f 238
8bbe427f 239wxBitmapRefData::~wxBitmapRefData()
c801d85f 240{
fd0eed64
RR
241 if (m_pixmap) gdk_pixmap_unref( m_pixmap );
242 if (m_bitmap) gdk_bitmap_unref( m_bitmap );
243 if (m_mask) delete m_mask;
244 if (m_palette) delete m_palette;
ff7b1510 245}
c801d85f
KB
246
247//-----------------------------------------------------------------------------
248
249#define M_BMPDATA ((wxBitmapRefData *)m_refData)
250
251IMPLEMENT_DYNAMIC_CLASS(wxBitmap,wxGDIObject)
252
8bbe427f 253wxBitmap::wxBitmap()
c801d85f 254{
fd0eed64 255 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
ff7b1510 256}
8bbe427f 257
debe6624 258wxBitmap::wxBitmap( int width, int height, int depth )
c801d85f 259{
c826213d
RR
260 Create( width, height, depth );
261
262 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
263}
264
265bool wxBitmap::Create( int width, int height, int depth )
266{
267 UnRef();
268
269 wxCHECK_MSG( (width > 0) && (height > 0), FALSE, wxT("invalid bitmap size") )
284b4c88 270
c2fa61e8 271 GdkVisual *visual = gdk_window_get_visual( wxGetRootWindow()->window );
103aab26 272 wxASSERT( visual );
284b4c88 273
103aab26
RR
274 if (depth == -1) depth = visual->depth;
275
c826213d
RR
276 wxCHECK_MSG( (depth == visual->depth) ||
277 (depth == 1), FALSE, wxT("invalid bitmap depth") )
8bbe427f 278
eefa26be 279 m_refData = new wxBitmapRefData();
fd0eed64 280 M_BMPDATA->m_mask = (wxMask *) NULL;
fd0eed64
RR
281 M_BMPDATA->m_width = width;
282 M_BMPDATA->m_height = height;
eefa26be
RR
283 if (depth == 1)
284 {
c2fa61e8 285 M_BMPDATA->m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, width, height, 1 );
eefa26be
RR
286 M_BMPDATA->m_bpp = 1;
287 }
288 else
289 {
c2fa61e8 290 M_BMPDATA->m_pixmap = gdk_pixmap_new( wxGetRootWindow()->window, width, height, depth );
103aab26 291 M_BMPDATA->m_bpp = visual->depth;
eefa26be 292 }
8bbe427f 293
c826213d 294 return Ok();
ff7b1510 295}
b5f01ae0 296
e838cc14 297bool wxBitmap::CreateFromXpm( const char **bits )
e52f60e6 298{
e838cc14 299 wxCHECK_MSG( bits != NULL, FALSE, wxT("invalid bitmap data") )
8bbe427f 300
c2fa61e8 301 GdkVisual *visual = gdk_window_get_visual( wxGetRootWindow()->window );
103aab26 302 wxASSERT( visual );
c2fa61e8 303
e52f60e6
RR
304 m_refData = new wxBitmapRefData();
305
306 GdkBitmap *mask = (GdkBitmap*) NULL;
8bbe427f 307
c2fa61e8 308 M_BMPDATA->m_pixmap = gdk_pixmap_create_from_xpm_d( wxGetRootWindow()->window, &mask, NULL, (gchar **) bits );
8bbe427f 309
e838cc14 310 wxCHECK_MSG( M_BMPDATA->m_pixmap, FALSE, wxT("couldn't create pixmap") );
8bbe427f 311
fd0eed64
RR
312 if (mask)
313 {
314 M_BMPDATA->m_mask = new wxMask();
315 M_BMPDATA->m_mask->m_bitmap = mask;
316 }
8bbe427f 317
fd0eed64 318 gdk_window_get_size( M_BMPDATA->m_pixmap, &(M_BMPDATA->m_width), &(M_BMPDATA->m_height) );
8bbe427f 319
103aab26 320 M_BMPDATA->m_bpp = visual->depth; // ?
c2fa61e8 321
fd0eed64 322 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
e838cc14
VZ
323
324 return TRUE;
ff7b1510 325}
b5f01ae0
VS
326
327bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
328{
329 wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") )
330 wxCHECK_MSG( depth == -1 || depth == 1, FALSE, wxT("invalid bitmap depth") )
331
332 m_refData = new wxBitmapRefData();
c2fa61e8 333
b5f01ae0
VS
334 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
335
336 // ------
337 // convertion to mono bitmap:
338 // ------
339 if (depth == 1)
340 {
341 int width = image.GetWidth();
342 int height = image.GetHeight();
343
344 SetHeight( height );
345 SetWidth( width );
346
c2fa61e8 347 SetBitmap( gdk_pixmap_new( wxGetRootWindow()->window, width, height, 1 ) );
b5f01ae0
VS
348
349 SetDepth( 1 );
350
c2fa61e8 351 GdkVisual *visual = gdk_window_get_visual( wxGetRootWindow()->window );
b5f01ae0
VS
352 wxASSERT( visual );
353
354 // Create picture image
355
356 unsigned char *data_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
357
358 GdkImage *data_image =
359 gdk_image_new_bitmap( visual, data_data, width, height );
360
361 // Create mask image
362
363 GdkImage *mask_image = (GdkImage*) NULL;
364
365 if (image.HasMask())
366 {
367 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
368
369 mask_image = gdk_image_new_bitmap( visual, mask_data, width, height );
370
371 wxMask *mask = new wxMask();
c2fa61e8 372 mask->m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, width, height, 1 );
b5f01ae0
VS
373
374 SetMask( mask );
375 }
376
377 int r_mask = image.GetMaskRed();
378 int g_mask = image.GetMaskGreen();
379 int b_mask = image.GetMaskBlue();
380
381 unsigned char* data = image.GetData();
382
383 int index = 0;
384 for (int y = 0; y < height; y++)
385 {
386 for (int x = 0; x < width; x++)
387 {
388 int r = data[index];
389 index++;
390 int g = data[index];
391 index++;
392 int b = data[index];
393 index++;
394
395 if (image.HasMask())
396 {
397 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
398 gdk_image_put_pixel( mask_image, x, y, 1 );
399 else
400 gdk_image_put_pixel( mask_image, x, y, 0 );
401 }
402
403 if ((r == 255) && (b == 255) && (g == 255))
404 gdk_image_put_pixel( data_image, x, y, 1 );
405 else
406 gdk_image_put_pixel( data_image, x, y, 0 );
407
408 } // for
409 } // for
410
411 // Blit picture
412
413 GdkGC *data_gc = gdk_gc_new( GetBitmap() );
414
415 gdk_draw_image( GetBitmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
416
417 gdk_image_destroy( data_image );
418 gdk_gc_unref( data_gc );
419
420 // Blit mask
421
422 if (image.HasMask())
423 {
424 GdkGC *mask_gc = gdk_gc_new( GetMask()->GetBitmap() );
425
426 gdk_draw_image( GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
427
428 gdk_image_destroy( mask_image );
429 gdk_gc_unref( mask_gc );
430 }
431 }
c2fa61e8 432
b5f01ae0
VS
433 // ------
434 // convertion to colour bitmap:
435 // ------
436 else
437 {
438 int width = image.GetWidth();
439 int height = image.GetHeight();
440
441 SetHeight( height );
442 SetWidth( width );
443
c2fa61e8 444 SetPixmap( gdk_pixmap_new( wxGetRootWindow()->window, width, height, -1 ) );
b5f01ae0
VS
445
446 // Retrieve depth
447
c2fa61e8 448 GdkVisual *visual = gdk_window_get_visual( wxGetRootWindow()->window );
b5f01ae0
VS
449 wxASSERT( visual );
450
451 int bpp = visual->depth;
452
453 SetDepth( bpp );
454
455 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
456 if (bpp < 8) bpp = 8;
457
458#if (GTK_MINOR_VERSION > 0)
459
460 if (!image.HasMask() && (bpp > 8))
461 {
462 static bool s_hasInitialized = FALSE;
463
464 if (!s_hasInitialized)
465 {
466 gdk_rgb_init();
467 s_hasInitialized = TRUE;
468 }
469
470 GdkGC *gc = gdk_gc_new( GetPixmap() );
471
472 gdk_draw_rgb_image( GetPixmap(),
473 gc,
474 0, 0,
475 width, height,
476 GDK_RGB_DITHER_NONE,
477 image.GetData(),
478 width*3 );
479
480 gdk_gc_unref( gc );
481 return TRUE;
482 }
483
484#endif
485
486 // Create picture image
487
488 GdkImage *data_image =
489 gdk_image_new( GDK_IMAGE_FASTEST, visual, width, height );
490
491 // Create mask image
492
493 GdkImage *mask_image = (GdkImage*) NULL;
494
495 if (image.HasMask())
496 {
497 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
498
499 mask_image = gdk_image_new_bitmap( visual, mask_data, width, height );
500
501 wxMask *mask = new wxMask();
c2fa61e8 502 mask->m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, width, height, 1 );
b5f01ae0
VS
503
504 SetMask( mask );
505 }
506
507 // Render
508
509 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
510 byte_order b_o = RGB;
511
512 if (bpp >= 24)
513 {
514 if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask)) b_o = RGB;
515 else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask)) b_o = RGB;
516 else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask)) b_o = BRG;
517 else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
518 else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask)) b_o = GRB;
519 else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask)) b_o = GBR;
520 }
521
522 int r_mask = image.GetMaskRed();
523 int g_mask = image.GetMaskGreen();
524 int b_mask = image.GetMaskBlue();
525
526 unsigned char* data = image.GetData();
527
528 int index = 0;
529 for (int y = 0; y < height; y++)
530 {
531 for (int x = 0; x < width; x++)
532 {
533 int r = data[index];
534 index++;
535 int g = data[index];
536 index++;
537 int b = data[index];
538 index++;
539
540 if (image.HasMask())
541 {
542 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
543 gdk_image_put_pixel( mask_image, x, y, 1 );
544 else
545 gdk_image_put_pixel( mask_image, x, y, 0 );
546 }
547
548 switch (bpp)
549 {
550 case 8:
551 {
552 int pixel = -1;
553 if (wxTheApp->m_colorCube)
554 {
555 pixel = wxTheApp->m_colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
556 }
557 else
558 {
559 GdkColormap *cmap = gtk_widget_get_default_colormap();
560 GdkColor *colors = cmap->colors;
561 int max = 3 * (65536);
562
563 for (int i = 0; i < cmap->size; i++)
564 {
565 int rdiff = (r << 8) - colors[i].red;
566 int gdiff = (g << 8) - colors[i].green;
567 int bdiff = (b << 8) - colors[i].blue;
568 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
569 if (sum < max) { pixel = i; max = sum; }
570 }
571 }
572
573 gdk_image_put_pixel( data_image, x, y, pixel );
574
575 break;
576 }
577 case 15:
578 {
579 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
580 gdk_image_put_pixel( data_image, x, y, pixel );
581 break;
582 }
583 case 16:
584 {
585 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
586 gdk_image_put_pixel( data_image, x, y, pixel );
587 break;
588 }
589 case 32:
590 case 24:
591 {
592 guint32 pixel = 0;
593 switch (b_o)
594 {
595 case RGB: pixel = (r << 16) | (g << 8) | b; break;
596 case RBG: pixel = (r << 16) | (b << 8) | g; break;
597 case BRG: pixel = (b << 16) | (r << 8) | g; break;
598 case BGR: pixel = (b << 16) | (g << 8) | r; break;
599 case GRB: pixel = (g << 16) | (r << 8) | b; break;
600 case GBR: pixel = (g << 16) | (b << 8) | r; break;
601 }
602 gdk_image_put_pixel( data_image, x, y, pixel );
603 }
604 default: break;
605 }
606 } // for
607 } // for
608
609 // Blit picture
610
611 GdkGC *data_gc = gdk_gc_new( GetPixmap() );
612
613 gdk_draw_image( GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height );
614
615 gdk_image_destroy( data_image );
616 gdk_gc_unref( data_gc );
617
618 // Blit mask
619
620 if (image.HasMask())
621 {
622 GdkGC *mask_gc = gdk_gc_new( GetMask()->GetBitmap() );
623
624 gdk_draw_image( GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height );
625
626 gdk_image_destroy( mask_image );
627 gdk_gc_unref( mask_gc );
628 }
629 }
630
631 return TRUE;
632}
633
634wxImage wxBitmap::ConvertToImage() const
635{
636 wxImage image;
c2fa61e8 637
b5f01ae0
VS
638 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
639
640 GdkImage *gdk_image = (GdkImage*) NULL;
641 if (GetPixmap())
642 {
643 gdk_image = gdk_image_get( GetPixmap(),
644 0, 0,
645 GetWidth(), GetHeight() );
646 } else
647 if (GetBitmap())
648 {
649 gdk_image = gdk_image_get( GetBitmap(),
650 0, 0,
651 GetWidth(), GetHeight() );
652 } else
653 {
654 wxFAIL_MSG( wxT("Ill-formed bitmap") );
655 }
656
657 wxCHECK_MSG( gdk_image, wxNullImage, wxT("couldn't create image") );
c2fa61e8 658
b5f01ae0
VS
659 image.Create( GetWidth(), GetHeight() );
660 char unsigned *data = image.GetData();
661
662 if (!data)
663 {
664 gdk_image_destroy( gdk_image );
665 wxFAIL_MSG( wxT("couldn't create image") );
666 return wxNullImage;
667 }
668
669 GdkImage *gdk_image_mask = (GdkImage*) NULL;
670 if (GetMask())
671 {
672 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
673 0, 0,
674 GetWidth(), GetHeight() );
675
676 image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
677 }
678
679 int bpp = -1;
680 int red_shift_right = 0;
681 int green_shift_right = 0;
682 int blue_shift_right = 0;
683 int red_shift_left = 0;
684 int green_shift_left = 0;
685 int blue_shift_left = 0;
686 bool use_shift = FALSE;
687
688 if (GetPixmap())
689 {
690 GdkVisual *visual = gdk_window_get_visual( GetPixmap() );
691
c2fa61e8 692 if (visual == NULL) visual = gdk_window_get_visual( wxGetRootWindow()->window );
b5f01ae0
VS
693 bpp = visual->depth;
694 if (bpp == 16) bpp = visual->red_prec + visual->green_prec + visual->blue_prec;
695 red_shift_right = visual->red_shift;
696 red_shift_left = 8-visual->red_prec;
697 green_shift_right = visual->green_shift;
698 green_shift_left = 8-visual->green_prec;
699 blue_shift_right = visual->blue_shift;
700 blue_shift_left = 8-visual->blue_prec;
701
702 use_shift = (visual->type == GDK_VISUAL_TRUE_COLOR) || (visual->type == GDK_VISUAL_DIRECT_COLOR);
703 }
704 if (GetBitmap())
705 {
706 bpp = 1;
707 }
708
709
710 GdkColormap *cmap = gtk_widget_get_default_colormap();
711
712 long pos = 0;
713 for (int j = 0; j < GetHeight(); j++)
714 {
715 for (int i = 0; i < GetWidth(); i++)
716 {
717 wxUint32 pixel = gdk_image_get_pixel( gdk_image, i, j );
718 if (bpp == 1)
719 {
720 if (pixel == 0)
721 {
722 data[pos] = 0;
723 data[pos+1] = 0;
724 data[pos+2] = 0;
725 }
726 else
727 {
728 data[pos] = 255;
729 data[pos+1] = 255;
730 data[pos+2] = 255;
731 }
732 }
733 else if (use_shift)
734 {
735 data[pos] = (pixel >> red_shift_right) << red_shift_left;
736 data[pos+1] = (pixel >> green_shift_right) << green_shift_left;
737 data[pos+2] = (pixel >> blue_shift_right) << blue_shift_left;
738 }
739 else if (cmap->colors)
740 {
741 data[pos] = cmap->colors[pixel].red >> 8;
742 data[pos+1] = cmap->colors[pixel].green >> 8;
743 data[pos+2] = cmap->colors[pixel].blue >> 8;
744 }
745 else
746 {
747 wxFAIL_MSG( wxT("Image conversion failed. Unknown visual type.") );
748 }
749
750 if (gdk_image_mask)
751 {
752 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
753 if (mask_pixel == 0)
754 {
755 data[pos] = 16;
756 data[pos+1] = 16;
757 data[pos+2] = 16;
758 }
759 }
760
761 pos += 3;
762 }
763 }
764
765 gdk_image_destroy( gdk_image );
c2fa61e8 766 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
b5f01ae0
VS
767
768 return image;
769}
770
c801d85f
KB
771wxBitmap::wxBitmap( const wxBitmap& bmp )
772{
fd0eed64 773 Ref( bmp );
8bbe427f 774
fd0eed64 775 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
ff7b1510 776}
6f65e337 777
debe6624 778wxBitmap::wxBitmap( const wxString &filename, int type )
c801d85f 779{
fd0eed64 780 LoadFile( filename, type );
8bbe427f 781
fd0eed64 782 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
ff7b1510 783}
c801d85f 784
debe6624 785wxBitmap::wxBitmap( const char bits[], int width, int height, int WXUNUSED(depth))
6f65e337 786{
fd0eed64 787 m_refData = new wxBitmapRefData();
6f65e337 788
fd0eed64 789 M_BMPDATA->m_mask = (wxMask *) NULL;
8bbe427f 790 M_BMPDATA->m_bitmap =
c2fa61e8 791 gdk_bitmap_create_from_data( wxGetRootWindow()->window, (gchar *) bits, width, height );
fd0eed64
RR
792 M_BMPDATA->m_width = width;
793 M_BMPDATA->m_height = height;
794 M_BMPDATA->m_bpp = 1;
6f65e337 795
223d09f6 796 wxCHECK_RET( M_BMPDATA->m_bitmap, wxT("couldn't create bitmap") );
8bbe427f 797
fd0eed64 798 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
6f65e337 799}
8bbe427f
VZ
800
801wxBitmap::~wxBitmap()
c801d85f 802{
fd0eed64 803 if (wxTheBitmapList) wxTheBitmapList->DeleteObject(this);
ff7b1510 804}
8bbe427f 805
c801d85f
KB
806wxBitmap& wxBitmap::operator = ( const wxBitmap& bmp )
807{
8bbe427f
VZ
808 if (*this == bmp) return (*this);
809 Ref( bmp );
810 return *this;
ff7b1510 811}
8bbe427f 812
f6bcfd97 813bool wxBitmap::operator == ( const wxBitmap& bmp ) const
c801d85f 814{
8bbe427f 815 return m_refData == bmp.m_refData;
ff7b1510 816}
8bbe427f 817
f6bcfd97 818bool wxBitmap::operator != ( const wxBitmap& bmp ) const
c801d85f 819{
8bbe427f 820 return m_refData != bmp.m_refData;
ff7b1510 821}
8bbe427f 822
91b8de8d 823bool wxBitmap::Ok() const
c801d85f 824{
fd0eed64 825 return (m_refData != NULL);
ff7b1510 826}
8bbe427f 827
91b8de8d 828int wxBitmap::GetHeight() const
c801d85f 829{
223d09f6 830 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
e55ad60e 831
fd0eed64 832 return M_BMPDATA->m_height;
ff7b1510 833}
c801d85f 834
91b8de8d 835int wxBitmap::GetWidth() const
c801d85f 836{
223d09f6 837 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
8bbe427f 838
fd0eed64 839 return M_BMPDATA->m_width;
ff7b1510 840}
c801d85f 841
91b8de8d 842int wxBitmap::GetDepth() const
c801d85f 843{
223d09f6 844 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
8bbe427f 845
fd0eed64 846 return M_BMPDATA->m_bpp;
ff7b1510 847}
c801d85f 848
91b8de8d 849wxMask *wxBitmap::GetMask() const
c801d85f 850{
223d09f6 851 wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") );
8bbe427f 852
fd0eed64 853 return M_BMPDATA->m_mask;
ff7b1510 854}
c801d85f
KB
855
856void wxBitmap::SetMask( wxMask *mask )
857{
223d09f6 858 wxCHECK_RET( Ok(), wxT("invalid bitmap") );
8bbe427f 859
fd0eed64 860 if (M_BMPDATA->m_mask) delete M_BMPDATA->m_mask;
8bbe427f 861
fd0eed64 862 M_BMPDATA->m_mask = mask;
ff7b1510 863}
c801d85f 864
17bec151
RR
865wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
866{
867 wxCHECK_MSG( Ok() &&
13111b2a
VZ
868 (rect.x >= 0) && (rect.y >= 0) &&
869 (rect.x+rect.width <= M_BMPDATA->m_width) && (rect.y+rect.height <= M_BMPDATA->m_height),
17bec151 870 wxNullBitmap, wxT("invalid bitmap or bitmap region") );
13111b2a 871
17bec151
RR
872 wxBitmap ret( rect.width, rect.height, M_BMPDATA->m_bpp );
873 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
13111b2a 874
17bec151
RR
875 if (ret.GetPixmap())
876 {
877 GdkGC *gc = gdk_gc_new( ret.GetPixmap() );
13111b2a
VZ
878 gdk_draw_pixmap( ret.GetPixmap(), gc, GetPixmap(), rect.x, rect.y, 0, 0, rect.width, rect.height );
879 gdk_gc_destroy( gc );
17bec151
RR
880 }
881 else
882 {
883 GdkGC *gc = gdk_gc_new( ret.GetBitmap() );
f6bcfd97 884 gdk_wx_draw_bitmap( ret.GetBitmap(), gc, GetBitmap(), rect.x, rect.y, 0, 0, rect.width, rect.height );
13111b2a 885 gdk_gc_destroy( gc );
17bec151 886 }
13111b2a 887
17bec151
RR
888 if (GetMask())
889 {
890 wxMask *mask = new wxMask;
c2fa61e8 891 mask->m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, rect.width, rect.height, 1 );
13111b2a 892
17bec151 893 GdkGC *gc = gdk_gc_new( mask->m_bitmap );
f6bcfd97 894 gdk_wx_draw_bitmap( mask->m_bitmap, gc, M_BMPDATA->m_mask->m_bitmap, 0, 0, rect.x, rect.y, rect.width, rect.height );
13111b2a
VZ
895 gdk_gc_destroy( gc );
896
897 ret.SetMask( mask );
17bec151 898 }
13111b2a 899
17bec151
RR
900 return ret;
901}
902
fd0eed64 903bool wxBitmap::SaveFile( const wxString &name, int type, wxPalette *WXUNUSED(palette) )
c801d85f 904{
223d09f6 905 wxCHECK_MSG( Ok(), FALSE, wxT("invalid bitmap") );
8bbe427f 906
b75dd496 907 // Try to save the bitmap via wxImage handlers:
fd0eed64 908 {
4bc67cc5 909 wxImage image( *this );
284b4c88 910 if (image.Ok()) return image.SaveFile( name, type );
fd0eed64 911 }
8bbe427f 912
fd0eed64 913 return FALSE;
ff7b1510 914}
c801d85f 915
fd0eed64 916bool wxBitmap::LoadFile( const wxString &name, int type )
c801d85f 917{
fd0eed64 918 UnRef();
8bbe427f 919
fd0eed64 920 if (!wxFileExists(name)) return FALSE;
8bbe427f 921
c2fa61e8 922 GdkVisual *visual = gdk_window_get_visual( wxGetRootWindow()->window );
103aab26 923 wxASSERT( visual );
c2fa61e8 924
fd0eed64
RR
925 if (type == wxBITMAP_TYPE_XPM)
926 {
927 m_refData = new wxBitmapRefData();
8bbe427f 928
fd0eed64 929 GdkBitmap *mask = (GdkBitmap*) NULL;
8bbe427f 930
c2fa61e8 931 M_BMPDATA->m_pixmap = gdk_pixmap_create_from_xpm( wxGetRootWindow()->window, &mask, NULL, name.fn_str() );
8bbe427f 932
fd0eed64
RR
933 if (mask)
934 {
935 M_BMPDATA->m_mask = new wxMask();
936 M_BMPDATA->m_mask->m_bitmap = mask;
937 }
8bbe427f 938
fd0eed64 939 gdk_window_get_size( M_BMPDATA->m_pixmap, &(M_BMPDATA->m_width), &(M_BMPDATA->m_height) );
c2fa61e8 940
103aab26 941 M_BMPDATA->m_bpp = visual->depth;
fd0eed64 942 }
b75dd496 943 else // try if wxImage can load it
fd0eed64
RR
944 {
945 wxImage image;
b75dd496 946 if (!image.LoadFile( name, type )) return FALSE;
4bc67cc5 947 if (image.Ok()) *this = image.ConvertToBitmap();
b75dd496 948 else return FALSE;
fd0eed64 949 }
8bbe427f 950
fd0eed64 951 return TRUE;
ff7b1510 952}
8bbe427f 953
91b8de8d 954wxPalette *wxBitmap::GetPalette() const
c801d85f 955{
fd0eed64 956 if (!Ok()) return (wxPalette *) NULL;
8bbe427f 957
fd0eed64 958 return M_BMPDATA->m_palette;
ff7b1510 959}
c801d85f 960
4bc67cc5
RR
961void wxBitmap::SetHeight( int height )
962{
963 if (!m_refData) m_refData = new wxBitmapRefData();
964
965 M_BMPDATA->m_height = height;
966}
967
968void wxBitmap::SetWidth( int width )
969{
970 if (!m_refData) m_refData = new wxBitmapRefData();
971
972 M_BMPDATA->m_width = width;
973}
974
975void wxBitmap::SetDepth( int depth )
976{
977 if (!m_refData) m_refData = new wxBitmapRefData();
978
979 M_BMPDATA->m_bpp = depth;
980}
981
982void wxBitmap::SetPixmap( GdkPixmap *pixmap )
983{
984 if (!m_refData) m_refData = new wxBitmapRefData();
985
986 M_BMPDATA->m_pixmap = pixmap;
987}
988
82ea63e6
RR
989void wxBitmap::SetBitmap( GdkPixmap *bitmap )
990{
991 if (!m_refData) m_refData = new wxBitmapRefData();
992
993 M_BMPDATA->m_bitmap = bitmap;
994}
995
91b8de8d 996GdkPixmap *wxBitmap::GetPixmap() const
c801d85f 997{
223d09f6 998 wxCHECK_MSG( Ok(), (GdkPixmap *) NULL, wxT("invalid bitmap") );
8bbe427f 999
fd0eed64 1000 return M_BMPDATA->m_pixmap;
ff7b1510 1001}
8bbe427f 1002
91b8de8d 1003GdkBitmap *wxBitmap::GetBitmap() const
6f65e337 1004{
223d09f6 1005 wxCHECK_MSG( Ok(), (GdkBitmap *) NULL, wxT("invalid bitmap") );
8bbe427f 1006
fd0eed64 1007 return M_BMPDATA->m_bitmap;
ff7b1510 1008}