]> git.saurik.com Git - wxWidgets.git/blame - src/motif/bitmap.cpp
Split wxCanvas into two (wxVectorCanvas).
[wxWidgets.git] / src / motif / bitmap.cpp
CommitLineData
4bb6408c
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: bitmap.cpp
3// Purpose: wxBitmap
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "bitmap.h"
14#endif
15
bcd055ae
JJ
16#ifdef __VMS
17#define XtParent XTPARENT
18#endif
19
4bb6408c
JS
20#include "wx/setup.h"
21#include "wx/utils.h"
22#include "wx/palette.h"
23#include "wx/bitmap.h"
24#include "wx/icon.h"
25#include "wx/log.h"
a4294b78 26#include "wx/control.h"
321db4b6 27#include "wx/dcmemory.h"
b75dd496 28#include "wx/image.h"
4bb6408c 29
338dd992
JJ
30#ifdef __VMS__
31#pragma message disable nosimpint
32#endif
f97c9854 33#include <Xm/Xm.h>
338dd992
JJ
34#ifdef __VMS__
35#pragma message enable nosimpint
36#endif
f97c9854
JS
37
38#include "wx/motif/private.h"
39
31528cd3
VZ
40#if wxHAVE_LIB_XPM
41 #include <X11/xpm.h>
f97c9854
JS
42#endif
43
e838cc14
VZ
44IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
45IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
4bb6408c
JS
46
47wxBitmapRefData::wxBitmapRefData()
48{
49 m_ok = FALSE;
50 m_width = 0;
51 m_height = 0;
52 m_depth = 0;
53 m_quality = 0;
54 m_numColors = 0;
55 m_bitmapMask = NULL;
31528cd3 56
16c1f7f3
JS
57 m_pixmap = (WXPixmap) 0;
58 m_display = (WXDisplay*) 0;
31528cd3 59
f97c9854
JS
60 m_freePixmap = TRUE; //TODO: necessary?
61 m_freeColors = (unsigned long*) 0;
62 m_freeColorsCount = 0;
31528cd3 63
f97c9854
JS
64 // These 5 variables are for wxControl
65 m_insensPixmap = (WXPixmap) 0;
66 m_labelPixmap = (WXPixmap) 0;
67 m_armPixmap = (WXPixmap) 0;
68 m_image = (WXImage*) 0;
69 m_insensImage = (WXImage*) 0;
4bb6408c
JS
70}
71
72wxBitmapRefData::~wxBitmapRefData()
73{
f97c9854
JS
74 if (m_labelPixmap)
75 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_labelPixmap);
31528cd3 76
f97c9854
JS
77 if (m_armPixmap)
78 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_armPixmap);
31528cd3 79
f97c9854
JS
80 if (m_insensPixmap)
81 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_insensPixmap);
31528cd3 82
f97c9854
JS
83 if (m_image)
84 {
85 XmUninstallImage ((XImage*) m_image);
86 XtFree ((char *) (XImage*) m_image);
87 }
31528cd3 88
f97c9854
JS
89 if (m_insensImage)
90 {
91 XmUninstallImage ((XImage*) m_insensImage);
92 delete[] ((XImage*) m_insensImage)->data;
93 XtFree ((char *) (XImage*) m_insensImage);
94 }
95 if (m_pixmap && m_freePixmap)
96 XFreePixmap ((Display*) m_display, (Pixmap) m_pixmap);
31528cd3 97
f97c9854
JS
98 if (m_freeColors)
99 {
2d120f83
JS
100 int screen = DefaultScreen((Display*) m_display);
101 Colormap cmp = DefaultColormap((Display*) m_display,screen);
102 long llp;
103 for(llp = 0;llp < m_freeColorsCount;llp++)
104 XFreeColors((Display*) m_display, cmp, &m_freeColors[llp], 1, 0L);
105 delete m_freeColors;
f97c9854 106 };
31528cd3 107
4bb6408c
JS
108 if (m_bitmapMask)
109 delete m_bitmapMask;
110 m_bitmapMask = NULL;
111}
112
113wxList wxBitmap::sm_handlers;
114
1696c178
JJ
115#define M_BMPDATA ((wxBitmapRefData *)m_refData)
116
4bb6408c
JS
117wxBitmap::wxBitmap()
118{
119 m_refData = NULL;
31528cd3 120
4bb6408c
JS
121 if ( wxTheBitmapList )
122 wxTheBitmapList->AddBitmap(this);
123}
124
125wxBitmap::~wxBitmap()
126{
127 if (wxTheBitmapList)
128 wxTheBitmapList->DeleteObject(this);
129}
130
f97c9854 131wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
4bb6408c
JS
132{
133 m_refData = new wxBitmapRefData;
31528cd3 134
f97c9854 135 (void) Create((void*) bits, wxBITMAP_TYPE_XBM_DATA, width, height, depth);
31528cd3 136
4bb6408c
JS
137 if ( wxTheBitmapList )
138 wxTheBitmapList->AddBitmap(this);
139}
140
141wxBitmap::wxBitmap(int w, int h, int d)
142{
143 (void)Create(w, h, d);
31528cd3 144
4bb6408c
JS
145 if ( wxTheBitmapList )
146 wxTheBitmapList->AddBitmap(this);
147}
148
149wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth)
150{
151 (void) Create(data, type, width, height, depth);
31528cd3 152
4bb6408c
JS
153 if ( wxTheBitmapList )
154 wxTheBitmapList->AddBitmap(this);
155}
156
157wxBitmap::wxBitmap(const wxString& filename, long type)
158{
159 LoadFile(filename, (int)type);
31528cd3 160
4bb6408c
JS
161 if ( wxTheBitmapList )
162 wxTheBitmapList->AddBitmap(this);
163}
164
f97c9854
JS
165// Create from XPM data
166static wxControl* sg_Control = NULL;
a4294b78 167wxBitmap::wxBitmap(char **data, wxControl* control)
4bb6408c 168{
f97c9854
JS
169 // Pass the control to the Create function using a global
170 sg_Control = control;
31528cd3 171
4bb6408c 172 (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
31528cd3 173
f97c9854 174 sg_Control = (wxControl*) NULL;
4bb6408c 175}
4bb6408c 176
e838cc14
VZ
177bool wxBitmap::CreateFromXpm(const char **bits)
178{
179 wxCHECK_MSG( bits, FALSE, _T("NULL pointer in wxBitmap::CreateFromXpm") );
180
181 return Create(bits, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
182}
183
4bb6408c
JS
184bool wxBitmap::Create(int w, int h, int d)
185{
186 UnRef();
31528cd3 187
4bb6408c 188 m_refData = new wxBitmapRefData;
31528cd3 189
f97c9854 190 if (d < 1)
2d120f83 191 d = wxDisplayDepth();
31528cd3 192
4bb6408c
JS
193 M_BITMAPDATA->m_width = w;
194 M_BITMAPDATA->m_height = h;
195 M_BITMAPDATA->m_depth = d;
f97c9854 196 M_BITMAPDATA->m_freePixmap = TRUE;
31528cd3 197
f97c9854 198 Display *dpy = (Display*) wxGetDisplay();
31528cd3 199
f97c9854 200 M_BITMAPDATA->m_display = dpy; /* MATTHEW: [4] Remember the display */
31528cd3 201
f97c9854 202 M_BITMAPDATA->m_pixmap = (WXPixmap) XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)),
2d120f83 203 w, h, d);
31528cd3 204
f97c9854 205 M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_pixmap != (WXPixmap) 0) ;
4bb6408c
JS
206 return M_BITMAPDATA->m_ok;
207}
208
209bool wxBitmap::LoadFile(const wxString& filename, long type)
210{
211 UnRef();
31528cd3 212
4bb6408c 213 m_refData = new wxBitmapRefData;
31528cd3 214
4bb6408c 215 wxBitmapHandler *handler = FindHandler(type);
31528cd3 216
4bb6408c 217 if ( handler == NULL ) {
b75dd496
VS
218 wxImage image;
219 if (!image.LoadFile( filename, type )) return FALSE;
220 if (image.Ok())
221 {
222 *this = image.ConvertToBitmap();
223 return TRUE;
224 }
225 else return FALSE;
4bb6408c 226 }
31528cd3 227
4bb6408c
JS
228 return handler->LoadFile(this, filename, type, -1, -1);
229}
230
231bool wxBitmap::Create(void *data, long type, int width, int height, int depth)
232{
233 UnRef();
31528cd3 234
4bb6408c 235 m_refData = new wxBitmapRefData;
31528cd3 236
4bb6408c 237 wxBitmapHandler *handler = FindHandler(type);
31528cd3 238
4bb6408c 239 if ( handler == NULL ) {
7bcb11d3 240 wxLogWarning("no data bitmap handler for type %d defined.", type);
31528cd3 241
4bb6408c
JS
242 return FALSE;
243 }
31528cd3 244
4bb6408c
JS
245 return handler->Create(this, data, type, width, height, depth);
246}
247
248bool wxBitmap::SaveFile(const wxString& filename, int type, const wxPalette *palette)
249{
250 wxBitmapHandler *handler = FindHandler(type);
31528cd3 251
b75dd496
VS
252 if ( handler == NULL ) { // try wxImage
253 wxImage image( *this );
254 if (image.Ok()) return image.SaveFile( filename, type );
255 else return FALSE;
2d120f83 256 }
31528cd3 257
2d120f83 258 return handler->SaveFile(this, filename, type, palette);
4bb6408c
JS
259}
260
261void wxBitmap::SetWidth(int w)
262{
263 if (!M_BITMAPDATA)
264 m_refData = new wxBitmapRefData;
31528cd3 265
4bb6408c
JS
266 M_BITMAPDATA->m_width = w;
267}
268
269void wxBitmap::SetHeight(int h)
270{
271 if (!M_BITMAPDATA)
272 m_refData = new wxBitmapRefData;
31528cd3 273
4bb6408c
JS
274 M_BITMAPDATA->m_height = h;
275}
276
277void wxBitmap::SetDepth(int d)
278{
279 if (!M_BITMAPDATA)
280 m_refData = new wxBitmapRefData;
31528cd3 281
4bb6408c
JS
282 M_BITMAPDATA->m_depth = d;
283}
284
285void wxBitmap::SetQuality(int q)
286{
287 if (!M_BITMAPDATA)
288 m_refData = new wxBitmapRefData;
31528cd3 289
4bb6408c
JS
290 M_BITMAPDATA->m_quality = q;
291}
292
293void wxBitmap::SetOk(bool isOk)
294{
295 if (!M_BITMAPDATA)
296 m_refData = new wxBitmapRefData;
31528cd3 297
4bb6408c
JS
298 M_BITMAPDATA->m_ok = isOk;
299}
300
301void wxBitmap::SetPalette(const wxPalette& palette)
302{
303 if (!M_BITMAPDATA)
304 m_refData = new wxBitmapRefData;
31528cd3 305
4bb6408c
JS
306 M_BITMAPDATA->m_bitmapPalette = palette ;
307}
308
309void wxBitmap::SetMask(wxMask *mask)
310{
311 if (!M_BITMAPDATA)
312 m_refData = new wxBitmapRefData;
31528cd3 313
4bb6408c
JS
314 M_BITMAPDATA->m_bitmapMask = mask ;
315}
316
1696c178
JJ
317wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
318{
319 wxCHECK_MSG( Ok() &&
320 (rect.x >= 0) && (rect.y >= 0) &&
321 (rect.x+rect.width <= M_BMPDATA->m_width) && (rect.y+rect.height <= M_BMPDATA->m_height),
322 wxNullBitmap, wxT("invalid bitmap or bitmap region") );
323
324 wxBitmap ret( rect.width, rect.height, 0 );
325 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
326
327 // The remaining still TODO
328 return ret;
329}
330
4bb6408c
JS
331void wxBitmap::AddHandler(wxBitmapHandler *handler)
332{
333 sm_handlers.Append(handler);
334}
335
336void wxBitmap::InsertHandler(wxBitmapHandler *handler)
337{
338 sm_handlers.Insert(handler);
339}
340
341bool wxBitmap::RemoveHandler(const wxString& name)
342{
343 wxBitmapHandler *handler = FindHandler(name);
344 if ( handler )
345 {
346 sm_handlers.DeleteObject(handler);
347 return TRUE;
348 }
349 else
350 return FALSE;
351}
352
353wxBitmapHandler *wxBitmap::FindHandler(const wxString& name)
354{
355 wxNode *node = sm_handlers.First();
356 while ( node )
357 {
358 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
359 if ( handler->GetName() == name )
360 return handler;
361 node = node->Next();
362 }
363 return NULL;
364}
365
366wxBitmapHandler *wxBitmap::FindHandler(const wxString& extension, long bitmapType)
367{
368 wxNode *node = sm_handlers.First();
369 while ( node )
370 {
371 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
372 if ( handler->GetExtension() == extension &&
2d120f83 373 (bitmapType == -1 || handler->GetType() == bitmapType) )
4bb6408c
JS
374 return handler;
375 node = node->Next();
376 }
377 return NULL;
378}
379
380wxBitmapHandler *wxBitmap::FindHandler(long bitmapType)
381{
382 wxNode *node = sm_handlers.First();
383 while ( node )
384 {
385 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
386 if (handler->GetType() == bitmapType)
387 return handler;
388 node = node->Next();
389 }
390 return NULL;
391}
392
393/*
2d120f83
JS
394* wxMask
395*/
4bb6408c
JS
396
397wxMask::wxMask()
398{
16c1f7f3 399 m_pixmap = (WXPixmap) 0;
4bb6408c
JS
400}
401
402// Construct a mask from a bitmap and a colour indicating
403// the transparent area
404wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
405{
16c1f7f3 406 m_pixmap = (WXPixmap) 0;
31528cd3 407
4bb6408c
JS
408 Create(bitmap, colour);
409}
410
411// Construct a mask from a bitmap and a palette index indicating
412// the transparent area
413wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
414{
16c1f7f3 415 m_pixmap = (WXPixmap) 0;
31528cd3 416
4bb6408c
JS
417 Create(bitmap, paletteIndex);
418}
419
420// Construct a mask from a mono bitmap (copies the bitmap).
421wxMask::wxMask(const wxBitmap& bitmap)
422{
16c1f7f3 423 m_pixmap = (WXPixmap) 0;
31528cd3 424
4bb6408c
JS
425 Create(bitmap);
426}
427
428wxMask::~wxMask()
429{
f97c9854
JS
430 // TODO: this may be the wrong display
431 if ( m_pixmap )
432 XFreePixmap ((Display*) wxGetDisplay(), (Pixmap) m_pixmap);
4bb6408c
JS
433}
434
435// Create a mask from a mono bitmap (copies the bitmap).
f9e02ac7 436bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap))
4bb6408c 437{
2d120f83 438 // TODO
4bb6408c
JS
439 return FALSE;
440}
441
442// Create a mask from a bitmap and a palette index indicating
443// the transparent area
f9e02ac7 444bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap), int WXUNUSED(paletteIndex))
4bb6408c 445{
2d120f83 446 // TODO
4bb6408c
JS
447 return FALSE;
448}
449
450// Create a mask from a bitmap and a colour indicating
451// the transparent area
f9e02ac7 452bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap), const wxColour& WXUNUSED(colour))
4bb6408c 453{
2d120f83 454 // TODO
4bb6408c
JS
455 return FALSE;
456}
457
458/*
2d120f83
JS
459* wxBitmapHandler
460*/
4bb6408c
JS
461
462IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
463
31528cd3 464bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap), void *WXUNUSED(data), long WXUNUSED(type),
2d120f83 465 int WXUNUSED(width), int WXUNUSED(height), int WXUNUSED(depth))
4bb6408c
JS
466{
467 return FALSE;
468}
469
f9e02ac7 470bool wxBitmapHandler::LoadFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), long WXUNUSED(type),
2d120f83 471 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight))
4bb6408c
JS
472{
473 return FALSE;
474}
475
31528cd3 476bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), int WXUNUSED(type),
2d120f83 477 const wxPalette *WXUNUSED(palette))
4bb6408c
JS
478{
479 return FALSE;
480}
481
482/*
2d120f83
JS
483* Standard handlers
484*/
4bb6408c 485
f97c9854 486class WXDLLEXPORT wxXBMFileHandler: public wxBitmapHandler
4bb6408c 487{
f97c9854 488 DECLARE_DYNAMIC_CLASS(wxXBMFileHandler)
4bb6408c 489public:
f97c9854 490 inline wxXBMFileHandler()
4bb6408c 491 {
f97c9854
JS
492 m_name = "XBM file";
493 m_extension = "xbm";
494 m_type = wxBITMAP_TYPE_XBM;
4bb6408c 495 };
31528cd3 496
4bb6408c 497 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
2d120f83 498 int desiredWidth, int desiredHeight);
4bb6408c 499};
f97c9854
JS
500IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler, wxBitmapHandler)
501
f9e02ac7 502bool wxXBMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags),
2d120f83 503 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight))
f97c9854
JS
504{
505 M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
31528cd3 506
f97c9854
JS
507 int hotX, hotY;
508 unsigned int w, h;
509 Pixmap pixmap;
31528cd3 510
f97c9854
JS
511 Display *dpy = (Display*) wxGetDisplay();
512 M_BITMAPDATA->m_display = (WXDisplay*) dpy;
31528cd3 513
f97c9854 514 int value = XReadBitmapFile (dpy, RootWindow (dpy, DefaultScreen (dpy)),
2d120f83 515 (char*) (const char*) name, &w, &h, &pixmap, &hotX, &hotY);
f97c9854
JS
516 M_BITMAPHANDLERDATA->m_width = w;
517 M_BITMAPHANDLERDATA->m_height = h;
518 M_BITMAPHANDLERDATA->m_depth = 1;
519 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap;
31528cd3 520
f97c9854
JS
521 if ((value == BitmapFileInvalid) ||
522 (value == BitmapOpenFailed) ||
523 (value == BitmapNoMemory))
524 {
525 M_BITMAPHANDLERDATA->m_ok = FALSE;
526 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) 0;
527 }
528 else
529 M_BITMAPHANDLERDATA->m_ok = TRUE;
31528cd3 530
f97c9854
JS
531 return M_BITMAPHANDLERDATA->m_ok ;
532}
533
534class WXDLLEXPORT wxXBMDataHandler: public wxBitmapHandler
535{
536 DECLARE_DYNAMIC_CLASS(wxXBMDataHandler)
537public:
538 inline wxXBMDataHandler()
539 {
540 m_name = "XBM data";
541 m_extension = "xbm";
542 m_type = wxBITMAP_TYPE_XBM_DATA;
543 };
31528cd3 544
f97c9854
JS
545 virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1);
546};
547IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler, wxBitmapHandler)
548
31528cd3 549bool wxXBMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags),
2d120f83 550 int width, int height, int WXUNUSED(depth))
f97c9854
JS
551{
552 M_BITMAPHANDLERDATA->m_width = width;
553 M_BITMAPHANDLERDATA->m_height = height;
554 M_BITMAPHANDLERDATA->m_depth = 1;
555 M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
31528cd3 556
f97c9854
JS
557 Display *dpy = (Display*) wxGetDisplay();
558 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
31528cd3 559
f97c9854
JS
560 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) XCreateBitmapFromData (dpy, RootWindow (dpy, DefaultScreen (dpy)), (char*) data, width, height);
561 M_BITMAPHANDLERDATA->m_ok = (M_BITMAPHANDLERDATA->m_pixmap != (WXPixmap) 0) ;
31528cd3 562
f97c9854
JS
563 // code for wxControl. TODO: can we avoid doing this until we need it?
564 // E.g. have CreateButtonPixmaps which is called on demand.
565 XImage* image = (XImage *) XtMalloc (sizeof (XImage));
566 image->width = width;
567 image->height = height;
568 image->data = (char*) data;
569 image->depth = 1;
570 image->xoffset = 0;
571 image->format = XYBitmap;
572 image->byte_order = LSBFirst;
573 image->bitmap_unit = 8;
574 image->bitmap_bit_order = LSBFirst;
575 image->bitmap_pad = 8;
576 image->bytes_per_line = (width + 7) >> 3;
31528cd3 577
f97c9854
JS
578 char tmp[128];
579 sprintf (tmp, "Im%x", (unsigned int) image);
580 XmInstallImage (image, tmp);
31528cd3 581
f97c9854 582 // Build our manually stipped pixmap.
31528cd3 583
f97c9854
JS
584 int bpl = (width + 7) / 8;
585 char *data1 = new char[height * bpl];
586 char* bits = (char*) data;
587 int i;
588 for (i = 0; i < height; i++)
589 {
590 int mask = i % 2 ? 0x55 : 0xaa;
591 int j;
592 for (j = 0; j < bpl; j++)
593 data1[i * bpl + j] = bits[i * bpl + j] & mask;
594 }
595 XImage* insensImage = (XImage *) XtMalloc (sizeof (XImage));
596 insensImage->width = width;
597 insensImage->height = height;
598 insensImage->data = data1;
599 insensImage->depth = 1;
600 insensImage->xoffset = 0;
601 insensImage->format = XYBitmap;
602 insensImage->byte_order = LSBFirst;
603 insensImage->bitmap_unit = 8;
604 insensImage->bitmap_bit_order = LSBFirst;
605 insensImage->bitmap_pad = 8;
606 insensImage->bytes_per_line = bpl;
31528cd3 607
f97c9854
JS
608 sprintf (tmp, "Not%x", (unsigned int)insensImage);
609 XmInstallImage (insensImage, tmp);
31528cd3 610
f97c9854
JS
611 M_BITMAPHANDLERDATA->m_image = (WXImage*) image;
612 M_BITMAPHANDLERDATA->m_insensImage = (WXImage*) insensImage;
31528cd3 613
f97c9854
JS
614 return TRUE;
615}
616
31528cd3 617#if wxHAVE_LIB_XPM
f97c9854
JS
618class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler
619{
620 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler)
621public:
622 inline wxXPMFileHandler()
623 {
624 m_name = "XPM file";
625 m_extension = "xpm";
626 m_type = wxBITMAP_TYPE_XPM;
627 };
31528cd3 628
f97c9854 629 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
2d120f83 630 int desiredWidth, int desiredHeight);
f97c9854
JS
631 virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
632};
633
634IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler)
635
f9e02ac7 636bool wxXPMFileHandler::LoadFile( wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags),
2d120f83 637 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight) )
f97c9854 638{
a4294b78 639 Display *dpy = (Display*) wxGetDisplay();
f97c9854 640 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
31528cd3 641
f97c9854
JS
642 XpmAttributes xpmAttr;
643 Pixmap pixmap;
644 Pixmap mask = 0;
31528cd3 645
f97c9854
JS
646 M_BITMAPHANDLERDATA->m_ok = FALSE;
647 xpmAttr.valuemask = XpmReturnInfos | XpmCloseness;
648 xpmAttr.closeness = 40000;
649 int errorStatus = XpmReadFileToPixmap(dpy,
650 RootWindow(dpy, DefaultScreen(dpy)), (char*) (const char*) name,
651 &pixmap, &mask, &xpmAttr);
31528cd3 652
f97c9854
JS
653 if (errorStatus == XpmSuccess)
654 {
655 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap;
656 if ( mask )
657 {
658 M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask;
659 M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask);
660 }
31528cd3 661
0d57be45
JS
662 unsigned int depthRet;
663 int xRet, yRet;
664 unsigned int widthRet, heightRet, borderWidthRet;
665 Window rootWindowRet;
666 XGetGeometry(dpy, pixmap, &rootWindowRet, &xRet, &yRet,
667 &widthRet, &heightRet, &borderWidthRet, &depthRet);
31528cd3 668
f97c9854
JS
669 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
670 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
31528cd3 671
2d120f83 672 /*
f97c9854
JS
673 if ( xpmAttr.npixels > 2 )
674 {
2d120f83 675 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
f97c9854
JS
676 } else
677 {
2d120f83 678 M_BITMAPHANDLERDATA->m_depth = 1; // mono
f97c9854 679 }
2d120f83 680 */
31528cd3 681
0d57be45 682 M_BITMAPHANDLERDATA->m_depth = depthRet;
31528cd3 683
2d120f83 684 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
31528cd3 685
2d120f83 686 XpmFreeAttributes(&xpmAttr);
31528cd3 687
f97c9854 688 M_BITMAPHANDLERDATA->m_ok = TRUE;
a4294b78 689 return TRUE;
f97c9854
JS
690 } else
691 {
2d120f83 692 // XpmDebugError(errorStatus, name);
f97c9854
JS
693 M_BITMAPHANDLERDATA->m_ok = FALSE;
694 return FALSE;
695 }
696}
697
31528cd3 698bool wxXPMFileHandler::SaveFile( wxBitmap *bitmap, const wxString& name, int WXUNUSED(type),
2d120f83 699 const wxPalette *WXUNUSED(palette))
f97c9854
JS
700{
701 if (M_BITMAPHANDLERDATA->m_ok && M_BITMAPHANDLERDATA->m_pixmap)
702 {
703 Display *dpy = (Display*) M_BITMAPHANDLERDATA->m_display;
704 int errorStatus = XpmWriteFileFromPixmap(dpy, (char*) (const char*) name,
2d120f83
JS
705 (Pixmap) M_BITMAPHANDLERDATA->m_pixmap,
706 (M_BITMAPHANDLERDATA->m_bitmapMask ? (Pixmap) M_BITMAPHANDLERDATA->m_bitmapMask->GetPixmap() : (Pixmap) 0),
707 (XpmAttributes *) NULL);
f97c9854 708 if (errorStatus == XpmSuccess)
2d120f83 709 return TRUE;
f97c9854 710 else
2d120f83 711 return FALSE;
f97c9854
JS
712 }
713 else
714 return FALSE;
715}
716
717class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler
718{
719 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
720public:
a4294b78 721 inline wxXPMDataHandler()
f97c9854
JS
722 {
723 m_name = "XPM data";
724 m_extension = "xpm";
725 m_type = wxBITMAP_TYPE_XPM_DATA;
726 };
31528cd3 727
f97c9854
JS
728 virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1);
729};
730IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
731
31528cd3 732bool wxXPMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags),
2d120f83 733 int width, int height, int WXUNUSED(depth))
f97c9854
JS
734{
735 M_BITMAPHANDLERDATA->m_width = width;
736 M_BITMAPHANDLERDATA->m_height = height;
737 M_BITMAPHANDLERDATA->m_depth = 1;
738 M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
31528cd3 739
a4294b78 740 Display *dpy = (Display*) wxGetDisplay();
f97c9854 741 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
31528cd3 742
f97c9854 743 XpmAttributes xpmAttr;
31528cd3 744
f97c9854 745 xpmAttr.valuemask = XpmReturnInfos; /* nothing yet, but get infos back */
31528cd3 746
f97c9854
JS
747 XpmColorSymbol symbolicColors[4];
748 if (sg_Control && sg_Control->GetMainWidget())
749 {
750 symbolicColors[0].name = "foreground";
751 symbolicColors[0].value = NULL;
752 symbolicColors[1].name = "background";
753 symbolicColors[1].value = NULL;
754 XtVaGetValues((Widget) sg_Control->GetMainWidget(),
755 XmNforeground, &symbolicColors[0].pixel,
756 XmNbackground, &symbolicColors[1].pixel,NULL);
757 xpmAttr.numsymbols = 2;
758 xpmAttr.colorsymbols = symbolicColors;
759 xpmAttr.valuemask |= XpmColorSymbols; // add flag
760 }
31528cd3 761
f97c9854
JS
762 Pixmap pixmap;
763 Pixmap mask = 0;
764 int ErrorStatus = XpmCreatePixmapFromData(dpy, RootWindow(dpy, DefaultScreen(dpy)),
2d120f83 765 (char**) data, &pixmap, &mask, &xpmAttr);
f97c9854
JS
766 if (ErrorStatus == XpmSuccess)
767 {
768 // Set attributes
769 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
770 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
31528cd3 771
0d57be45
JS
772 unsigned int depthRet;
773 int xRet, yRet;
774 unsigned int widthRet, heightRet, borderWidthRet;
775 Window rootWindowRet;
776 XGetGeometry(dpy, pixmap, &rootWindowRet, &xRet, &yRet,
777 &widthRet, &heightRet, &borderWidthRet, &depthRet);
31528cd3 778
2d120f83
JS
779 /*
780 if ( xpmAttr.npixels > 2 )
781 {
f97c9854 782 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
2d120f83
JS
783 } else
784 {
f97c9854 785 M_BITMAPHANDLERDATA->m_depth = 1; // mono
2d120f83
JS
786 }
787 */
31528cd3 788
0d57be45 789 M_BITMAPHANDLERDATA->m_depth = depthRet;
31528cd3 790
f97c9854
JS
791 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
792 XpmFreeAttributes(&xpmAttr);
793 M_BITMAPHANDLERDATA->m_ok = TRUE;
794 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap;
795 if ( mask )
796 {
797 M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask;
798 M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask);
799 }
800 }
801 else
802 {
2d120f83 803 // XpmDebugError(ErrorStatus, NULL);
f97c9854
JS
804 M_BITMAPHANDLERDATA->m_ok = FALSE;
805 }
806 return M_BITMAPHANDLERDATA->m_ok ;
807}
808
31528cd3 809#endif // wxHAVE_LIB_XPM
4bb6408c
JS
810
811void wxBitmap::CleanUpHandlers()
812{
813 wxNode *node = sm_handlers.First();
814 while ( node )
815 {
816 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
817 wxNode *next = node->Next();
818 delete handler;
819 delete node;
820 node = next;
821 }
822}
823
824void wxBitmap::InitStandardHandlers()
825{
f97c9854
JS
826 // Initialize all standard bitmap or derived class handlers here.
827 AddHandler(new wxXBMFileHandler);
828 AddHandler(new wxXBMDataHandler);
31528cd3
VZ
829
830 // XPM is considered standard for Motif, although it can be omitted if
831 // libXpm is not installed
832#if wxHAVE_LIB_XPM
4bb6408c
JS
833 AddHandler(new wxXPMFileHandler);
834 AddHandler(new wxXPMDataHandler);
31528cd3 835#endif // wxHAVE_LIB_XPM
f97c9854
JS
836}
837
838WXPixmap wxBitmap::GetLabelPixmap (WXWidget w)
839{
2d120f83
JS
840 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
841 return M_BITMAPDATA->m_pixmap;
31528cd3 842
2d120f83 843 Display *dpy = (Display*) M_BITMAPDATA->m_display;
31528cd3 844
f97c9854 845#ifdef FOO
2d120f83
JS
846 /*
847 If we do:
848 if (labelPixmap) return labelPixmap;
849 things can be wrong, because colors can have been changed.
31528cd3 850
2d120f83
JS
851 If we do:
852 if (labelPixmap)
853 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
854 we got BadDrawable if the pixmap is referenced by multiples widgets
31528cd3 855
2d120f83 856 this is a catch22!!
31528cd3 857
e838cc14
VZ
858 So, before doing thing really clean, I just do nothing; if the pixmap is
859 referenced by many widgets, Motif performs caching functions.
860 And if pixmap is referenced with multiples colors, we just have some
861 memory leaks... I hope we can deal with them...
2d120f83
JS
862 */
863 // Must be destroyed, because colours can have been changed!
864 if (M_BITMAPDATA->m_labelPixmap)
865 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_labelPixmap);
f97c9854 866#endif
31528cd3 867
2d120f83
JS
868 char tmp[128];
869 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
31528cd3 870
2d120f83
JS
871 Pixel fg, bg;
872 Widget widget = (Widget) w;
31528cd3 873
2d120f83
JS
874 while (XmIsGadget ( widget ))
875 widget = XtParent (widget);
876 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
31528cd3 877
2d120f83 878 M_BITMAPDATA->m_labelPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 879
2d120f83 880 return M_BITMAPDATA->m_labelPixmap;
f97c9854
JS
881}
882
883WXPixmap wxBitmap::GetArmPixmap (WXWidget w)
884{
2d120f83
JS
885 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
886 return M_BITMAPDATA->m_pixmap;
31528cd3 887
2d120f83 888 Display *dpy = (Display*) M_BITMAPDATA->m_display;
f97c9854 889#ifdef FOO
e838cc14
VZ
890 // See GetLabelPixmap () comment
891
892 // Must be destroyed, because colours can have been changed!
893 if (M_BITMAPDATA->m_armPixmap)
894 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_armPixmap);
f97c9854 895#endif
31528cd3 896
e838cc14
VZ
897 char tmp[128];
898 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
31528cd3 899
e838cc14
VZ
900 Pixel fg, bg;
901 Widget widget = (Widget) w;
31528cd3 902
e838cc14
VZ
903 XtVaGetValues (widget, XmNarmColor, &bg, NULL);
904 while (XmIsGadget (widget))
905 widget = XtParent (widget);
906 XtVaGetValues (widget, XmNforeground, &fg, NULL);
31528cd3 907
e838cc14 908 M_BITMAPDATA->m_armPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 909
e838cc14 910 return M_BITMAPDATA->m_armPixmap;
f97c9854
JS
911}
912
913WXPixmap wxBitmap::GetInsensPixmap (WXWidget w)
914{
2d120f83 915 Display *dpy = (Display*) M_BITMAPDATA->m_display;
31528cd3 916
0d57be45 917 if (M_BITMAPDATA->m_insensPixmap)
2d120f83 918 return M_BITMAPDATA->m_insensPixmap;
31528cd3 919
2d120f83
JS
920 if (!w)
921 {
922 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XCreateInsensitivePixmap(dpy, (Pixmap) M_BITMAPDATA->m_pixmap);
923 if (M_BITMAPDATA->m_insensPixmap)
924 return M_BITMAPDATA->m_insensPixmap;
925 else
926 return M_BITMAPDATA->m_pixmap;
927 }
31528cd3 928
2d120f83
JS
929 if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0)
930 return M_BITMAPDATA->m_pixmap;
31528cd3 931
f97c9854 932#ifdef FOO
2d120f83
JS
933 See GetLabelPixmap () comment
934 // Must be destroyed, because colours can have been changed!
935 if (M_BITMAPDATA->m_insensPixmap)
936 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), (Pixmap) M_BITMAPDATA->m_insensPixmap);
f97c9854 937#endif
31528cd3 938
e838cc14
VZ
939 char tmp[128];
940 sprintf (tmp, "Not%x", (unsigned int) M_BITMAPDATA->m_insensImage);
31528cd3 941
e838cc14
VZ
942 Pixel fg, bg;
943 Widget widget = (Widget) w;
31528cd3 944
e838cc14
VZ
945 while (XmIsGadget (widget))
946 widget = XtParent (widget);
947 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
31528cd3 948
e838cc14 949 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 950
e838cc14 951 return M_BITMAPDATA->m_insensPixmap;
f97c9854
JS
952}
953
954// We may need this sometime...
955
956/****************************************************************************
957
2d120f83
JS
958 NAME
959 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
31528cd3 960
e838cc14
VZ
961 SYNOPSIS
962 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
31528cd3 963
e838cc14
VZ
964 DESCRIPTION
965 This function creates a grayed-out copy of the argument pixmap, suitable
966 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
31528cd3 967
e838cc14
VZ
968 RETURN VALUES
969 The return value is the new Pixmap id or zero on error. Errors include
970 a NULL display argument or an invalid Pixmap argument.
31528cd3 971
e838cc14
VZ
972 ERRORS
973 If one of the XLib functions fail, it will produce a X error. The
974 default X error handler prints a diagnostic and calls exit().
31528cd3 975
e838cc14
VZ
976 SEE ALSO
977 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
978 XFillRectangle(3), exit(2)
31528cd3 979
e838cc14
VZ
980 AUTHOR
981 John R Veregge - john@puente.jpl.nasa.gov
982 Advanced Engineering and Prototyping Group (AEG)
983 Information Systems Technology Section (395)
984 Jet Propulsion Lab - Calif Institute of Technology
31528cd3 985
f97c9854
JS
986*****************************************************************************/
987
988Pixmap
989XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
990
991{
e838cc14
VZ
992 static char stipple_data[] =
993 {
994 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
f97c9854
JS
995 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
996 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
997 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA
e838cc14 998 };
f97c9854
JS
999 GC gc;
1000 Pixmap ipixmap, stipple;
1001 unsigned width, height, depth;
31528cd3 1002
f97c9854
JS
1003 Window window; /* These return values */
1004 unsigned border; /* from XGetGeometry() */
1005 int x, y; /* are not needed. */
31528cd3 1006
f97c9854 1007 ipixmap = 0;
31528cd3 1008
f97c9854 1009 if ( NULL == display || 0 == pixmap )
2d120f83 1010 return ipixmap;
31528cd3 1011
f97c9854 1012 if ( 0 == XGetGeometry( display, pixmap, &window, &x, &y,
e838cc14
VZ
1013 &width, &height, &border, &depth )
1014 )
2d120f83 1015 return ipixmap; /* BadDrawable: probably an invalid pixmap */
31528cd3 1016
e838cc14
VZ
1017 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
1018 */
f97c9854
JS
1019 stipple = XCreateBitmapFromData( display, pixmap, stipple_data, 16, 16 );
1020 if ( 0 != stipple )
1021 {
2d120f83
JS
1022 gc = XCreateGC( display, pixmap, (XtGCMask)0, (XGCValues*)NULL );
1023 if ( NULL != gc )
f97c9854 1024 {
e838cc14
VZ
1025 /* Create an identical copy of the argument pixmap.
1026 */
2d120f83
JS
1027 ipixmap = XCreatePixmap( display, pixmap, width, height, depth );
1028 if ( 0 != ipixmap )
1029 {
e838cc14
VZ
1030 /* Copy the argument pixmap into the new pixmap.
1031 */
2d120f83 1032 XCopyArea( display, pixmap, ipixmap,
e838cc14 1033 gc, 0, 0, width, height, 0, 0 );
31528cd3 1034
e838cc14
VZ
1035 /* Refill the new pixmap using the stipple algorithm/pixmap.
1036 */
2d120f83
JS
1037 XSetStipple( display, gc, stipple );
1038 XSetFillStyle( display, gc, FillStippled );
1039 XFillRectangle( display, ipixmap, gc, 0, 0, width, height );
1040 }
1041 XFreeGC( display, gc );
f97c9854 1042 }
2d120f83 1043 XFreePixmap( display, stipple );
f97c9854
JS
1044 }
1045 return ipixmap;
4bb6408c 1046}
f97c9854 1047
321db4b6
JS
1048// Creates a bitmap with transparent areas drawn in
1049// the given colour.
d166a4f8 1050wxBitmap wxCreateMaskedBitmap(const wxBitmap& bitmap, wxColour& colour)
321db4b6
JS
1051{
1052 wxBitmap newBitmap(bitmap.GetWidth(),
2d120f83
JS
1053 bitmap.GetHeight(),
1054 bitmap.GetDepth());
321db4b6
JS
1055 wxMemoryDC destDC;
1056 wxMemoryDC srcDC;
1057 srcDC.SelectObject(bitmap);
1058 destDC.SelectObject(newBitmap);
31528cd3 1059
321db4b6
JS
1060 wxBrush brush(colour, wxSOLID);
1061 destDC.SetOptimization(FALSE);
1062 destDC.SetBackground(brush);
1063 destDC.Clear();
1064 destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(), & srcDC, 0, 0, wxCOPY, TRUE);
31528cd3 1065
321db4b6
JS
1066 return newBitmap;
1067}