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