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