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