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