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