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