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