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