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