]> git.saurik.com Git - wxWidgets.git/blob - src/motif/bitmap.cpp
fix bug in Borland (bcc32 really hates ?)
[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 wxConstCast(name.c_str(), char), &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)),
573 wxConstCast(name.c_str(), char),
574 &pixmap, &mask, &xpmAttr);
575
576 if (errorStatus == XpmSuccess)
577 {
578 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap;
579 if ( mask )
580 {
581 M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask;
582 M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask);
583 }
584
585 unsigned int depthRet;
586 int xRet, yRet;
587 unsigned int widthRet, heightRet, borderWidthRet;
588 Window rootWindowRet;
589 XGetGeometry(dpy, pixmap, &rootWindowRet, &xRet, &yRet,
590 &widthRet, &heightRet, &borderWidthRet, &depthRet);
591
592 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
593 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
594
595 /*
596 if ( xpmAttr.npixels > 2 )
597 {
598 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
599 } else
600 {
601 M_BITMAPHANDLERDATA->m_depth = 1; // mono
602 }
603 */
604
605 M_BITMAPHANDLERDATA->m_depth = depthRet;
606
607 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
608
609 XpmFreeAttributes(&xpmAttr);
610
611 M_BITMAPHANDLERDATA->m_ok = TRUE;
612 return TRUE;
613 } else
614 {
615 // XpmDebugError(errorStatus, name);
616 M_BITMAPHANDLERDATA->m_ok = FALSE;
617 return FALSE;
618 }
619 }
620
621 bool wxXPMFileHandler::SaveFile( const wxBitmap *bitmap, const wxString& name,
622 wxBitmapType WXUNUSED(type),
623 const wxPalette *WXUNUSED(palette))
624 {
625 if (M_BITMAPHANDLERDATA->m_ok && M_BITMAPHANDLERDATA->m_pixmap)
626 {
627 Display *dpy = (Display*) M_BITMAPHANDLERDATA->m_display;
628 int errorStatus = XpmWriteFileFromPixmap(dpy,
629 wxConstCast(name.c_str(), char),
630 (Pixmap) M_BITMAPHANDLERDATA->m_pixmap,
631 (M_BITMAPHANDLERDATA->m_bitmapMask ? (Pixmap) M_BITMAPHANDLERDATA->m_bitmapMask->GetPixmap() : (Pixmap) 0),
632 (XpmAttributes *) NULL);
633 if (errorStatus == XpmSuccess)
634 return TRUE;
635 else
636 return FALSE;
637 }
638 else
639 return FALSE;
640 }
641
642 class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler
643 {
644 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
645 public:
646 inline wxXPMDataHandler()
647 {
648 m_name = "XPM data";
649 m_extension = "xpm";
650 m_type = wxBITMAP_TYPE_XPM_DATA;
651 };
652
653 virtual bool Create(wxBitmap *bitmap, void *data, long flags,
654 int width, int height, int depth = 1);
655 };
656 IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
657
658 bool wxXPMDataHandler::Create( wxBitmap *bitmap, void *data,
659 long WXUNUSED(flags),
660 int width, int height, int WXUNUSED(depth))
661 {
662 M_BITMAPHANDLERDATA->m_width = width;
663 M_BITMAPHANDLERDATA->m_height = height;
664 M_BITMAPHANDLERDATA->m_depth = 1;
665 M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
666
667 Display *dpy = (Display*) wxGetDisplay();
668 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
669
670 XpmAttributes xpmAttr;
671
672 xpmAttr.valuemask = XpmReturnInfos; /* nothing yet, but get infos back */
673
674 XpmColorSymbol symbolicColors[4];
675 if (sg_Control && sg_Control->GetMainWidget())
676 {
677 symbolicColors[0].name = "foreground";
678 symbolicColors[0].value = NULL;
679 symbolicColors[1].name = "background";
680 symbolicColors[1].value = NULL;
681 XtVaGetValues((Widget) sg_Control->GetMainWidget(),
682 XmNforeground, &symbolicColors[0].pixel,
683 XmNbackground, &symbolicColors[1].pixel,NULL);
684 xpmAttr.numsymbols = 2;
685 xpmAttr.colorsymbols = symbolicColors;
686 xpmAttr.valuemask |= XpmColorSymbols; // add flag
687 }
688
689 Pixmap pixmap;
690 Pixmap mask = 0;
691 int ErrorStatus = XpmCreatePixmapFromData(dpy, RootWindow(dpy, DefaultScreen(dpy)),
692 (char**) data, &pixmap, &mask, &xpmAttr);
693 if (ErrorStatus == XpmSuccess)
694 {
695 // Set attributes
696 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
697 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
698
699 unsigned int depthRet;
700 int xRet, yRet;
701 unsigned int widthRet, heightRet, borderWidthRet;
702 Window rootWindowRet;
703 XGetGeometry(dpy, pixmap, &rootWindowRet, &xRet, &yRet,
704 &widthRet, &heightRet, &borderWidthRet, &depthRet);
705
706 /*
707 if ( xpmAttr.npixels > 2 )
708 {
709 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
710 } else
711 {
712 M_BITMAPHANDLERDATA->m_depth = 1; // mono
713 }
714 */
715
716 M_BITMAPHANDLERDATA->m_depth = depthRet;
717
718 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
719 XpmFreeAttributes(&xpmAttr);
720 M_BITMAPHANDLERDATA->m_ok = TRUE;
721 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap;
722 if ( mask )
723 {
724 M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask;
725 M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask);
726 }
727 }
728 else
729 {
730 // XpmDebugError(ErrorStatus, NULL);
731 M_BITMAPHANDLERDATA->m_ok = FALSE;
732 }
733 return M_BITMAPHANDLERDATA->m_ok ;
734 }
735
736 #endif // wxHAVE_LIB_XPM
737
738 void wxBitmap::InitStandardHandlers()
739 {
740 // Initialize all standard bitmap or derived class handlers here.
741 AddHandler(new wxXBMFileHandler);
742 AddHandler(new wxXBMDataHandler);
743
744 // XPM is considered standard for Motif, although it can be omitted if
745 // libXpm is not installed
746 #if wxHAVE_LIB_XPM
747 AddHandler(new wxXPMFileHandler);
748 AddHandler(new wxXPMDataHandler);
749 #endif // wxHAVE_LIB_XPM
750 }
751
752 WXPixmap wxBitmap::GetLabelPixmap (WXWidget w)
753 {
754 if (!M_BITMAPDATA)
755 return (WXPixmap)NULL;
756 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
757 return M_BITMAPDATA->m_pixmap;
758
759 Display *dpy = (Display*) M_BITMAPDATA->m_display;
760
761 #ifdef FOO
762 /*
763 If we do:
764 if (labelPixmap) return labelPixmap;
765 things can be wrong, because colors can have been changed.
766
767 If we do:
768 if (labelPixmap)
769 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
770 we got BadDrawable if the pixmap is referenced by multiples widgets
771
772 this is a catch22!!
773
774 So, before doing thing really clean, I just do nothing; if the pixmap is
775 referenced by many widgets, Motif performs caching functions.
776 And if pixmap is referenced with multiples colors, we just have some
777 memory leaks... I hope we can deal with them...
778 */
779 // Must be destroyed, because colours can have been changed!
780 if (M_BITMAPDATA->m_labelPixmap)
781 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_labelPixmap);
782 #endif
783
784 char tmp[128];
785 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
786
787 Pixel fg, bg;
788 Widget widget = (Widget) w;
789
790 while (XmIsGadget ( widget ))
791 widget = XtParent (widget);
792 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
793
794 M_BITMAPDATA->m_labelPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
795
796 return M_BITMAPDATA->m_labelPixmap;
797 }
798
799 WXPixmap wxBitmap::GetArmPixmap (WXWidget w)
800 {
801 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
802 return M_BITMAPDATA->m_pixmap;
803
804 Display *dpy = (Display*) M_BITMAPDATA->m_display;
805 #ifdef FOO
806 // See GetLabelPixmap () comment
807
808 // Must be destroyed, because colours can have been changed!
809 if (M_BITMAPDATA->m_armPixmap)
810 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_armPixmap);
811 #endif
812
813 char tmp[128];
814 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
815
816 Pixel fg, bg;
817 Widget widget = (Widget) w;
818
819 XtVaGetValues (widget, XmNarmColor, &bg, NULL);
820 while (XmIsGadget (widget))
821 widget = XtParent (widget);
822 XtVaGetValues (widget, XmNforeground, &fg, NULL);
823
824 M_BITMAPDATA->m_armPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
825
826 return M_BITMAPDATA->m_armPixmap;
827 }
828
829 WXPixmap wxBitmap::GetInsensPixmap (WXWidget w)
830 {
831 Display *dpy = (Display*) M_BITMAPDATA->m_display;
832
833 if (!M_BITMAPDATA)
834 return (WXPixmap)NULL;
835 if (M_BITMAPDATA->m_insensPixmap)
836 return M_BITMAPDATA->m_insensPixmap;
837
838 if (!w)
839 {
840 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XCreateInsensitivePixmap(dpy, (Pixmap) M_BITMAPDATA->m_pixmap);
841 if (M_BITMAPDATA->m_insensPixmap)
842 return M_BITMAPDATA->m_insensPixmap;
843 else
844 return M_BITMAPDATA->m_pixmap;
845 }
846
847 if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0)
848 return M_BITMAPDATA->m_pixmap;
849
850 #ifdef FOO
851 See GetLabelPixmap () comment
852 // Must be destroyed, because colours can have been changed!
853 if (M_BITMAPDATA->m_insensPixmap)
854 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), (Pixmap) M_BITMAPDATA->m_insensPixmap);
855 #endif
856
857 char tmp[128];
858 sprintf (tmp, "Not%x", (unsigned int) M_BITMAPDATA->m_insensImage);
859
860 Pixel fg, bg;
861 Widget widget = (Widget) w;
862
863 while (XmIsGadget (widget))
864 widget = XtParent (widget);
865 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
866
867 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
868
869 return M_BITMAPDATA->m_insensPixmap;
870 }
871
872 // We may need this sometime...
873
874 /****************************************************************************
875
876 NAME
877 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
878
879 SYNOPSIS
880 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
881
882 DESCRIPTION
883 This function creates a grayed-out copy of the argument pixmap, suitable
884 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
885
886 RETURN VALUES
887 The return value is the new Pixmap id or zero on error. Errors include
888 a NULL display argument or an invalid Pixmap argument.
889
890 ERRORS
891 If one of the XLib functions fail, it will produce a X error. The
892 default X error handler prints a diagnostic and calls exit().
893
894 SEE ALSO
895 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
896 XFillRectangle(3), exit(2)
897
898 AUTHOR
899 John R Veregge - john@puente.jpl.nasa.gov
900 Advanced Engineering and Prototyping Group (AEG)
901 Information Systems Technology Section (395)
902 Jet Propulsion Lab - Calif Institute of Technology
903
904 *****************************************************************************/
905
906 Pixmap
907 XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
908
909 {
910 static char stipple_data[] =
911 {
912 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
913 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
914 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
915 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA
916 };
917 GC gc;
918 Pixmap ipixmap, stipple;
919 unsigned width, height, depth;
920
921 Window window; /* These return values */
922 unsigned border; /* from XGetGeometry() */
923 int x, y; /* are not needed. */
924
925 ipixmap = 0;
926
927 if ( NULL == display || 0 == pixmap )
928 return ipixmap;
929
930 if ( 0 == XGetGeometry( display, pixmap, &window, &x, &y,
931 &width, &height, &border, &depth )
932 )
933 return ipixmap; /* BadDrawable: probably an invalid pixmap */
934
935 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
936 */
937 stipple = XCreateBitmapFromData( display, pixmap, stipple_data, 16, 16 );
938 if ( 0 != stipple )
939 {
940 gc = XCreateGC( display, pixmap, (XtGCMask)0, (XGCValues*)NULL );
941 if ( NULL != gc )
942 {
943 /* Create an identical copy of the argument pixmap.
944 */
945 ipixmap = XCreatePixmap( display, pixmap, width, height, depth );
946 if ( 0 != ipixmap )
947 {
948 /* Copy the argument pixmap into the new pixmap.
949 */
950 XCopyArea( display, pixmap, ipixmap,
951 gc, 0, 0, width, height, 0, 0 );
952
953 /* Refill the new pixmap using the stipple algorithm/pixmap.
954 */
955 XSetStipple( display, gc, stipple );
956 XSetFillStyle( display, gc, FillStippled );
957 XFillRectangle( display, ipixmap, gc, 0, 0, width, height );
958 }
959 XFreeGC( display, gc );
960 }
961 XFreePixmap( display, stipple );
962 }
963 return ipixmap;
964 }
965
966 // Creates a bitmap with transparent areas drawn in
967 // the given colour.
968 wxBitmap wxCreateMaskedBitmap(const wxBitmap& bitmap, wxColour& colour)
969 {
970 wxBitmap newBitmap(bitmap.GetWidth(),
971 bitmap.GetHeight(),
972 bitmap.GetDepth());
973 wxMemoryDC destDC;
974 wxMemoryDC srcDC;
975 srcDC.SelectObject(bitmap);
976 destDC.SelectObject(newBitmap);
977
978 wxBrush brush(colour, wxSOLID);
979 destDC.SetOptimization(FALSE);
980 destDC.SetBackground(brush);
981 destDC.Clear();
982 destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(), & srcDC, 0, 0, wxCOPY, TRUE);
983
984 return newBitmap;
985 }
986
987
988
989
990 //-----------------------------------------------------------------------------
991 // wxImage conversion routines
992 //-----------------------------------------------------------------------------
993
994 /*
995
996 Date: Wed, 05 Jan 2000 11:45:40 +0100
997 From: Frits Boel <boel@niob.knaw.nl>
998 To: julian.smart@ukonline.co.uk
999 Subject: Patch for Motif ConvertToBitmap
1000
1001 Hi Julian,
1002
1003 I've been working on a wxWin application for image processing. From the
1004 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1005 till I looked in the source code of image.cpp. I saw that converting a
1006 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1007 to the 256 colors of the palet. A very time-consuming piece of code!
1008
1009 Because I wanted a faster application, I've made a 'patch' for this. In
1010 short: every pixel of the image is compared to a sorted list with
1011 colors. If the color is found in the list, the palette entry is
1012 returned; if the color is not found, the color palette is searched and
1013 then the palette entry is returned and the color added to the sorted
1014 list.
1015
1016 Maybe there is another method for this, namely changing the palette
1017 itself (if the colors are known, as is the case with tiffs with a
1018 colormap). I did not look at this, maybe someone else did?
1019
1020 The code of the patch is attached, have a look on it, and maybe you will
1021 ship it with the next release of wxMotif?
1022
1023 Regards,
1024
1025 Frits Boel
1026 Software engineer at Hubrecht Laboratory, The Netherlands.
1027
1028 */
1029
1030 class wxSearchColor
1031 {
1032 public:
1033 wxSearchColor( void );
1034 wxSearchColor( int size, XColor *colors );
1035 ~wxSearchColor( void );
1036
1037 int SearchColor( int r, int g, int b );
1038 private:
1039 int AddColor( unsigned int value, int pos );
1040
1041 int size;
1042 XColor *colors;
1043 unsigned int *color;
1044 int *entry;
1045
1046 int bottom;
1047 int top;
1048 };
1049
1050 wxSearchColor::wxSearchColor( void )
1051 {
1052 size = 0;
1053 colors = (XColor*) NULL;
1054 color = (unsigned int *) NULL;
1055 entry = (int*) NULL;
1056
1057 bottom = 0;
1058 top = 0;
1059 }
1060
1061 wxSearchColor::wxSearchColor( int size_, XColor *colors_ )
1062 {
1063 int i;
1064 size = size_;
1065 colors = colors_;
1066 color = new unsigned int[size];
1067 entry = new int [size];
1068
1069 for (i = 0; i < size; i++ ) {
1070 entry[i] = -1;
1071 }
1072
1073 bottom = top = ( size >> 1 );
1074 }
1075
1076 wxSearchColor::~wxSearchColor( void )
1077 {
1078 if ( color ) delete color;
1079 if ( entry ) delete entry;
1080 }
1081
1082 int wxSearchColor::SearchColor( int r, int g, int b )
1083 {
1084 unsigned int value = ( ( ( r * 256 ) + g ) * 256 ) + b;
1085 int begin = bottom;
1086 int end = top;
1087 int middle = 0;
1088
1089 while ( begin <= end ) {
1090
1091 middle = ( begin + end ) >> 1;
1092
1093 if ( value == color[middle] ) {
1094 return( entry[middle] );
1095 } else if ( value < color[middle] ) {
1096 end = middle - 1;
1097 } else {
1098 begin = middle + 1;
1099 }
1100
1101 }
1102
1103 return AddColor( value, middle );
1104 }
1105
1106 int wxSearchColor::AddColor( unsigned int value, int pos )
1107 {
1108 int i;
1109 int pixel = -1;
1110 int max = 3 * (65536);
1111 for ( i = 0; i < 256; i++ ) {
1112 int rdiff = ((value >> 8) & 0xFF00 ) - colors[i].red;
1113 int gdiff = ((value ) & 0xFF00 ) - colors[i].green;
1114 int bdiff = ((value << 8) & 0xFF00 ) - colors[i].blue;
1115 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1116 if (sum < max) { pixel = i; max = sum; }
1117 }
1118
1119 if ( entry[pos] < 0 ) {
1120 color[pos] = value;
1121 entry[pos] = pixel;
1122 } else if ( value < color[pos] ) {
1123
1124 if ( bottom > 0 ) {
1125 for ( i = bottom; i < pos; i++ ) {
1126 color[i-1] = color[i];
1127 entry[i-1] = entry[i];
1128 }
1129 bottom--;
1130 color[pos-1] = value;
1131 entry[pos-1] = pixel;
1132 } else if ( top < size-1 ) {
1133 for ( i = top; i >= pos; i-- ) {
1134 color[i+1] = color[i];
1135 entry[i+1] = entry[i];
1136 }
1137 top++;
1138 color[pos] = value;
1139 entry[pos] = pixel;
1140 }
1141
1142 } else {
1143
1144 if ( top < size-1 ) {
1145 for ( i = top; i > pos; i-- ) {
1146 color[i+1] = color[i];
1147 entry[i+1] = entry[i];
1148 }
1149 top++;
1150 color[pos+1] = value;
1151 entry[pos+1] = pixel;
1152 } else if ( bottom > 0 ) {
1153 for ( i = bottom; i < pos; i++ ) {
1154 color[i-1] = color[i];
1155 entry[i-1] = entry[i];
1156 }
1157 bottom--;
1158 color[pos] = value;
1159 entry[pos] = pixel;
1160 }
1161
1162 }
1163
1164 return( pixel );
1165 }
1166
1167
1168 bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
1169 {
1170 wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") )
1171 wxCHECK_MSG( depth == -1, FALSE, wxT("invalid bitmap depth") )
1172
1173 m_refData = new wxBitmapRefData();
1174
1175 int width = image.GetWidth();
1176 int height = image.GetHeight();
1177
1178 SetHeight( height );
1179 SetWidth( width );
1180
1181 Display *dpy = (Display*) wxGetDisplay();
1182 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1183 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1184
1185 // Create image
1186
1187 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
1188 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
1189
1190 Create( width, height, bpp );
1191
1192 // Create mask
1193
1194 XImage *mask_image = (XImage*) NULL;
1195 if (image.HasMask())
1196 {
1197 mask_image = XCreateImage( dpy, vis, 1, ZPixmap, 0, 0, width, height, 32, 0 );
1198 mask_image->data = (char*) malloc( mask_image->bytes_per_line * mask_image->height );
1199 }
1200
1201 // Retrieve depth info
1202
1203 XVisualInfo vinfo_template;
1204 XVisualInfo *vi;
1205
1206 vinfo_template.visual = vis;
1207 vinfo_template.visualid = XVisualIDFromVisual( vis );
1208 vinfo_template.depth = bpp;
1209 int nitem = 0;
1210
1211 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1212
1213 wxCHECK_MSG( vi, FALSE, wxT("no visual") );
1214
1215 XFree( vi );
1216
1217 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1218 if (bpp < 8) bpp = 8;
1219
1220 // Render
1221
1222 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1223 byte_order b_o = RGB;
1224
1225 if (bpp >= 24)
1226 {
1227 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1228 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1229 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1230 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1231 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1232 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1233 }
1234
1235 int r_mask = image.GetMaskRed();
1236 int g_mask = image.GetMaskGreen();
1237 int b_mask = image.GetMaskBlue();
1238
1239 XColor colors[256];
1240 if (bpp == 8)
1241 {
1242 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
1243
1244 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1245 XQueryColors( dpy, cmap, colors, 256 );
1246 }
1247
1248 wxSearchColor scolor( 256, colors );
1249 unsigned char* data = image.GetData();
1250
1251 bool hasMask = image.HasMask();
1252
1253 int index = 0;
1254 for (int y = 0; y < height; y++)
1255 {
1256 for (int x = 0; x < width; x++)
1257 {
1258 int r = data[index];
1259 index++;
1260 int g = data[index];
1261 index++;
1262 int b = data[index];
1263 index++;
1264
1265 if (hasMask)
1266 {
1267 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1268 XPutPixel( mask_image, x, y, 0 );
1269 else
1270 XPutPixel( mask_image, x, y, 1 );
1271 }
1272
1273 switch (bpp)
1274 {
1275 case 8:
1276 {
1277 #if 0 // Old, slower code
1278 int pixel = -1;
1279 /*
1280 if (wxTheApp->m_colorCube)
1281 {
1282 pixel = wxTheApp->m_colorCube
1283 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1284 }
1285 else
1286 {
1287 */
1288 int max = 3 * (65536);
1289 for (int i = 0; i < 256; i++)
1290 {
1291 int rdiff = (r << 8) - colors[i].red;
1292 int gdiff = (g << 8) - colors[i].green;
1293 int bdiff = (b << 8) - colors[i].blue;
1294 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1295 if (sum < max) { pixel = i; max = sum; }
1296 }
1297 /*
1298 }
1299 */
1300 #endif
1301
1302 // And this is all to get the 'right' color...
1303 int pixel = scolor.SearchColor( r, g, b );
1304 XPutPixel( data_image, x, y, pixel );
1305 break;
1306 }
1307 case 15:
1308 {
1309 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1310 XPutPixel( data_image, x, y, pixel );
1311 break;
1312 }
1313 case 16:
1314 {
1315 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1316 XPutPixel( data_image, x, y, pixel );
1317 break;
1318 }
1319 case 32:
1320 case 24:
1321 {
1322 int pixel = 0;
1323 switch (b_o)
1324 {
1325 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1326 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1327 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1328 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1329 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1330 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1331 }
1332 XPutPixel( data_image, x, y, pixel );
1333 }
1334 default: break;
1335 }
1336 } // for
1337 } // for
1338
1339 // Blit picture
1340
1341 XGCValues gcvalues;
1342 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1343 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1344 XPutImage( dpy, (Drawable)GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
1345
1346 XDestroyImage( data_image );
1347 XFreeGC( dpy, gc );
1348
1349 // Blit mask
1350 if (image.HasMask())
1351 {
1352 wxBitmap maskBitmap(width, height, 1);
1353
1354 GC gcMask = XCreateGC( dpy, (Pixmap) maskBitmap.GetPixmap(), (XtGCMask) 0, (XGCValues*)NULL );
1355 XPutImage( dpy, (Drawable)maskBitmap.GetPixmap(), gcMask, mask_image, 0, 0, 0, 0, width, height );
1356
1357 XDestroyImage( mask_image );
1358 XFreeGC( dpy, gcMask );
1359
1360 wxMask* mask = new wxMask;
1361 mask->SetPixmap(maskBitmap.GetPixmap());
1362
1363 SetMask(mask);
1364
1365 maskBitmap.SetPixmapNull();
1366 }
1367
1368
1369 return TRUE;
1370 }
1371
1372 wxImage wxBitmap::ConvertToImage() const
1373 {
1374 wxImage image;
1375
1376 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
1377
1378 Display *dpy = (Display*) wxGetDisplay();
1379 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1380 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1381
1382 XImage *ximage = XGetImage( dpy,
1383 (Drawable)GetPixmap(),
1384 0, 0,
1385 GetWidth(), GetHeight(),
1386 AllPlanes, ZPixmap );
1387
1388 wxCHECK_MSG( ximage, wxNullImage, wxT("couldn't create image") );
1389
1390 image.Create( GetWidth(), GetHeight() );
1391 char unsigned *data = image.GetData();
1392
1393 if (!data)
1394 {
1395 XDestroyImage( ximage );
1396 wxFAIL_MSG( wxT("couldn't create image") );
1397 return wxNullImage;
1398 }
1399
1400 /*
1401 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1402 if (GetMask())
1403 {
1404 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
1405 0, 0,
1406 GetWidth(), GetHeight() );
1407
1408 image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1409 }
1410 */
1411
1412 // Retrieve depth info
1413
1414 XVisualInfo vinfo_template;
1415 XVisualInfo *vi;
1416
1417 vinfo_template.visual = vis;
1418 vinfo_template.visualid = XVisualIDFromVisual( vis );
1419 vinfo_template.depth = bpp;
1420 int nitem = 0;
1421
1422 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1423
1424 wxCHECK_MSG( vi, wxNullImage, wxT("no visual") );
1425
1426 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1427
1428 XFree( vi );
1429
1430 XColor colors[256];
1431 if (bpp == 8)
1432 {
1433 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
1434
1435 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1436 XQueryColors( dpy, cmap, colors, 256 );
1437 }
1438
1439 long pos = 0;
1440 for (int j = 0; j < GetHeight(); j++)
1441 {
1442 for (int i = 0; i < GetWidth(); i++)
1443 {
1444 int pixel = XGetPixel( ximage, i, j );
1445 if (bpp <= 8)
1446 {
1447 data[pos] = colors[pixel].red >> 8;
1448 data[pos+1] = colors[pixel].green >> 8;
1449 data[pos+2] = colors[pixel].blue >> 8;
1450 } else if (bpp == 15)
1451 {
1452 data[pos] = (pixel >> 7) & 0xf8;
1453 data[pos+1] = (pixel >> 2) & 0xf8;
1454 data[pos+2] = (pixel << 3) & 0xf8;
1455 } else if (bpp == 16)
1456 {
1457 data[pos] = (pixel >> 8) & 0xf8;
1458 data[pos+1] = (pixel >> 3) & 0xfc;
1459 data[pos+2] = (pixel << 3) & 0xf8;
1460 } else
1461 {
1462 data[pos] = (pixel >> 16) & 0xff;
1463 data[pos+1] = (pixel >> 8) & 0xff;
1464 data[pos+2] = pixel & 0xff;
1465 }
1466
1467 /*
1468 if (gdk_image_mask)
1469 {
1470 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1471 if (mask_pixel == 0)
1472 {
1473 data[pos] = 16;
1474 data[pos+1] = 16;
1475 data[pos+2] = 16;
1476 }
1477 }
1478 */
1479
1480 pos += 3;
1481 }
1482 }
1483
1484 XDestroyImage( ximage );
1485 /*
1486 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1487 */
1488
1489 return image;
1490 }