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