]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk1/bitmap.cpp
wxWave class for wxGTK (linux)
[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 "gdk/gdkprivate.h"
17#include "gdk/gdkx.h"
18
19//-----------------------------------------------------------------------------
20// wxMask
21//-----------------------------------------------------------------------------
22
23IMPLEMENT_DYNAMIC_CLASS(wxMask,wxObject)
24
25wxMask::wxMask(void)
26{
27 m_bitmap = (GdkBitmap *) NULL;
28}
29
30wxMask::wxMask( const wxBitmap& WXUNUSED(bitmap), const wxColour& WXUNUSED(colour) )
31{
32}
33
34wxMask::wxMask( const wxBitmap& WXUNUSED(bitmap), int WXUNUSED(paletteIndex) )
35{
36}
37
38wxMask::wxMask( const wxBitmap& WXUNUSED(bitmap) )
39{
40}
41
42wxMask::~wxMask(void)
43{
44 if (m_bitmap) gdk_bitmap_unref( m_bitmap );
45}
46
47GdkBitmap *wxMask::GetBitmap(void) const
48{
49 return m_bitmap;
50}
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;
64 GdkBitmap *m_bitmap;
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{
74 m_pixmap = (GdkPixmap *) NULL;
75 m_bitmap = (GdkBitmap *) NULL;
76 m_mask = (wxMask *) NULL;
77 m_width = 0;
78 m_height = 0;
79 m_bpp = 0;
80 m_palette = (wxPalette *) NULL;
81}
82
83wxBitmapRefData::~wxBitmapRefData(void)
84{
85 if (m_pixmap) gdk_pixmap_unref( m_pixmap );
86 if (m_bitmap) gdk_bitmap_unref( m_bitmap );
87 if (m_mask) delete m_mask;
88 if (m_palette) delete m_palette;
89}
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);
100}
101
102wxBitmap::wxBitmap( int width, int height, int depth )
103{
104 m_refData = new wxBitmapRefData();
105 M_BMPDATA->m_mask = (wxMask *) NULL;
106 M_BMPDATA->m_pixmap =
107 gdk_pixmap_new( (GdkWindow*) &gdk_root_parent, width, height, depth );
108 M_BMPDATA->m_width = width;
109 M_BMPDATA->m_height = height;
110 M_BMPDATA->m_bpp = depth;
111
112 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
113}
114
115wxBitmap::wxBitmap( char **bits )
116{
117 m_refData = new wxBitmapRefData();
118
119 GdkBitmap *mask = NULL;
120
121 M_BMPDATA->m_pixmap =
122 gdk_pixmap_create_from_xpm_d( (GdkWindow*) &gdk_root_parent, &mask, NULL, (gchar **) bits );
123
124 if (mask)
125 {
126 M_BMPDATA->m_mask = new wxMask();
127 M_BMPDATA->m_mask->m_bitmap = mask;
128 }
129
130 gdk_window_get_size( M_BMPDATA->m_pixmap, &(M_BMPDATA->m_width), &(M_BMPDATA->m_height) );
131
132 M_BMPDATA->m_bpp = 24; // ?
133
134 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
135}
136
137wxBitmap::wxBitmap( const wxBitmap& bmp )
138{
139 Ref( bmp );
140
141 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
142}
143
144wxBitmap::wxBitmap( const wxBitmap* bmp )
145{
146 if (bmp) Ref( *bmp );
147
148 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
149}
150
151wxBitmap::wxBitmap( const wxString &filename, int type )
152{
153 LoadFile( filename, type );
154
155 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
156}
157
158wxBitmap::wxBitmap( const char bits[], int width, int height, int WXUNUSED(depth))
159{
160 m_refData = new wxBitmapRefData();
161
162 M_BMPDATA->m_mask = (wxMask *) NULL;
163 M_BMPDATA->m_bitmap =
164 gdk_bitmap_create_from_data( (GdkWindow*) &gdk_root_parent, (gchar *) bits, width, height );
165 M_BMPDATA->m_width = width;
166 M_BMPDATA->m_height = height;
167 M_BMPDATA->m_bpp = 1;
168
169 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
170}
171
172wxBitmap::~wxBitmap(void)
173{
174 if (wxTheBitmapList) wxTheBitmapList->DeleteObject(this);
175}
176
177wxBitmap& wxBitmap::operator = ( const wxBitmap& bmp )
178{
179 if (*this == bmp) return (*this);
180 Ref( bmp );
181 return *this;
182}
183
184bool wxBitmap::operator == ( const wxBitmap& bmp )
185{
186 return m_refData == bmp.m_refData;
187}
188
189bool wxBitmap::operator != ( const wxBitmap& bmp )
190{
191 return m_refData != bmp.m_refData;
192}
193
194bool wxBitmap::Ok(void) const
195{
196 return (m_refData != NULL);
197}
198
199int wxBitmap::GetHeight(void) const
200{
201 if (!Ok())
202 {
203 wxFAIL_MSG( "invalid bitmap" );
204 return -1;
205 }
206
207 return M_BMPDATA->m_height;
208}
209
210int wxBitmap::GetWidth(void) const
211{
212 if (!Ok())
213 {
214 wxFAIL_MSG( "invalid bitmap" );
215 return -1;
216 }
217
218 return M_BMPDATA->m_width;
219}
220
221int wxBitmap::GetDepth(void) const
222{
223 if (!Ok())
224 {
225 wxFAIL_MSG( "invalid bitmap" );
226 return -1;
227 }
228
229 return M_BMPDATA->m_bpp;
230}
231
232void wxBitmap::SetHeight( int height )
233{
234 if (!Ok()) return;
235
236 wxFAIL_MSG( "wxBitmap::SetHeight not implemented" );
237
238 M_BMPDATA->m_height = height;
239}
240
241void wxBitmap::SetWidth( int width )
242{
243 if (!Ok()) return;
244
245 wxFAIL_MSG( "wxBitmap::SetWidth not implemented" );
246
247 M_BMPDATA->m_width = width;
248}
249
250void wxBitmap::SetDepth( int depth )
251{
252 if (!Ok()) return;
253
254 wxFAIL_MSG( "wxBitmap::SetDepth not implemented" );
255
256 M_BMPDATA->m_bpp = depth;
257}
258
259wxMask *wxBitmap::GetMask(void) const
260{
261 if (!Ok())
262 {
263 wxFAIL_MSG( "invalid bitmap" );
264 return (wxMask *) NULL;
265 }
266
267 return M_BMPDATA->m_mask;
268}
269
270void wxBitmap::SetMask( wxMask *mask )
271{
272 if (!Ok())
273 {
274 wxFAIL_MSG( "invalid bitmap" );
275 return;
276 }
277
278 if (M_BMPDATA->m_mask) delete M_BMPDATA->m_mask;
279
280 M_BMPDATA->m_mask = mask;
281}
282
283bool wxBitmap::SaveFile( const wxString &WXUNUSED(name), int WXUNUSED(type),
284 wxPalette *WXUNUSED(palette) )
285{
286 if (!Ok())
287 {
288 wxFAIL_MSG( "invalid bitmap" );
289 return FALSE;
290 }
291
292 return FALSE;
293}
294
295bool wxBitmap::LoadFile( const wxString &WXUNUSED(name), int WXUNUSED(type) )
296{
297 if (!Ok())
298 {
299 wxFAIL_MSG( "invalid bitmap" );
300 return FALSE;
301 }
302
303 return FALSE;
304}
305
306wxPalette *wxBitmap::GetPalette(void) const
307{
308 if (!Ok()) return (wxPalette *) NULL;
309 return M_BMPDATA->m_palette;
310}
311
312GdkPixmap *wxBitmap::GetPixmap(void) const
313{
314 if (!Ok())
315 {
316 wxFAIL_MSG( "invalid bitmap" );
317 return (GdkPixmap *) NULL;
318 }
319
320 return M_BMPDATA->m_pixmap;
321}
322
323GdkBitmap *wxBitmap::GetBitmap(void) const
324{
325 if (!Ok())
326 {
327 wxFAIL_MSG( "invalid bitmap" );
328 return (GdkBitmap *) NULL;
329 }
330
331 return M_BMPDATA->m_bitmap;
332}
333
334wxBitmap::wxBitmap( const wxImage &image )
335{
336 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
337
338 if (!image.Ok()) return;
339
340 m_refData = new wxBitmapRefData();
341
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
348
349 GdkImage *data_image =
350 gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
351
352 M_BMPDATA->m_pixmap =
353 gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 );
354
355 // Create mask
356
357 GdkImage *mask_image = (GdkImage*) NULL;
358
359 if (image.HasMask())
360 {
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 );
367 }
368
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
450
451 GdkGC *data_gc = gdk_gc_new( M_BMPDATA->m_pixmap );
452
453 gdk_draw_image( M_BMPDATA->m_pixmap, data_gc, data_image, 0, 0, 0, 0, width, height );
454
455 gdk_image_destroy( data_image );
456 gdk_gc_unref( data_gc );
457
458 // Blit mask
459
460 if (image.HasMask())
461 {
462 GdkGC *mask_gc = gdk_gc_new( M_BMPDATA->m_mask->m_bitmap );
463
464 gdk_draw_image( M_BMPDATA->m_mask->m_bitmap, mask_gc, mask_image, 0, 0, 0, 0, width, height );
465
466 gdk_image_destroy( mask_image );
467 gdk_gc_unref( mask_gc );
468 }
469
470}
471
472wxImage wxBitmap::ConvertToImage() const
473{
474 wxImage image;
475
476 if (!Ok())
477 {
478 wxFAIL_MSG( "invalid bitmap" );
479 return image;
480 }
481
482 GdkImage *gdk_image = gdk_image_get( M_BMPDATA->m_pixmap, 0, 0, M_BMPDATA->m_width, M_BMPDATA->m_height );
483
484 if (!gdk_image) return image;
485
486 image.Create( M_BMPDATA->m_width, M_BMPDATA->m_height );
487 char unsigned *data = image.GetData();
488
489 int bpp = gdk_image->bpp;
490 GdkColormap *cmap = gtk_widget_get_default_colormap();
491
492 long pos = 0;
493 for (int j = 0; j < M_BMPDATA->m_height; j++)
494 {
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 }
522 }
523
524 gdk_image_destroy( gdk_image );
525
526 return image;
527}
528
529
530