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