]> git.saurik.com Git - wxWidgets.git/blob - src/motif/bitmap.cpp
allow TABbing into multiline text controls even if they're not editable
[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, int 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 = wxBitmap(image);
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 %ld 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->ConvertToImage();
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)
833 return (WXPixmap)NULL;
834 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
835 return M_BITMAPDATA->m_pixmap;
836
837 Display *dpy = (Display*) M_BITMAPDATA->m_display;
838
839 #ifdef FOO
840 /*
841 If we do:
842 if (labelPixmap) return labelPixmap;
843 things can be wrong, because colors can have been changed.
844
845 If we do:
846 if (labelPixmap)
847 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
848 we got BadDrawable if the pixmap is referenced by multiples widgets
849
850 this is a catch22!!
851
852 So, before doing thing really clean, I just do nothing; if the pixmap is
853 referenced by many widgets, Motif performs caching functions.
854 And if pixmap is referenced with multiples colors, we just have some
855 memory leaks... I hope we can deal with them...
856 */
857 // Must be destroyed, because colours can have been changed!
858 if (M_BITMAPDATA->m_labelPixmap)
859 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_labelPixmap);
860 #endif
861
862 char tmp[128];
863 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
864
865 Pixel fg, bg;
866 Widget widget = (Widget) w;
867
868 while (XmIsGadget ( widget ))
869 widget = XtParent (widget);
870 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
871
872 M_BITMAPDATA->m_labelPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
873
874 return M_BITMAPDATA->m_labelPixmap;
875 }
876
877 WXPixmap wxBitmap::GetArmPixmap (WXWidget w)
878 {
879 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
880 return M_BITMAPDATA->m_pixmap;
881
882 Display *dpy = (Display*) M_BITMAPDATA->m_display;
883 #ifdef FOO
884 // See GetLabelPixmap () comment
885
886 // Must be destroyed, because colours can have been changed!
887 if (M_BITMAPDATA->m_armPixmap)
888 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_armPixmap);
889 #endif
890
891 char tmp[128];
892 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
893
894 Pixel fg, bg;
895 Widget widget = (Widget) w;
896
897 XtVaGetValues (widget, XmNarmColor, &bg, NULL);
898 while (XmIsGadget (widget))
899 widget = XtParent (widget);
900 XtVaGetValues (widget, XmNforeground, &fg, NULL);
901
902 M_BITMAPDATA->m_armPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
903
904 return M_BITMAPDATA->m_armPixmap;
905 }
906
907 WXPixmap wxBitmap::GetInsensPixmap (WXWidget w)
908 {
909 Display *dpy = (Display*) M_BITMAPDATA->m_display;
910
911 if (!M_BITMAPDATA)
912 return (WXPixmap)NULL;
913 if (M_BITMAPDATA->m_insensPixmap)
914 return M_BITMAPDATA->m_insensPixmap;
915
916 if (!w)
917 {
918 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XCreateInsensitivePixmap(dpy, (Pixmap) M_BITMAPDATA->m_pixmap);
919 if (M_BITMAPDATA->m_insensPixmap)
920 return M_BITMAPDATA->m_insensPixmap;
921 else
922 return M_BITMAPDATA->m_pixmap;
923 }
924
925 if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0)
926 return M_BITMAPDATA->m_pixmap;
927
928 #ifdef FOO
929 See GetLabelPixmap () comment
930 // Must be destroyed, because colours can have been changed!
931 if (M_BITMAPDATA->m_insensPixmap)
932 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), (Pixmap) M_BITMAPDATA->m_insensPixmap);
933 #endif
934
935 char tmp[128];
936 sprintf (tmp, "Not%x", (unsigned int) M_BITMAPDATA->m_insensImage);
937
938 Pixel fg, bg;
939 Widget widget = (Widget) w;
940
941 while (XmIsGadget (widget))
942 widget = XtParent (widget);
943 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
944
945 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
946
947 return M_BITMAPDATA->m_insensPixmap;
948 }
949
950 // We may need this sometime...
951
952 /****************************************************************************
953
954 NAME
955 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
956
957 SYNOPSIS
958 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
959
960 DESCRIPTION
961 This function creates a grayed-out copy of the argument pixmap, suitable
962 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
963
964 RETURN VALUES
965 The return value is the new Pixmap id or zero on error. Errors include
966 a NULL display argument or an invalid Pixmap argument.
967
968 ERRORS
969 If one of the XLib functions fail, it will produce a X error. The
970 default X error handler prints a diagnostic and calls exit().
971
972 SEE ALSO
973 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
974 XFillRectangle(3), exit(2)
975
976 AUTHOR
977 John R Veregge - john@puente.jpl.nasa.gov
978 Advanced Engineering and Prototyping Group (AEG)
979 Information Systems Technology Section (395)
980 Jet Propulsion Lab - Calif Institute of Technology
981
982 *****************************************************************************/
983
984 Pixmap
985 XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
986
987 {
988 static char stipple_data[] =
989 {
990 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
991 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
992 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
993 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA
994 };
995 GC gc;
996 Pixmap ipixmap, stipple;
997 unsigned width, height, depth;
998
999 Window window; /* These return values */
1000 unsigned border; /* from XGetGeometry() */
1001 int x, y; /* are not needed. */
1002
1003 ipixmap = 0;
1004
1005 if ( NULL == display || 0 == pixmap )
1006 return ipixmap;
1007
1008 if ( 0 == XGetGeometry( display, pixmap, &window, &x, &y,
1009 &width, &height, &border, &depth )
1010 )
1011 return ipixmap; /* BadDrawable: probably an invalid pixmap */
1012
1013 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
1014 */
1015 stipple = XCreateBitmapFromData( display, pixmap, stipple_data, 16, 16 );
1016 if ( 0 != stipple )
1017 {
1018 gc = XCreateGC( display, pixmap, (XtGCMask)0, (XGCValues*)NULL );
1019 if ( NULL != gc )
1020 {
1021 /* Create an identical copy of the argument pixmap.
1022 */
1023 ipixmap = XCreatePixmap( display, pixmap, width, height, depth );
1024 if ( 0 != ipixmap )
1025 {
1026 /* Copy the argument pixmap into the new pixmap.
1027 */
1028 XCopyArea( display, pixmap, ipixmap,
1029 gc, 0, 0, width, height, 0, 0 );
1030
1031 /* Refill the new pixmap using the stipple algorithm/pixmap.
1032 */
1033 XSetStipple( display, gc, stipple );
1034 XSetFillStyle( display, gc, FillStippled );
1035 XFillRectangle( display, ipixmap, gc, 0, 0, width, height );
1036 }
1037 XFreeGC( display, gc );
1038 }
1039 XFreePixmap( display, stipple );
1040 }
1041 return ipixmap;
1042 }
1043
1044 // Creates a bitmap with transparent areas drawn in
1045 // the given colour.
1046 wxBitmap wxCreateMaskedBitmap(const wxBitmap& bitmap, wxColour& colour)
1047 {
1048 wxBitmap newBitmap(bitmap.GetWidth(),
1049 bitmap.GetHeight(),
1050 bitmap.GetDepth());
1051 wxMemoryDC destDC;
1052 wxMemoryDC srcDC;
1053 srcDC.SelectObject(bitmap);
1054 destDC.SelectObject(newBitmap);
1055
1056 wxBrush brush(colour, wxSOLID);
1057 destDC.SetOptimization(FALSE);
1058 destDC.SetBackground(brush);
1059 destDC.Clear();
1060 destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(), & srcDC, 0, 0, wxCOPY, TRUE);
1061
1062 return newBitmap;
1063 }
1064
1065
1066
1067
1068 //-----------------------------------------------------------------------------
1069 // wxImage conversion routines
1070 //-----------------------------------------------------------------------------
1071
1072 /*
1073
1074 Date: Wed, 05 Jan 2000 11:45:40 +0100
1075 From: Frits Boel <boel@niob.knaw.nl>
1076 To: julian.smart@ukonline.co.uk
1077 Subject: Patch for Motif ConvertToBitmap
1078
1079 Hi Julian,
1080
1081 I've been working on a wxWin application for image processing. From the
1082 beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1083 till I looked in the source code of image.cpp. I saw that converting a
1084 wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1085 to the 256 colors of the palet. A very time-consuming piece of code!
1086
1087 Because I wanted a faster application, I've made a 'patch' for this. In
1088 short: every pixel of the image is compared to a sorted list with
1089 colors. If the color is found in the list, the palette entry is
1090 returned; if the color is not found, the color palette is searched and
1091 then the palette entry is returned and the color added to the sorted
1092 list.
1093
1094 Maybe there is another method for this, namely changing the palette
1095 itself (if the colors are known, as is the case with tiffs with a
1096 colormap). I did not look at this, maybe someone else did?
1097
1098 The code of the patch is attached, have a look on it, and maybe you will
1099 ship it with the next release of wxMotif?
1100
1101 Regards,
1102
1103 Frits Boel
1104 Software engineer at Hubrecht Laboratory, The Netherlands.
1105
1106 */
1107
1108 class wxSearchColor
1109 {
1110 public:
1111 wxSearchColor( void );
1112 wxSearchColor( int size, XColor *colors );
1113 ~wxSearchColor( void );
1114
1115 int SearchColor( int r, int g, int b );
1116 private:
1117 int AddColor( unsigned int value, int pos );
1118
1119 int size;
1120 XColor *colors;
1121 unsigned int *color;
1122 int *entry;
1123
1124 int bottom;
1125 int top;
1126 };
1127
1128 wxSearchColor::wxSearchColor( void )
1129 {
1130 size = 0;
1131 colors = (XColor*) NULL;
1132 color = (unsigned int *) NULL;
1133 entry = (int*) NULL;
1134
1135 bottom = 0;
1136 top = 0;
1137 }
1138
1139 wxSearchColor::wxSearchColor( int size_, XColor *colors_ )
1140 {
1141 int i;
1142 size = size_;
1143 colors = colors_;
1144 color = new unsigned int[size];
1145 entry = new int [size];
1146
1147 for (i = 0; i < size; i++ ) {
1148 entry[i] = -1;
1149 }
1150
1151 bottom = top = ( size >> 1 );
1152 }
1153
1154 wxSearchColor::~wxSearchColor( void )
1155 {
1156 if ( color ) delete color;
1157 if ( entry ) delete entry;
1158 }
1159
1160 int wxSearchColor::SearchColor( int r, int g, int b )
1161 {
1162 unsigned int value = ( ( ( r * 256 ) + g ) * 256 ) + b;
1163 int begin = bottom;
1164 int end = top;
1165 int middle = 0;
1166
1167 while ( begin <= end ) {
1168
1169 middle = ( begin + end ) >> 1;
1170
1171 if ( value == color[middle] ) {
1172 return( entry[middle] );
1173 } else if ( value < color[middle] ) {
1174 end = middle - 1;
1175 } else {
1176 begin = middle + 1;
1177 }
1178
1179 }
1180
1181 return AddColor( value, middle );
1182 }
1183
1184 int wxSearchColor::AddColor( unsigned int value, int pos )
1185 {
1186 int i;
1187 int pixel = -1;
1188 int max = 3 * (65536);
1189 for ( i = 0; i < 256; i++ ) {
1190 int rdiff = ((value >> 8) & 0xFF00 ) - colors[i].red;
1191 int gdiff = ((value ) & 0xFF00 ) - colors[i].green;
1192 int bdiff = ((value << 8) & 0xFF00 ) - colors[i].blue;
1193 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1194 if (sum < max) { pixel = i; max = sum; }
1195 }
1196
1197 if ( entry[pos] < 0 ) {
1198 color[pos] = value;
1199 entry[pos] = pixel;
1200 } else if ( value < color[pos] ) {
1201
1202 if ( bottom > 0 ) {
1203 for ( i = bottom; i < pos; i++ ) {
1204 color[i-1] = color[i];
1205 entry[i-1] = entry[i];
1206 }
1207 bottom--;
1208 color[pos-1] = value;
1209 entry[pos-1] = pixel;
1210 } else if ( top < size-1 ) {
1211 for ( i = top; i >= pos; i-- ) {
1212 color[i+1] = color[i];
1213 entry[i+1] = entry[i];
1214 }
1215 top++;
1216 color[pos] = value;
1217 entry[pos] = pixel;
1218 }
1219
1220 } else {
1221
1222 if ( top < size-1 ) {
1223 for ( i = top; i > pos; i-- ) {
1224 color[i+1] = color[i];
1225 entry[i+1] = entry[i];
1226 }
1227 top++;
1228 color[pos+1] = value;
1229 entry[pos+1] = pixel;
1230 } else if ( bottom > 0 ) {
1231 for ( i = bottom; i < pos; i++ ) {
1232 color[i-1] = color[i];
1233 entry[i-1] = entry[i];
1234 }
1235 bottom--;
1236 color[pos] = value;
1237 entry[pos] = pixel;
1238 }
1239
1240 }
1241
1242 return( pixel );
1243 }
1244
1245
1246 bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
1247 {
1248 wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") )
1249 wxCHECK_MSG( depth == -1, FALSE, wxT("invalid bitmap depth") )
1250
1251 m_refData = new wxBitmapRefData();
1252
1253 int width = image.GetWidth();
1254 int height = image.GetHeight();
1255
1256 SetHeight( height );
1257 SetWidth( width );
1258
1259 Display *dpy = (Display*) wxGetDisplay();
1260 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1261 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1262
1263 // Create image
1264
1265 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
1266 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
1267
1268 Create( width, height, bpp );
1269
1270 // Create mask
1271
1272 XImage *mask_image = (XImage*) NULL;
1273 if (image.HasMask())
1274 {
1275 mask_image = XCreateImage( dpy, vis, 1, ZPixmap, 0, 0, width, height, 32, 0 );
1276 mask_image->data = (char*) malloc( mask_image->bytes_per_line * mask_image->height );
1277 }
1278
1279 // Retrieve depth info
1280
1281 XVisualInfo vinfo_template;
1282 XVisualInfo *vi;
1283
1284 vinfo_template.visual = vis;
1285 vinfo_template.visualid = XVisualIDFromVisual( vis );
1286 vinfo_template.depth = bpp;
1287 int nitem = 0;
1288
1289 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1290
1291 wxCHECK_MSG( vi, FALSE, wxT("no visual") );
1292
1293 XFree( vi );
1294
1295 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1296 if (bpp < 8) bpp = 8;
1297
1298 // Render
1299
1300 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1301 byte_order b_o = RGB;
1302
1303 if (bpp >= 24)
1304 {
1305 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1306 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1307 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1308 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1309 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1310 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1311 }
1312
1313 int r_mask = image.GetMaskRed();
1314 int g_mask = image.GetMaskGreen();
1315 int b_mask = image.GetMaskBlue();
1316
1317 XColor colors[256];
1318 if (bpp == 8)
1319 {
1320 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
1321
1322 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1323 XQueryColors( dpy, cmap, colors, 256 );
1324 }
1325
1326 wxSearchColor scolor( 256, colors );
1327 unsigned char* data = image.GetData();
1328
1329 bool hasMask = image.HasMask();
1330
1331 int index = 0;
1332 for (int y = 0; y < height; y++)
1333 {
1334 for (int x = 0; x < width; x++)
1335 {
1336 int r = data[index];
1337 index++;
1338 int g = data[index];
1339 index++;
1340 int b = data[index];
1341 index++;
1342
1343 if (hasMask)
1344 {
1345 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1346 XPutPixel( mask_image, x, y, 0 );
1347 else
1348 XPutPixel( mask_image, x, y, 1 );
1349 }
1350
1351 switch (bpp)
1352 {
1353 case 8:
1354 {
1355 #if 0 // Old, slower code
1356 int pixel = -1;
1357 /*
1358 if (wxTheApp->m_colorCube)
1359 {
1360 pixel = wxTheApp->m_colorCube
1361 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1362 }
1363 else
1364 {
1365 */
1366 int max = 3 * (65536);
1367 for (int i = 0; i < 256; i++)
1368 {
1369 int rdiff = (r << 8) - colors[i].red;
1370 int gdiff = (g << 8) - colors[i].green;
1371 int bdiff = (b << 8) - colors[i].blue;
1372 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1373 if (sum < max) { pixel = i; max = sum; }
1374 }
1375 /*
1376 }
1377 */
1378 #endif
1379
1380 // And this is all to get the 'right' color...
1381 int pixel = scolor.SearchColor( r, g, b );
1382 XPutPixel( data_image, x, y, pixel );
1383 break;
1384 }
1385 case 15:
1386 {
1387 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1388 XPutPixel( data_image, x, y, pixel );
1389 break;
1390 }
1391 case 16:
1392 {
1393 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1394 XPutPixel( data_image, x, y, pixel );
1395 break;
1396 }
1397 case 32:
1398 case 24:
1399 {
1400 int pixel = 0;
1401 switch (b_o)
1402 {
1403 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1404 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1405 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1406 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1407 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1408 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1409 }
1410 XPutPixel( data_image, x, y, pixel );
1411 }
1412 default: break;
1413 }
1414 } // for
1415 } // for
1416
1417 // Blit picture
1418
1419 XGCValues gcvalues;
1420 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1421 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1422 XPutImage( dpy, (Drawable)GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
1423
1424 XDestroyImage( data_image );
1425 XFreeGC( dpy, gc );
1426
1427 // Blit mask
1428 if (image.HasMask())
1429 {
1430 wxBitmap maskBitmap(width, height, 1);
1431
1432 GC gcMask = XCreateGC( dpy, (Pixmap) maskBitmap.GetPixmap(), (XtGCMask) 0, (XGCValues*)NULL );
1433 XPutImage( dpy, (Drawable)maskBitmap.GetPixmap(), gcMask, mask_image, 0, 0, 0, 0, width, height );
1434
1435 XDestroyImage( mask_image );
1436 XFreeGC( dpy, gcMask );
1437
1438 wxMask* mask = new wxMask;
1439 mask->SetPixmap(maskBitmap.GetPixmap());
1440
1441 SetMask(mask);
1442
1443 maskBitmap.SetPixmapNull();
1444 }
1445
1446
1447 return TRUE;
1448 }
1449
1450 wxImage wxBitmap::ConvertToImage() const
1451 {
1452 wxImage image;
1453
1454 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
1455
1456 Display *dpy = (Display*) wxGetDisplay();
1457 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1458 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1459
1460 XImage *ximage = XGetImage( dpy,
1461 (Drawable)GetPixmap(),
1462 0, 0,
1463 GetWidth(), GetHeight(),
1464 AllPlanes, ZPixmap );
1465
1466 wxCHECK_MSG( ximage, wxNullImage, wxT("couldn't create image") );
1467
1468 image.Create( GetWidth(), GetHeight() );
1469 char unsigned *data = image.GetData();
1470
1471 if (!data)
1472 {
1473 XDestroyImage( ximage );
1474 wxFAIL_MSG( wxT("couldn't create image") );
1475 return wxNullImage;
1476 }
1477
1478 /*
1479 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1480 if (GetMask())
1481 {
1482 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
1483 0, 0,
1484 GetWidth(), GetHeight() );
1485
1486 image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1487 }
1488 */
1489
1490 // Retrieve depth info
1491
1492 XVisualInfo vinfo_template;
1493 XVisualInfo *vi;
1494
1495 vinfo_template.visual = vis;
1496 vinfo_template.visualid = XVisualIDFromVisual( vis );
1497 vinfo_template.depth = bpp;
1498 int nitem = 0;
1499
1500 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1501
1502 wxCHECK_MSG( vi, wxNullImage, wxT("no visual") );
1503
1504 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1505
1506 XFree( vi );
1507
1508 XColor colors[256];
1509 if (bpp == 8)
1510 {
1511 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
1512
1513 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1514 XQueryColors( dpy, cmap, colors, 256 );
1515 }
1516
1517 long pos = 0;
1518 for (int j = 0; j < GetHeight(); j++)
1519 {
1520 for (int i = 0; i < GetWidth(); i++)
1521 {
1522 int pixel = XGetPixel( ximage, i, j );
1523 if (bpp <= 8)
1524 {
1525 data[pos] = colors[pixel].red >> 8;
1526 data[pos+1] = colors[pixel].green >> 8;
1527 data[pos+2] = colors[pixel].blue >> 8;
1528 } else if (bpp == 15)
1529 {
1530 data[pos] = (pixel >> 7) & 0xf8;
1531 data[pos+1] = (pixel >> 2) & 0xf8;
1532 data[pos+2] = (pixel << 3) & 0xf8;
1533 } else if (bpp == 16)
1534 {
1535 data[pos] = (pixel >> 8) & 0xf8;
1536 data[pos+1] = (pixel >> 3) & 0xfc;
1537 data[pos+2] = (pixel << 3) & 0xf8;
1538 } else
1539 {
1540 data[pos] = (pixel >> 16) & 0xff;
1541 data[pos+1] = (pixel >> 8) & 0xff;
1542 data[pos+2] = pixel & 0xff;
1543 }
1544
1545 /*
1546 if (gdk_image_mask)
1547 {
1548 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1549 if (mask_pixel == 0)
1550 {
1551 data[pos] = 16;
1552 data[pos+1] = 16;
1553 data[pos+2] = 16;
1554 }
1555 }
1556 */
1557
1558 pos += 3;
1559 }
1560 }
1561
1562 XDestroyImage( ximage );
1563 /*
1564 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1565 */
1566
1567 return image;
1568 }