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