]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/bitmap.cpp
no message
[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
c801d85f
KB
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
11#pragma implementation "bitmap.h"
12#endif
13
14#include "wx/bitmap.h"
52cbfcf0 15#include "wx/icon.h"
c801d85f 16#include "gdk/gdkprivate.h"
01111366 17#include "gdk/gdkx.h"
c801d85f
KB
18
19//-----------------------------------------------------------------------------
20// wxMask
21//-----------------------------------------------------------------------------
22
23IMPLEMENT_DYNAMIC_CLASS(wxMask,wxObject)
24
25wxMask::wxMask(void)
26{
c67daf87 27 m_bitmap = (GdkBitmap *) NULL;
ff7b1510 28}
c801d85f
KB
29
30wxMask::wxMask( const wxBitmap& WXUNUSED(bitmap), const wxColour& WXUNUSED(colour) )
31{
ff7b1510 32}
c801d85f 33
debe6624 34wxMask::wxMask( const wxBitmap& WXUNUSED(bitmap), int WXUNUSED(paletteIndex) )
c801d85f 35{
ff7b1510 36}
c801d85f
KB
37
38wxMask::wxMask( const wxBitmap& WXUNUSED(bitmap) )
39{
ff7b1510 40}
c801d85f
KB
41
42wxMask::~wxMask(void)
43{
c801d85f 44 if (m_bitmap) gdk_bitmap_unref( m_bitmap );
ff7b1510 45}
c801d85f
KB
46
47GdkBitmap *wxMask::GetBitmap(void) const
48{
49 return m_bitmap;
ff7b1510 50}
c801d85f
KB
51
52//-----------------------------------------------------------------------------
53// wxBitmap
54//-----------------------------------------------------------------------------
55
56class wxBitmapRefData: public wxObjectRefData
57{
58 public:
59
60 wxBitmapRefData(void);
61 ~wxBitmapRefData(void);
62
63 GdkPixmap *m_pixmap;
6f65e337 64 GdkBitmap *m_bitmap;
c801d85f
KB
65 wxMask *m_mask;
66 int m_width;
67 int m_height;
68 int m_bpp;
69 wxPalette *m_palette;
70};
71
72wxBitmapRefData::wxBitmapRefData(void)
73{
c67daf87
UR
74 m_pixmap = (GdkPixmap *) NULL;
75 m_bitmap = (GdkBitmap *) NULL;
76 m_mask = (wxMask *) NULL;
c801d85f
KB
77 m_width = 0;
78 m_height = 0;
79 m_bpp = 0;
c67daf87 80 m_palette = (wxPalette *) NULL;
ff7b1510 81}
c801d85f
KB
82
83wxBitmapRefData::~wxBitmapRefData(void)
84{
c801d85f 85 if (m_pixmap) gdk_pixmap_unref( m_pixmap );
219f895a 86 if (m_bitmap) gdk_bitmap_unref( m_bitmap );
c801d85f
KB
87 if (m_mask) delete m_mask;
88 if (m_palette) delete m_palette;
ff7b1510 89}
c801d85f
KB
90
91//-----------------------------------------------------------------------------
92
93#define M_BMPDATA ((wxBitmapRefData *)m_refData)
94
95IMPLEMENT_DYNAMIC_CLASS(wxBitmap,wxGDIObject)
96
97wxBitmap::wxBitmap(void)
98{
99 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
ff7b1510 100}
c801d85f 101
debe6624 102wxBitmap::wxBitmap( int width, int height, int depth )
c801d85f
KB
103{
104 m_refData = new wxBitmapRefData();
c67daf87 105 M_BMPDATA->m_mask = (wxMask *) NULL;
c801d85f
KB
106 M_BMPDATA->m_pixmap =
107 gdk_pixmap_new( (GdkWindow*) &gdk_root_parent, width, height, depth );
0180d5da
RR
108 M_BMPDATA->m_width = width;
109 M_BMPDATA->m_height = height;
c801d85f
KB
110 M_BMPDATA->m_bpp = depth;
111
112 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
ff7b1510 113}
c801d85f
KB
114
115wxBitmap::wxBitmap( char **bits )
116{
117 m_refData = new wxBitmapRefData();
c801d85f 118
219f895a
RR
119 GdkBitmap *mask = NULL;
120
c801d85f
KB
121 M_BMPDATA->m_pixmap =
122 gdk_pixmap_create_from_xpm_d( (GdkWindow*) &gdk_root_parent, &mask, NULL, (gchar **) bits );
219f895a 123
c801d85f
KB
124 if (mask)
125 {
126 M_BMPDATA->m_mask = new wxMask();
127 M_BMPDATA->m_mask->m_bitmap = mask;
ff7b1510 128 }
219f895a 129
0180d5da
RR
130 gdk_window_get_size( M_BMPDATA->m_pixmap, &(M_BMPDATA->m_width), &(M_BMPDATA->m_height) );
131
c801d85f
KB
132 M_BMPDATA->m_bpp = 24; // ?
133
134 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
ff7b1510 135}
c801d85f
KB
136
137wxBitmap::wxBitmap( const wxBitmap& bmp )
138{
139 Ref( bmp );
140
141 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
ff7b1510 142}
c801d85f
KB
143
144wxBitmap::wxBitmap( const wxBitmap* bmp )
145{
146 if (bmp) Ref( *bmp );
147
148 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
ff7b1510 149}
6f65e337 150
debe6624 151wxBitmap::wxBitmap( const wxString &filename, int type )
c801d85f
KB
152{
153 LoadFile( filename, type );
ff7b1510
RR
154
155 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
156}
c801d85f 157
debe6624 158wxBitmap::wxBitmap( const char bits[], int width, int height, int WXUNUSED(depth))
6f65e337
JS
159{
160 m_refData = new wxBitmapRefData();
161
c67daf87 162 M_BMPDATA->m_mask = (wxMask *) NULL;
6f65e337
JS
163 M_BMPDATA->m_bitmap =
164 gdk_bitmap_create_from_data( (GdkWindow*) &gdk_root_parent, (gchar *) bits, width, height );
0180d5da
RR
165 M_BMPDATA->m_width = width;
166 M_BMPDATA->m_height = height;
6f65e337
JS
167 M_BMPDATA->m_bpp = 1;
168
169 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
170}
171
c801d85f
KB
172wxBitmap::~wxBitmap(void)
173{
174 if (wxTheBitmapList) wxTheBitmapList->DeleteObject(this);
ff7b1510 175}
c801d85f
KB
176
177wxBitmap& wxBitmap::operator = ( const wxBitmap& bmp )
178{
179 if (*this == bmp) return (*this);
180 Ref( bmp );
181 return *this;
ff7b1510 182}
c801d85f
KB
183
184bool wxBitmap::operator == ( const wxBitmap& bmp )
185{
186 return m_refData == bmp.m_refData;
ff7b1510 187}
c801d85f
KB
188
189bool wxBitmap::operator != ( const wxBitmap& bmp )
190{
191 return m_refData != bmp.m_refData;
ff7b1510 192}
c801d85f
KB
193
194bool wxBitmap::Ok(void) const
195{
cf7a7e13 196 return (m_refData != NULL);
ff7b1510 197}
c801d85f
KB
198
199int wxBitmap::GetHeight(void) const
200{
e55ad60e
RR
201 if (!Ok())
202 {
203 wxFAIL_MSG( "invalid bitmap" );
204 return -1;
205 }
206
c801d85f 207 return M_BMPDATA->m_height;
ff7b1510 208}
c801d85f
KB
209
210int wxBitmap::GetWidth(void) const
211{
e55ad60e
RR
212 if (!Ok())
213 {
214 wxFAIL_MSG( "invalid bitmap" );
215 return -1;
216 }
217
c801d85f 218 return M_BMPDATA->m_width;
ff7b1510 219}
c801d85f
KB
220
221int wxBitmap::GetDepth(void) const
222{
e55ad60e
RR
223 if (!Ok())
224 {
225 wxFAIL_MSG( "invalid bitmap" );
226 return -1;
227 }
228
c801d85f 229 return M_BMPDATA->m_bpp;
ff7b1510 230}
c801d85f 231
debe6624 232void wxBitmap::SetHeight( int height )
c801d85f
KB
233{
234 if (!Ok()) return;
cf7a7e13
RR
235
236 wxFAIL_MSG( "wxBitmap::SetHeight not implemented" );
237
c801d85f 238 M_BMPDATA->m_height = height;
ff7b1510 239}
c801d85f 240
debe6624 241void wxBitmap::SetWidth( int width )
c801d85f
KB
242{
243 if (!Ok()) return;
cf7a7e13
RR
244
245 wxFAIL_MSG( "wxBitmap::SetWidth not implemented" );
246
c801d85f 247 M_BMPDATA->m_width = width;
ff7b1510 248}
c801d85f 249
debe6624 250void wxBitmap::SetDepth( int depth )
c801d85f
KB
251{
252 if (!Ok()) return;
cf7a7e13
RR
253
254 wxFAIL_MSG( "wxBitmap::SetDepth not implemented" );
255
c801d85f 256 M_BMPDATA->m_bpp = depth;
ff7b1510 257}
c801d85f
KB
258
259wxMask *wxBitmap::GetMask(void) const
260{
e55ad60e
RR
261 if (!Ok())
262 {
263 wxFAIL_MSG( "invalid bitmap" );
264 return (wxMask *) NULL;
265 }
219f895a 266
c801d85f 267 return M_BMPDATA->m_mask;
ff7b1510 268}
c801d85f
KB
269
270void wxBitmap::SetMask( wxMask *mask )
271{
e55ad60e
RR
272 if (!Ok())
273 {
274 wxFAIL_MSG( "invalid bitmap" );
275 return;
276 }
219f895a 277
c801d85f 278 if (M_BMPDATA->m_mask) delete M_BMPDATA->m_mask;
cf7a7e13 279
c801d85f 280 M_BMPDATA->m_mask = mask;
ff7b1510 281}
c801d85f 282
01111366 283bool wxBitmap::SaveFile( const wxString &WXUNUSED(name), int WXUNUSED(type),
c801d85f
KB
284 wxPalette *WXUNUSED(palette) )
285{
e55ad60e
RR
286 if (!Ok())
287 {
288 wxFAIL_MSG( "invalid bitmap" );
289 return FALSE;
290 }
291
c801d85f 292 return FALSE;
ff7b1510 293}
c801d85f 294
01111366 295bool wxBitmap::LoadFile( const wxString &WXUNUSED(name), int WXUNUSED(type) )
c801d85f 296{
01111366 297 if (!Ok())
c801d85f 298 {
01111366 299 wxFAIL_MSG( "invalid bitmap" );
c801d85f 300 return FALSE;
ff7b1510 301 }
cf7a7e13 302
c801d85f 303 return FALSE;
ff7b1510 304}
c801d85f
KB
305
306wxPalette *wxBitmap::GetPalette(void) const
307{
c67daf87 308 if (!Ok()) return (wxPalette *) NULL;
c801d85f 309 return M_BMPDATA->m_palette;
ff7b1510 310}
c801d85f
KB
311
312GdkPixmap *wxBitmap::GetPixmap(void) const
313{
e55ad60e
RR
314 if (!Ok())
315 {
316 wxFAIL_MSG( "invalid bitmap" );
317 return (GdkPixmap *) NULL;
318 }
cf7a7e13 319
c801d85f 320 return M_BMPDATA->m_pixmap;
ff7b1510 321}
c801d85f 322
6f65e337
JS
323GdkBitmap *wxBitmap::GetBitmap(void) const
324{
e55ad60e
RR
325 if (!Ok())
326 {
327 wxFAIL_MSG( "invalid bitmap" );
328 return (GdkBitmap *) NULL;
329 }
219f895a 330
6f65e337 331 return M_BMPDATA->m_bitmap;
ff7b1510 332}
6f65e337 333
01111366 334wxBitmap::wxBitmap( const wxImage &image )
219f895a 335{
01111366 336 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
219f895a 337
01111366 338 if (!image.Ok()) return;
219f895a 339
01111366 340 m_refData = new wxBitmapRefData();
cf7a7e13 341
01111366
RR
342 M_BMPDATA->m_height = image.GetHeight();
343 M_BMPDATA->m_width = image.GetWidth();
344 int width = image.GetWidth();
345 int height = image.GetHeight();
346
347 // Create picture
cf7a7e13 348
01111366
RR
349 GdkImage *data_image =
350 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
cf7a7e13 351
01111366
RR
352 M_BMPDATA->m_pixmap =
353 gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 );
354
355 // Create mask
cf7a7e13 356
01111366 357 GdkImage *mask_image = (GdkImage*) NULL;
cf7a7e13 358
01111366 359 if (image.HasMask())
cf7a7e13 360 {
01111366
RR
361 unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height );
362
363 mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height );
364
365 M_BMPDATA->m_mask = new wxMask();
366 M_BMPDATA->m_mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 );
cf7a7e13
RR
367 }
368
01111366
RR
369 // Retrieve depth
370
371 M_BMPDATA->m_bpp = data_image->depth;
372
373 int render_depth = 8;
374 if (M_BMPDATA->m_bpp > 8) render_depth = M_BMPDATA->m_bpp;
375
376 // Render
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 for (int x = 0; x < width; x++)
387 {
388 int r = data[index];
389 index++;
390 int g = data[index];
391 index++;
392 int b = data[index];
393 index++;
394
395 if (image.HasMask())
396 {
397 if ((r == r_mask) && (b = b_mask) && (g = g_mask))
398 gdk_image_put_pixel( mask_image, x, y, 0 );
399 else
400 gdk_image_put_pixel( mask_image, x, y, 1 );
401 }
402
403 switch (render_depth)
404 {
405 case 8:
406 {
407 GdkColormap *cmap = gtk_widget_get_default_colormap();
408 GdkColor *colors = cmap->colors;
409 int max = 3 * (65536);
410 int index = -1;
411
412 for (int i = 0; i < cmap->size; i++)
413 {
414 int rdiff = (r << 8) - colors[i].red;
415 int gdiff = (g << 8) - colors[i].green;
416 int bdiff = (b << 8) - colors[i].blue;
417 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
418 if (sum < max) { index = i; max = sum; }
419 }
420
421 gdk_image_put_pixel( data_image, x, y, index );
422
423 break;
424 }
425 case 15:
426 {
427 guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
428 gdk_image_put_pixel( data_image, x, y, pixel );
429 break;
430 }
431 case 16:
432 {
433 guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
434 gdk_image_put_pixel( data_image, x, y, pixel );
435 break;
436 }
437 case 24:
438 {
439 break;
440 }
441 case 32:
442 {
443 break;
444 }
445 default: break;
446 }
447 }
448
449 // Blit picture
cf7a7e13 450
01111366 451 GdkGC *data_gc = gdk_gc_new( M_BMPDATA->m_pixmap );
cf7a7e13 452
01111366 453 gdk_draw_image( M_BMPDATA->m_pixmap, data_gc, data_image, 0, 0, 0, 0, width, height );
cf7a7e13 454
01111366
RR
455 gdk_image_destroy( data_image );
456 gdk_gc_unref( data_gc );
cf7a7e13 457
01111366 458 // Blit mask
cf7a7e13 459
01111366
RR
460 if (image.HasMask())
461 {
462 GdkGC *mask_gc = gdk_gc_new( M_BMPDATA->m_mask->m_bitmap );
cf7a7e13 463
01111366 464 gdk_draw_image( M_BMPDATA->m_mask->m_bitmap, mask_gc, mask_image, 0, 0, 0, 0, width, height );
cf7a7e13 465
01111366
RR
466 gdk_image_destroy( mask_image );
467 gdk_gc_unref( mask_gc );
468 }
469
ff7b1510 470}
219f895a 471
01111366 472wxImage wxBitmap::ConvertToImage() const
219f895a 473{
01111366
RR
474 wxImage image;
475
e55ad60e
RR
476 if (!Ok())
477 {
478 wxFAIL_MSG( "invalid bitmap" );
01111366 479 return image;
e55ad60e 480 }
219f895a 481
01111366 482 GdkImage *gdk_image = gdk_image_get( M_BMPDATA->m_pixmap, 0, 0, M_BMPDATA->m_width, M_BMPDATA->m_height );
cf7a7e13 483
01111366 484 if (!gdk_image) return image;
cf7a7e13 485
01111366
RR
486 image.Create( M_BMPDATA->m_width, M_BMPDATA->m_height );
487 char unsigned *data = image.GetData();
cf7a7e13 488
01111366
RR
489 int bpp = gdk_image->bpp;
490 GdkColormap *cmap = gtk_widget_get_default_colormap();
cf7a7e13 491
01111366
RR
492 long pos = 0;
493 for (int j = 0; j < M_BMPDATA->m_height; j++)
219f895a 494 {
01111366
RR
495 for (int i = 0; i < M_BMPDATA->m_width; i++)
496 {
497 int pixel = gdk_image_get_pixel( gdk_image, i, j );
498 if (bpp <= 8)
499 {
500 data[pos] = cmap->colors[pixel].red >> 8;
501 data[pos+1] = cmap->colors[pixel].green >> 8;
502 data[pos+2] = cmap->colors[pixel].blue >> 8;
503 } else if (bpp == 15)
504 {
505 data[pos] = (pixel >> 7) & 0xf8;
506 data[pos+1] = (pixel >> 3) & 0xf8;
507 data[pos+2] = (pixel << 3) & 0xf8;
508 } else if (bpp == 16)
509 {
510 data[pos] = (pixel >> 8) & 0xf8;
511 data[pos+1] = (pixel >> 3) & 0xfc;
512 data[pos+2] = (pixel << 3) & 0xf8;
513 } else
514 {
515 data[pos] = (pixel >> 16) & 0xff;
516 data[pos+1] = (pixel >> 8) & 0xff;
517 data[pos+2] = pixel & 0xff;
518 }
519
520 pos += 3;
521 }
ff7b1510 522 }
219f895a 523
01111366 524 gdk_image_destroy( gdk_image );
cf7a7e13 525
01111366 526 return image;
ff7b1510 527}
219f895a
RR
528
529
01111366 530