]> git.saurik.com Git - wxWidgets.git/blame - src/motif/bitmap.cpp
1. wxMenu{Item|Bar} modifications for wxMotif
[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
31528cd3
VZ
29#if wxHAVE_LIB_XPM
30 #include <X11/xpm.h>
f97c9854
JS
31#endif
32
4bb6408c 33#if !USE_SHARED_LIBRARIES
31528cd3
VZ
34 IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
35 IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
4bb6408c
JS
36#endif
37
38wxBitmapRefData::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;
31528cd3 47
16c1f7f3
JS
48 m_pixmap = (WXPixmap) 0;
49 m_display = (WXDisplay*) 0;
31528cd3 50
f97c9854
JS
51 m_freePixmap = TRUE; //TODO: necessary?
52 m_freeColors = (unsigned long*) 0;
53 m_freeColorsCount = 0;
31528cd3 54
f97c9854
JS
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;
4bb6408c
JS
61}
62
63wxBitmapRefData::~wxBitmapRefData()
64{
f97c9854
JS
65 if (m_labelPixmap)
66 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_labelPixmap);
31528cd3 67
f97c9854
JS
68 if (m_armPixmap)
69 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_armPixmap);
31528cd3 70
f97c9854
JS
71 if (m_insensPixmap)
72 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_insensPixmap);
31528cd3 73
f97c9854
JS
74 if (m_image)
75 {
76 XmUninstallImage ((XImage*) m_image);
77 XtFree ((char *) (XImage*) m_image);
78 }
31528cd3 79
f97c9854
JS
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);
31528cd3 88
f97c9854
JS
89 if (m_freeColors)
90 {
2d120f83
JS
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;
f97c9854 97 };
31528cd3 98
4bb6408c
JS
99 if (m_bitmapMask)
100 delete m_bitmapMask;
101 m_bitmapMask = NULL;
102}
103
104wxList wxBitmap::sm_handlers;
105
106wxBitmap::wxBitmap()
107{
108 m_refData = NULL;
31528cd3 109
4bb6408c
JS
110 if ( wxTheBitmapList )
111 wxTheBitmapList->AddBitmap(this);
112}
113
114wxBitmap::~wxBitmap()
115{
116 if (wxTheBitmapList)
117 wxTheBitmapList->DeleteObject(this);
118}
119
f97c9854 120wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
4bb6408c
JS
121{
122 m_refData = new wxBitmapRefData;
31528cd3 123
f97c9854 124 (void) Create((void*) bits, wxBITMAP_TYPE_XBM_DATA, width, height, depth);
31528cd3 125
4bb6408c
JS
126 if ( wxTheBitmapList )
127 wxTheBitmapList->AddBitmap(this);
128}
129
130wxBitmap::wxBitmap(int w, int h, int d)
131{
132 (void)Create(w, h, d);
31528cd3 133
4bb6408c
JS
134 if ( wxTheBitmapList )
135 wxTheBitmapList->AddBitmap(this);
136}
137
138wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth)
139{
140 (void) Create(data, type, width, height, depth);
31528cd3 141
4bb6408c
JS
142 if ( wxTheBitmapList )
143 wxTheBitmapList->AddBitmap(this);
144}
145
146wxBitmap::wxBitmap(const wxString& filename, long type)
147{
148 LoadFile(filename, (int)type);
31528cd3 149
4bb6408c
JS
150 if ( wxTheBitmapList )
151 wxTheBitmapList->AddBitmap(this);
152}
153
f97c9854
JS
154// Create from XPM data
155static wxControl* sg_Control = NULL;
a4294b78 156wxBitmap::wxBitmap(char **data, wxControl* control)
4bb6408c 157{
f97c9854
JS
158 // Pass the control to the Create function using a global
159 sg_Control = control;
31528cd3 160
4bb6408c 161 (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
31528cd3 162
f97c9854 163 sg_Control = (wxControl*) NULL;
4bb6408c 164}
4bb6408c
JS
165
166bool wxBitmap::Create(int w, int h, int d)
167{
168 UnRef();
31528cd3 169
4bb6408c 170 m_refData = new wxBitmapRefData;
31528cd3 171
f97c9854 172 if (d < 1)
2d120f83 173 d = wxDisplayDepth();
31528cd3 174
4bb6408c
JS
175 M_BITMAPDATA->m_width = w;
176 M_BITMAPDATA->m_height = h;
177 M_BITMAPDATA->m_depth = d;
f97c9854 178 M_BITMAPDATA->m_freePixmap = TRUE;
31528cd3 179
f97c9854 180 Display *dpy = (Display*) wxGetDisplay();
31528cd3 181
f97c9854 182 M_BITMAPDATA->m_display = dpy; /* MATTHEW: [4] Remember the display */
31528cd3 183
f97c9854 184 M_BITMAPDATA->m_pixmap = (WXPixmap) XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)),
2d120f83 185 w, h, d);
31528cd3 186
f97c9854 187 M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_pixmap != (WXPixmap) 0) ;
4bb6408c
JS
188 return M_BITMAPDATA->m_ok;
189}
190
191bool wxBitmap::LoadFile(const wxString& filename, long type)
192{
193 UnRef();
31528cd3 194
4bb6408c 195 m_refData = new wxBitmapRefData;
31528cd3 196
4bb6408c 197 wxBitmapHandler *handler = FindHandler(type);
31528cd3 198
4bb6408c 199 if ( handler == NULL ) {
7bcb11d3 200 wxLogWarning("%s: no bitmap handler for type %d defined.", (const char*) filename, type);
31528cd3 201
4bb6408c
JS
202 return FALSE;
203 }
31528cd3 204
4bb6408c
JS
205 return handler->LoadFile(this, filename, type, -1, -1);
206}
207
208bool wxBitmap::Create(void *data, long type, int width, int height, int depth)
209{
210 UnRef();
31528cd3 211
4bb6408c 212 m_refData = new wxBitmapRefData;
31528cd3 213
4bb6408c 214 wxBitmapHandler *handler = FindHandler(type);
31528cd3 215
4bb6408c 216 if ( handler == NULL ) {
7bcb11d3 217 wxLogWarning("no data bitmap handler for type %d defined.", type);
31528cd3 218
4bb6408c
JS
219 return FALSE;
220 }
31528cd3 221
4bb6408c
JS
222 return handler->Create(this, data, type, width, height, depth);
223}
224
225bool wxBitmap::SaveFile(const wxString& filename, int type, const wxPalette *palette)
226{
227 wxBitmapHandler *handler = FindHandler(type);
31528cd3 228
4bb6408c
JS
229 if ( handler == NULL ) {
230 wxLogWarning("no bitmap handler for type %d defined.", type);
31528cd3 231
4bb6408c 232 return FALSE;
2d120f83 233 }
31528cd3 234
2d120f83 235 return handler->SaveFile(this, filename, type, palette);
4bb6408c
JS
236}
237
238void wxBitmap::SetWidth(int w)
239{
240 if (!M_BITMAPDATA)
241 m_refData = new wxBitmapRefData;
31528cd3 242
4bb6408c
JS
243 M_BITMAPDATA->m_width = w;
244}
245
246void wxBitmap::SetHeight(int h)
247{
248 if (!M_BITMAPDATA)
249 m_refData = new wxBitmapRefData;
31528cd3 250
4bb6408c
JS
251 M_BITMAPDATA->m_height = h;
252}
253
254void wxBitmap::SetDepth(int d)
255{
256 if (!M_BITMAPDATA)
257 m_refData = new wxBitmapRefData;
31528cd3 258
4bb6408c
JS
259 M_BITMAPDATA->m_depth = d;
260}
261
262void wxBitmap::SetQuality(int q)
263{
264 if (!M_BITMAPDATA)
265 m_refData = new wxBitmapRefData;
31528cd3 266
4bb6408c
JS
267 M_BITMAPDATA->m_quality = q;
268}
269
270void wxBitmap::SetOk(bool isOk)
271{
272 if (!M_BITMAPDATA)
273 m_refData = new wxBitmapRefData;
31528cd3 274
4bb6408c
JS
275 M_BITMAPDATA->m_ok = isOk;
276}
277
278void wxBitmap::SetPalette(const wxPalette& palette)
279{
280 if (!M_BITMAPDATA)
281 m_refData = new wxBitmapRefData;
31528cd3 282
4bb6408c
JS
283 M_BITMAPDATA->m_bitmapPalette = palette ;
284}
285
286void wxBitmap::SetMask(wxMask *mask)
287{
288 if (!M_BITMAPDATA)
289 m_refData = new wxBitmapRefData;
31528cd3 290
4bb6408c
JS
291 M_BITMAPDATA->m_bitmapMask = mask ;
292}
293
294void wxBitmap::AddHandler(wxBitmapHandler *handler)
295{
296 sm_handlers.Append(handler);
297}
298
299void wxBitmap::InsertHandler(wxBitmapHandler *handler)
300{
301 sm_handlers.Insert(handler);
302}
303
304bool 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
316wxBitmapHandler *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
329wxBitmapHandler *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 &&
2d120f83 336 (bitmapType == -1 || handler->GetType() == bitmapType) )
4bb6408c
JS
337 return handler;
338 node = node->Next();
339 }
340 return NULL;
341}
342
343wxBitmapHandler *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/*
2d120f83
JS
357* wxMask
358*/
4bb6408c
JS
359
360wxMask::wxMask()
361{
16c1f7f3 362 m_pixmap = (WXPixmap) 0;
4bb6408c
JS
363}
364
365// Construct a mask from a bitmap and a colour indicating
366// the transparent area
367wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
368{
16c1f7f3 369 m_pixmap = (WXPixmap) 0;
31528cd3 370
4bb6408c
JS
371 Create(bitmap, colour);
372}
373
374// Construct a mask from a bitmap and a palette index indicating
375// the transparent area
376wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
377{
16c1f7f3 378 m_pixmap = (WXPixmap) 0;
31528cd3 379
4bb6408c
JS
380 Create(bitmap, paletteIndex);
381}
382
383// Construct a mask from a mono bitmap (copies the bitmap).
384wxMask::wxMask(const wxBitmap& bitmap)
385{
16c1f7f3 386 m_pixmap = (WXPixmap) 0;
31528cd3 387
4bb6408c
JS
388 Create(bitmap);
389}
390
391wxMask::~wxMask()
392{
f97c9854
JS
393 // TODO: this may be the wrong display
394 if ( m_pixmap )
395 XFreePixmap ((Display*) wxGetDisplay(), (Pixmap) m_pixmap);
4bb6408c
JS
396}
397
398// Create a mask from a mono bitmap (copies the bitmap).
f9e02ac7 399bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap))
4bb6408c 400{
2d120f83 401 // TODO
4bb6408c
JS
402 return FALSE;
403}
404
405// Create a mask from a bitmap and a palette index indicating
406// the transparent area
f9e02ac7 407bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap), int WXUNUSED(paletteIndex))
4bb6408c 408{
2d120f83 409 // TODO
4bb6408c
JS
410 return FALSE;
411}
412
413// Create a mask from a bitmap and a colour indicating
414// the transparent area
f9e02ac7 415bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap), const wxColour& WXUNUSED(colour))
4bb6408c 416{
2d120f83 417 // TODO
4bb6408c
JS
418 return FALSE;
419}
420
421/*
2d120f83
JS
422* wxBitmapHandler
423*/
4bb6408c
JS
424
425IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
426
31528cd3 427bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap), void *WXUNUSED(data), long WXUNUSED(type),
2d120f83 428 int WXUNUSED(width), int WXUNUSED(height), int WXUNUSED(depth))
4bb6408c
JS
429{
430 return FALSE;
431}
432
f9e02ac7 433bool wxBitmapHandler::LoadFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), long WXUNUSED(type),
2d120f83 434 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight))
4bb6408c
JS
435{
436 return FALSE;
437}
438
31528cd3 439bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), int WXUNUSED(type),
2d120f83 440 const wxPalette *WXUNUSED(palette))
4bb6408c
JS
441{
442 return FALSE;
443}
444
445/*
2d120f83
JS
446* Standard handlers
447*/
4bb6408c 448
f97c9854 449class WXDLLEXPORT wxXBMFileHandler: public wxBitmapHandler
4bb6408c 450{
f97c9854 451 DECLARE_DYNAMIC_CLASS(wxXBMFileHandler)
4bb6408c 452public:
f97c9854 453 inline wxXBMFileHandler()
4bb6408c 454 {
f97c9854
JS
455 m_name = "XBM file";
456 m_extension = "xbm";
457 m_type = wxBITMAP_TYPE_XBM;
4bb6408c 458 };
31528cd3 459
4bb6408c 460 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
2d120f83 461 int desiredWidth, int desiredHeight);
4bb6408c 462};
f97c9854
JS
463IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler, wxBitmapHandler)
464
f9e02ac7 465bool wxXBMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags),
2d120f83 466 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight))
f97c9854
JS
467{
468 M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
31528cd3 469
f97c9854
JS
470 int hotX, hotY;
471 unsigned int w, h;
472 Pixmap pixmap;
31528cd3 473
f97c9854
JS
474 Display *dpy = (Display*) wxGetDisplay();
475 M_BITMAPDATA->m_display = (WXDisplay*) dpy;
31528cd3 476
f97c9854 477 int value = XReadBitmapFile (dpy, RootWindow (dpy, DefaultScreen (dpy)),
2d120f83 478 (char*) (const char*) name, &w, &h, &pixmap, &hotX, &hotY);
f97c9854
JS
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;
31528cd3 483
f97c9854
JS
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;
31528cd3 493
f97c9854
JS
494 return M_BITMAPHANDLERDATA->m_ok ;
495}
496
497class WXDLLEXPORT wxXBMDataHandler: public wxBitmapHandler
498{
499 DECLARE_DYNAMIC_CLASS(wxXBMDataHandler)
500public:
501 inline wxXBMDataHandler()
502 {
503 m_name = "XBM data";
504 m_extension = "xbm";
505 m_type = wxBITMAP_TYPE_XBM_DATA;
506 };
31528cd3 507
f97c9854
JS
508 virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1);
509};
510IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler, wxBitmapHandler)
511
31528cd3 512bool wxXBMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags),
2d120f83 513 int width, int height, int WXUNUSED(depth))
f97c9854
JS
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;
31528cd3 519
f97c9854
JS
520 Display *dpy = (Display*) wxGetDisplay();
521 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
31528cd3 522
f97c9854
JS
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) ;
31528cd3 525
f97c9854
JS
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;
31528cd3 540
f97c9854
JS
541 char tmp[128];
542 sprintf (tmp, "Im%x", (unsigned int) image);
543 XmInstallImage (image, tmp);
31528cd3 544
f97c9854 545 // Build our manually stipped pixmap.
31528cd3 546
f97c9854
JS
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;
31528cd3 570
f97c9854
JS
571 sprintf (tmp, "Not%x", (unsigned int)insensImage);
572 XmInstallImage (insensImage, tmp);
31528cd3 573
f97c9854
JS
574 M_BITMAPHANDLERDATA->m_image = (WXImage*) image;
575 M_BITMAPHANDLERDATA->m_insensImage = (WXImage*) insensImage;
31528cd3 576
f97c9854
JS
577 return TRUE;
578}
579
31528cd3 580#if wxHAVE_LIB_XPM
f97c9854
JS
581class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler
582{
583 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler)
584public:
585 inline wxXPMFileHandler()
586 {
587 m_name = "XPM file";
588 m_extension = "xpm";
589 m_type = wxBITMAP_TYPE_XPM;
590 };
31528cd3 591
f97c9854 592 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
2d120f83 593 int desiredWidth, int desiredHeight);
f97c9854
JS
594 virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
595};
596
597IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler)
598
f9e02ac7 599bool wxXPMFileHandler::LoadFile( wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags),
2d120f83 600 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight) )
f97c9854 601{
a4294b78 602 Display *dpy = (Display*) wxGetDisplay();
f97c9854 603 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
31528cd3 604
f97c9854
JS
605 XpmAttributes xpmAttr;
606 Pixmap pixmap;
607 Pixmap mask = 0;
31528cd3 608
f97c9854
JS
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);
31528cd3 615
f97c9854
JS
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 }
31528cd3 624
0d57be45
JS
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);
31528cd3 631
f97c9854
JS
632 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
633 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
31528cd3 634
2d120f83 635 /*
f97c9854
JS
636 if ( xpmAttr.npixels > 2 )
637 {
2d120f83 638 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
f97c9854
JS
639 } else
640 {
2d120f83 641 M_BITMAPHANDLERDATA->m_depth = 1; // mono
f97c9854 642 }
2d120f83 643 */
31528cd3 644
0d57be45 645 M_BITMAPHANDLERDATA->m_depth = depthRet;
31528cd3 646
2d120f83 647 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
31528cd3 648
2d120f83 649 XpmFreeAttributes(&xpmAttr);
31528cd3 650
f97c9854 651 M_BITMAPHANDLERDATA->m_ok = TRUE;
a4294b78 652 return TRUE;
f97c9854
JS
653 } else
654 {
2d120f83 655 // XpmDebugError(errorStatus, name);
f97c9854
JS
656 M_BITMAPHANDLERDATA->m_ok = FALSE;
657 return FALSE;
658 }
659}
660
31528cd3 661bool wxXPMFileHandler::SaveFile( wxBitmap *bitmap, const wxString& name, int WXUNUSED(type),
2d120f83 662 const wxPalette *WXUNUSED(palette))
f97c9854
JS
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,
2d120f83
JS
668 (Pixmap) M_BITMAPHANDLERDATA->m_pixmap,
669 (M_BITMAPHANDLERDATA->m_bitmapMask ? (Pixmap) M_BITMAPHANDLERDATA->m_bitmapMask->GetPixmap() : (Pixmap) 0),
670 (XpmAttributes *) NULL);
f97c9854 671 if (errorStatus == XpmSuccess)
2d120f83 672 return TRUE;
f97c9854 673 else
2d120f83 674 return FALSE;
f97c9854
JS
675 }
676 else
677 return FALSE;
678}
679
680class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler
681{
682 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
683public:
a4294b78 684 inline wxXPMDataHandler()
f97c9854
JS
685 {
686 m_name = "XPM data";
687 m_extension = "xpm";
688 m_type = wxBITMAP_TYPE_XPM_DATA;
689 };
31528cd3 690
f97c9854
JS
691 virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1);
692};
693IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
694
31528cd3 695bool wxXPMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags),
2d120f83 696 int width, int height, int WXUNUSED(depth))
f97c9854
JS
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;
31528cd3 702
a4294b78 703 Display *dpy = (Display*) wxGetDisplay();
f97c9854 704 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
31528cd3 705
f97c9854 706 XpmAttributes xpmAttr;
31528cd3 707
f97c9854 708 xpmAttr.valuemask = XpmReturnInfos; /* nothing yet, but get infos back */
31528cd3 709
f97c9854
JS
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 }
31528cd3 724
f97c9854
JS
725 Pixmap pixmap;
726 Pixmap mask = 0;
727 int ErrorStatus = XpmCreatePixmapFromData(dpy, RootWindow(dpy, DefaultScreen(dpy)),
2d120f83 728 (char**) data, &pixmap, &mask, &xpmAttr);
f97c9854
JS
729 if (ErrorStatus == XpmSuccess)
730 {
731 // Set attributes
732 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
733 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
31528cd3 734
0d57be45
JS
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);
31528cd3 741
2d120f83
JS
742 /*
743 if ( xpmAttr.npixels > 2 )
744 {
f97c9854 745 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
2d120f83
JS
746 } else
747 {
f97c9854 748 M_BITMAPHANDLERDATA->m_depth = 1; // mono
2d120f83
JS
749 }
750 */
31528cd3 751
0d57be45 752 M_BITMAPHANDLERDATA->m_depth = depthRet;
31528cd3 753
f97c9854
JS
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 {
2d120f83 766 // XpmDebugError(ErrorStatus, NULL);
f97c9854
JS
767 M_BITMAPHANDLERDATA->m_ok = FALSE;
768 }
769 return M_BITMAPHANDLERDATA->m_ok ;
770}
771
31528cd3 772#endif // wxHAVE_LIB_XPM
4bb6408c
JS
773
774void 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
787void wxBitmap::InitStandardHandlers()
788{
f97c9854
JS
789 // Initialize all standard bitmap or derived class handlers here.
790 AddHandler(new wxXBMFileHandler);
791 AddHandler(new wxXBMDataHandler);
31528cd3
VZ
792
793 // XPM is considered standard for Motif, although it can be omitted if
794 // libXpm is not installed
795#if wxHAVE_LIB_XPM
4bb6408c
JS
796 AddHandler(new wxXPMFileHandler);
797 AddHandler(new wxXPMDataHandler);
31528cd3 798#endif // wxHAVE_LIB_XPM
f97c9854
JS
799}
800
801WXPixmap wxBitmap::GetLabelPixmap (WXWidget w)
802{
2d120f83
JS
803 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
804 return M_BITMAPDATA->m_pixmap;
31528cd3 805
2d120f83 806 Display *dpy = (Display*) M_BITMAPDATA->m_display;
31528cd3 807
f97c9854 808#ifdef FOO
2d120f83
JS
809 /*
810 If we do:
811 if (labelPixmap) return labelPixmap;
812 things can be wrong, because colors can have been changed.
31528cd3 813
2d120f83
JS
814 If we do:
815 if (labelPixmap)
816 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
817 we got BadDrawable if the pixmap is referenced by multiples widgets
31528cd3 818
2d120f83 819 this is a catch22!!
31528cd3 820
2d120f83
JS
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);
f97c9854 829#endif
31528cd3 830
2d120f83
JS
831 char tmp[128];
832 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
31528cd3 833
2d120f83
JS
834 Pixel fg, bg;
835 Widget widget = (Widget) w;
31528cd3 836
2d120f83
JS
837 while (XmIsGadget ( widget ))
838 widget = XtParent (widget);
839 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
31528cd3 840
2d120f83 841 M_BITMAPDATA->m_labelPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 842
2d120f83 843 return M_BITMAPDATA->m_labelPixmap;
f97c9854
JS
844}
845
846WXPixmap wxBitmap::GetArmPixmap (WXWidget w)
847{
2d120f83
JS
848 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
849 return M_BITMAPDATA->m_pixmap;
31528cd3 850
2d120f83 851 Display *dpy = (Display*) M_BITMAPDATA->m_display;
f97c9854 852#ifdef FOO
2d120f83
JS
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);
f97c9854 857#endif
31528cd3 858
2d120f83
JS
859 char tmp[128];
860 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
31528cd3 861
2d120f83
JS
862 Pixel fg, bg;
863 Widget widget = (Widget) w;
31528cd3 864
2d120f83
JS
865 XtVaGetValues (widget, XmNarmColor, &bg, NULL);
866 while (XmIsGadget (widget))
867 widget = XtParent (widget);
868 XtVaGetValues (widget, XmNforeground, &fg, NULL);
31528cd3 869
2d120f83 870 M_BITMAPDATA->m_armPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 871
2d120f83 872 return M_BITMAPDATA->m_armPixmap;
f97c9854
JS
873}
874
875WXPixmap wxBitmap::GetInsensPixmap (WXWidget w)
876{
2d120f83 877 Display *dpy = (Display*) M_BITMAPDATA->m_display;
31528cd3 878
0d57be45 879 if (M_BITMAPDATA->m_insensPixmap)
2d120f83 880 return M_BITMAPDATA->m_insensPixmap;
31528cd3 881
2d120f83
JS
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 }
31528cd3 890
2d120f83
JS
891 if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0)
892 return M_BITMAPDATA->m_pixmap;
31528cd3 893
f97c9854 894#ifdef FOO
2d120f83
JS
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);
f97c9854 899#endif
31528cd3 900
2d120f83
JS
901 char tmp[128];
902 sprintf (tmp, "Not%x", (unsigned int) M_BITMAPDATA->m_insensImage);
31528cd3 903
2d120f83
JS
904 Pixel fg, bg;
905 Widget widget = (Widget) w;
31528cd3 906
2d120f83
JS
907 while (XmIsGadget (widget))
908 widget = XtParent (widget);
909 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
31528cd3 910
2d120f83 911 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 912
2d120f83 913 return M_BITMAPDATA->m_insensPixmap;
f97c9854
JS
914}
915
916// We may need this sometime...
917
918/****************************************************************************
919
2d120f83
JS
920 NAME
921 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
31528cd3 922
2d120f83 923 SYNOPSIS
f97c9854 924 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
31528cd3 925
2d120f83
JS
926 DESCRIPTION
927 This function creates a grayed-out copy of the argument pixmap, suitable
928 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
31528cd3 929
2d120f83
JS
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.
31528cd3 933
2d120f83
JS
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().
31528cd3 937
2d120f83
JS
938 SEE ALSO
939 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
940 XFillRectangle(3), exit(2)
31528cd3 941
2d120f83
JS
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
31528cd3 947
f97c9854
JS
948*****************************************************************************/
949
950Pixmap
951XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
952
953{
2d120f83 954 static
31528cd3 955 char stipple_data[] =
2d120f83
JS
956 {
957 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
f97c9854
JS
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
2d120f83 961 };
f97c9854
JS
962 GC gc;
963 Pixmap ipixmap, stipple;
964 unsigned width, height, depth;
31528cd3 965
f97c9854
JS
966 Window window; /* These return values */
967 unsigned border; /* from XGetGeometry() */
968 int x, y; /* are not needed. */
31528cd3 969
f97c9854 970 ipixmap = 0;
31528cd3 971
f97c9854 972 if ( NULL == display || 0 == pixmap )
2d120f83 973 return ipixmap;
31528cd3 974
f97c9854 975 if ( 0 == XGetGeometry( display, pixmap, &window, &x, &y,
2d120f83
JS
976 &width, &height, &border, &depth )
977 )
978 return ipixmap; /* BadDrawable: probably an invalid pixmap */
31528cd3 979
2d120f83 980 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
f97c9854
JS
981 */
982 stipple = XCreateBitmapFromData( display, pixmap, stipple_data, 16, 16 );
983 if ( 0 != stipple )
984 {
2d120f83
JS
985 gc = XCreateGC( display, pixmap, (XtGCMask)0, (XGCValues*)NULL );
986 if ( NULL != gc )
f97c9854 987 {
2d120f83
JS
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 );
31528cd3 997
2d120f83
JS
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 );
f97c9854 1005 }
2d120f83 1006 XFreePixmap( display, stipple );
f97c9854
JS
1007 }
1008 return ipixmap;
4bb6408c 1009}
f97c9854 1010
321db4b6
JS
1011// Creates a bitmap with transparent areas drawn in
1012// the given colour.
1013wxBitmap wxCreateMaskedBitmap(wxBitmap& bitmap, wxColour& colour)
1014{
1015 wxBitmap newBitmap(bitmap.GetWidth(),
2d120f83
JS
1016 bitmap.GetHeight(),
1017 bitmap.GetDepth());
321db4b6
JS
1018 wxMemoryDC destDC;
1019 wxMemoryDC srcDC;
1020 srcDC.SelectObject(bitmap);
1021 destDC.SelectObject(newBitmap);
31528cd3 1022
321db4b6
JS
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);
31528cd3 1028
321db4b6
JS
1029 return newBitmap;
1030}