]> git.saurik.com Git - wxWidgets.git/blame - src/motif/bitmap.cpp
Updated version
[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 {
79f1dd05 214 *this = wxBitmap(image);
b75dd496
VS
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 244 if ( handler == NULL ) { // try wxImage
79f1dd05 245 wxImage image = this->ConvertToImage();
b75dd496
VS
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{
54c7aaca
MB
832 if (!M_BITMAPDATA)
833 return (WXPixmap)NULL;
2d120f83
JS
834 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
835 return M_BITMAPDATA->m_pixmap;
31528cd3 836
2d120f83 837 Display *dpy = (Display*) M_BITMAPDATA->m_display;
31528cd3 838
f97c9854 839#ifdef FOO
2d120f83
JS
840 /*
841 If we do:
842 if (labelPixmap) return labelPixmap;
843 things can be wrong, because colors can have been changed.
31528cd3 844
2d120f83
JS
845 If we do:
846 if (labelPixmap)
847 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
848 we got BadDrawable if the pixmap is referenced by multiples widgets
31528cd3 849
2d120f83 850 this is a catch22!!
31528cd3 851
e838cc14
VZ
852 So, before doing thing really clean, I just do nothing; if the pixmap is
853 referenced by many widgets, Motif performs caching functions.
854 And if pixmap is referenced with multiples colors, we just have some
855 memory leaks... I hope we can deal with them...
2d120f83
JS
856 */
857 // Must be destroyed, because colours can have been changed!
858 if (M_BITMAPDATA->m_labelPixmap)
859 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_labelPixmap);
f97c9854 860#endif
31528cd3 861
2d120f83
JS
862 char tmp[128];
863 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
31528cd3 864
2d120f83
JS
865 Pixel fg, bg;
866 Widget widget = (Widget) w;
31528cd3 867
2d120f83
JS
868 while (XmIsGadget ( widget ))
869 widget = XtParent (widget);
870 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
31528cd3 871
2d120f83 872 M_BITMAPDATA->m_labelPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 873
2d120f83 874 return M_BITMAPDATA->m_labelPixmap;
f97c9854
JS
875}
876
877WXPixmap wxBitmap::GetArmPixmap (WXWidget w)
878{
2d120f83
JS
879 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
880 return M_BITMAPDATA->m_pixmap;
31528cd3 881
2d120f83 882 Display *dpy = (Display*) M_BITMAPDATA->m_display;
f97c9854 883#ifdef FOO
e838cc14
VZ
884 // See GetLabelPixmap () comment
885
886 // Must be destroyed, because colours can have been changed!
887 if (M_BITMAPDATA->m_armPixmap)
888 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_armPixmap);
f97c9854 889#endif
31528cd3 890
e838cc14
VZ
891 char tmp[128];
892 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
31528cd3 893
e838cc14
VZ
894 Pixel fg, bg;
895 Widget widget = (Widget) w;
31528cd3 896
e838cc14
VZ
897 XtVaGetValues (widget, XmNarmColor, &bg, NULL);
898 while (XmIsGadget (widget))
899 widget = XtParent (widget);
900 XtVaGetValues (widget, XmNforeground, &fg, NULL);
31528cd3 901
e838cc14 902 M_BITMAPDATA->m_armPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 903
e838cc14 904 return M_BITMAPDATA->m_armPixmap;
f97c9854
JS
905}
906
907WXPixmap wxBitmap::GetInsensPixmap (WXWidget w)
908{
2d120f83 909 Display *dpy = (Display*) M_BITMAPDATA->m_display;
54c7aaca
MB
910
911 if (!M_BITMAPDATA)
912 return (WXPixmap)NULL;
0d57be45 913 if (M_BITMAPDATA->m_insensPixmap)
2d120f83 914 return M_BITMAPDATA->m_insensPixmap;
31528cd3 915
2d120f83
JS
916 if (!w)
917 {
918 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XCreateInsensitivePixmap(dpy, (Pixmap) M_BITMAPDATA->m_pixmap);
919 if (M_BITMAPDATA->m_insensPixmap)
920 return M_BITMAPDATA->m_insensPixmap;
921 else
922 return M_BITMAPDATA->m_pixmap;
923 }
31528cd3 924
2d120f83
JS
925 if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0)
926 return M_BITMAPDATA->m_pixmap;
31528cd3 927
f97c9854 928#ifdef FOO
2d120f83
JS
929 See GetLabelPixmap () comment
930 // Must be destroyed, because colours can have been changed!
931 if (M_BITMAPDATA->m_insensPixmap)
932 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), (Pixmap) M_BITMAPDATA->m_insensPixmap);
f97c9854 933#endif
31528cd3 934
e838cc14
VZ
935 char tmp[128];
936 sprintf (tmp, "Not%x", (unsigned int) M_BITMAPDATA->m_insensImage);
31528cd3 937
e838cc14
VZ
938 Pixel fg, bg;
939 Widget widget = (Widget) w;
31528cd3 940
e838cc14
VZ
941 while (XmIsGadget (widget))
942 widget = XtParent (widget);
943 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
31528cd3 944
e838cc14 945 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 946
e838cc14 947 return M_BITMAPDATA->m_insensPixmap;
f97c9854
JS
948}
949
950// We may need this sometime...
951
952/****************************************************************************
953
2d120f83
JS
954 NAME
955 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
31528cd3 956
e838cc14
VZ
957 SYNOPSIS
958 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
31528cd3 959
e838cc14
VZ
960 DESCRIPTION
961 This function creates a grayed-out copy of the argument pixmap, suitable
962 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
31528cd3 963
e838cc14
VZ
964 RETURN VALUES
965 The return value is the new Pixmap id or zero on error. Errors include
966 a NULL display argument or an invalid Pixmap argument.
31528cd3 967
e838cc14
VZ
968 ERRORS
969 If one of the XLib functions fail, it will produce a X error. The
970 default X error handler prints a diagnostic and calls exit().
31528cd3 971
e838cc14
VZ
972 SEE ALSO
973 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
974 XFillRectangle(3), exit(2)
31528cd3 975
e838cc14
VZ
976 AUTHOR
977 John R Veregge - john@puente.jpl.nasa.gov
978 Advanced Engineering and Prototyping Group (AEG)
979 Information Systems Technology Section (395)
980 Jet Propulsion Lab - Calif Institute of Technology
31528cd3 981
f97c9854
JS
982*****************************************************************************/
983
984Pixmap
985XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
986
987{
e838cc14
VZ
988 static char stipple_data[] =
989 {
990 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
f97c9854
JS
991 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
992 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
993 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA
e838cc14 994 };
f97c9854
JS
995 GC gc;
996 Pixmap ipixmap, stipple;
997 unsigned width, height, depth;
31528cd3 998
f97c9854
JS
999 Window window; /* These return values */
1000 unsigned border; /* from XGetGeometry() */
1001 int x, y; /* are not needed. */
31528cd3 1002
f97c9854 1003 ipixmap = 0;
31528cd3 1004
f97c9854 1005 if ( NULL == display || 0 == pixmap )
2d120f83 1006 return ipixmap;
31528cd3 1007
f97c9854 1008 if ( 0 == XGetGeometry( display, pixmap, &window, &x, &y,
e838cc14
VZ
1009 &width, &height, &border, &depth )
1010 )
2d120f83 1011 return ipixmap; /* BadDrawable: probably an invalid pixmap */
31528cd3 1012
e838cc14
VZ
1013 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
1014 */
f97c9854
JS
1015 stipple = XCreateBitmapFromData( display, pixmap, stipple_data, 16, 16 );
1016 if ( 0 != stipple )
1017 {
2d120f83
JS
1018 gc = XCreateGC( display, pixmap, (XtGCMask)0, (XGCValues*)NULL );
1019 if ( NULL != gc )
f97c9854 1020 {
e838cc14
VZ
1021 /* Create an identical copy of the argument pixmap.
1022 */
2d120f83
JS
1023 ipixmap = XCreatePixmap( display, pixmap, width, height, depth );
1024 if ( 0 != ipixmap )
1025 {
e838cc14
VZ
1026 /* Copy the argument pixmap into the new pixmap.
1027 */
2d120f83 1028 XCopyArea( display, pixmap, ipixmap,
e838cc14 1029 gc, 0, 0, width, height, 0, 0 );
31528cd3 1030
e838cc14
VZ
1031 /* Refill the new pixmap using the stipple algorithm/pixmap.
1032 */
2d120f83
JS
1033 XSetStipple( display, gc, stipple );
1034 XSetFillStyle( display, gc, FillStippled );
1035 XFillRectangle( display, ipixmap, gc, 0, 0, width, height );
1036 }
1037 XFreeGC( display, gc );
f97c9854 1038 }
2d120f83 1039 XFreePixmap( display, stipple );
f97c9854
JS
1040 }
1041 return ipixmap;
4bb6408c 1042}
f97c9854 1043
321db4b6
JS
1044// Creates a bitmap with transparent areas drawn in
1045// the given colour.
d166a4f8 1046wxBitmap wxCreateMaskedBitmap(const wxBitmap& bitmap, wxColour& colour)
321db4b6
JS
1047{
1048 wxBitmap newBitmap(bitmap.GetWidth(),
2d120f83
JS
1049 bitmap.GetHeight(),
1050 bitmap.GetDepth());
321db4b6
JS
1051 wxMemoryDC destDC;
1052 wxMemoryDC srcDC;
1053 srcDC.SelectObject(bitmap);
1054 destDC.SelectObject(newBitmap);
31528cd3 1055
321db4b6
JS
1056 wxBrush brush(colour, wxSOLID);
1057 destDC.SetOptimization(FALSE);
1058 destDC.SetBackground(brush);
1059 destDC.Clear();
1060 destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(), & srcDC, 0, 0, wxCOPY, TRUE);
31528cd3 1061
321db4b6
JS
1062 return newBitmap;
1063}
fec19ea9
VS
1064
1065
1066
1067
1068//-----------------------------------------------------------------------------
1069// wxImage conversion routines
1070//-----------------------------------------------------------------------------
1071
1072/*
1073
1074Date: Wed, 05 Jan 2000 11:45:40 +0100
1075From: Frits Boel <boel@niob.knaw.nl>
1076To: julian.smart@ukonline.co.uk
1077Subject: Patch for Motif ConvertToBitmap
1078
1079Hi Julian,
1080
1081I've been working on a wxWin application for image processing. From the
1082beginning, I was surprised by the (lack of) speed of ConvertToBitmap,
1083till I looked in the source code of image.cpp. I saw that converting a
1084wxImage to a bitmap with 8-bit pixels is done with comparing every pixel
1085to the 256 colors of the palet. A very time-consuming piece of code!
1086
1087Because I wanted a faster application, I've made a 'patch' for this. In
1088short: every pixel of the image is compared to a sorted list with
1089colors. If the color is found in the list, the palette entry is
1090returned; if the color is not found, the color palette is searched and
1091then the palette entry is returned and the color added to the sorted
1092list.
1093
1094Maybe there is another method for this, namely changing the palette
1095itself (if the colors are known, as is the case with tiffs with a
1096colormap). I did not look at this, maybe someone else did?
1097
1098The code of the patch is attached, have a look on it, and maybe you will
1099ship it with the next release of wxMotif?
1100
1101Regards,
1102
1103Frits Boel
1104Software engineer at Hubrecht Laboratory, The Netherlands.
1105
1106*/
1107
1108class wxSearchColor
1109{
1110public:
1111 wxSearchColor( void );
1112 wxSearchColor( int size, XColor *colors );
1113 ~wxSearchColor( void );
1114
1115 int SearchColor( int r, int g, int b );
1116private:
1117 int AddColor( unsigned int value, int pos );
1118
1119 int size;
1120 XColor *colors;
1121 unsigned int *color;
1122 int *entry;
1123
1124 int bottom;
1125 int top;
1126};
1127
1128wxSearchColor::wxSearchColor( void )
1129{
1130 size = 0;
1131 colors = (XColor*) NULL;
1132 color = (unsigned int *) NULL;
1133 entry = (int*) NULL;
1134
1135 bottom = 0;
1136 top = 0;
1137}
1138
1139wxSearchColor::wxSearchColor( int size_, XColor *colors_ )
1140{
1141 int i;
1142 size = size_;
1143 colors = colors_;
1144 color = new unsigned int[size];
1145 entry = new int [size];
1146
1147 for (i = 0; i < size; i++ ) {
1148 entry[i] = -1;
1149 }
1150
1151 bottom = top = ( size >> 1 );
1152}
1153
1154wxSearchColor::~wxSearchColor( void )
1155{
1156 if ( color ) delete color;
1157 if ( entry ) delete entry;
1158}
1159
1160int wxSearchColor::SearchColor( int r, int g, int b )
1161{
1162 unsigned int value = ( ( ( r * 256 ) + g ) * 256 ) + b;
1163 int begin = bottom;
1164 int end = top;
1165 int middle = 0;
1166
1167 while ( begin <= end ) {
1168
1169 middle = ( begin + end ) >> 1;
1170
1171 if ( value == color[middle] ) {
1172 return( entry[middle] );
1173 } else if ( value < color[middle] ) {
1174 end = middle - 1;
1175 } else {
1176 begin = middle + 1;
1177 }
1178
1179 }
1180
1181 return AddColor( value, middle );
1182}
1183
1184int wxSearchColor::AddColor( unsigned int value, int pos )
1185{
1186 int i;
1187 int pixel = -1;
1188 int max = 3 * (65536);
1189 for ( i = 0; i < 256; i++ ) {
1190 int rdiff = ((value >> 8) & 0xFF00 ) - colors[i].red;
1191 int gdiff = ((value ) & 0xFF00 ) - colors[i].green;
1192 int bdiff = ((value << 8) & 0xFF00 ) - colors[i].blue;
1193 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1194 if (sum < max) { pixel = i; max = sum; }
1195 }
1196
1197 if ( entry[pos] < 0 ) {
1198 color[pos] = value;
1199 entry[pos] = pixel;
1200 } else if ( value < color[pos] ) {
1201
1202 if ( bottom > 0 ) {
1203 for ( i = bottom; i < pos; i++ ) {
1204 color[i-1] = color[i];
1205 entry[i-1] = entry[i];
1206 }
1207 bottom--;
1208 color[pos-1] = value;
1209 entry[pos-1] = pixel;
1210 } else if ( top < size-1 ) {
1211 for ( i = top; i >= pos; i-- ) {
1212 color[i+1] = color[i];
1213 entry[i+1] = entry[i];
1214 }
1215 top++;
1216 color[pos] = value;
1217 entry[pos] = pixel;
1218 }
1219
1220 } else {
1221
1222 if ( top < size-1 ) {
1223 for ( i = top; i > pos; i-- ) {
1224 color[i+1] = color[i];
1225 entry[i+1] = entry[i];
1226 }
1227 top++;
1228 color[pos+1] = value;
1229 entry[pos+1] = pixel;
1230 } else if ( bottom > 0 ) {
1231 for ( i = bottom; i < pos; i++ ) {
1232 color[i-1] = color[i];
1233 entry[i-1] = entry[i];
1234 }
1235 bottom--;
1236 color[pos] = value;
1237 entry[pos] = pixel;
1238 }
1239
1240 }
1241
1242 return( pixel );
1243}
1244
1245
1246bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
1247{
1248 wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") )
1249 wxCHECK_MSG( depth == -1, FALSE, wxT("invalid bitmap depth") )
1250
1251 m_refData = new wxBitmapRefData();
fec19ea9
VS
1252
1253 int width = image.GetWidth();
1254 int height = image.GetHeight();
1255
1256 SetHeight( height );
1257 SetWidth( width );
1258
1259 Display *dpy = (Display*) wxGetDisplay();
1260 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1261 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1262
1263 // Create image
1264
1265 XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
1266 data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
1267
1268 Create( width, height, bpp );
1269
1270 // Create mask
1271
1272 XImage *mask_image = (XImage*) NULL;
1273 if (image.HasMask())
1274 {
1275 mask_image = XCreateImage( dpy, vis, 1, ZPixmap, 0, 0, width, height, 32, 0 );
1276 mask_image->data = (char*) malloc( mask_image->bytes_per_line * mask_image->height );
1277 }
1278
1279 // Retrieve depth info
1280
1281 XVisualInfo vinfo_template;
1282 XVisualInfo *vi;
1283
1284 vinfo_template.visual = vis;
1285 vinfo_template.visualid = XVisualIDFromVisual( vis );
1286 vinfo_template.depth = bpp;
1287 int nitem = 0;
1288
1289 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1290
1291 wxCHECK_MSG( vi, FALSE, wxT("no visual") );
1292
1293 XFree( vi );
1294
1295 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1296 if (bpp < 8) bpp = 8;
1297
1298 // Render
1299
1300 enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
1301 byte_order b_o = RGB;
1302
1303 if (bpp >= 24)
1304 {
1305 if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB;
1306 else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB;
1307 else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG;
1308 else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR;
1309 else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB;
1310 else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR;
1311 }
1312
1313 int r_mask = image.GetMaskRed();
1314 int g_mask = image.GetMaskGreen();
1315 int b_mask = image.GetMaskBlue();
1316
1317 XColor colors[256];
1318 if (bpp == 8)
1319 {
1320 Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy );
1321
1322 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1323 XQueryColors( dpy, cmap, colors, 256 );
1324 }
1325
1326 wxSearchColor scolor( 256, colors );
1327 unsigned char* data = image.GetData();
1328
1329 bool hasMask = image.HasMask();
1330
1331 int index = 0;
1332 for (int y = 0; y < height; y++)
1333 {
1334 for (int x = 0; x < width; x++)
1335 {
1336 int r = data[index];
1337 index++;
1338 int g = data[index];
1339 index++;
1340 int b = data[index];
1341 index++;
1342
1343 if (hasMask)
1344 {
1345 if ((r == r_mask) && (b == b_mask) && (g == g_mask))
1346 XPutPixel( mask_image, x, y, 0 );
1347 else
1348 XPutPixel( mask_image, x, y, 1 );
1349 }
1350
1351 switch (bpp)
1352 {
1353 case 8:
1354 {
1355#if 0 // Old, slower code
1356 int pixel = -1;
1357 /*
1358 if (wxTheApp->m_colorCube)
1359 {
1360 pixel = wxTheApp->m_colorCube
1361 [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
1362 }
1363 else
1364 {
1365 */
1366 int max = 3 * (65536);
1367 for (int i = 0; i < 256; i++)
1368 {
1369 int rdiff = (r << 8) - colors[i].red;
1370 int gdiff = (g << 8) - colors[i].green;
1371 int bdiff = (b << 8) - colors[i].blue;
1372 int sum = abs (rdiff) + abs (gdiff) + abs (bdiff);
1373 if (sum < max) { pixel = i; max = sum; }
1374 }
1375 /*
1376 }
1377 */
1378#endif
1379
1380 // And this is all to get the 'right' color...
1381 int pixel = scolor.SearchColor( r, g, b );
1382 XPutPixel( data_image, x, y, pixel );
1383 break;
1384 }
1385 case 15:
1386 {
1387 int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
1388 XPutPixel( data_image, x, y, pixel );
1389 break;
1390 }
1391 case 16:
1392 {
1393 int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
1394 XPutPixel( data_image, x, y, pixel );
1395 break;
1396 }
1397 case 32:
1398 case 24:
1399 {
1400 int pixel = 0;
1401 switch (b_o)
1402 {
1403 case RGB: pixel = (r << 16) | (g << 8) | b; break;
1404 case RBG: pixel = (r << 16) | (b << 8) | g; break;
1405 case BRG: pixel = (b << 16) | (r << 8) | g; break;
1406 case BGR: pixel = (b << 16) | (g << 8) | r; break;
1407 case GRB: pixel = (g << 16) | (r << 8) | b; break;
1408 case GBR: pixel = (g << 16) | (b << 8) | r; break;
1409 }
1410 XPutPixel( data_image, x, y, pixel );
1411 }
1412 default: break;
1413 }
1414 } // for
1415 } // for
1416
1417 // Blit picture
1418
1419 XGCValues gcvalues;
1420 gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) );
1421 GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues );
1422 XPutImage( dpy, (Drawable)GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height );
1423
1424 XDestroyImage( data_image );
1425 XFreeGC( dpy, gc );
1426
1427 // Blit mask
1428 if (image.HasMask())
1429 {
1430 wxBitmap maskBitmap(width, height, 1);
1431
1432 GC gcMask = XCreateGC( dpy, (Pixmap) maskBitmap.GetPixmap(), (XtGCMask) 0, (XGCValues*)NULL );
1433 XPutImage( dpy, (Drawable)maskBitmap.GetPixmap(), gcMask, mask_image, 0, 0, 0, 0, width, height );
1434
1435 XDestroyImage( mask_image );
1436 XFreeGC( dpy, gcMask );
1437
1438 wxMask* mask = new wxMask;
1439 mask->SetPixmap(maskBitmap.GetPixmap());
1440
1441 SetMask(mask);
1442
1443 maskBitmap.SetPixmapNull();
1444 }
1445
1446
1447 return TRUE;
1448}
1449
1450wxImage wxBitmap::ConvertToImage() const
1451{
1452 wxImage image;
1453
1454 wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
1455
1456 Display *dpy = (Display*) wxGetDisplay();
1457 Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) );
1458 int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) );
1459
1460 XImage *ximage = XGetImage( dpy,
1461 (Drawable)GetPixmap(),
1462 0, 0,
1463 GetWidth(), GetHeight(),
1464 AllPlanes, ZPixmap );
1465
1466 wxCHECK_MSG( ximage, wxNullImage, wxT("couldn't create image") );
1467
1468 image.Create( GetWidth(), GetHeight() );
1469 char unsigned *data = image.GetData();
1470
1471 if (!data)
1472 {
1473 XDestroyImage( ximage );
1474 wxFAIL_MSG( wxT("couldn't create image") );
1475 return wxNullImage;
1476 }
1477
1478 /*
1479 GdkImage *gdk_image_mask = (GdkImage*) NULL;
1480 if (GetMask())
1481 {
1482 gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(),
1483 0, 0,
1484 GetWidth(), GetHeight() );
1485
1486 image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
1487 }
1488 */
1489
1490 // Retrieve depth info
1491
1492 XVisualInfo vinfo_template;
1493 XVisualInfo *vi;
1494
1495 vinfo_template.visual = vis;
1496 vinfo_template.visualid = XVisualIDFromVisual( vis );
1497 vinfo_template.depth = bpp;
1498 int nitem = 0;
1499
1500 vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem );
1501
1502 wxCHECK_MSG( vi, wxNullImage, wxT("no visual") );
1503
1504 if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15;
1505
1506 XFree( vi );
1507
1508 XColor colors[256];
1509 if (bpp == 8)
1510 {
1511 Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy );
1512
1513 for (int i = 0; i < 256; i++) colors[i].pixel = i;
1514 XQueryColors( dpy, cmap, colors, 256 );
1515 }
1516
1517 long pos = 0;
1518 for (int j = 0; j < GetHeight(); j++)
1519 {
1520 for (int i = 0; i < GetWidth(); i++)
1521 {
1522 int pixel = XGetPixel( ximage, i, j );
1523 if (bpp <= 8)
1524 {
1525 data[pos] = colors[pixel].red >> 8;
1526 data[pos+1] = colors[pixel].green >> 8;
1527 data[pos+2] = colors[pixel].blue >> 8;
1528 } else if (bpp == 15)
1529 {
1530 data[pos] = (pixel >> 7) & 0xf8;
1531 data[pos+1] = (pixel >> 2) & 0xf8;
1532 data[pos+2] = (pixel << 3) & 0xf8;
1533 } else if (bpp == 16)
1534 {
1535 data[pos] = (pixel >> 8) & 0xf8;
1536 data[pos+1] = (pixel >> 3) & 0xfc;
1537 data[pos+2] = (pixel << 3) & 0xf8;
1538 } else
1539 {
1540 data[pos] = (pixel >> 16) & 0xff;
1541 data[pos+1] = (pixel >> 8) & 0xff;
1542 data[pos+2] = pixel & 0xff;
1543 }
1544
1545 /*
1546 if (gdk_image_mask)
1547 {
1548 int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
1549 if (mask_pixel == 0)
1550 {
1551 data[pos] = 16;
1552 data[pos+1] = 16;
1553 data[pos+2] = 16;
1554 }
1555 }
1556 */
1557
1558 pos += 3;
1559 }
1560 }
1561
1562 XDestroyImage( ximage );
1563 /*
1564 if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
1565 */
1566
1567 return image;
1568}