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