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