removed USE_SHARED_LIBRARY(IES)
[wxWidgets.git] / src / motif / bitmap.cpp
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"
22 #include "wx/control.h"
23 #include "wx/dcmemory.h"
24 #include "wx/image.h"
25
26 #ifdef __VMS__
27 #pragma message disable nosimpint
28 #endif
29 #include <Xm/Xm.h>
30 #ifdef __VMS__
31 #pragma message enable nosimpint
32 #endif
33
34 #include "wx/motif/private.h"
35
36 #if wxHAVE_LIB_XPM
37 #include <X11/xpm.h>
38 #endif
39
40 IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
41 IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
42
43 wxBitmapRefData::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;
52
53 m_pixmap = (WXPixmap) 0;
54 m_display = (WXDisplay*) 0;
55
56 m_freePixmap = TRUE; //TODO: necessary?
57 m_freeColors = (unsigned long*) 0;
58 m_freeColorsCount = 0;
59
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;
66 }
67
68 wxBitmapRefData::~wxBitmapRefData()
69 {
70 if (m_labelPixmap)
71 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_labelPixmap);
72
73 if (m_armPixmap)
74 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_armPixmap);
75
76 if (m_insensPixmap)
77 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_insensPixmap);
78
79 if (m_image)
80 {
81 XmUninstallImage ((XImage*) m_image);
82 XtFree ((char *) (XImage*) m_image);
83 }
84
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);
93
94 if (m_freeColors)
95 {
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;
102 };
103
104 if (m_bitmapMask)
105 delete m_bitmapMask;
106 m_bitmapMask = NULL;
107 }
108
109 wxList wxBitmap::sm_handlers;
110
111 wxBitmap::wxBitmap()
112 {
113 m_refData = NULL;
114
115 if ( wxTheBitmapList )
116 wxTheBitmapList->AddBitmap(this);
117 }
118
119 wxBitmap::~wxBitmap()
120 {
121 if (wxTheBitmapList)
122 wxTheBitmapList->DeleteObject(this);
123 }
124
125 wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
126 {
127 m_refData = new wxBitmapRefData;
128
129 (void) Create((void*) bits, wxBITMAP_TYPE_XBM_DATA, width, height, depth);
130
131 if ( wxTheBitmapList )
132 wxTheBitmapList->AddBitmap(this);
133 }
134
135 wxBitmap::wxBitmap(int w, int h, int d)
136 {
137 (void)Create(w, h, d);
138
139 if ( wxTheBitmapList )
140 wxTheBitmapList->AddBitmap(this);
141 }
142
143 wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth)
144 {
145 (void) Create(data, type, width, height, depth);
146
147 if ( wxTheBitmapList )
148 wxTheBitmapList->AddBitmap(this);
149 }
150
151 wxBitmap::wxBitmap(const wxString& filename, long type)
152 {
153 LoadFile(filename, (int)type);
154
155 if ( wxTheBitmapList )
156 wxTheBitmapList->AddBitmap(this);
157 }
158
159 // Create from XPM data
160 static wxControl* sg_Control = NULL;
161 wxBitmap::wxBitmap(char **data, wxControl* control)
162 {
163 // Pass the control to the Create function using a global
164 sg_Control = control;
165
166 (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
167
168 sg_Control = (wxControl*) NULL;
169 }
170
171 bool wxBitmap::Create(int w, int h, int d)
172 {
173 UnRef();
174
175 m_refData = new wxBitmapRefData;
176
177 if (d < 1)
178 d = wxDisplayDepth();
179
180 M_BITMAPDATA->m_width = w;
181 M_BITMAPDATA->m_height = h;
182 M_BITMAPDATA->m_depth = d;
183 M_BITMAPDATA->m_freePixmap = TRUE;
184
185 Display *dpy = (Display*) wxGetDisplay();
186
187 M_BITMAPDATA->m_display = dpy; /* MATTHEW: [4] Remember the display */
188
189 M_BITMAPDATA->m_pixmap = (WXPixmap) XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)),
190 w, h, d);
191
192 M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_pixmap != (WXPixmap) 0) ;
193 return M_BITMAPDATA->m_ok;
194 }
195
196 bool wxBitmap::LoadFile(const wxString& filename, long type)
197 {
198 UnRef();
199
200 m_refData = new wxBitmapRefData;
201
202 wxBitmapHandler *handler = FindHandler(type);
203
204 if ( handler == NULL ) {
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;
213 }
214
215 return handler->LoadFile(this, filename, type, -1, -1);
216 }
217
218 bool wxBitmap::Create(void *data, long type, int width, int height, int depth)
219 {
220 UnRef();
221
222 m_refData = new wxBitmapRefData;
223
224 wxBitmapHandler *handler = FindHandler(type);
225
226 if ( handler == NULL ) {
227 wxLogWarning("no data bitmap handler for type %d defined.", type);
228
229 return FALSE;
230 }
231
232 return handler->Create(this, data, type, width, height, depth);
233 }
234
235 bool wxBitmap::SaveFile(const wxString& filename, int type, const wxPalette *palette)
236 {
237 wxBitmapHandler *handler = FindHandler(type);
238
239 if ( handler == NULL ) { // try wxImage
240 wxImage image( *this );
241 if (image.Ok()) return image.SaveFile( filename, type );
242 else return FALSE;
243 }
244
245 return handler->SaveFile(this, filename, type, palette);
246 }
247
248 void wxBitmap::SetWidth(int w)
249 {
250 if (!M_BITMAPDATA)
251 m_refData = new wxBitmapRefData;
252
253 M_BITMAPDATA->m_width = w;
254 }
255
256 void wxBitmap::SetHeight(int h)
257 {
258 if (!M_BITMAPDATA)
259 m_refData = new wxBitmapRefData;
260
261 M_BITMAPDATA->m_height = h;
262 }
263
264 void wxBitmap::SetDepth(int d)
265 {
266 if (!M_BITMAPDATA)
267 m_refData = new wxBitmapRefData;
268
269 M_BITMAPDATA->m_depth = d;
270 }
271
272 void wxBitmap::SetQuality(int q)
273 {
274 if (!M_BITMAPDATA)
275 m_refData = new wxBitmapRefData;
276
277 M_BITMAPDATA->m_quality = q;
278 }
279
280 void wxBitmap::SetOk(bool isOk)
281 {
282 if (!M_BITMAPDATA)
283 m_refData = new wxBitmapRefData;
284
285 M_BITMAPDATA->m_ok = isOk;
286 }
287
288 void wxBitmap::SetPalette(const wxPalette& palette)
289 {
290 if (!M_BITMAPDATA)
291 m_refData = new wxBitmapRefData;
292
293 M_BITMAPDATA->m_bitmapPalette = palette ;
294 }
295
296 void wxBitmap::SetMask(wxMask *mask)
297 {
298 if (!M_BITMAPDATA)
299 m_refData = new wxBitmapRefData;
300
301 M_BITMAPDATA->m_bitmapMask = mask ;
302 }
303
304 void wxBitmap::AddHandler(wxBitmapHandler *handler)
305 {
306 sm_handlers.Append(handler);
307 }
308
309 void wxBitmap::InsertHandler(wxBitmapHandler *handler)
310 {
311 sm_handlers.Insert(handler);
312 }
313
314 bool 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
326 wxBitmapHandler *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
339 wxBitmapHandler *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 &&
346 (bitmapType == -1 || handler->GetType() == bitmapType) )
347 return handler;
348 node = node->Next();
349 }
350 return NULL;
351 }
352
353 wxBitmapHandler *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 /*
367 * wxMask
368 */
369
370 wxMask::wxMask()
371 {
372 m_pixmap = (WXPixmap) 0;
373 }
374
375 // Construct a mask from a bitmap and a colour indicating
376 // the transparent area
377 wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
378 {
379 m_pixmap = (WXPixmap) 0;
380
381 Create(bitmap, colour);
382 }
383
384 // Construct a mask from a bitmap and a palette index indicating
385 // the transparent area
386 wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
387 {
388 m_pixmap = (WXPixmap) 0;
389
390 Create(bitmap, paletteIndex);
391 }
392
393 // Construct a mask from a mono bitmap (copies the bitmap).
394 wxMask::wxMask(const wxBitmap& bitmap)
395 {
396 m_pixmap = (WXPixmap) 0;
397
398 Create(bitmap);
399 }
400
401 wxMask::~wxMask()
402 {
403 // TODO: this may be the wrong display
404 if ( m_pixmap )
405 XFreePixmap ((Display*) wxGetDisplay(), (Pixmap) m_pixmap);
406 }
407
408 // Create a mask from a mono bitmap (copies the bitmap).
409 bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap))
410 {
411 // TODO
412 return FALSE;
413 }
414
415 // Create a mask from a bitmap and a palette index indicating
416 // the transparent area
417 bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap), int WXUNUSED(paletteIndex))
418 {
419 // TODO
420 return FALSE;
421 }
422
423 // Create a mask from a bitmap and a colour indicating
424 // the transparent area
425 bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap), const wxColour& WXUNUSED(colour))
426 {
427 // TODO
428 return FALSE;
429 }
430
431 /*
432 * wxBitmapHandler
433 */
434
435 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
436
437 bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap), void *WXUNUSED(data), long WXUNUSED(type),
438 int WXUNUSED(width), int WXUNUSED(height), int WXUNUSED(depth))
439 {
440 return FALSE;
441 }
442
443 bool wxBitmapHandler::LoadFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), long WXUNUSED(type),
444 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight))
445 {
446 return FALSE;
447 }
448
449 bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), int WXUNUSED(type),
450 const wxPalette *WXUNUSED(palette))
451 {
452 return FALSE;
453 }
454
455 /*
456 * Standard handlers
457 */
458
459 class WXDLLEXPORT wxXBMFileHandler: public wxBitmapHandler
460 {
461 DECLARE_DYNAMIC_CLASS(wxXBMFileHandler)
462 public:
463 inline wxXBMFileHandler()
464 {
465 m_name = "XBM file";
466 m_extension = "xbm";
467 m_type = wxBITMAP_TYPE_XBM;
468 };
469
470 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
471 int desiredWidth, int desiredHeight);
472 };
473 IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler, wxBitmapHandler)
474
475 bool wxXBMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags),
476 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight))
477 {
478 M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
479
480 int hotX, hotY;
481 unsigned int w, h;
482 Pixmap pixmap;
483
484 Display *dpy = (Display*) wxGetDisplay();
485 M_BITMAPDATA->m_display = (WXDisplay*) dpy;
486
487 int value = XReadBitmapFile (dpy, RootWindow (dpy, DefaultScreen (dpy)),
488 (char*) (const char*) name, &w, &h, &pixmap, &hotX, &hotY);
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;
493
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;
503
504 return M_BITMAPHANDLERDATA->m_ok ;
505 }
506
507 class WXDLLEXPORT wxXBMDataHandler: public wxBitmapHandler
508 {
509 DECLARE_DYNAMIC_CLASS(wxXBMDataHandler)
510 public:
511 inline wxXBMDataHandler()
512 {
513 m_name = "XBM data";
514 m_extension = "xbm";
515 m_type = wxBITMAP_TYPE_XBM_DATA;
516 };
517
518 virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1);
519 };
520 IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler, wxBitmapHandler)
521
522 bool wxXBMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags),
523 int width, int height, int WXUNUSED(depth))
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;
529
530 Display *dpy = (Display*) wxGetDisplay();
531 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
532
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) ;
535
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;
550
551 char tmp[128];
552 sprintf (tmp, "Im%x", (unsigned int) image);
553 XmInstallImage (image, tmp);
554
555 // Build our manually stipped pixmap.
556
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;
580
581 sprintf (tmp, "Not%x", (unsigned int)insensImage);
582 XmInstallImage (insensImage, tmp);
583
584 M_BITMAPHANDLERDATA->m_image = (WXImage*) image;
585 M_BITMAPHANDLERDATA->m_insensImage = (WXImage*) insensImage;
586
587 return TRUE;
588 }
589
590 #if wxHAVE_LIB_XPM
591 class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler
592 {
593 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler)
594 public:
595 inline wxXPMFileHandler()
596 {
597 m_name = "XPM file";
598 m_extension = "xpm";
599 m_type = wxBITMAP_TYPE_XPM;
600 };
601
602 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
603 int desiredWidth, int desiredHeight);
604 virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
605 };
606
607 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler)
608
609 bool wxXPMFileHandler::LoadFile( wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags),
610 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight) )
611 {
612 Display *dpy = (Display*) wxGetDisplay();
613 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
614
615 XpmAttributes xpmAttr;
616 Pixmap pixmap;
617 Pixmap mask = 0;
618
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);
625
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 }
634
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);
641
642 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
643 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
644
645 /*
646 if ( xpmAttr.npixels > 2 )
647 {
648 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
649 } else
650 {
651 M_BITMAPHANDLERDATA->m_depth = 1; // mono
652 }
653 */
654
655 M_BITMAPHANDLERDATA->m_depth = depthRet;
656
657 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
658
659 XpmFreeAttributes(&xpmAttr);
660
661 M_BITMAPHANDLERDATA->m_ok = TRUE;
662 return TRUE;
663 } else
664 {
665 // XpmDebugError(errorStatus, name);
666 M_BITMAPHANDLERDATA->m_ok = FALSE;
667 return FALSE;
668 }
669 }
670
671 bool wxXPMFileHandler::SaveFile( wxBitmap *bitmap, const wxString& name, int WXUNUSED(type),
672 const wxPalette *WXUNUSED(palette))
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,
678 (Pixmap) M_BITMAPHANDLERDATA->m_pixmap,
679 (M_BITMAPHANDLERDATA->m_bitmapMask ? (Pixmap) M_BITMAPHANDLERDATA->m_bitmapMask->GetPixmap() : (Pixmap) 0),
680 (XpmAttributes *) NULL);
681 if (errorStatus == XpmSuccess)
682 return TRUE;
683 else
684 return FALSE;
685 }
686 else
687 return FALSE;
688 }
689
690 class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler
691 {
692 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
693 public:
694 inline wxXPMDataHandler()
695 {
696 m_name = "XPM data";
697 m_extension = "xpm";
698 m_type = wxBITMAP_TYPE_XPM_DATA;
699 };
700
701 virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1);
702 };
703 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
704
705 bool wxXPMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags),
706 int width, int height, int WXUNUSED(depth))
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;
712
713 Display *dpy = (Display*) wxGetDisplay();
714 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
715
716 XpmAttributes xpmAttr;
717
718 xpmAttr.valuemask = XpmReturnInfos; /* nothing yet, but get infos back */
719
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 }
734
735 Pixmap pixmap;
736 Pixmap mask = 0;
737 int ErrorStatus = XpmCreatePixmapFromData(dpy, RootWindow(dpy, DefaultScreen(dpy)),
738 (char**) data, &pixmap, &mask, &xpmAttr);
739 if (ErrorStatus == XpmSuccess)
740 {
741 // Set attributes
742 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
743 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
744
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);
751
752 /*
753 if ( xpmAttr.npixels > 2 )
754 {
755 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
756 } else
757 {
758 M_BITMAPHANDLERDATA->m_depth = 1; // mono
759 }
760 */
761
762 M_BITMAPHANDLERDATA->m_depth = depthRet;
763
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 {
776 // XpmDebugError(ErrorStatus, NULL);
777 M_BITMAPHANDLERDATA->m_ok = FALSE;
778 }
779 return M_BITMAPHANDLERDATA->m_ok ;
780 }
781
782 #endif // wxHAVE_LIB_XPM
783
784 void 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
797 void wxBitmap::InitStandardHandlers()
798 {
799 // Initialize all standard bitmap or derived class handlers here.
800 AddHandler(new wxXBMFileHandler);
801 AddHandler(new wxXBMDataHandler);
802
803 // XPM is considered standard for Motif, although it can be omitted if
804 // libXpm is not installed
805 #if wxHAVE_LIB_XPM
806 AddHandler(new wxXPMFileHandler);
807 AddHandler(new wxXPMDataHandler);
808 #endif // wxHAVE_LIB_XPM
809 }
810
811 WXPixmap wxBitmap::GetLabelPixmap (WXWidget w)
812 {
813 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
814 return M_BITMAPDATA->m_pixmap;
815
816 Display *dpy = (Display*) M_BITMAPDATA->m_display;
817
818 #ifdef FOO
819 /*
820 If we do:
821 if (labelPixmap) return labelPixmap;
822 things can be wrong, because colors can have been changed.
823
824 If we do:
825 if (labelPixmap)
826 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
827 we got BadDrawable if the pixmap is referenced by multiples widgets
828
829 this is a catch22!!
830
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);
839 #endif
840
841 char tmp[128];
842 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
843
844 Pixel fg, bg;
845 Widget widget = (Widget) w;
846
847 while (XmIsGadget ( widget ))
848 widget = XtParent (widget);
849 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
850
851 M_BITMAPDATA->m_labelPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
852
853 return M_BITMAPDATA->m_labelPixmap;
854 }
855
856 WXPixmap wxBitmap::GetArmPixmap (WXWidget w)
857 {
858 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
859 return M_BITMAPDATA->m_pixmap;
860
861 Display *dpy = (Display*) M_BITMAPDATA->m_display;
862 #ifdef FOO
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);
867 #endif
868
869 char tmp[128];
870 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
871
872 Pixel fg, bg;
873 Widget widget = (Widget) w;
874
875 XtVaGetValues (widget, XmNarmColor, &bg, NULL);
876 while (XmIsGadget (widget))
877 widget = XtParent (widget);
878 XtVaGetValues (widget, XmNforeground, &fg, NULL);
879
880 M_BITMAPDATA->m_armPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
881
882 return M_BITMAPDATA->m_armPixmap;
883 }
884
885 WXPixmap wxBitmap::GetInsensPixmap (WXWidget w)
886 {
887 Display *dpy = (Display*) M_BITMAPDATA->m_display;
888
889 if (M_BITMAPDATA->m_insensPixmap)
890 return M_BITMAPDATA->m_insensPixmap;
891
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 }
900
901 if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0)
902 return M_BITMAPDATA->m_pixmap;
903
904 #ifdef FOO
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);
909 #endif
910
911 char tmp[128];
912 sprintf (tmp, "Not%x", (unsigned int) M_BITMAPDATA->m_insensImage);
913
914 Pixel fg, bg;
915 Widget widget = (Widget) w;
916
917 while (XmIsGadget (widget))
918 widget = XtParent (widget);
919 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
920
921 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
922
923 return M_BITMAPDATA->m_insensPixmap;
924 }
925
926 // We may need this sometime...
927
928 /****************************************************************************
929
930 NAME
931 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
932
933 SYNOPSIS
934 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
935
936 DESCRIPTION
937 This function creates a grayed-out copy of the argument pixmap, suitable
938 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
939
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.
943
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().
947
948 SEE ALSO
949 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
950 XFillRectangle(3), exit(2)
951
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
957
958 *****************************************************************************/
959
960 Pixmap
961 XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
962
963 {
964 static
965 char stipple_data[] =
966 {
967 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
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
971 };
972 GC gc;
973 Pixmap ipixmap, stipple;
974 unsigned width, height, depth;
975
976 Window window; /* These return values */
977 unsigned border; /* from XGetGeometry() */
978 int x, y; /* are not needed. */
979
980 ipixmap = 0;
981
982 if ( NULL == display || 0 == pixmap )
983 return ipixmap;
984
985 if ( 0 == XGetGeometry( display, pixmap, &window, &x, &y,
986 &width, &height, &border, &depth )
987 )
988 return ipixmap; /* BadDrawable: probably an invalid pixmap */
989
990 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
991 */
992 stipple = XCreateBitmapFromData( display, pixmap, stipple_data, 16, 16 );
993 if ( 0 != stipple )
994 {
995 gc = XCreateGC( display, pixmap, (XtGCMask)0, (XGCValues*)NULL );
996 if ( NULL != gc )
997 {
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 );
1007
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 );
1015 }
1016 XFreePixmap( display, stipple );
1017 }
1018 return ipixmap;
1019 }
1020
1021 // Creates a bitmap with transparent areas drawn in
1022 // the given colour.
1023 wxBitmap wxCreateMaskedBitmap(const wxBitmap& bitmap, wxColour& colour)
1024 {
1025 wxBitmap newBitmap(bitmap.GetWidth(),
1026 bitmap.GetHeight(),
1027 bitmap.GetDepth());
1028 wxMemoryDC destDC;
1029 wxMemoryDC srcDC;
1030 srcDC.SelectObject(bitmap);
1031 destDC.SelectObject(newBitmap);
1032
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);
1038
1039 return newBitmap;
1040 }