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