]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/bitmap.cpp
Fixed some broken things related to context help, fixed memory leak
[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"
83624f79 19
20e05ffb 20#include <gdk/gdk.h>
d76fe38b 21#include <gtk/gtk.h>
13111b2a 22
f6bcfd97
BP
23extern void gdk_wx_draw_bitmap (GdkDrawable *drawable,
24 GdkGC *gc,
25 GdkDrawable *src,
26 gint xsrc,
27 gint ysrc,
28 gint xdest,
29 gint ydest,
30 gint width,
31 gint height);
32
d76fe38b
RR
33//-----------------------------------------------------------------------------
34// data
35//-----------------------------------------------------------------------------
36
37extern GtkWidget *wxRootWindow;
c801d85f
KB
38
39//-----------------------------------------------------------------------------
40// wxMask
41//-----------------------------------------------------------------------------
42
43IMPLEMENT_DYNAMIC_CLASS(wxMask,wxObject)
44
8bbe427f 45wxMask::wxMask()
c801d85f 46{
fd0eed64 47 m_bitmap = (GdkBitmap *) NULL;
ff7b1510 48}
c801d85f 49
91b8de8d 50wxMask::wxMask( const wxBitmap& bitmap, const wxColour& colour )
c801d85f 51{
72a7edf0 52 m_bitmap = (GdkBitmap *) NULL;
91b8de8d 53 Create( bitmap, colour );
ff7b1510 54}
c801d85f 55
91b8de8d 56wxMask::wxMask( const wxBitmap& bitmap, int paletteIndex )
c801d85f 57{
72a7edf0 58 m_bitmap = (GdkBitmap *) NULL;
91b8de8d 59 Create( bitmap, paletteIndex );
ff7b1510 60}
c801d85f 61
91b8de8d 62wxMask::wxMask( const wxBitmap& bitmap )
c801d85f 63{
72a7edf0 64 m_bitmap = (GdkBitmap *) NULL;
91b8de8d 65 Create( bitmap );
ff7b1510 66}
c801d85f 67
8bbe427f 68wxMask::~wxMask()
c801d85f 69{
13111b2a 70 if (m_bitmap)
72a7edf0 71 gdk_bitmap_unref( m_bitmap );
ff7b1510 72}
c801d85f 73
1fb4de31
RR
74bool wxMask::Create( const wxBitmap& bitmap,
75 const wxColour& colour )
91b8de8d
RR
76{
77 if (m_bitmap)
284b4c88 78 {
91b8de8d 79 gdk_bitmap_unref( m_bitmap );
284b4c88 80 m_bitmap = (GdkBitmap*) NULL;
91b8de8d 81 }
13111b2a 82
1fb4de31
RR
83 wxImage image( bitmap );
84 if (!image.Ok()) return FALSE;
13111b2a 85
d76fe38b 86 m_bitmap = gdk_pixmap_new( wxRootWindow->window, image.GetWidth(), image.GetHeight(), 1 );
f9ee644e 87 GdkGC *gc = gdk_gc_new( m_bitmap );
13111b2a 88
f9ee644e
RR
89 GdkColor color;
90 color.red = 65000;
91 color.green = 65000;
92 color.blue = 65000;
93 color.pixel = 1;
94 gdk_gc_set_foreground( gc, &color );
95 gdk_gc_set_fill( gc, GDK_SOLID );
96 gdk_draw_rectangle( m_bitmap, gc, TRUE, 0, 0, image.GetWidth(), image.GetHeight() );
13111b2a 97
1fb4de31
RR
98 unsigned char *data = image.GetData();
99 int index = 0;
13111b2a 100
1fb4de31
RR
101 unsigned char red = colour.Red();
102 unsigned char green = colour.Green();
103 unsigned char blue = colour.Blue();
13111b2a 104
103aab26
RR
105 GdkVisual *visual = gdk_window_get_visual( wxRootWindow->window );
106 wxASSERT( visual );
107
1fb4de31
RR
108 int bpp = visual->depth;
109 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
110 if (bpp == 15)
111 {
112 red = red & 0xf8;
1fb4de31 113 green = green & 0xf8;
f6bcfd97 114 blue = blue & 0xf8;
1fb4de31
RR
115 }
116 if (bpp == 16)
117 {
118 red = red & 0xf8;
f6bcfd97
BP
119 green = green & 0xfc;
120 blue = blue & 0xf8;
1fb4de31 121 }
13111b2a 122
f9ee644e
RR
123 color.red = 0;
124 color.green = 0;
125 color.blue = 0;
126 color.pixel = 0;
127 gdk_gc_set_foreground( gc, &color );
13111b2a 128
1fb4de31 129 for (int j = 0; j < image.GetHeight(); j++)
f9ee644e 130 {
f2593d0d
RR
131 int start_x = -1;
132 int i;
133 for (i = 0; i < image.GetWidth(); i++)
1fb4de31 134 {
13111b2a
VZ
135 if ((data[index] == red) &&
136 (data[index+1] == green) &&
137 (data[index+2] == blue))
138 {
139 if (start_x == -1)
140 start_x = i;
141 }
142 else
143 {
144 if (start_x != -1)
145 {
146 gdk_draw_line( m_bitmap, gc, start_x, j, i-1, j );
147 start_x = -1;
148 }
f9ee644e
RR
149 }
150 index += 3;
151 }
152 if (start_x != -1)
153 gdk_draw_line( m_bitmap, gc, start_x, j, i, j );
154 }
1fb4de31 155
f9ee644e 156 gdk_gc_unref( gc );
1fb4de31 157
f9ee644e 158 return TRUE;
91b8de8d
RR
159}
160
284b4c88
VZ
161bool wxMask::Create( const wxBitmap& WXUNUSED(bitmap),
162 int WXUNUSED(paletteIndex) )
91b8de8d
RR
163{
164 if (m_bitmap)
284b4c88 165 {
91b8de8d 166 gdk_bitmap_unref( m_bitmap );
284b4c88 167 m_bitmap = (GdkBitmap*) NULL;
91b8de8d 168 }
284b4c88 169
223d09f6 170 wxFAIL_MSG( wxT("not implemented") );
284b4c88 171
91b8de8d
RR
172 return FALSE;
173}
174
175bool wxMask::Create( const wxBitmap& bitmap )
176{
177 if (m_bitmap)
284b4c88 178 {
91b8de8d 179 gdk_bitmap_unref( m_bitmap );
284b4c88 180 m_bitmap = (GdkBitmap*) NULL;
91b8de8d 181 }
284b4c88 182
91b8de8d 183 if (!bitmap.Ok()) return FALSE;
284b4c88 184
223d09f6 185 wxCHECK_MSG( bitmap.GetBitmap(), FALSE, wxT("Cannot create mask from colour bitmap") );
284b4c88 186
d76fe38b 187 m_bitmap = gdk_pixmap_new( wxRootWindow->window, bitmap.GetWidth(), bitmap.GetHeight(), 1 );
284b4c88 188
91b8de8d 189 if (!m_bitmap) return FALSE;
284b4c88 190
91b8de8d 191 GdkGC *gc = gdk_gc_new( m_bitmap );
284b4c88 192
f6bcfd97 193 gdk_wx_draw_bitmap( m_bitmap, gc, bitmap.GetBitmap(), 0, 0, 0, 0, bitmap.GetWidth(), bitmap.GetHeight() );
284b4c88 194
91b8de8d 195 gdk_gc_unref( gc );
284b4c88 196
91b8de8d
RR
197 return TRUE;
198}
199
200GdkBitmap *wxMask::GetBitmap() const
c801d85f 201{
fd0eed64 202 return m_bitmap;
ff7b1510 203}
8bbe427f 204
c801d85f
KB
205//-----------------------------------------------------------------------------
206// wxBitmap
207//-----------------------------------------------------------------------------
208
209class wxBitmapRefData: public wxObjectRefData
210{
fd0eed64 211public:
f2593d0d
RR
212 wxBitmapRefData();
213 ~wxBitmapRefData();
214
215 GdkPixmap *m_pixmap;
216 GdkBitmap *m_bitmap;
217 wxMask *m_mask;
218 int m_width;
219 int m_height;
220 int m_bpp;
221 wxPalette *m_palette;
c801d85f
KB
222};
223
8bbe427f 224wxBitmapRefData::wxBitmapRefData()
c801d85f 225{
fd0eed64
RR
226 m_pixmap = (GdkPixmap *) NULL;
227 m_bitmap = (GdkBitmap *) NULL;
228 m_mask = (wxMask *) NULL;
229 m_width = 0;
230 m_height = 0;
231 m_bpp = 0;
232 m_palette = (wxPalette *) NULL;
ff7b1510 233}
c801d85f 234
8bbe427f 235wxBitmapRefData::~wxBitmapRefData()
c801d85f 236{
fd0eed64
RR
237 if (m_pixmap) gdk_pixmap_unref( m_pixmap );
238 if (m_bitmap) gdk_bitmap_unref( m_bitmap );
239 if (m_mask) delete m_mask;
240 if (m_palette) delete m_palette;
ff7b1510 241}
c801d85f
KB
242
243//-----------------------------------------------------------------------------
244
245#define M_BMPDATA ((wxBitmapRefData *)m_refData)
246
247IMPLEMENT_DYNAMIC_CLASS(wxBitmap,wxGDIObject)
248
8bbe427f 249wxBitmap::wxBitmap()
c801d85f 250{
fd0eed64 251 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
ff7b1510 252}
8bbe427f 253
debe6624 254wxBitmap::wxBitmap( int width, int height, int depth )
c801d85f 255{
c826213d
RR
256 Create( width, height, depth );
257
258 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
259}
260
261bool wxBitmap::Create( int width, int height, int depth )
262{
263 UnRef();
264
265 wxCHECK_MSG( (width > 0) && (height > 0), FALSE, wxT("invalid bitmap size") )
284b4c88 266
103aab26
RR
267 GdkVisual *visual = gdk_window_get_visual( wxRootWindow->window );
268 wxASSERT( visual );
284b4c88 269
103aab26
RR
270 if (depth == -1) depth = visual->depth;
271
c826213d
RR
272 wxCHECK_MSG( (depth == visual->depth) ||
273 (depth == 1), FALSE, wxT("invalid bitmap depth") )
8bbe427f 274
eefa26be 275 m_refData = new wxBitmapRefData();
fd0eed64 276 M_BMPDATA->m_mask = (wxMask *) NULL;
fd0eed64
RR
277 M_BMPDATA->m_width = width;
278 M_BMPDATA->m_height = height;
eefa26be
RR
279 if (depth == 1)
280 {
d76fe38b 281 M_BMPDATA->m_bitmap = gdk_pixmap_new( wxRootWindow->window, width, height, 1 );
eefa26be
RR
282 M_BMPDATA->m_bpp = 1;
283 }
284 else
285 {
d76fe38b 286 M_BMPDATA->m_pixmap = gdk_pixmap_new( wxRootWindow->window, width, height, depth );
103aab26 287 M_BMPDATA->m_bpp = visual->depth;
eefa26be 288 }
8bbe427f 289
c826213d 290 return Ok();
ff7b1510 291}
e838cc14 292bool wxBitmap::CreateFromXpm( const char **bits )
e52f60e6 293{
e838cc14 294 wxCHECK_MSG( bits != NULL, FALSE, wxT("invalid bitmap data") )
8bbe427f 295
103aab26
RR
296 GdkVisual *visual = gdk_window_get_visual( wxRootWindow->window );
297 wxASSERT( visual );
298
e52f60e6
RR
299 m_refData = new wxBitmapRefData();
300
301 GdkBitmap *mask = (GdkBitmap*) NULL;
8bbe427f 302
d76fe38b 303 M_BMPDATA->m_pixmap = gdk_pixmap_create_from_xpm_d( wxRootWindow->window, &mask, NULL, (gchar **) bits );
8bbe427f 304
e838cc14 305 wxCHECK_MSG( M_BMPDATA->m_pixmap, FALSE, wxT("couldn't create pixmap") );
8bbe427f 306
fd0eed64
RR
307 if (mask)
308 {
309 M_BMPDATA->m_mask = new wxMask();
310 M_BMPDATA->m_mask->m_bitmap = mask;
311 }
8bbe427f 312
fd0eed64 313 gdk_window_get_size( M_BMPDATA->m_pixmap, &(M_BMPDATA->m_width), &(M_BMPDATA->m_height) );
8bbe427f 314
103aab26
RR
315 M_BMPDATA->m_bpp = visual->depth; // ?
316
fd0eed64 317 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
e838cc14
VZ
318
319 return TRUE;
ff7b1510 320}
8bbe427f 321
c801d85f
KB
322wxBitmap::wxBitmap( const wxBitmap& bmp )
323{
fd0eed64 324 Ref( bmp );
8bbe427f 325
fd0eed64 326 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
ff7b1510 327}
6f65e337 328
debe6624 329wxBitmap::wxBitmap( const wxString &filename, int type )
c801d85f 330{
fd0eed64 331 LoadFile( filename, type );
8bbe427f 332
fd0eed64 333 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
ff7b1510 334}
c801d85f 335
debe6624 336wxBitmap::wxBitmap( const char bits[], int width, int height, int WXUNUSED(depth))
6f65e337 337{
fd0eed64 338 m_refData = new wxBitmapRefData();
6f65e337 339
fd0eed64 340 M_BMPDATA->m_mask = (wxMask *) NULL;
8bbe427f 341 M_BMPDATA->m_bitmap =
d76fe38b 342 gdk_bitmap_create_from_data( wxRootWindow->window, (gchar *) bits, width, height );
fd0eed64
RR
343 M_BMPDATA->m_width = width;
344 M_BMPDATA->m_height = height;
345 M_BMPDATA->m_bpp = 1;
6f65e337 346
223d09f6 347 wxCHECK_RET( M_BMPDATA->m_bitmap, wxT("couldn't create bitmap") );
8bbe427f 348
fd0eed64 349 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
6f65e337 350}
8bbe427f
VZ
351
352wxBitmap::~wxBitmap()
c801d85f 353{
fd0eed64 354 if (wxTheBitmapList) wxTheBitmapList->DeleteObject(this);
ff7b1510 355}
8bbe427f 356
c801d85f
KB
357wxBitmap& wxBitmap::operator = ( const wxBitmap& bmp )
358{
8bbe427f
VZ
359 if (*this == bmp) return (*this);
360 Ref( bmp );
361 return *this;
ff7b1510 362}
8bbe427f 363
f6bcfd97 364bool wxBitmap::operator == ( const wxBitmap& bmp ) const
c801d85f 365{
8bbe427f 366 return m_refData == bmp.m_refData;
ff7b1510 367}
8bbe427f 368
f6bcfd97 369bool wxBitmap::operator != ( const wxBitmap& bmp ) const
c801d85f 370{
8bbe427f 371 return m_refData != bmp.m_refData;
ff7b1510 372}
8bbe427f 373
91b8de8d 374bool wxBitmap::Ok() const
c801d85f 375{
fd0eed64 376 return (m_refData != NULL);
ff7b1510 377}
8bbe427f 378
91b8de8d 379int wxBitmap::GetHeight() const
c801d85f 380{
223d09f6 381 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
e55ad60e 382
fd0eed64 383 return M_BMPDATA->m_height;
ff7b1510 384}
c801d85f 385
91b8de8d 386int wxBitmap::GetWidth() const
c801d85f 387{
223d09f6 388 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
8bbe427f 389
fd0eed64 390 return M_BMPDATA->m_width;
ff7b1510 391}
c801d85f 392
91b8de8d 393int wxBitmap::GetDepth() const
c801d85f 394{
223d09f6 395 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
8bbe427f 396
fd0eed64 397 return M_BMPDATA->m_bpp;
ff7b1510 398}
c801d85f 399
91b8de8d 400wxMask *wxBitmap::GetMask() const
c801d85f 401{
223d09f6 402 wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") );
8bbe427f 403
fd0eed64 404 return M_BMPDATA->m_mask;
ff7b1510 405}
c801d85f
KB
406
407void wxBitmap::SetMask( wxMask *mask )
408{
223d09f6 409 wxCHECK_RET( Ok(), wxT("invalid bitmap") );
8bbe427f 410
fd0eed64 411 if (M_BMPDATA->m_mask) delete M_BMPDATA->m_mask;
8bbe427f 412
fd0eed64 413 M_BMPDATA->m_mask = mask;
ff7b1510 414}
c801d85f 415
17bec151
RR
416wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
417{
418 wxCHECK_MSG( Ok() &&
13111b2a
VZ
419 (rect.x >= 0) && (rect.y >= 0) &&
420 (rect.x+rect.width <= M_BMPDATA->m_width) && (rect.y+rect.height <= M_BMPDATA->m_height),
17bec151 421 wxNullBitmap, wxT("invalid bitmap or bitmap region") );
13111b2a 422
17bec151
RR
423 wxBitmap ret( rect.width, rect.height, M_BMPDATA->m_bpp );
424 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
13111b2a 425
17bec151
RR
426 if (ret.GetPixmap())
427 {
428 GdkGC *gc = gdk_gc_new( ret.GetPixmap() );
13111b2a
VZ
429 gdk_draw_pixmap( ret.GetPixmap(), gc, GetPixmap(), rect.x, rect.y, 0, 0, rect.width, rect.height );
430 gdk_gc_destroy( gc );
17bec151
RR
431 }
432 else
433 {
434 GdkGC *gc = gdk_gc_new( ret.GetBitmap() );
f6bcfd97 435 gdk_wx_draw_bitmap( ret.GetBitmap(), gc, GetBitmap(), rect.x, rect.y, 0, 0, rect.width, rect.height );
13111b2a 436 gdk_gc_destroy( gc );
17bec151 437 }
13111b2a 438
17bec151
RR
439 if (GetMask())
440 {
441 wxMask *mask = new wxMask;
d76fe38b 442 mask->m_bitmap = gdk_pixmap_new( wxRootWindow->window, rect.width, rect.height, 1 );
13111b2a 443
17bec151 444 GdkGC *gc = gdk_gc_new( mask->m_bitmap );
f6bcfd97 445 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
446 gdk_gc_destroy( gc );
447
448 ret.SetMask( mask );
17bec151 449 }
13111b2a 450
17bec151
RR
451 return ret;
452}
453
fd0eed64 454bool wxBitmap::SaveFile( const wxString &name, int type, wxPalette *WXUNUSED(palette) )
c801d85f 455{
223d09f6 456 wxCHECK_MSG( Ok(), FALSE, wxT("invalid bitmap") );
8bbe427f 457
b75dd496 458 // Try to save the bitmap via wxImage handlers:
fd0eed64 459 {
4bc67cc5 460 wxImage image( *this );
284b4c88 461 if (image.Ok()) return image.SaveFile( name, type );
fd0eed64 462 }
8bbe427f 463
fd0eed64 464 return FALSE;
ff7b1510 465}
c801d85f 466
fd0eed64 467bool wxBitmap::LoadFile( const wxString &name, int type )
c801d85f 468{
fd0eed64 469 UnRef();
8bbe427f 470
fd0eed64 471 if (!wxFileExists(name)) return FALSE;
8bbe427f 472
103aab26
RR
473 GdkVisual *visual = gdk_window_get_visual( wxRootWindow->window );
474 wxASSERT( visual );
475
fd0eed64
RR
476 if (type == wxBITMAP_TYPE_XPM)
477 {
478 m_refData = new wxBitmapRefData();
8bbe427f 479
fd0eed64 480 GdkBitmap *mask = (GdkBitmap*) NULL;
8bbe427f 481
d76fe38b 482 M_BMPDATA->m_pixmap = gdk_pixmap_create_from_xpm( wxRootWindow->window, &mask, NULL, name.fn_str() );
8bbe427f 483
fd0eed64
RR
484 if (mask)
485 {
486 M_BMPDATA->m_mask = new wxMask();
487 M_BMPDATA->m_mask->m_bitmap = mask;
488 }
8bbe427f 489
fd0eed64 490 gdk_window_get_size( M_BMPDATA->m_pixmap, &(M_BMPDATA->m_width), &(M_BMPDATA->m_height) );
103aab26
RR
491
492 M_BMPDATA->m_bpp = visual->depth;
fd0eed64 493 }
b75dd496 494 else // try if wxImage can load it
fd0eed64
RR
495 {
496 wxImage image;
b75dd496 497 if (!image.LoadFile( name, type )) return FALSE;
4bc67cc5 498 if (image.Ok()) *this = image.ConvertToBitmap();
b75dd496 499 else return FALSE;
fd0eed64 500 }
8bbe427f 501
fd0eed64 502 return TRUE;
ff7b1510 503}
8bbe427f 504
91b8de8d 505wxPalette *wxBitmap::GetPalette() const
c801d85f 506{
fd0eed64 507 if (!Ok()) return (wxPalette *) NULL;
8bbe427f 508
fd0eed64 509 return M_BMPDATA->m_palette;
ff7b1510 510}
c801d85f 511
4bc67cc5
RR
512void wxBitmap::SetHeight( int height )
513{
514 if (!m_refData) m_refData = new wxBitmapRefData();
515
516 M_BMPDATA->m_height = height;
517}
518
519void wxBitmap::SetWidth( int width )
520{
521 if (!m_refData) m_refData = new wxBitmapRefData();
522
523 M_BMPDATA->m_width = width;
524}
525
526void wxBitmap::SetDepth( int depth )
527{
528 if (!m_refData) m_refData = new wxBitmapRefData();
529
530 M_BMPDATA->m_bpp = depth;
531}
532
533void wxBitmap::SetPixmap( GdkPixmap *pixmap )
534{
535 if (!m_refData) m_refData = new wxBitmapRefData();
536
537 M_BMPDATA->m_pixmap = pixmap;
538}
539
82ea63e6
RR
540void wxBitmap::SetBitmap( GdkPixmap *bitmap )
541{
542 if (!m_refData) m_refData = new wxBitmapRefData();
543
544 M_BMPDATA->m_bitmap = bitmap;
545}
546
91b8de8d 547GdkPixmap *wxBitmap::GetPixmap() const
c801d85f 548{
223d09f6 549 wxCHECK_MSG( Ok(), (GdkPixmap *) NULL, wxT("invalid bitmap") );
8bbe427f 550
fd0eed64 551 return M_BMPDATA->m_pixmap;
ff7b1510 552}
8bbe427f 553
91b8de8d 554GdkBitmap *wxBitmap::GetBitmap() const
6f65e337 555{
223d09f6 556 wxCHECK_MSG( Ok(), (GdkBitmap *) NULL, wxT("invalid bitmap") );
8bbe427f 557
fd0eed64 558 return M_BMPDATA->m_bitmap;
ff7b1510 559}