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