]> git.saurik.com Git - wxWidgets.git/blame - src/motif/bitmap.cpp
Changes to WXDLLEXPORT keyword position for VC++ 6.0; changed
[wxWidgets.git] / src / motif / bitmap.cpp
CommitLineData
4bb6408c
JS
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"
a4294b78 22#include "wx/control.h"
321db4b6 23#include "wx/dcmemory.h"
4bb6408c 24
f97c9854
JS
25#include <Xm/Xm.h>
26
27#include "wx/motif/private.h"
28
29// TODO: correct symbol, path?
a4294b78 30#if wxUSE_XPM
f97c9854
JS
31#include <X11/xpm.h>
32#endif
33
4bb6408c
JS
34#if !USE_SHARED_LIBRARIES
35IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
36IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
37#endif
38
39wxBitmapRefData::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;
16c1f7f3
JS
48
49 m_pixmap = (WXPixmap) 0;
50 m_display = (WXDisplay*) 0;
f97c9854
JS
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;
4bb6408c
JS
62}
63
64wxBitmapRefData::~wxBitmapRefData()
65{
f97c9854
JS
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 };
4bb6408c
JS
99
100 if (m_bitmapMask)
101 delete m_bitmapMask;
102 m_bitmapMask = NULL;
103}
104
105wxList wxBitmap::sm_handlers;
106
107wxBitmap::wxBitmap()
108{
109 m_refData = NULL;
110
111 if ( wxTheBitmapList )
112 wxTheBitmapList->AddBitmap(this);
113}
114
115wxBitmap::~wxBitmap()
116{
117 if (wxTheBitmapList)
118 wxTheBitmapList->DeleteObject(this);
119}
120
f97c9854 121wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
4bb6408c
JS
122{
123 m_refData = new wxBitmapRefData;
124
f97c9854 125 (void) Create((void*) bits, wxBITMAP_TYPE_XBM_DATA, width, height, depth);
4bb6408c
JS
126
127 if ( wxTheBitmapList )
128 wxTheBitmapList->AddBitmap(this);
129}
130
131wxBitmap::wxBitmap(int w, int h, int d)
132{
133 (void)Create(w, h, d);
134
135 if ( wxTheBitmapList )
136 wxTheBitmapList->AddBitmap(this);
137}
138
139wxBitmap::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
147wxBitmap::wxBitmap(const wxString& filename, long type)
148{
149 LoadFile(filename, (int)type);
150
151 if ( wxTheBitmapList )
152 wxTheBitmapList->AddBitmap(this);
153}
154
f97c9854
JS
155// Create from XPM data
156static wxControl* sg_Control = NULL;
a4294b78 157wxBitmap::wxBitmap(char **data, wxControl* control)
4bb6408c 158{
f97c9854
JS
159 // Pass the control to the Create function using a global
160 sg_Control = control;
161
4bb6408c 162 (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
f97c9854
JS
163
164 sg_Control = (wxControl*) NULL;
4bb6408c 165}
4bb6408c
JS
166
167bool wxBitmap::Create(int w, int h, int d)
168{
169 UnRef();
170
171 m_refData = new wxBitmapRefData;
172
f97c9854
JS
173 if (d < 1)
174 d = wxDisplayDepth();
175
4bb6408c
JS
176 M_BITMAPDATA->m_width = w;
177 M_BITMAPDATA->m_height = h;
178 M_BITMAPDATA->m_depth = d;
f97c9854 179 M_BITMAPDATA->m_freePixmap = TRUE;
4bb6408c 180
f97c9854 181 Display *dpy = (Display*) wxGetDisplay();
4bb6408c 182
f97c9854
JS
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) ;
4bb6408c
JS
189 return M_BITMAPDATA->m_ok;
190}
191
192bool 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
209bool 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
226bool 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
239void wxBitmap::SetWidth(int w)
240{
241 if (!M_BITMAPDATA)
242 m_refData = new wxBitmapRefData;
243
244 M_BITMAPDATA->m_width = w;
245}
246
247void wxBitmap::SetHeight(int h)
248{
249 if (!M_BITMAPDATA)
250 m_refData = new wxBitmapRefData;
251
252 M_BITMAPDATA->m_height = h;
253}
254
255void wxBitmap::SetDepth(int d)
256{
257 if (!M_BITMAPDATA)
258 m_refData = new wxBitmapRefData;
259
260 M_BITMAPDATA->m_depth = d;
261}
262
263void wxBitmap::SetQuality(int q)
264{
265 if (!M_BITMAPDATA)
266 m_refData = new wxBitmapRefData;
267
268 M_BITMAPDATA->m_quality = q;
269}
270
271void wxBitmap::SetOk(bool isOk)
272{
273 if (!M_BITMAPDATA)
274 m_refData = new wxBitmapRefData;
275
276 M_BITMAPDATA->m_ok = isOk;
277}
278
279void wxBitmap::SetPalette(const wxPalette& palette)
280{
281 if (!M_BITMAPDATA)
282 m_refData = new wxBitmapRefData;
283
284 M_BITMAPDATA->m_bitmapPalette = palette ;
285}
286
287void wxBitmap::SetMask(wxMask *mask)
288{
289 if (!M_BITMAPDATA)
290 m_refData = new wxBitmapRefData;
291
292 M_BITMAPDATA->m_bitmapMask = mask ;
293}
294
295void wxBitmap::AddHandler(wxBitmapHandler *handler)
296{
297 sm_handlers.Append(handler);
298}
299
300void wxBitmap::InsertHandler(wxBitmapHandler *handler)
301{
302 sm_handlers.Insert(handler);
303}
304
305bool 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
317wxBitmapHandler *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
330wxBitmapHandler *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
344wxBitmapHandler *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
361wxMask::wxMask()
362{
16c1f7f3 363 m_pixmap = (WXPixmap) 0;
4bb6408c
JS
364}
365
366// Construct a mask from a bitmap and a colour indicating
367// the transparent area
368wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
369{
16c1f7f3
JS
370 m_pixmap = (WXPixmap) 0;
371
4bb6408c
JS
372 Create(bitmap, colour);
373}
374
375// Construct a mask from a bitmap and a palette index indicating
376// the transparent area
377wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
378{
16c1f7f3 379 m_pixmap = (WXPixmap) 0;
4bb6408c
JS
380
381 Create(bitmap, paletteIndex);
382}
383
384// Construct a mask from a mono bitmap (copies the bitmap).
385wxMask::wxMask(const wxBitmap& bitmap)
386{
16c1f7f3 387 m_pixmap = (WXPixmap) 0;
4bb6408c
JS
388
389 Create(bitmap);
390}
391
392wxMask::~wxMask()
393{
f97c9854
JS
394 // TODO: this may be the wrong display
395 if ( m_pixmap )
396 XFreePixmap ((Display*) wxGetDisplay(), (Pixmap) m_pixmap);
4bb6408c
JS
397}
398
399// Create a mask from a mono bitmap (copies the bitmap).
f9e02ac7 400bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap))
4bb6408c
JS
401{
402// TODO
403 return FALSE;
404}
405
406// Create a mask from a bitmap and a palette index indicating
407// the transparent area
f9e02ac7 408bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap), int WXUNUSED(paletteIndex))
4bb6408c
JS
409{
410// TODO
411 return FALSE;
412}
413
414// Create a mask from a bitmap and a colour indicating
415// the transparent area
f9e02ac7 416bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap), const wxColour& WXUNUSED(colour))
4bb6408c
JS
417{
418// TODO
419 return FALSE;
420}
421
422/*
423 * wxBitmapHandler
424 */
425
426IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
427
f9e02ac7
RR
428bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap), void *WXUNUSED(data), long WXUNUSED(type),
429 int WXUNUSED(width), int WXUNUSED(height), int WXUNUSED(depth))
4bb6408c
JS
430{
431 return FALSE;
432}
433
f9e02ac7
RR
434bool wxBitmapHandler::LoadFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), long WXUNUSED(type),
435 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight))
4bb6408c
JS
436{
437 return FALSE;
438}
439
f9e02ac7
RR
440bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), int WXUNUSED(type),
441 const wxPalette *WXUNUSED(palette))
4bb6408c
JS
442{
443 return FALSE;
444}
445
446/*
447 * Standard handlers
448 */
449
f97c9854 450class WXDLLEXPORT wxXBMFileHandler: public wxBitmapHandler
4bb6408c 451{
f97c9854 452 DECLARE_DYNAMIC_CLASS(wxXBMFileHandler)
4bb6408c 453public:
f97c9854 454 inline wxXBMFileHandler()
4bb6408c 455 {
f97c9854
JS
456 m_name = "XBM file";
457 m_extension = "xbm";
458 m_type = wxBITMAP_TYPE_XBM;
4bb6408c
JS
459 };
460
461 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
462 int desiredWidth, int desiredHeight);
463};
f97c9854
JS
464IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler, wxBitmapHandler)
465
f9e02ac7
RR
466bool wxXBMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags),
467 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight))
f97c9854
JS
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
498class WXDLLEXPORT wxXBMDataHandler: public wxBitmapHandler
499{
500 DECLARE_DYNAMIC_CLASS(wxXBMDataHandler)
501public:
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};
511IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler, wxBitmapHandler)
512
f9e02ac7
RR
513bool wxXBMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags),
514 int width, int height, int WXUNUSED(depth))
f97c9854
JS
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
a4294b78 581#if wxUSE_XPM
f97c9854
JS
582class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler
583{
584 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler)
585public:
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
598IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler)
599
f9e02ac7
RR
600bool wxXPMFileHandler::LoadFile( wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags),
601 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight) )
f97c9854 602{
a4294b78 603 Display *dpy = (Display*) wxGetDisplay();
f97c9854
JS
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
0d57be45
JS
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
f97c9854
JS
633 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
634 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
0d57be45
JS
635
636 /*
f97c9854
JS
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 }
0d57be45
JS
644 */
645
646 M_BITMAPHANDLERDATA->m_depth = depthRet;
f97c9854
JS
647
648 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
649
650 XpmFreeAttributes(&xpmAttr);
651
652 M_BITMAPHANDLERDATA->m_ok = TRUE;
a4294b78 653 return TRUE;
f97c9854
JS
654 } else
655 {
656// XpmDebugError(errorStatus, name);
657 M_BITMAPHANDLERDATA->m_ok = FALSE;
658 return FALSE;
659 }
660}
661
f9e02ac7
RR
662bool wxXPMFileHandler::SaveFile( wxBitmap *bitmap, const wxString& name, int WXUNUSED(type),
663 const wxPalette *WXUNUSED(palette))
f97c9854
JS
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
681class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler
682{
683 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
684public:
a4294b78 685 inline wxXPMDataHandler()
f97c9854
JS
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};
694IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
695
f9e02ac7
RR
696bool wxXPMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags),
697 int width, int height, int WXUNUSED(depth))
f97c9854
JS
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
a4294b78 704 Display *dpy = (Display*) wxGetDisplay();
f97c9854
JS
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;
0d57be45
JS
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 /*
f97c9854
JS
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 }
0d57be45
JS
751 */
752
753 M_BITMAPHANDLERDATA->m_depth = depthRet;
754
f97c9854
JS
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
4bb6408c
JS
774
775void 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
788void wxBitmap::InitStandardHandlers()
789{
f97c9854
JS
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.
a4294b78 796#if wxUSE_XPM
4bb6408c
JS
797 AddHandler(new wxXPMFileHandler);
798 AddHandler(new wxXPMDataHandler);
f97c9854
JS
799#endif
800}
801
802WXPixmap 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
847WXPixmap 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
876WXPixmap wxBitmap::GetInsensPixmap (WXWidget w)
877{
878 Display *dpy = (Display*) M_BITMAPDATA->m_display;
879
0d57be45
JS
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
f97c9854
JS
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
921NAME
922 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
923
924SYNOPSIS
925 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
926
927DESCRIPTION
928 This function creates a grayed-out copy of the argument pixmap, suitable
929 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
930
931RETURN 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
935ERRORS
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
939SEE ALSO
940 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
941 XFillRectangle(3), exit(2)
942
943AUTHOR
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
951Pixmap
952XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
953
954{
955static
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;
4bb6408c 1010}
f97c9854 1011
321db4b6
JS
1012// Creates a bitmap with transparent areas drawn in
1013// the given colour.
1014wxBitmap 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}