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