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