]> git.saurik.com Git - wxWidgets.git/blob - src/motif/bitmap.cpp
try to create smaller executables
[wxWidgets.git] / src / motif / bitmap.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: bitmap.cpp
3 // Purpose: wxBitmap
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 17/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "bitmap.h"
14 #endif
15
16 #ifdef __VMS
17 #define XtParent XTPARENT
18 #endif
19
20 #include "wx/setup.h"
21 #include "wx/utils.h"
22 #include "wx/palette.h"
23 #include "wx/bitmap.h"
24 #include "wx/icon.h"
25 #include "wx/log.h"
26 #include "wx/control.h"
27 #include "wx/dcmemory.h"
28 #include "wx/image.h"
29 #include "wx/app.h"
30
31 #ifdef __VMS__
32 #pragma message disable nosimpint
33 #endif
34 #include <Xm/Xm.h>
35 #ifdef __VMS__
36 #pragma message enable nosimpint
37 #endif
38
39 #include "wx/motif/private.h"
40
41 #if wxHAVE_LIB_XPM
42 #include <X11/xpm.h>
43 #endif
44 #include <math.h>
45
46
47 IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
48 IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
49
50 wxBitmapRefData::wxBitmapRefData()
51 {
52 m_ok = FALSE;
53 m_width = 0;
54 m_height = 0;
55 m_depth = 0;
56 m_quality = 0;
57 m_numColors = 0;
58 m_bitmapMask = NULL;
59
60 m_pixmap = (WXPixmap) 0;
61 m_display = (WXDisplay*) 0;
62
63 m_freePixmap = TRUE; //TODO: necessary?
64 m_freeColors = (unsigned long*) 0;
65 m_freeColorsCount = 0;
66
67 // These 5 variables are for wxControl
68 m_insensPixmap = (WXPixmap) 0;
69 m_labelPixmap = (WXPixmap) 0;
70 m_armPixmap = (WXPixmap) 0;
71 m_image = (WXImage*) 0;
72 m_insensImage = (WXImage*) 0;
73 }
74
75 wxBitmapRefData::~wxBitmapRefData()
76 {
77 if (m_labelPixmap)
78 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_labelPixmap);
79
80 if (m_armPixmap)
81 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_armPixmap);
82
83 if (m_insensPixmap)
84 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_insensPixmap);
85
86 if (m_image)
87 {
88 XmUninstallImage ((XImage*) m_image);
89 XtFree ((char *) (XImage*) m_image);
90 }
91
92 if (m_insensImage)
93 {
94 XmUninstallImage ((XImage*) m_insensImage);
95 delete[] ((XImage*) m_insensImage)->data;
96 XtFree ((char *) (XImage*) m_insensImage);
97 }
98 if (m_pixmap && m_freePixmap)
99 XFreePixmap ((Display*) m_display, (Pixmap) m_pixmap);
100
101 if (m_freeColors)
102 {
103 int screen = DefaultScreen((Display*) m_display);
104 Colormap cmp = DefaultColormap((Display*) m_display,screen);
105 long llp;
106 for(llp = 0;llp < m_freeColorsCount;llp++)
107 XFreeColors((Display*) m_display, cmp, &m_freeColors[llp], 1, 0L);
108 delete m_freeColors;
109 };
110
111 if (m_bitmapMask)
112 delete m_bitmapMask;
113 m_bitmapMask = NULL;
114 }
115
116 #define M_BMPDATA ((wxBitmapRefData *)m_refData)
117
118 wxBitmap::wxBitmap()
119 {
120 m_refData = NULL;
121 }
122
123 wxBitmap::~wxBitmap()
124 {
125 }
126
127 wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
128 {
129 m_refData = new wxBitmapRefData;
130
131 (void) Create((void*) bits, wxBITMAP_TYPE_XBM_DATA, width, height, depth);
132 }
133
134 wxBitmap::wxBitmap(int w, int h, int d)
135 {
136 (void)Create(w, h, d);
137 }
138
139 wxBitmap::wxBitmap(void *data, wxBitmapType type,
140 int width, int height, int depth)
141 {
142 (void) Create(data, type, width, height, depth);
143 }
144
145 wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type)
146 {
147 LoadFile(filename, type);
148 }
149
150 // Create from XPM data
151 static wxControl* sg_Control = NULL;
152 wxBitmap::wxBitmap(char **data, wxControl* control)
153 {
154 // Pass the control to the Create function using a global
155 sg_Control = control;
156
157 (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
158
159 sg_Control = (wxControl*) NULL;
160 }
161
162 bool wxBitmap::CreateFromXpm(const char **bits)
163 {
164 wxCHECK_MSG( bits, FALSE, _T("NULL pointer in wxBitmap::CreateFromXpm") );
165
166 return Create(bits, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
167 }
168
169 bool wxBitmap::CopyFromIcon(const wxIcon& icon)
170 {
171 *this = icon;
172 return TRUE;
173 }
174
175 bool wxBitmap::Create(int w, int h, int d)
176 {
177 UnRef();
178
179 m_refData = new wxBitmapRefData;
180
181 if (d < 1)
182 d = wxDisplayDepth();
183
184 M_BITMAPDATA->m_width = w;
185 M_BITMAPDATA->m_height = h;
186 M_BITMAPDATA->m_depth = d;
187 M_BITMAPDATA->m_freePixmap = TRUE;
188
189 Display *dpy = (Display*) wxGetDisplay();
190
191 M_BITMAPDATA->m_display = dpy; /* MATTHEW: [4] Remember the display */
192
193 M_BITMAPDATA->m_pixmap = (WXPixmap) XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)),
194 w, h, d);
195
196 M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_pixmap != (WXPixmap) 0) ;
197 return M_BITMAPDATA->m_ok;
198 }
199
200 bool wxBitmap::LoadFile(const wxString& filename, wxBitmapType type)
201 {
202 UnRef();
203
204 m_refData = new wxBitmapRefData;
205
206 wxBitmapHandler *handler = FindHandler(type);
207
208 if ( handler == NULL ) {
209 wxImage image;
210 if (!image.LoadFile( filename, type )) return FALSE;
211 if (image.Ok())
212 {
213 *this = wxBitmap(image);
214 return TRUE;
215 }
216 else return FALSE;
217 }
218
219 return handler->LoadFile(this, filename, type, -1, -1);
220 }
221
222 bool wxBitmap::Create(void *data, wxBitmapType type,
223 int width, int height, int depth)
224 {
225 UnRef();
226
227 m_refData = new wxBitmapRefData;
228
229 wxBitmapHandler *handler = FindHandler(type);
230
231 if ( handler == NULL ) {
232 wxLogWarning("no data bitmap handler for type %ld defined.",
233 (long)type);
234
235 return FALSE;
236 }
237
238 return handler->Create(this, data, type, width, height, depth);
239 }
240
241 bool wxBitmap::SaveFile(const wxString& filename, wxBitmapType type,
242 const wxPalette *palette) const
243 {
244 wxBitmapHandler *handler = FindHandler(type);
245
246 if ( handler == NULL ) { // try wxImage
247 wxImage image = this->ConvertToImage();
248 if (image.Ok()) return image.SaveFile( filename, type );
249 else return FALSE;
250 }
251
252 return handler->SaveFile(this, filename, type, palette);
253 }
254
255 void wxBitmap::SetWidth(int w)
256 {
257 if (!M_BITMAPDATA)
258 m_refData = new wxBitmapRefData;
259
260 M_BITMAPDATA->m_width = w;
261 }
262
263 void wxBitmap::SetHeight(int h)
264 {
265 if (!M_BITMAPDATA)
266 m_refData = new wxBitmapRefData;
267
268 M_BITMAPDATA->m_height = h;
269 }
270
271 void wxBitmap::SetDepth(int d)
272 {
273 if (!M_BITMAPDATA)
274 m_refData = new wxBitmapRefData;
275
276 M_BITMAPDATA->m_depth = d;
277 }
278
279 void wxBitmap::SetQuality(int q)
280 {
281 if (!M_BITMAPDATA)
282 m_refData = new wxBitmapRefData;
283
284 M_BITMAPDATA->m_quality = q;
285 }
286
287 void wxBitmap::SetOk(bool isOk)
288 {
289 if (!M_BITMAPDATA)
290 m_refData = new wxBitmapRefData;
291
292 M_BITMAPDATA->m_ok = isOk;
293 }
294
295 void wxBitmap::SetPalette(const wxPalette& palette)
296 {
297 if (!M_BITMAPDATA)
298 m_refData = new wxBitmapRefData;
299
300 M_BITMAPDATA->m_bitmapPalette = palette ;
301 }
302
303 void wxBitmap::SetMask(wxMask *mask)
304 {
305 if (!M_BITMAPDATA)
306 m_refData = new wxBitmapRefData;
307
308 M_BITMAPDATA->m_bitmapMask = mask ;
309 }
310
311 wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
312 {
313 wxCHECK_MSG( Ok() &&
314 (rect.x >= 0) && (rect.y >= 0) &&
315 (rect.x+rect.width <= M_BMPDATA->m_width) && (rect.y+rect.height <= M_BMPDATA->m_height),
316 wxNullBitmap, wxT("invalid bitmap or bitmap region") );
317
318 wxBitmap ret( rect.width, rect.height, 0 );
319 wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
320
321 // The remaining still TODO
322 return ret;
323 }
324
325 /*
326 * wxMask
327 */
328
329 wxMask::wxMask()
330 {
331 m_pixmap = (WXPixmap) 0;
332 }
333
334 // Construct a mask from a bitmap and a colour indicating
335 // the transparent area
336 wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
337 {
338 m_pixmap = (WXPixmap) 0;
339
340 Create(bitmap, colour);
341 }
342
343 // Construct a mask from a bitmap and a palette index indicating
344 // the transparent area
345 wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
346 {
347 m_pixmap = (WXPixmap) 0;
348
349 Create(bitmap, paletteIndex);
350 }
351
352 // Construct a mask from a mono bitmap (copies the bitmap).
353 wxMask::wxMask(const wxBitmap& bitmap)
354 {
355 m_pixmap = (WXPixmap) 0;
356
357 Create(bitmap);
358 }
359
360 wxMask::~wxMask()
361 {
362 // TODO: this may be the wrong display
363 if ( m_pixmap )
364 XFreePixmap ((Display*) wxGetDisplay(), (Pixmap) m_pixmap);
365 }
366
367 // Create a mask from a mono bitmap (copies the bitmap).
368 bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap))
369 {
370 // TODO
371 return FALSE;
372 }
373
374 // Create a mask from a bitmap and a palette index indicating
375 // the transparent area
376 bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap), int WXUNUSED(paletteIndex))
377 {
378 // TODO
379 return FALSE;
380 }
381
382 // Create a mask from a bitmap and a colour indicating
383 // the transparent area
384 bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap), const wxColour& WXUNUSED(colour))
385 {
386 // TODO
387 return FALSE;
388 }
389
390 /*
391 * wxBitmapHandler
392 */
393
394 IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
395
396 /*
397 * Standard handlers
398 */
399
400 class WXDLLEXPORT wxXBMFileHandler: public wxBitmapHandler
401 {
402 DECLARE_DYNAMIC_CLASS(wxXBMFileHandler)
403 public:
404 inline wxXBMFileHandler()
405 {
406 m_name = "XBM file";
407 m_extension = "xbm";
408 m_type = wxBITMAP_TYPE_XBM;
409 };
410
411 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
412 int desiredWidth, int desiredHeight);
413 };
414
415 IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler, wxBitmapHandler)
416
417 bool wxXBMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name,
418 long WXUNUSED(flags),
419 int WXUNUSED(desiredWidth),
420 int WXUNUSED(desiredHeight))
421 {
422 M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
423
424 int hotX, hotY;
425 unsigned int w, h;
426 Pixmap pixmap;
427
428 Display *dpy = (Display*) wxGetDisplay();
429 M_BITMAPDATA->m_display = (WXDisplay*) dpy;
430
431 int value = XReadBitmapFile (dpy, RootWindow (dpy, DefaultScreen (dpy)),
432 (char*) (const char*) name, &w, &h, &pixmap, &hotX, &hotY);
433 M_BITMAPHANDLERDATA->m_width = w;
434 M_BITMAPHANDLERDATA->m_height = h;
435 M_BITMAPHANDLERDATA->m_depth = 1;
436 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap;
437
438 if ((value == BitmapFileInvalid) ||
439 (value == BitmapOpenFailed) ||
440 (value == BitmapNoMemory))
441 {
442 M_BITMAPHANDLERDATA->m_ok = FALSE;
443 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) 0;
444 }
445 else
446 M_BITMAPHANDLERDATA->m_ok = TRUE;
447
448 return M_BITMAPHANDLERDATA->m_ok ;
449 }
450
451 class WXDLLEXPORT wxXBMDataHandler: public wxBitmapHandler
452 {
453 DECLARE_DYNAMIC_CLASS(wxXBMDataHandler)
454 public:
455 inline wxXBMDataHandler()
456 {
457 m_name = "XBM data";
458 m_extension = "xbm";
459 m_type = wxBITMAP_TYPE_XBM_DATA;
460 };
461
462 virtual bool Create(wxBitmap *bitmap, void *data, long flags,
463 int width, int height, int depth = 1);
464 };
465 IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler, wxBitmapHandler)
466
467 bool wxXBMDataHandler::Create( wxBitmap *bitmap, void *data,
468 long WXUNUSED(flags),
469 int width, int height, int WXUNUSED(depth))
470 {
471 M_BITMAPHANDLERDATA->m_width = width;
472 M_BITMAPHANDLERDATA->m_height = height;
473 M_BITMAPHANDLERDATA->m_depth = 1;
474 M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
475
476 Display *dpy = (Display*) wxGetDisplay();
477 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
478
479 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) XCreateBitmapFromData (dpy, RootWindow (dpy, DefaultScreen (dpy)), (char*) data, width, height);
480 M_BITMAPHANDLERDATA->m_ok = (M_BITMAPHANDLERDATA->m_pixmap != (WXPixmap) 0) ;
481
482 // code for wxControl. TODO: can we avoid doing this until we need it?
483 // E.g. have CreateButtonPixmaps which is called on demand.
484 XImage* image = (XImage *) XtMalloc (sizeof (XImage));
485 image->width = width;
486 image->height = height;
487 image->data = (char*) data;
488 image->depth = 1;
489 image->xoffset = 0;
490 image->format = XYBitmap;
491 image->byte_order = LSBFirst;
492 image->bitmap_unit = 8;
493 image->bitmap_bit_order = LSBFirst;
494 image->bitmap_pad = 8;
495 image->bytes_per_line = (width + 7) >> 3;
496
497 char tmp[128];
498 sprintf (tmp, "Im%x", (unsigned int) image);
499 XmInstallImage (image, tmp);
500
501 // Build our manually stipped pixmap.
502
503 int bpl = (width + 7) / 8;
504 char *data1 = new char[height * bpl];
505 char* bits = (char*) data;
506 int i;
507 for (i = 0; i < height; i++)
508 {
509 int mask = i % 2 ? 0x55 : 0xaa;
510 int j;
511 for (j = 0; j < bpl; j++)
512 data1[i * bpl + j] = bits[i * bpl + j] & mask;
513 }
514 XImage* insensImage = (XImage *) XtMalloc (sizeof (XImage));
515 insensImage->width = width;
516 insensImage->height = height;
517 insensImage->data = data1;
518 insensImage->depth = 1;
519 insensImage->xoffset = 0;
520 insensImage->format = XYBitmap;
521 insensImage->byte_order = LSBFirst;
522 insensImage->bitmap_unit = 8;
523 insensImage->bitmap_bit_order = LSBFirst;
524 insensImage->bitmap_pad = 8;
525 insensImage->bytes_per_line = bpl;
526
527 sprintf (tmp, "Not%x", (unsigned int)insensImage);
528 XmInstallImage (insensImage, tmp);
529
530 M_BITMAPHANDLERDATA->m_image = (WXImage*) image;
531 M_BITMAPHANDLERDATA->m_insensImage = (WXImage*) insensImage;
532
533 return TRUE;
534 }
535
536 #if wxHAVE_LIB_XPM
537 class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler
538 {
539 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler)
540 public:
541 inline wxXPMFileHandler()
542 {
543 m_name = "XPM file";
544 m_extension = "xpm";
545 m_type = wxBITMAP_TYPE_XPM;
546 };
547
548 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
549 int desiredWidth, int desiredHeight);
550 virtual bool SaveFile(const wxBitmap *bitmap, const wxString& name,
551 wxBitmapType type, const wxPalette *palette = NULL);
552 };
553
554 IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler)
555
556 bool wxXPMFileHandler::LoadFile( wxBitmap *bitmap, const wxString& name,
557 long WXUNUSED(flags),
558 int WXUNUSED(desiredWidth),
559 int WXUNUSED(desiredHeight) )
560 {
561 Display *dpy = (Display*) wxGetDisplay();
562 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
563
564 XpmAttributes xpmAttr;
565 Pixmap pixmap;
566 Pixmap mask = 0;
567
568 M_BITMAPHANDLERDATA->m_ok = FALSE;
569 xpmAttr.valuemask = XpmReturnInfos | XpmCloseness;
570 xpmAttr.closeness = 40000;
571 int errorStatus = XpmReadFileToPixmap(dpy,
572 RootWindow(dpy, DefaultScreen(dpy)), (char*) (const char*) name,
573 &pixmap, &mask, &xpmAttr);
574
575 if (errorStatus == XpmSuccess)
576 {
577 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap;
578 if ( mask )
579 {
580 M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask;
581 M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask);
582 }
583
584 unsigned int depthRet;
585 int xRet, yRet;
586 unsigned int widthRet, heightRet, borderWidthRet;
587 Window rootWindowRet;
588 XGetGeometry(dpy, pixmap, &rootWindowRet, &xRet, &yRet,
589 &widthRet, &heightRet, &borderWidthRet, &depthRet);
590
591 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
592 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
593
594 /*
595 if ( xpmAttr.npixels > 2 )
596 {
597 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
598 } else
599 {
600 M_BITMAPHANDLERDATA->m_depth = 1; // mono
601 }
602 */
603
604 M_BITMAPHANDLERDATA->m_depth = depthRet;
605
606 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
607
608 XpmFreeAttributes(&xpmAttr);
609
610 M_BITMAPHANDLERDATA->m_ok = TRUE;
611 return TRUE;
612 } else
613 {
614 // XpmDebugError(errorStatus, name);
615 M_BITMAPHANDLERDATA->m_ok = FALSE;
616 return FALSE;
617 }
618 }
619
620 bool wxXPMFileHandler::SaveFile( const wxBitmap *bitmap, const wxString& name,
621 wxBitmapType WXUNUSED(type),
622 const wxPalette *WXUNUSED(palette))
623 {
624 if (M_BITMAPHANDLERDATA->m_ok && M_BITMAPHANDLERDATA->m_pixmap)
625 {
626 Display *dpy = (Display*) M_BITMAPHANDLERDATA->m_display;
627 int errorStatus = XpmWriteFileFromPixmap(dpy, (char*) (const char*) name,
628 (Pixmap) M_BITMAPHANDLERDATA->m_pixmap,
629 (M_BITMAPHANDLERDATA->m_bitmapMask ? (Pixmap) M_BITMAPHANDLERDATA->m_bitmapMask->GetPixmap() : (Pixmap) 0),
630 (XpmAttributes *) NULL);
631 if (errorStatus == XpmSuccess)
632 return TRUE;
633 else
634 return FALSE;
635 }
636 else
637 return FALSE;
638 }
639
640 class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler
641 {
642 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
643 public:
644 inline wxXPMDataHandler()
645 {
646 m_name = "XPM data";
647 m_extension = "xpm";
648 m_type = wxBITMAP_TYPE_XPM_DATA;
649 };
650
651 virtual bool Create(wxBitmap *bitmap, void *data, long flags,
652 int width, int height, int depth = 1);
653 };
654 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
655
656 bool wxXPMDataHandler::Create( wxBitmap *bitmap, void *data,
657 long WXUNUSED(flags),
658 int width, int height, int WXUNUSED(depth))
659 {
660 M_BITMAPHANDLERDATA->m_width = width;
661 M_BITMAPHANDLERDATA->m_height = height;
662 M_BITMAPHANDLERDATA->m_depth = 1;
663 M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
664
665 Display *dpy = (Display*) wxGetDisplay();
666 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
667
668 XpmAttributes xpmAttr;
669
670 xpmAttr.valuemask = XpmReturnInfos; /* nothing yet, but get infos back */
671
672 XpmColorSymbol symbolicColors[4];
673 if (sg_Control && sg_Control->GetMainWidget())
674 {
675 symbolicColors[0].name = "foreground";
676 symbolicColors[0].value = NULL;
677 symbolicColors[1].name = "background";
678 symbolicColors[1].value = NULL;
679 XtVaGetValues((Widget) sg_Control->GetMainWidget(),
680 XmNforeground, &symbolicColors[0].pixel,
681 XmNbackground, &symbolicColors[1].pixel,NULL);
682 xpmAttr.numsymbols = 2;
683 xpmAttr.colorsymbols = symbolicColors;
684 xpmAttr.valuemask |= XpmColorSymbols; // add flag
685 }
686
687 Pixmap pixmap;
688 Pixmap mask = 0;
689 int ErrorStatus = XpmCreatePixmapFromData(dpy, RootWindow(dpy, DefaultScreen(dpy)),
690 (char**) data, &pixmap, &mask, &xpmAttr);
691 if (ErrorStatus == XpmSuccess)
692 {
693 // Set attributes
694 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
695 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
696
697 unsigned int depthRet;
698 int xRet, yRet;
699 unsigned int widthRet, heightRet, borderWidthRet;
700 Window rootWindowRet;
701 XGetGeometry(dpy, pixmap, &rootWindowRet, &xRet, &yRet,
702 &widthRet, &heightRet, &borderWidthRet, &depthRet);
703
704 /*
705 if ( xpmAttr.npixels > 2 )
706 {
707 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
708 } else
709 {
710 M_BITMAPHANDLERDATA->m_depth = 1; // mono
711 }
712 */
713
714 M_BITMAPHANDLERDATA->m_depth = depthRet;
715
716 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
717 XpmFreeAttributes(&xpmAttr);
718 M_BITMAPHANDLERDATA->m_ok = TRUE;
719 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap;
720 if ( mask )
721 {
722 M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask;
723 M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask);
724 }
725 }
726 else
727 {
728 // XpmDebugError(ErrorStatus, NULL);
729 M_BITMAPHANDLERDATA->m_ok = FALSE;
730 }
731 return M_BITMAPHANDLERDATA->m_ok ;
732 }
733
734 #endif // wxHAVE_LIB_XPM
735
736 void wxBitmap::InitStandardHandlers()
737 {
738 // Initialize all standard bitmap or derived class handlers here.
739 AddHandler(new wxXBMFileHandler);
740 AddHandler(new wxXBMDataHandler);
741
742 // XPM is considered standard for Motif, although it can be omitted if
743 // libXpm is not installed
744 #if wxHAVE_LIB_XPM
745 AddHandler(new wxXPMFileHandler);
746 AddHandler(new wxXPMDataHandler);
747 #endif // wxHAVE_LIB_XPM
748 }
749
750 WXPixmap wxBitmap::GetLabelPixmap (WXWidget w)
751 {
752 if (!M_BITMAPDATA)
753 return (WXPixmap)NULL;
754 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
755 return M_BITMAPDATA->m_pixmap;
756
757 Display *dpy = (Display*) M_BITMAPDATA->m_display;
758
759 #ifdef FOO
760 /*
761 If we do:
762 if (labelPixmap) return labelPixmap;
763 things can be wrong, because colors can have been changed.
764
765 If we do:
766 if (labelPixmap)
767 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
768 we got BadDrawable if the pixmap is referenced by multiples widgets
769
770 this is a catch22!!
771
772 So, before doing thing really clean, I just do nothing; if the pixmap is
773 referenced by many widgets, Motif performs caching functions.
774 And if pixmap is referenced with multiples colors, we just have some
775 memory leaks... I hope we can deal with them...
776 */
777 // Must be destroyed, because colours can have been changed!
778 if (M_BITMAPDATA->m_labelPixmap)
779 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_labelPixmap);
780 #endif
781
782 char tmp[128];
783 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
784
785 Pixel fg, bg;
786 Widget widget = (Widget) w;
787
788 while (XmIsGadget ( widget ))
789 widget = XtParent (widget);
790 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
791
792 M_BITMAPDATA->m_labelPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
793
794 return M_BITMAPDATA->m_labelPixmap;
795 }
796
797 WXPixmap wxBitmap::GetArmPixmap (WXWidget w)
798 {
799 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
800 return M_BITMAPDATA->m_pixmap;
801
802 Display *dpy = (Display*) M_BITMAPDATA->m_display;
803 #ifdef FOO
804 // See GetLabelPixmap () comment
805
806 // Must be destroyed, because colours can have been changed!
807 if (M_BITMAPDATA->m_armPixmap)
808 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_armPixmap);
809 #endif
810
811 char tmp[128];
812 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
813
814 Pixel fg, bg;
815 Widget widget = (Widget) w;
816
817 XtVaGetValues (widget, XmNarmColor, &bg, NULL);
818 while (XmIsGadget (widget))
819 widget = XtParent (widget);
820 XtVaGetValues (widget, XmNforeground, &fg, NULL);
821
822 M_BITMAPDATA->m_armPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
823
824 return M_BITMAPDATA->m_armPixmap;
825 }
826
827 WXPixmap wxBitmap::GetInsensPixmap (WXWidget w)
828 {
829 Display *dpy = (Display*) M_BITMAPDATA->m_display;
830
831 if (!M_BITMAPDATA)
832 return (WXPixmap)NULL;
833 if (M_BITMAPDATA->m_insensPixmap)
834 return M_BITMAPDATA->m_insensPixmap;
835
836 if (!w)
837 {
838 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XCreateInsensitivePixmap(dpy, (Pixmap) M_BITMAPDATA->m_pixmap);
839 if (M_BITMAPDATA->m_insensPixmap)
840 return M_BITMAPDATA->m_insensPixmap;
841 else
842 return M_BITMAPDATA->m_pixmap;
843 }
844
845 if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0)
846 return M_BITMAPDATA->m_pixmap;
847
848 #ifdef FOO
849 See GetLabelPixmap () comment
850 // Must be destroyed, because colours can have been changed!
851 if (M_BITMAPDATA->m_insensPixmap)
852 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), (Pixmap) M_BITMAPDATA->m_insensPixmap);
853 #endif
854
855 char tmp[128];
856 sprintf (tmp, "Not%x", (unsigned int) M_BITMAPDATA->m_insensImage);
857
858 Pixel fg, bg;
859 Widget widget = (Widget) w;
860
861 while (XmIsGadget (widget))
862 widget = XtParent (widget);
863 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
864
865 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
866
867 return M_BITMAPDATA->m_insensPixmap;
868 }
869
870 // We may need this sometime...
871
872 /****************************************************************************
873
874 NAME
875 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
876
877 SYNOPSIS
878 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
879
880 DESCRIPTION
881 This function creates a grayed-out copy of the argument pixmap, suitable
882 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
883
884 RETURN VALUES
885 The return value is the new Pixmap id or zero on error. Errors include
886 a NULL display argument or an invalid Pixmap argument.
887
888 ERRORS
889 If one of the XLib functions fail, it will produce a X error. The
890 default X error handler prints a diagnostic and calls exit().
891
892 SEE ALSO
893 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
894 XFillRectangle(3), exit(2)
895
896 AUTHOR
897 John R Veregge - john@puente.jpl.nasa.gov
898 Advanced Engineering and Prototyping Group (AEG)
899 Information Systems Technology Section (395)
900 Jet Propulsion Lab - Calif Institute of Technology
901
902 *****************************************************************************/
903
904 Pixmap
905 XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
906
907 {
908 static char stipple_data[] =
909 {
910 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
911 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
912 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
913 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA
914 };
915 GC gc;
916 Pixmap ipixmap, stipple;
917 unsigned width, height, depth;
918
919 Window window; /* These return values */
920 unsigned border; /* from XGetGeometry() */
921 int x, y; /* are not needed. */
922
923 ipixmap = 0;
924
925 if ( NULL == display || 0 == pixmap )
926 return ipixmap;
927
928 if ( 0 == XGetGeometry( display, pixmap, &window, &x, &y,
929 &width, &height, &border, &depth )
930 )
931 return ipixmap; /* BadDrawable: probably an invalid pixmap */
932
933 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
934 */
935 stipple = XCreateBitmapFromData( display, pixmap, stipple_data, 16, 16 );
936 if ( 0 != stipple )
937 {
938 gc = XCreateGC( display, pixmap, (XtGCMask)0, (XGCValues*)NULL );
939 if ( NULL != gc )
940 {
941 /* Create an identical copy of the argument pixmap.
942 */
943 ipixmap = XCreatePixmap( display, pixmap, width, height, depth );
944 if ( 0 != ipixmap )
945 {
946 /* Copy the argument pixmap into the new pixmap.
947 */
948 XCopyArea( display, pixmap, ipixmap,
949 gc, 0, 0, width, height, 0, 0 );
950
951 /* Refill the new pixmap using the stipple algorithm/pixmap.
952 */
953 XSetStipple( display, gc, stipple );
954 XSetFillStyle( display, gc, FillStippled );
955 XFillRectangle( display, ipixmap, gc, 0, 0, width, height );
956 }
957 XFreeGC( display, gc );
958 }
959 XFreePixmap( display, stipple );
960 }
961 return ipixmap;
962 }
963
964 // Creates a bitmap with transparent areas drawn in
965 // the given colour.
966 wxBitmap wxCreateMaskedBitmap(const wxBitmap& bitmap, wxColour& colour)
967 {
968 wxBitmap newBitmap(bitmap.GetWidth(),
969 bitmap.GetHeight(),
970 bitmap.GetDepth());
971 wxMemoryDC destDC;
972 wxMemoryDC srcDC;
973 srcDC.SelectObject(bitmap);
974 destDC.SelectObject(newBitmap);
975
976 wxBrush brush(colour, wxSOLID);
977 destDC.SetOptimization(FALSE);
978 destDC.SetBackground(brush);
979 destDC.Clear();
980 destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(), & srcDC, 0, 0, wxCOPY, TRUE);
981
982 return newBitmap;
983 }
984
985
986
987
988 //-----------------------------------------------------------------------------
989 // wxImage conversion routines
990 //-----------------------------------------------------------------------------
991
992 /*
993
994 Date: Wed, 05 Jan 2000 11:45:40 +0100
995 From: Frits Boel <boel@niob.knaw.nl>
996 To: julian.smart@ukonline.co.uk
997 Subject: Patch for Motif ConvertToBitmap
998
999 Hi Julian,
1000
1001 I've been working on a wxWin application for image processing. From the
1002 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1003 till I looked in the source code of image.cpp. I saw that converting a
1004 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1005 to the 256 colors of the palet. A very time-consuming piece of code!
1006
1007 Because I wanted a faster application, I've made a 'patch' for this. In
1008 short: every pixel of the image is compared to a sorted list with
1009 colors. If the color is found in the list, the palette entry is
1010 returned; if the color is not found, the color palette is searched and
1011 then the palette entry is returned and the color added to the sorted
1012 list.
1013
1014 Maybe there is another method for this, namely changing the palette
1015 itself (if the colors are known, as is the case with tiffs with a
1016 colormap). I did not look at this, maybe someone else did?
1017
1018 The code of the patch is attached, have a look on it, and maybe you will
1019 ship it with the next release of wxMotif?
1020
1021 Regards,
1022
1023 Frits Boel
1024 Software engineer at Hubrecht Laboratory, The Netherlands.
1025
1026 */
1027
1028 class wxSearchColor
1029 {
1030 public:
1031 wxSearchColor( void );
1032 wxSearchColor( int size, XColor *colors );
1033 ~wxSearchColor( void );
1034
1035 int SearchColor( int r, int g, int b );
1036 private:
1037 int AddColor( unsigned int value, int pos );
1038
1039 int size;
1040 XColor *colors;
1041 unsigned int *color;
1042 int *entry;
1043
1044 int bottom;
1045 int top;
1046 };
1047
1048 wxSearchColor::wxSearchColor( void )
1049 {
1050 size = 0;
1051 colors = (XColor*) NULL;
1052 color = (unsigned int *) NULL;
1053 entry = (int*) NULL;
1054
1055 bottom = 0;
1056 top = 0;
1057 }
1058
1059 wxSearchColor::wxSearchColor( int size_, XColor *colors_ )
1060 {
1061 int i;
1062 size = size_;
1063 colors = colors_;
1064 color = new unsigned int[size];
1065 entry = new int [size];
1066
1067 for (i = 0; i < size; i++ ) {
1068 entry[i] = -1;
1069 }
1070
1071 bottom = top = ( size >> 1 );
1072 }
1073
1074 wxSearchColor::~wxSearchColor( void )
1075 {
1076 if ( color ) delete color;
1077 if ( entry ) delete entry;
1078 }
1079
1080 int wxSearchColor::SearchColor( int r, int g, int b )
1081 {
1082 unsigned int value = ( ( ( r * 256 ) + g ) * 256 ) + b;
1083 int begin = bottom;
1084 int end = top;
1085 int middle = 0;
1086
1087 while ( begin <= end ) {
1088
1089 middle = ( begin + end ) >> 1;
1090
1091 if ( value == color[middle] ) {
1092 return( entry[middle] );
1093 } else if ( value < color[middle] ) {
1094 end = middle - 1;
1095 } else {
1096 begin = middle + 1;
1097 }
1098
1099 }
1100
1101 return AddColor( value, middle );
1102 }
1103
1104 int wxSearchColor::AddColor( unsigned int value, int pos )
1105 {
1106 int i;
1107 int pixel = -1;
1108 int max = 3 * (65536);
1109 for ( i = 0; i < 256; i++ ) {
1110 int rdiff = ((value >> 8) & 0xFF00 ) - colors[i].red;
1111 int gdiff = ((value ) & 0xFF00 ) - colors[i].green;
1112 int bdiff = ((value << 8) & 0xFF00 ) - colors[i].blue;
1113 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1114 if (sum < max) { pixel = i; max = sum; }
1115 }
1116
1117 if ( entry[pos] < 0 ) {
1118 color[pos] = value;
1119 entry[pos] = pixel;
1120 } else if ( value < color[pos] ) {
1121
1122 if ( bottom > 0 ) {
1123 for ( i = bottom; i < pos; i++ ) {
1124 color[i-1] = color[i];
1125 entry[i-1] = entry[i];
1126 }
1127 bottom--;
1128 color[pos-1] = value;
1129 entry[pos-1] = pixel;
1130 } else if ( top < size-1 ) {
1131 for ( i = top; i >= pos; i-- ) {
1132 color[i+1] = color[i];
1133 entry[i+1] = entry[i];
1134 }
1135 top++;
1136 color[pos] = value;
1137 entry[pos] = pixel;
1138 }
1139
1140 } else {
1141
1142 if ( top < size-1 ) {
1143 for ( i = top; i > pos; i-- ) {
1144 color[i+1] = color[i];
1145 entry[i+1] = entry[i];
1146 }
1147 top++;
1148 color[pos+1] = value;
1149 entry[pos+1] = pixel;
1150 } else if ( bottom > 0 ) {
1151 for ( i = bottom; i < pos; i++ ) {
1152 color[i-1] = color[i];
1153 entry[i-1] = entry[i];
1154 }
1155 bottom--;
1156 color[pos] = value;
1157 entry[pos] = pixel;
1158 }
1159
1160 }
1161
1162 return( pixel );
1163 }
1164
1165
1166 bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
1167 {
1168 wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") )
1169 wxCHECK_MSG( depth == -1, FALSE, wxT("invalid bitmap depth") )
1170
1171 m_refData = new wxBitmapRefData();
1172
1173 int width = image.GetWidth();
1174 int height = image.GetHeight();
1175
1176 SetHeight( height );
1177 SetWidth( width );
1178
1179 Display *dpy = (Display*) wxGetDisplay();
1180 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1181 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1182
1183 // Create image
1184
1185 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
1186 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
1187
1188 Create( width, height, bpp );
1189
1190 // Create mask
1191
1192 XImage *mask_image = (XImage*) NULL;
1193 if (image.HasMask())
1194 {
1195 mask_image = XCreateImage( dpy, vis, 1, ZPixmap, 0, 0, width, height, 32, 0 );
1196 mask_image->data = (char*) malloc( mask_image->bytes_per_line * mask_image->height );
1197 }
1198
1199 // Retrieve depth info
1200
1201 XVisualInfo vinfo_template;
1202 XVisualInfo *vi;
1203
1204 vinfo_template.visual = vis;
1205 vinfo_template.visualid = XVisualIDFromVisual( vis );
1206 vinfo_template.depth = bpp;
1207 int nitem = 0;
1208
1209 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1210
1211 wxCHECK_MSG( vi, FALSE, wxT("no visual") );
1212
1213 XFree( vi );
1214
1215 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1216 if (bpp < 8) bpp = 8;
1217
1218 // Render
1219
1220 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1221 byte_order b_o = RGB;
1222
1223 if (bpp >= 24)
1224 {
1225 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1226 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1227 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1228 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1229 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1230 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1231 }
1232
1233 int r_mask = image.GetMaskRed();
1234 int g_mask = image.GetMaskGreen();
1235 int b_mask = image.GetMaskBlue();
1236
1237 XColor colors[256];
1238 if (bpp == 8)
1239 {
1240 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
1241
1242 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1243 XQueryColors( dpy, cmap, colors, 256 );
1244 }
1245
1246 wxSearchColor scolor( 256, colors );
1247 unsigned char* data = image.GetData();
1248
1249 bool hasMask = image.HasMask();
1250
1251 int index = 0;
1252 for (int y = 0; y < height; y++)
1253 {
1254 for (int x = 0; x < width; x++)
1255 {
1256 int r = data[index];
1257 index++;
1258 int g = data[index];
1259 index++;
1260 int b = data[index];
1261 index++;
1262
1263 if (hasMask)
1264 {
1265 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1266 XPutPixel( mask_image, x, y, 0 );
1267 else
1268 XPutPixel( mask_image, x, y, 1 );
1269 }
1270
1271 switch (bpp)
1272 {
1273 case 8:
1274 {
1275 #if 0 // Old, slower code
1276 int pixel = -1;
1277 /*
1278 if (wxTheApp->m_colorCube)
1279 {
1280 pixel = wxTheApp->m_colorCube
1281 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1282 }
1283 else
1284 {
1285 */
1286 int max = 3 * (65536);
1287 for (int i = 0; i < 256; i++)
1288 {
1289 int rdiff = (r << 8) - colors[i].red;
1290 int gdiff = (g << 8) - colors[i].green;
1291 int bdiff = (b << 8) - colors[i].blue;
1292 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1293 if (sum < max) { pixel = i; max = sum; }
1294 }
1295 /*
1296 }
1297 */
1298 #endif
1299
1300 // And this is all to get the 'right' color...
1301 int pixel = scolor.SearchColor( r, g, b );
1302 XPutPixel( data_image, x, y, pixel );
1303 break;
1304 }
1305 case 15:
1306 {
1307 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1308 XPutPixel( data_image, x, y, pixel );
1309 break;
1310 }
1311 case 16:
1312 {
1313 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1314 XPutPixel( data_image, x, y, pixel );
1315 break;
1316 }
1317 case 32:
1318 case 24:
1319 {
1320 int pixel = 0;
1321 switch (b_o)
1322 {
1323 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1324 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1325 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1326 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1327 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1328 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1329 }
1330 XPutPixel( data_image, x, y, pixel );
1331 }
1332 default: break;
1333 }
1334 } // for
1335 } // for
1336
1337 // Blit picture
1338
1339 XGCValues gcvalues;
1340 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1341 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1342 XPutImage( dpy, (Drawable)GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
1343
1344 XDestroyImage( data_image );
1345 XFreeGC( dpy, gc );
1346
1347 // Blit mask
1348 if (image.HasMask())
1349 {
1350 wxBitmap maskBitmap(width, height, 1);
1351
1352 GC gcMask = XCreateGC( dpy, (Pixmap) maskBitmap.GetPixmap(), (XtGCMask) 0, (XGCValues*)NULL );
1353 XPutImage( dpy, (Drawable)maskBitmap.GetPixmap(), gcMask, mask_image, 0, 0, 0, 0, width, height );
1354
1355 XDestroyImage( mask_image );
1356 XFreeGC( dpy, gcMask );
1357
1358 wxMask* mask = new wxMask;
1359 mask->SetPixmap(maskBitmap.GetPixmap());
1360
1361 SetMask(mask);
1362
1363 maskBitmap.SetPixmapNull();
1364 }
1365
1366
1367 return TRUE;
1368 }
1369
1370 wxImage wxBitmap::ConvertToImage() const
1371 {
1372 wxImage image;
1373
1374 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
1375
1376 Display *dpy = (Display*) wxGetDisplay();
1377 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1378 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1379
1380 XImage *ximage = XGetImage( dpy,
1381 (Drawable)GetPixmap(),
1382 0, 0,
1383 GetWidth(), GetHeight(),
1384 AllPlanes, ZPixmap );
1385
1386 wxCHECK_MSG( ximage, wxNullImage, wxT("couldn't create image") );
1387
1388 image.Create( GetWidth(), GetHeight() );
1389 char unsigned *data = image.GetData();
1390
1391 if (!data)
1392 {
1393 XDestroyImage( ximage );
1394 wxFAIL_MSG( wxT("couldn't create image") );
1395 return wxNullImage;
1396 }
1397
1398 /*
1399 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1400 if (GetMask())
1401 {
1402 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
1403 0, 0,
1404 GetWidth(), GetHeight() );
1405
1406 image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1407 }
1408 */
1409
1410 // Retrieve depth info
1411
1412 XVisualInfo vinfo_template;
1413 XVisualInfo *vi;
1414
1415 vinfo_template.visual = vis;
1416 vinfo_template.visualid = XVisualIDFromVisual( vis );
1417 vinfo_template.depth = bpp;
1418 int nitem = 0;
1419
1420 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1421
1422 wxCHECK_MSG( vi, wxNullImage, wxT("no visual") );
1423
1424 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1425
1426 XFree( vi );
1427
1428 XColor colors[256];
1429 if (bpp == 8)
1430 {
1431 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
1432
1433 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1434 XQueryColors( dpy, cmap, colors, 256 );
1435 }
1436
1437 long pos = 0;
1438 for (int j = 0; j < GetHeight(); j++)
1439 {
1440 for (int i = 0; i < GetWidth(); i++)
1441 {
1442 int pixel = XGetPixel( ximage, i, j );
1443 if (bpp <= 8)
1444 {
1445 data[pos] = colors[pixel].red >> 8;
1446 data[pos+1] = colors[pixel].green >> 8;
1447 data[pos+2] = colors[pixel].blue >> 8;
1448 } else if (bpp == 15)
1449 {
1450 data[pos] = (pixel >> 7) & 0xf8;
1451 data[pos+1] = (pixel >> 2) & 0xf8;
1452 data[pos+2] = (pixel << 3) & 0xf8;
1453 } else if (bpp == 16)
1454 {
1455 data[pos] = (pixel >> 8) & 0xf8;
1456 data[pos+1] = (pixel >> 3) & 0xfc;
1457 data[pos+2] = (pixel << 3) & 0xf8;
1458 } else
1459 {
1460 data[pos] = (pixel >> 16) & 0xff;
1461 data[pos+1] = (pixel >> 8) & 0xff;
1462 data[pos+2] = pixel & 0xff;
1463 }
1464
1465 /*
1466 if (gdk_image_mask)
1467 {
1468 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1469 if (mask_pixel == 0)
1470 {
1471 data[pos] = 16;
1472 data[pos+1] = 16;
1473 data[pos+2] = 16;
1474 }
1475 }
1476 */
1477
1478 pos += 3;
1479 }
1480 }
1481
1482 XDestroyImage( ximage );
1483 /*
1484 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1485 */
1486
1487 return image;
1488 }