]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk/bitmap.cpp
a fix for the last fix
[wxWidgets.git] / src / gtk / 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
20#include <gdk/gdk.h>
21#include <gtk/gtk.h>
22
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
33//-----------------------------------------------------------------------------
34// data
35//-----------------------------------------------------------------------------
36
37extern GtkWidget *wxRootWindow;
38
39//-----------------------------------------------------------------------------
40// wxMask
41//-----------------------------------------------------------------------------
42
43IMPLEMENT_DYNAMIC_CLASS(wxMask,wxObject)
44
45wxMask::wxMask()
46{
47 m_bitmap = (GdkBitmap *) NULL;
48}
49
50wxMask::wxMask( const wxBitmap& bitmap, const wxColour& colour )
51{
52 m_bitmap = (GdkBitmap *) NULL;
53 Create( bitmap, colour );
54}
55
56wxMask::wxMask( const wxBitmap& bitmap, int paletteIndex )
57{
58 m_bitmap = (GdkBitmap *) NULL;
59 Create( bitmap, paletteIndex );
60}
61
62wxMask::wxMask( const wxBitmap& bitmap )
63{
64 m_bitmap = (GdkBitmap *) NULL;
65 Create( bitmap );
66}
67
68wxMask::~wxMask()
69{
70 if (m_bitmap)
71 gdk_bitmap_unref( m_bitmap );
72}
73
74bool wxMask::Create( const wxBitmap& bitmap,
75 const wxColour& colour )
76{
77 if (m_bitmap)
78 {
79 gdk_bitmap_unref( m_bitmap );
80 m_bitmap = (GdkBitmap*) NULL;
81 }
82
83 wxImage image( bitmap );
84 if (!image.Ok()) return FALSE;
85
86 m_bitmap = gdk_pixmap_new( wxRootWindow->window, image.GetWidth(), image.GetHeight(), 1 );
87 GdkGC *gc = gdk_gc_new( m_bitmap );
88
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() );
97
98 unsigned char *data = image.GetData();
99 int index = 0;
100
101 unsigned char red = colour.Red();
102 unsigned char green = colour.Green();
103 unsigned char blue = colour.Blue();
104
105 GdkVisual *visual = gdk_window_get_visual( wxRootWindow->window );
106 wxASSERT( visual );
107
108 int bpp = visual->depth;
109 if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
110 if (bpp == 15)
111 {
112 red = red & 0xf8;
113 green = green & 0xf8;
114 blue = blue & 0xf8;
115 }
116 if (bpp == 16)
117 {
118 red = red & 0xf8;
119 green = green & 0xfc;
120 blue = blue & 0xf8;
121 }
122
123 color.red = 0;
124 color.green = 0;
125 color.blue = 0;
126 color.pixel = 0;
127 gdk_gc_set_foreground( gc, &color );
128
129 for (int j = 0; j < image.GetHeight(); j++)
130 {
131 int start_x = -1;
132 int i;
133 for (i = 0; i < image.GetWidth(); i++)
134 {
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 }
149 }
150 index += 3;
151 }
152 if (start_x != -1)
153 gdk_draw_line( m_bitmap, gc, start_x, j, i, j );
154 }
155
156 gdk_gc_unref( gc );
157
158 return TRUE;
159}
160
161bool wxMask::Create( const wxBitmap& WXUNUSED(bitmap),
162 int WXUNUSED(paletteIndex) )
163{
164 if (m_bitmap)
165 {
166 gdk_bitmap_unref( m_bitmap );
167 m_bitmap = (GdkBitmap*) NULL;
168 }
169
170 wxFAIL_MSG( wxT("not implemented") );
171
172 return FALSE;
173}
174
175bool wxMask::Create( const wxBitmap& bitmap )
176{
177 if (m_bitmap)
178 {
179 gdk_bitmap_unref( m_bitmap );
180 m_bitmap = (GdkBitmap*) NULL;
181 }
182
183 if (!bitmap.Ok()) return FALSE;
184
185 wxCHECK_MSG( bitmap.GetBitmap(), FALSE, wxT("Cannot create mask from colour bitmap") );
186
187 m_bitmap = gdk_pixmap_new( wxRootWindow->window, bitmap.GetWidth(), bitmap.GetHeight(), 1 );
188
189 if (!m_bitmap) return FALSE;
190
191 GdkGC *gc = gdk_gc_new( m_bitmap );
192
193 gdk_wx_draw_bitmap( m_bitmap, gc, bitmap.GetBitmap(), 0, 0, 0, 0, bitmap.GetWidth(), bitmap.GetHeight() );
194
195 gdk_gc_unref( gc );
196
197 return TRUE;
198}
199
200GdkBitmap *wxMask::GetBitmap() const
201{
202 return m_bitmap;
203}
204
205//-----------------------------------------------------------------------------
206// wxBitmap
207//-----------------------------------------------------------------------------
208
209class wxBitmapRefData: public wxObjectRefData
210{
211public:
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;
222};
223
224wxBitmapRefData::wxBitmapRefData()
225{
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;
233}
234
235wxBitmapRefData::~wxBitmapRefData()
236{
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;
241}
242
243//-----------------------------------------------------------------------------
244
245#define M_BMPDATA ((wxBitmapRefData *)m_refData)
246
247IMPLEMENT_DYNAMIC_CLASS(wxBitmap,wxGDIObject)
248
249wxBitmap::wxBitmap()
250{
251 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
252}
253
254wxBitmap::wxBitmap( int width, int height, int depth )
255{
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") )
266
267 GdkVisual *visual = gdk_window_get_visual( wxRootWindow->window );
268 wxASSERT( visual );
269
270 if (depth == -1) depth = visual->depth;
271
272 wxCHECK_MSG( (depth == visual->depth) ||
273 (depth == 1), FALSE, wxT("invalid bitmap depth") )
274
275 m_refData = new wxBitmapRefData();
276 M_BMPDATA->m_mask = (wxMask *) NULL;
277 M_BMPDATA->m_width = width;
278 M_BMPDATA->m_height = height;
279 if (depth == 1)
280 {
281 M_BMPDATA->m_bitmap = gdk_pixmap_new( wxRootWindow->window, width, height, 1 );
282 M_BMPDATA->m_bpp = 1;
283 }
284 else
285 {
286 M_BMPDATA->m_pixmap = gdk_pixmap_new( wxRootWindow->window, width, height, depth );
287 M_BMPDATA->m_bpp = visual->depth;
288 }
289
290 return Ok();
291}
292bool wxBitmap::CreateFromXpm( const char **bits )
293{
294 wxCHECK_MSG( bits != NULL, FALSE, wxT("invalid bitmap data") )
295
296 GdkVisual *visual = gdk_window_get_visual( wxRootWindow->window );
297 wxASSERT( visual );
298
299 m_refData = new wxBitmapRefData();
300
301 GdkBitmap *mask = (GdkBitmap*) NULL;
302
303 M_BMPDATA->m_pixmap = gdk_pixmap_create_from_xpm_d( wxRootWindow->window, &mask, NULL, (gchar **) bits );
304
305 wxCHECK_MSG( M_BMPDATA->m_pixmap, FALSE, wxT("couldn't create pixmap") );
306
307 if (mask)
308 {
309 M_BMPDATA->m_mask = new wxMask();
310 M_BMPDATA->m_mask->m_bitmap = mask;
311 }
312
313 gdk_window_get_size( M_BMPDATA->m_pixmap, &(M_BMPDATA->m_width), &(M_BMPDATA->m_height) );
314
315 M_BMPDATA->m_bpp = visual->depth; // ?
316
317 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
318
319 return TRUE;
320}
321
322wxBitmap::wxBitmap( const wxBitmap& bmp )
323{
324 Ref( bmp );
325
326 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
327}
328
329wxBitmap::wxBitmap( const wxString &filename, int type )
330{
331 LoadFile( filename, type );
332
333 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
334}
335
336wxBitmap::wxBitmap( const char bits[], int width, int height, int WXUNUSED(depth))
337{
338 m_refData = new wxBitmapRefData();
339
340 M_BMPDATA->m_mask = (wxMask *) NULL;
341 M_BMPDATA->m_bitmap =
342 gdk_bitmap_create_from_data( wxRootWindow->window, (gchar *) bits, width, height );
343 M_BMPDATA->m_width = width;
344 M_BMPDATA->m_height = height;
345 M_BMPDATA->m_bpp = 1;
346
347 wxCHECK_RET( M_BMPDATA->m_bitmap, wxT("couldn't create bitmap") );
348
349 if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this);
350}
351
352wxBitmap::~wxBitmap()
353{
354 if (wxTheBitmapList) wxTheBitmapList->DeleteObject(this);
355}
356
357wxBitmap& wxBitmap::operator = ( const wxBitmap& bmp )
358{
359 if (*this == bmp) return (*this);
360 Ref( bmp );
361 return *this;
362}
363
364bool wxBitmap::operator == ( const wxBitmap& bmp ) const
365{
366 return m_refData == bmp.m_refData;
367}
368
369bool wxBitmap::operator != ( const wxBitmap& bmp ) const
370{
371 return m_refData != bmp.m_refData;
372}
373
374bool wxBitmap::Ok() const
375{
376 return (m_refData != NULL);
377}
378
379int wxBitmap::GetHeight() const
380{
381 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
382
383 return M_BMPDATA->m_height;
384}
385
386int wxBitmap::GetWidth() const
387{
388 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
389
390 return M_BMPDATA->m_width;
391}
392
393int wxBitmap::GetDepth() const
394{
395 wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
396
397 return M_BMPDATA->m_bpp;
398}
399
400wxMask *wxBitmap::GetMask() const
401{
402 wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") );
403
404 return M_BMPDATA->m_mask;
405}
406
407void wxBitmap::SetMask( wxMask *mask )
408{
409 wxCHECK_RET( Ok(), wxT("invalid bitmap") );
410
411 if (M_BMPDATA->m_mask) delete M_BMPDATA->m_mask;
412
413 M_BMPDATA->m_mask = mask;
414}
415
416wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
417{
418 wxCHECK_MSG( Ok() &&
419 (rect.x >= 0) && (rect.y >= 0) &&
420 (rect.x+rect.width <= M_BMPDATA->m_width) && (rect.y+rect.height <= M_BMPDATA->m_height),
421 wxNullBitmap, wxT("invalid bitmap or bitmap region") );
422
423 wxBitmap ret( rect.width, rect.height, M_BMPDATA->m_bpp );
424 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
425
426 if (ret.GetPixmap())
427 {
428 GdkGC *gc = gdk_gc_new( ret.GetPixmap() );
429 gdk_draw_pixmap( ret.GetPixmap(), gc, GetPixmap(), rect.x, rect.y, 0, 0, rect.width, rect.height );
430 gdk_gc_destroy( gc );
431 }
432 else
433 {
434 GdkGC *gc = gdk_gc_new( ret.GetBitmap() );
435 gdk_wx_draw_bitmap( ret.GetBitmap(), gc, GetBitmap(), rect.x, rect.y, 0, 0, rect.width, rect.height );
436 gdk_gc_destroy( gc );
437 }
438
439 if (GetMask())
440 {
441 wxMask *mask = new wxMask;
442 mask->m_bitmap = gdk_pixmap_new( wxRootWindow->window, rect.width, rect.height, 1 );
443
444 GdkGC *gc = gdk_gc_new( mask->m_bitmap );
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 );
446 gdk_gc_destroy( gc );
447
448 ret.SetMask( mask );
449 }
450
451 return ret;
452}
453
454bool wxBitmap::SaveFile( const wxString &name, int type, wxPalette *WXUNUSED(palette) )
455{
456 wxCHECK_MSG( Ok(), FALSE, wxT("invalid bitmap") );
457
458 // Try to save the bitmap via wxImage handlers:
459 {
460 wxImage image( *this );
461 if (image.Ok()) return image.SaveFile( name, type );
462 }
463
464 return FALSE;
465}
466
467bool wxBitmap::LoadFile( const wxString &name, int type )
468{
469 UnRef();
470
471 if (!wxFileExists(name)) return FALSE;
472
473 GdkVisual *visual = gdk_window_get_visual( wxRootWindow->window );
474 wxASSERT( visual );
475
476 if (type == wxBITMAP_TYPE_XPM)
477 {
478 m_refData = new wxBitmapRefData();
479
480 GdkBitmap *mask = (GdkBitmap*) NULL;
481
482 M_BMPDATA->m_pixmap = gdk_pixmap_create_from_xpm( wxRootWindow->window, &mask, NULL, name.fn_str() );
483
484 if (mask)
485 {
486 M_BMPDATA->m_mask = new wxMask();
487 M_BMPDATA->m_mask->m_bitmap = mask;
488 }
489
490 gdk_window_get_size( M_BMPDATA->m_pixmap, &(M_BMPDATA->m_width), &(M_BMPDATA->m_height) );
491
492 M_BMPDATA->m_bpp = visual->depth;
493 }
494 else // try if wxImage can load it
495 {
496 wxImage image;
497 if (!image.LoadFile( name, type )) return FALSE;
498 if (image.Ok()) *this = image.ConvertToBitmap();
499 else return FALSE;
500 }
501
502 return TRUE;
503}
504
505wxPalette *wxBitmap::GetPalette() const
506{
507 if (!Ok()) return (wxPalette *) NULL;
508
509 return M_BMPDATA->m_palette;
510}
511
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
540void wxBitmap::SetBitmap( GdkPixmap *bitmap )
541{
542 if (!m_refData) m_refData = new wxBitmapRefData();
543
544 M_BMPDATA->m_bitmap = bitmap;
545}
546
547GdkPixmap *wxBitmap::GetPixmap() const
548{
549 wxCHECK_MSG( Ok(), (GdkPixmap *) NULL, wxT("invalid bitmap") );
550
551 return M_BMPDATA->m_pixmap;
552}
553
554GdkBitmap *wxBitmap::GetBitmap() const
555{
556 wxCHECK_MSG( Ok(), (GdkBitmap *) NULL, wxT("invalid bitmap") );
557
558 return M_BMPDATA->m_bitmap;
559}