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