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