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