]> git.saurik.com Git - wxWidgets.git/blame - src/motif/bitmap.cpp
Win16 cursor/icon functions are not needed any longer
[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)),
d3a80c92 432 wxConstCast(name.c_str(), char), &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,
d3a80c92
MB
572 RootWindow(dpy, DefaultScreen(dpy)),
573 wxConstCast(name.c_str(), char),
f97c9854 574 &pixmap, &mask, &xpmAttr);
31528cd3 575
f97c9854
JS
576 if (errorStatus == XpmSuccess)
577 {
578 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap;
579 if ( mask )
580 {
581 M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask;
582 M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask);
583 }
31528cd3 584
0d57be45
JS
585 unsigned int depthRet;
586 int xRet, yRet;
587 unsigned int widthRet, heightRet, borderWidthRet;
588 Window rootWindowRet;
589 XGetGeometry(dpy, pixmap, &rootWindowRet, &xRet, &yRet,
590 &widthRet, &heightRet, &borderWidthRet, &depthRet);
31528cd3 591
f97c9854
JS
592 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
593 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
31528cd3 594
2d120f83 595 /*
f97c9854
JS
596 if ( xpmAttr.npixels > 2 )
597 {
2d120f83 598 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
f97c9854
JS
599 } else
600 {
2d120f83 601 M_BITMAPHANDLERDATA->m_depth = 1; // mono
f97c9854 602 }
2d120f83 603 */
31528cd3 604
0d57be45 605 M_BITMAPHANDLERDATA->m_depth = depthRet;
31528cd3 606
2d120f83 607 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
31528cd3 608
2d120f83 609 XpmFreeAttributes(&xpmAttr);
31528cd3 610
f97c9854 611 M_BITMAPHANDLERDATA->m_ok = TRUE;
a4294b78 612 return TRUE;
f97c9854
JS
613 } else
614 {
2d120f83 615 // XpmDebugError(errorStatus, name);
f97c9854
JS
616 M_BITMAPHANDLERDATA->m_ok = FALSE;
617 return FALSE;
618 }
619}
620
1bc822df
MB
621bool wxXPMFileHandler::SaveFile( const wxBitmap *bitmap, const wxString& name,
622 wxBitmapType WXUNUSED(type),
623 const wxPalette *WXUNUSED(palette))
f97c9854
JS
624{
625 if (M_BITMAPHANDLERDATA->m_ok && M_BITMAPHANDLERDATA->m_pixmap)
626 {
627 Display *dpy = (Display*) M_BITMAPHANDLERDATA->m_display;
d3a80c92
MB
628 int errorStatus = XpmWriteFileFromPixmap(dpy,
629 wxConstCast(name.c_str(), char),
2d120f83
JS
630 (Pixmap) M_BITMAPHANDLERDATA->m_pixmap,
631 (M_BITMAPHANDLERDATA->m_bitmapMask ? (Pixmap) M_BITMAPHANDLERDATA->m_bitmapMask->GetPixmap() : (Pixmap) 0),
632 (XpmAttributes *) NULL);
f97c9854 633 if (errorStatus == XpmSuccess)
2d120f83 634 return TRUE;
f97c9854 635 else
2d120f83 636 return FALSE;
f97c9854
JS
637 }
638 else
639 return FALSE;
640}
641
642class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler
643{
644 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
645public:
a4294b78 646 inline wxXPMDataHandler()
f97c9854
JS
647 {
648 m_name = "XPM data";
649 m_extension = "xpm";
650 m_type = wxBITMAP_TYPE_XPM_DATA;
651 };
31528cd3 652
1bc822df
MB
653 virtual bool Create(wxBitmap *bitmap, void *data, long flags,
654 int width, int height, int depth = 1);
f97c9854
JS
655};
656IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
657
1bc822df
MB
658bool wxXPMDataHandler::Create( wxBitmap *bitmap, void *data,
659 long WXUNUSED(flags),
2d120f83 660 int width, int height, int WXUNUSED(depth))
f97c9854
JS
661{
662 M_BITMAPHANDLERDATA->m_width = width;
663 M_BITMAPHANDLERDATA->m_height = height;
664 M_BITMAPHANDLERDATA->m_depth = 1;
665 M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
31528cd3 666
a4294b78 667 Display *dpy = (Display*) wxGetDisplay();
f97c9854 668 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
31528cd3 669
f97c9854 670 XpmAttributes xpmAttr;
31528cd3 671
f97c9854 672 xpmAttr.valuemask = XpmReturnInfos; /* nothing yet, but get infos back */
31528cd3 673
f97c9854
JS
674 XpmColorSymbol symbolicColors[4];
675 if (sg_Control && sg_Control->GetMainWidget())
676 {
677 symbolicColors[0].name = "foreground";
678 symbolicColors[0].value = NULL;
679 symbolicColors[1].name = "background";
680 symbolicColors[1].value = NULL;
681 XtVaGetValues((Widget) sg_Control->GetMainWidget(),
682 XmNforeground, &symbolicColors[0].pixel,
683 XmNbackground, &symbolicColors[1].pixel,NULL);
684 xpmAttr.numsymbols = 2;
685 xpmAttr.colorsymbols = symbolicColors;
686 xpmAttr.valuemask |= XpmColorSymbols; // add flag
687 }
31528cd3 688
f97c9854
JS
689 Pixmap pixmap;
690 Pixmap mask = 0;
691 int ErrorStatus = XpmCreatePixmapFromData(dpy, RootWindow(dpy, DefaultScreen(dpy)),
2d120f83 692 (char**) data, &pixmap, &mask, &xpmAttr);
f97c9854
JS
693 if (ErrorStatus == XpmSuccess)
694 {
695 // Set attributes
696 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
697 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
31528cd3 698
0d57be45
JS
699 unsigned int depthRet;
700 int xRet, yRet;
701 unsigned int widthRet, heightRet, borderWidthRet;
702 Window rootWindowRet;
703 XGetGeometry(dpy, pixmap, &rootWindowRet, &xRet, &yRet,
704 &widthRet, &heightRet, &borderWidthRet, &depthRet);
31528cd3 705
2d120f83
JS
706 /*
707 if ( xpmAttr.npixels > 2 )
708 {
f97c9854 709 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
2d120f83
JS
710 } else
711 {
f97c9854 712 M_BITMAPHANDLERDATA->m_depth = 1; // mono
2d120f83
JS
713 }
714 */
31528cd3 715
0d57be45 716 M_BITMAPHANDLERDATA->m_depth = depthRet;
31528cd3 717
f97c9854
JS
718 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
719 XpmFreeAttributes(&xpmAttr);
720 M_BITMAPHANDLERDATA->m_ok = TRUE;
721 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap;
722 if ( mask )
723 {
724 M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask;
725 M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask);
726 }
727 }
728 else
729 {
2d120f83 730 // XpmDebugError(ErrorStatus, NULL);
f97c9854
JS
731 M_BITMAPHANDLERDATA->m_ok = FALSE;
732 }
733 return M_BITMAPHANDLERDATA->m_ok ;
734}
735
31528cd3 736#endif // wxHAVE_LIB_XPM
4bb6408c 737
4bb6408c
JS
738void wxBitmap::InitStandardHandlers()
739{
f97c9854
JS
740 // Initialize all standard bitmap or derived class handlers here.
741 AddHandler(new wxXBMFileHandler);
742 AddHandler(new wxXBMDataHandler);
31528cd3
VZ
743
744 // XPM is considered standard for Motif, although it can be omitted if
745 // libXpm is not installed
746#if wxHAVE_LIB_XPM
4bb6408c
JS
747 AddHandler(new wxXPMFileHandler);
748 AddHandler(new wxXPMDataHandler);
31528cd3 749#endif // wxHAVE_LIB_XPM
f97c9854
JS
750}
751
752WXPixmap wxBitmap::GetLabelPixmap (WXWidget w)
753{
54c7aaca
MB
754 if (!M_BITMAPDATA)
755 return (WXPixmap)NULL;
2d120f83
JS
756 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
757 return M_BITMAPDATA->m_pixmap;
31528cd3 758
2d120f83 759 Display *dpy = (Display*) M_BITMAPDATA->m_display;
31528cd3 760
f97c9854 761#ifdef FOO
2d120f83
JS
762 /*
763 If we do:
764 if (labelPixmap) return labelPixmap;
765 things can be wrong, because colors can have been changed.
31528cd3 766
2d120f83
JS
767 If we do:
768 if (labelPixmap)
769 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
770 we got BadDrawable if the pixmap is referenced by multiples widgets
31528cd3 771
2d120f83 772 this is a catch22!!
31528cd3 773
e838cc14
VZ
774 So, before doing thing really clean, I just do nothing; if the pixmap is
775 referenced by many widgets, Motif performs caching functions.
776 And if pixmap is referenced with multiples colors, we just have some
777 memory leaks... I hope we can deal with them...
2d120f83
JS
778 */
779 // Must be destroyed, because colours can have been changed!
780 if (M_BITMAPDATA->m_labelPixmap)
781 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_labelPixmap);
f97c9854 782#endif
31528cd3 783
2d120f83
JS
784 char tmp[128];
785 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
31528cd3 786
2d120f83
JS
787 Pixel fg, bg;
788 Widget widget = (Widget) w;
31528cd3 789
2d120f83
JS
790 while (XmIsGadget ( widget ))
791 widget = XtParent (widget);
792 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
31528cd3 793
2d120f83 794 M_BITMAPDATA->m_labelPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 795
2d120f83 796 return M_BITMAPDATA->m_labelPixmap;
f97c9854
JS
797}
798
799WXPixmap wxBitmap::GetArmPixmap (WXWidget w)
800{
2d120f83
JS
801 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
802 return M_BITMAPDATA->m_pixmap;
31528cd3 803
2d120f83 804 Display *dpy = (Display*) M_BITMAPDATA->m_display;
f97c9854 805#ifdef FOO
e838cc14
VZ
806 // See GetLabelPixmap () comment
807
808 // Must be destroyed, because colours can have been changed!
809 if (M_BITMAPDATA->m_armPixmap)
810 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_armPixmap);
f97c9854 811#endif
31528cd3 812
e838cc14
VZ
813 char tmp[128];
814 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
31528cd3 815
e838cc14
VZ
816 Pixel fg, bg;
817 Widget widget = (Widget) w;
31528cd3 818
e838cc14
VZ
819 XtVaGetValues (widget, XmNarmColor, &bg, NULL);
820 while (XmIsGadget (widget))
821 widget = XtParent (widget);
822 XtVaGetValues (widget, XmNforeground, &fg, NULL);
31528cd3 823
e838cc14 824 M_BITMAPDATA->m_armPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 825
e838cc14 826 return M_BITMAPDATA->m_armPixmap;
f97c9854
JS
827}
828
829WXPixmap wxBitmap::GetInsensPixmap (WXWidget w)
830{
2d120f83 831 Display *dpy = (Display*) M_BITMAPDATA->m_display;
54c7aaca
MB
832
833 if (!M_BITMAPDATA)
834 return (WXPixmap)NULL;
0d57be45 835 if (M_BITMAPDATA->m_insensPixmap)
2d120f83 836 return M_BITMAPDATA->m_insensPixmap;
31528cd3 837
2d120f83
JS
838 if (!w)
839 {
840 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XCreateInsensitivePixmap(dpy, (Pixmap) M_BITMAPDATA->m_pixmap);
841 if (M_BITMAPDATA->m_insensPixmap)
842 return M_BITMAPDATA->m_insensPixmap;
843 else
844 return M_BITMAPDATA->m_pixmap;
845 }
31528cd3 846
2d120f83
JS
847 if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0)
848 return M_BITMAPDATA->m_pixmap;
31528cd3 849
f97c9854 850#ifdef FOO
2d120f83
JS
851 See GetLabelPixmap () comment
852 // Must be destroyed, because colours can have been changed!
853 if (M_BITMAPDATA->m_insensPixmap)
854 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), (Pixmap) M_BITMAPDATA->m_insensPixmap);
f97c9854 855#endif
31528cd3 856
e838cc14
VZ
857 char tmp[128];
858 sprintf (tmp, "Not%x", (unsigned int) M_BITMAPDATA->m_insensImage);
31528cd3 859
e838cc14
VZ
860 Pixel fg, bg;
861 Widget widget = (Widget) w;
31528cd3 862
e838cc14
VZ
863 while (XmIsGadget (widget))
864 widget = XtParent (widget);
865 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
31528cd3 866
e838cc14 867 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 868
e838cc14 869 return M_BITMAPDATA->m_insensPixmap;
f97c9854
JS
870}
871
872// We may need this sometime...
873
874/****************************************************************************
875
2d120f83
JS
876 NAME
877 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
31528cd3 878
e838cc14
VZ
879 SYNOPSIS
880 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
31528cd3 881
e838cc14
VZ
882 DESCRIPTION
883 This function creates a grayed-out copy of the argument pixmap, suitable
884 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
31528cd3 885
e838cc14
VZ
886 RETURN VALUES
887 The return value is the new Pixmap id or zero on error. Errors include
888 a NULL display argument or an invalid Pixmap argument.
31528cd3 889
e838cc14
VZ
890 ERRORS
891 If one of the XLib functions fail, it will produce a X error. The
892 default X error handler prints a diagnostic and calls exit().
31528cd3 893
e838cc14
VZ
894 SEE ALSO
895 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
896 XFillRectangle(3), exit(2)
31528cd3 897
e838cc14
VZ
898 AUTHOR
899 John R Veregge - john@puente.jpl.nasa.gov
900 Advanced Engineering and Prototyping Group (AEG)
901 Information Systems Technology Section (395)
902 Jet Propulsion Lab - Calif Institute of Technology
31528cd3 903
f97c9854
JS
904*****************************************************************************/
905
906Pixmap
907XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
908
909{
e838cc14
VZ
910 static char stipple_data[] =
911 {
912 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
f97c9854
JS
913 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
914 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
915 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA
e838cc14 916 };
f97c9854
JS
917 GC gc;
918 Pixmap ipixmap, stipple;
919 unsigned width, height, depth;
31528cd3 920
f97c9854
JS
921 Window window; /* These return values */
922 unsigned border; /* from XGetGeometry() */
923 int x, y; /* are not needed. */
31528cd3 924
f97c9854 925 ipixmap = 0;
31528cd3 926
f97c9854 927 if ( NULL == display || 0 == pixmap )
2d120f83 928 return ipixmap;
31528cd3 929
f97c9854 930 if ( 0 == XGetGeometry( display, pixmap, &window, &x, &y,
e838cc14
VZ
931 &width, &height, &border, &depth )
932 )
2d120f83 933 return ipixmap; /* BadDrawable: probably an invalid pixmap */
31528cd3 934
e838cc14
VZ
935 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
936 */
f97c9854
JS
937 stipple = XCreateBitmapFromData( display, pixmap, stipple_data, 16, 16 );
938 if ( 0 != stipple )
939 {
2d120f83
JS
940 gc = XCreateGC( display, pixmap, (XtGCMask)0, (XGCValues*)NULL );
941 if ( NULL != gc )
f97c9854 942 {
e838cc14
VZ
943 /* Create an identical copy of the argument pixmap.
944 */
2d120f83
JS
945 ipixmap = XCreatePixmap( display, pixmap, width, height, depth );
946 if ( 0 != ipixmap )
947 {
e838cc14
VZ
948 /* Copy the argument pixmap into the new pixmap.
949 */
2d120f83 950 XCopyArea( display, pixmap, ipixmap,
e838cc14 951 gc, 0, 0, width, height, 0, 0 );
31528cd3 952
e838cc14
VZ
953 /* Refill the new pixmap using the stipple algorithm/pixmap.
954 */
2d120f83
JS
955 XSetStipple( display, gc, stipple );
956 XSetFillStyle( display, gc, FillStippled );
957 XFillRectangle( display, ipixmap, gc, 0, 0, width, height );
958 }
959 XFreeGC( display, gc );
f97c9854 960 }
2d120f83 961 XFreePixmap( display, stipple );
f97c9854
JS
962 }
963 return ipixmap;
4bb6408c 964}
f97c9854 965
321db4b6
JS
966// Creates a bitmap with transparent areas drawn in
967// the given colour.
d166a4f8 968wxBitmap wxCreateMaskedBitmap(const wxBitmap& bitmap, wxColour& colour)
321db4b6
JS
969{
970 wxBitmap newBitmap(bitmap.GetWidth(),
2d120f83
JS
971 bitmap.GetHeight(),
972 bitmap.GetDepth());
321db4b6
JS
973 wxMemoryDC destDC;
974 wxMemoryDC srcDC;
975 srcDC.SelectObject(bitmap);
976 destDC.SelectObject(newBitmap);
31528cd3 977
321db4b6
JS
978 wxBrush brush(colour, wxSOLID);
979 destDC.SetOptimization(FALSE);
980 destDC.SetBackground(brush);
981 destDC.Clear();
982 destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(), & srcDC, 0, 0, wxCOPY, TRUE);
31528cd3 983
321db4b6
JS
984 return newBitmap;
985}
fec19ea9
VS
986
987
988
989
990//-----------------------------------------------------------------------------
991// wxImage conversion routines
992//-----------------------------------------------------------------------------
993
994/*
995
996Date: Wed, 05 Jan 2000 11:45:40 +0100
997From: Frits Boel <boel@niob.knaw.nl>
998To: julian.smart@ukonline.co.uk
999Subject: Patch for Motif ConvertToBitmap
1000
1001Hi Julian,
1002
1003I've been working on a wxWin application for image processing. From the
1004beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1005till I looked in the source code of image.cpp. I saw that converting a
1006wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1007to the 256 colors of the palet. A very time-consuming piece of code!
1008
1009Because I wanted a faster application, I've made a 'patch' for this. In
1010short: every pixel of the image is compared to a sorted list with
1011colors. If the color is found in the list, the palette entry is
1012returned; if the color is not found, the color palette is searched and
1013then the palette entry is returned and the color added to the sorted
1014list.
1015
1016Maybe there is another method for this, namely changing the palette
1017itself (if the colors are known, as is the case with tiffs with a
1018colormap). I did not look at this, maybe someone else did?
1019
1020The code of the patch is attached, have a look on it, and maybe you will
1021ship it with the next release of wxMotif?
1022
1023Regards,
1024
1025Frits Boel
1026Software engineer at Hubrecht Laboratory, The Netherlands.
1027
1028*/
1029
1030class wxSearchColor
1031{
1032public:
1033 wxSearchColor( void );
1034 wxSearchColor( int size, XColor *colors );
1035 ~wxSearchColor( void );
1036
1037 int SearchColor( int r, int g, int b );
1038private:
1039 int AddColor( unsigned int value, int pos );
1040
1041 int size;
1042 XColor *colors;
1043 unsigned int *color;
1044 int *entry;
1045
1046 int bottom;
1047 int top;
1048};
1049
1050wxSearchColor::wxSearchColor( void )
1051{
1052 size = 0;
1053 colors = (XColor*) NULL;
1054 color = (unsigned int *) NULL;
1055 entry = (int*) NULL;
1056
1057 bottom = 0;
1058 top = 0;
1059}
1060
1061wxSearchColor::wxSearchColor( int size_, XColor *colors_ )
1062{
1063 int i;
1064 size = size_;
1065 colors = colors_;
1066 color = new unsigned int[size];
1067 entry = new int [size];
1068
1069 for (i = 0; i < size; i++ ) {
1070 entry[i] = -1;
1071 }
1072
1073 bottom = top = ( size >> 1 );
1074}
1075
1076wxSearchColor::~wxSearchColor( void )
1077{
1078 if ( color ) delete color;
1079 if ( entry ) delete entry;
1080}
1081
1082int wxSearchColor::SearchColor( int r, int g, int b )
1083{
1084 unsigned int value = ( ( ( r * 256 ) + g ) * 256 ) + b;
1085 int begin = bottom;
1086 int end = top;
1087 int middle = 0;
1088
1089 while ( begin <= end ) {
1090
1091 middle = ( begin + end ) >> 1;
1092
1093 if ( value == color[middle] ) {
1094 return( entry[middle] );
1095 } else if ( value < color[middle] ) {
1096 end = middle - 1;
1097 } else {
1098 begin = middle + 1;
1099 }
1100
1101 }
1102
1103 return AddColor( value, middle );
1104}
1105
1106int wxSearchColor::AddColor( unsigned int value, int pos )
1107{
1108 int i;
1109 int pixel = -1;
1110 int max = 3 * (65536);
1111 for ( i = 0; i < 256; i++ ) {
1112 int rdiff = ((value >> 8) & 0xFF00 ) - colors[i].red;
1113 int gdiff = ((value ) & 0xFF00 ) - colors[i].green;
1114 int bdiff = ((value << 8) & 0xFF00 ) - colors[i].blue;
1115 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1116 if (sum < max) { pixel = i; max = sum; }
1117 }
1118
1119 if ( entry[pos] < 0 ) {
1120 color[pos] = value;
1121 entry[pos] = pixel;
1122 } else if ( value < color[pos] ) {
1123
1124 if ( bottom > 0 ) {
1125 for ( i = bottom; i < pos; i++ ) {
1126 color[i-1] = color[i];
1127 entry[i-1] = entry[i];
1128 }
1129 bottom--;
1130 color[pos-1] = value;
1131 entry[pos-1] = pixel;
1132 } else if ( top < size-1 ) {
1133 for ( i = top; i >= pos; i-- ) {
1134 color[i+1] = color[i];
1135 entry[i+1] = entry[i];
1136 }
1137 top++;
1138 color[pos] = value;
1139 entry[pos] = pixel;
1140 }
1141
1142 } else {
1143
1144 if ( top < size-1 ) {
1145 for ( i = top; i > pos; i-- ) {
1146 color[i+1] = color[i];
1147 entry[i+1] = entry[i];
1148 }
1149 top++;
1150 color[pos+1] = value;
1151 entry[pos+1] = pixel;
1152 } else if ( bottom > 0 ) {
1153 for ( i = bottom; i < pos; i++ ) {
1154 color[i-1] = color[i];
1155 entry[i-1] = entry[i];
1156 }
1157 bottom--;
1158 color[pos] = value;
1159 entry[pos] = pixel;
1160 }
1161
1162 }
1163
1164 return( pixel );
1165}
1166
1167
1168bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
1169{
1170 wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") )
1171 wxCHECK_MSG( depth == -1, FALSE, wxT("invalid bitmap depth") )
1172
1173 m_refData = new wxBitmapRefData();
fec19ea9
VS
1174
1175 int width = image.GetWidth();
1176 int height = image.GetHeight();
1177
1178 SetHeight( height );
1179 SetWidth( width );
1180
1181 Display *dpy = (Display*) wxGetDisplay();
1182 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1183 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1184
1185 // Create image
1186
1187 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
1188 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
1189
1190 Create( width, height, bpp );
1191
1192 // Create mask
1193
1194 XImage *mask_image = (XImage*) NULL;
1195 if (image.HasMask())
1196 {
1197 mask_image = XCreateImage( dpy, vis, 1, ZPixmap, 0, 0, width, height, 32, 0 );
1198 mask_image->data = (char*) malloc( mask_image->bytes_per_line * mask_image->height );
1199 }
1200
1201 // Retrieve depth info
1202
1203 XVisualInfo vinfo_template;
1204 XVisualInfo *vi;
1205
1206 vinfo_template.visual = vis;
1207 vinfo_template.visualid = XVisualIDFromVisual( vis );
1208 vinfo_template.depth = bpp;
1209 int nitem = 0;
1210
1211 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1212
1213 wxCHECK_MSG( vi, FALSE, wxT("no visual") );
1214
1215 XFree( vi );
1216
1217 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1218 if (bpp < 8) bpp = 8;
1219
1220 // Render
1221
1222 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1223 byte_order b_o = RGB;
1224
1225 if (bpp >= 24)
1226 {
1227 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1228 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1229 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1230 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1231 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1232 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1233 }
1234
1235 int r_mask = image.GetMaskRed();
1236 int g_mask = image.GetMaskGreen();
1237 int b_mask = image.GetMaskBlue();
1238
1239 XColor colors[256];
1240 if (bpp == 8)
1241 {
1242 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
1243
1244 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1245 XQueryColors( dpy, cmap, colors, 256 );
1246 }
1247
1248 wxSearchColor scolor( 256, colors );
1249 unsigned char* data = image.GetData();
1250
1251 bool hasMask = image.HasMask();
1252
1253 int index = 0;
1254 for (int y = 0; y < height; y++)
1255 {
1256 for (int x = 0; x < width; x++)
1257 {
1258 int r = data[index];
1259 index++;
1260 int g = data[index];
1261 index++;
1262 int b = data[index];
1263 index++;
1264
1265 if (hasMask)
1266 {
1267 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1268 XPutPixel( mask_image, x, y, 0 );
1269 else
1270 XPutPixel( mask_image, x, y, 1 );
1271 }
1272
1273 switch (bpp)
1274 {
1275 case 8:
1276 {
1277#if 0 // Old, slower code
1278 int pixel = -1;
1279 /*
1280 if (wxTheApp->m_colorCube)
1281 {
1282 pixel = wxTheApp->m_colorCube
1283 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1284 }
1285 else
1286 {
1287 */
1288 int max = 3 * (65536);
1289 for (int i = 0; i < 256; i++)
1290 {
1291 int rdiff = (r << 8) - colors[i].red;
1292 int gdiff = (g << 8) - colors[i].green;
1293 int bdiff = (b << 8) - colors[i].blue;
1294 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1295 if (sum < max) { pixel = i; max = sum; }
1296 }
1297 /*
1298 }
1299 */
1300#endif
1301
1302 // And this is all to get the 'right' color...
1303 int pixel = scolor.SearchColor( r, g, b );
1304 XPutPixel( data_image, x, y, pixel );
1305 break;
1306 }
1307 case 15:
1308 {
1309 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1310 XPutPixel( data_image, x, y, pixel );
1311 break;
1312 }
1313 case 16:
1314 {
1315 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1316 XPutPixel( data_image, x, y, pixel );
1317 break;
1318 }
1319 case 32:
1320 case 24:
1321 {
1322 int pixel = 0;
1323 switch (b_o)
1324 {
1325 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1326 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1327 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1328 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1329 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1330 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1331 }
1332 XPutPixel( data_image, x, y, pixel );
1333 }
1334 default: break;
1335 }
1336 } // for
1337 } // for
1338
1339 // Blit picture
1340
1341 XGCValues gcvalues;
1342 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1343 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1344 XPutImage( dpy, (Drawable)GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
1345
1346 XDestroyImage( data_image );
1347 XFreeGC( dpy, gc );
1348
1349 // Blit mask
1350 if (image.HasMask())
1351 {
1352 wxBitmap maskBitmap(width, height, 1);
1353
1354 GC gcMask = XCreateGC( dpy, (Pixmap) maskBitmap.GetPixmap(), (XtGCMask) 0, (XGCValues*)NULL );
1355 XPutImage( dpy, (Drawable)maskBitmap.GetPixmap(), gcMask, mask_image, 0, 0, 0, 0, width, height );
1356
1357 XDestroyImage( mask_image );
1358 XFreeGC( dpy, gcMask );
1359
1360 wxMask* mask = new wxMask;
1361 mask->SetPixmap(maskBitmap.GetPixmap());
1362
1363 SetMask(mask);
1364
1365 maskBitmap.SetPixmapNull();
1366 }
1367
1368
1369 return TRUE;
1370}
1371
1372wxImage wxBitmap::ConvertToImage() const
1373{
1374 wxImage image;
1375
1376 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
1377
1378 Display *dpy = (Display*) wxGetDisplay();
1379 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1380 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1381
1382 XImage *ximage = XGetImage( dpy,
1383 (Drawable)GetPixmap(),
1384 0, 0,
1385 GetWidth(), GetHeight(),
1386 AllPlanes, ZPixmap );
1387
1388 wxCHECK_MSG( ximage, wxNullImage, wxT("couldn't create image") );
1389
1390 image.Create( GetWidth(), GetHeight() );
1391 char unsigned *data = image.GetData();
1392
1393 if (!data)
1394 {
1395 XDestroyImage( ximage );
1396 wxFAIL_MSG( wxT("couldn't create image") );
1397 return wxNullImage;
1398 }
1399
1400 /*
1401 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1402 if (GetMask())
1403 {
1404 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
1405 0, 0,
1406 GetWidth(), GetHeight() );
1407
1408 image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1409 }
1410 */
1411
1412 // Retrieve depth info
1413
1414 XVisualInfo vinfo_template;
1415 XVisualInfo *vi;
1416
1417 vinfo_template.visual = vis;
1418 vinfo_template.visualid = XVisualIDFromVisual( vis );
1419 vinfo_template.depth = bpp;
1420 int nitem = 0;
1421
1422 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1423
1424 wxCHECK_MSG( vi, wxNullImage, wxT("no visual") );
1425
1426 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1427
1428 XFree( vi );
1429
1430 XColor colors[256];
1431 if (bpp == 8)
1432 {
1433 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
1434
1435 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1436 XQueryColors( dpy, cmap, colors, 256 );
1437 }
1438
1439 long pos = 0;
1440 for (int j = 0; j < GetHeight(); j++)
1441 {
1442 for (int i = 0; i < GetWidth(); i++)
1443 {
1444 int pixel = XGetPixel( ximage, i, j );
1445 if (bpp <= 8)
1446 {
1447 data[pos] = colors[pixel].red >> 8;
1448 data[pos+1] = colors[pixel].green >> 8;
1449 data[pos+2] = colors[pixel].blue >> 8;
1450 } else if (bpp == 15)
1451 {
1452 data[pos] = (pixel >> 7) & 0xf8;
1453 data[pos+1] = (pixel >> 2) & 0xf8;
1454 data[pos+2] = (pixel << 3) & 0xf8;
1455 } else if (bpp == 16)
1456 {
1457 data[pos] = (pixel >> 8) & 0xf8;
1458 data[pos+1] = (pixel >> 3) & 0xfc;
1459 data[pos+2] = (pixel << 3) & 0xf8;
1460 } else
1461 {
1462 data[pos] = (pixel >> 16) & 0xff;
1463 data[pos+1] = (pixel >> 8) & 0xff;
1464 data[pos+2] = pixel & 0xff;
1465 }
1466
1467 /*
1468 if (gdk_image_mask)
1469 {
1470 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1471 if (mask_pixel == 0)
1472 {
1473 data[pos] = 16;
1474 data[pos+1] = 16;
1475 data[pos+2] = 16;
1476 }
1477 }
1478 */
1479
1480 pos += 3;
1481 }
1482 }
1483
1484 XDestroyImage( ximage );
1485 /*
1486 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1487 */
1488
1489 return image;
1490}