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