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