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