X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2d120f8391920145647ec10e84629bc21fa9f1bb..891d0563f7f43b640c4e0e78c30f038b2127fffb:/src/motif/bitmap.cpp?ds=sidebyside diff --git a/src/motif/bitmap.cpp b/src/motif/bitmap.cpp index 2f1b0e5218..21a9b7ae91 100644 --- a/src/motif/bitmap.cpp +++ b/src/motif/bitmap.cpp @@ -13,27 +13,41 @@ #pragma implementation "bitmap.h" #endif -#include "wx/setup.h" +#ifdef __VMS +#define XtParent XTPARENT +#endif + +#include "wx/defs.h" #include "wx/utils.h" #include "wx/palette.h" #include "wx/bitmap.h" #include "wx/icon.h" #include "wx/log.h" -#include "wx/control.h" #include "wx/dcmemory.h" +#include "wx/image.h" +#include "wx/app.h" +#if 0 +#ifdef __VMS__ +#pragma message disable nosimpint +#endif #include +#ifdef __VMS__ +#pragma message enable nosimpint +#endif +#endif -#include "wx/motif/private.h" +#include +#include -#if wxUSE_XPM -#include +#if wxHAVE_LIB_XPM + #include #endif +#include + -#if !USE_SHARED_LIBRARIES IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject) IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject) -#endif wxBitmapRefData::wxBitmapRefData() { @@ -41,51 +55,64 @@ wxBitmapRefData::wxBitmapRefData() m_width = 0; m_height = 0; m_depth = 0; - m_quality = 0; - m_numColors = 0; + // XXX m_quality = 0; + // m_numColors = 0; m_bitmapMask = NULL; - + m_pixmap = (WXPixmap) 0; m_display = (WXDisplay*) 0; - - m_freePixmap = TRUE; //TODO: necessary? + + // m_freePixmap = TRUE; //TODO: necessary? +#if 0 m_freeColors = (unsigned long*) 0; m_freeColorsCount = 0; - +#endif + // These 5 variables are for wxControl +#if 0 m_insensPixmap = (WXPixmap) 0; m_labelPixmap = (WXPixmap) 0; m_armPixmap = (WXPixmap) 0; +#endif +#if 0 m_image = (WXImage*) 0; m_insensImage = (WXImage*) 0; +#endif } wxBitmapRefData::~wxBitmapRefData() { +#if 0 if (m_labelPixmap) XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_labelPixmap); - + if (m_armPixmap) XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_armPixmap); - + if (m_insensPixmap) XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_insensPixmap); - +#endif + +#if 0 if (m_image) { XmUninstallImage ((XImage*) m_image); XtFree ((char *) (XImage*) m_image); } - +#endif + +#if 0 if (m_insensImage) { XmUninstallImage ((XImage*) m_insensImage); delete[] ((XImage*) m_insensImage)->data; XtFree ((char *) (XImage*) m_insensImage); } - if (m_pixmap && m_freePixmap) +#endif + if (m_pixmap /* && m_freePixmap */) XFreePixmap ((Display*) m_display, (Pixmap) m_pixmap); - + +#if 0 if (m_freeColors) { int screen = DefaultScreen((Display*) m_display); @@ -95,143 +122,151 @@ wxBitmapRefData::~wxBitmapRefData() XFreeColors((Display*) m_display, cmp, &m_freeColors[llp], 1, 0L); delete m_freeColors; }; - +#endif + if (m_bitmapMask) delete m_bitmapMask; m_bitmapMask = NULL; } -wxList wxBitmap::sm_handlers; +#define M_BMPDATA ((wxBitmapRefData *)m_refData) wxBitmap::wxBitmap() { m_refData = NULL; - - if ( wxTheBitmapList ) - wxTheBitmapList->AddBitmap(this); } wxBitmap::~wxBitmap() { - if (wxTheBitmapList) - wxTheBitmapList->DeleteObject(this); } wxBitmap::wxBitmap(const char bits[], int width, int height, int depth) { m_refData = new wxBitmapRefData; - + (void) Create((void*) bits, wxBITMAP_TYPE_XBM_DATA, width, height, depth); - - if ( wxTheBitmapList ) - wxTheBitmapList->AddBitmap(this); } wxBitmap::wxBitmap(int w, int h, int d) { (void)Create(w, h, d); - - if ( wxTheBitmapList ) - wxTheBitmapList->AddBitmap(this); } -wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth) +wxBitmap::wxBitmap(void *data, wxBitmapType type, + int width, int height, int depth) { (void) Create(data, type, width, height, depth); - - if ( wxTheBitmapList ) - wxTheBitmapList->AddBitmap(this); } -wxBitmap::wxBitmap(const wxString& filename, long type) +wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type) { - LoadFile(filename, (int)type); - - if ( wxTheBitmapList ) - wxTheBitmapList->AddBitmap(this); + LoadFile(filename, type); } +#if 0 // Create from XPM data static wxControl* sg_Control = NULL; wxBitmap::wxBitmap(char **data, wxControl* control) { // Pass the control to the Create function using a global sg_Control = control; - + (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0); - + sg_Control = (wxControl*) NULL; } +#endif + +bool wxBitmap::CreateFromXpm(const char **bits) +{ + wxCHECK_MSG( bits, FALSE, _T("NULL pointer in wxBitmap::CreateFromXpm") ); + + return Create(bits, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0); +} + +bool wxBitmap::CopyFromIcon(const wxIcon& icon) +{ + *this = icon; + return TRUE; +} bool wxBitmap::Create(int w, int h, int d) { UnRef(); - + m_refData = new wxBitmapRefData; - + if (d < 1) d = wxDisplayDepth(); - + M_BITMAPDATA->m_width = w; M_BITMAPDATA->m_height = h; M_BITMAPDATA->m_depth = d; - M_BITMAPDATA->m_freePixmap = TRUE; - + // M_BITMAPDATA->m_freePixmap = TRUE; + Display *dpy = (Display*) wxGetDisplay(); - + M_BITMAPDATA->m_display = dpy; /* MATTHEW: [4] Remember the display */ - + M_BITMAPDATA->m_pixmap = (WXPixmap) XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)), w, h, d); - + M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_pixmap != (WXPixmap) 0) ; return M_BITMAPDATA->m_ok; } -bool wxBitmap::LoadFile(const wxString& filename, long type) +bool wxBitmap::LoadFile(const wxString& filename, wxBitmapType type) { UnRef(); - + m_refData = new wxBitmapRefData; - + wxBitmapHandler *handler = FindHandler(type); - + if ( handler == NULL ) { - wxLogWarning("no bitmap handler for type %d defined.", type); - - return FALSE; + wxImage image; + if (!image.LoadFile( filename, type )) return FALSE; + if (image.Ok()) + { + *this = wxBitmap(image); + return TRUE; + } + else return FALSE; } - + return handler->LoadFile(this, filename, type, -1, -1); } -bool wxBitmap::Create(void *data, long type, int width, int height, int depth) +bool wxBitmap::Create(void *data, wxBitmapType type, + int width, int height, int depth) { UnRef(); - + m_refData = new wxBitmapRefData; - + wxBitmapHandler *handler = FindHandler(type); - + if ( handler == NULL ) { - wxLogWarning("no bitmap handler for type %d defined.", type); - + wxLogWarning("no data bitmap handler for type %ld defined.", + (long)type); + return FALSE; } - + return handler->Create(this, data, type, width, height, depth); } -bool wxBitmap::SaveFile(const wxString& filename, int type, const wxPalette *palette) +bool wxBitmap::SaveFile(const wxString& filename, wxBitmapType type, + const wxPalette *palette) const { wxBitmapHandler *handler = FindHandler(type); - - if ( handler == NULL ) { - wxLogWarning("no bitmap handler for type %d defined.", type); - - return FALSE; + + if ( handler == NULL ) { // try wxImage + wxImage image = this->ConvertToImage(); + if (image.Ok()) return image.SaveFile( filename, type ); + else return FALSE; } - + return handler->SaveFile(this, filename, type, palette); } @@ -239,7 +274,7 @@ void wxBitmap::SetWidth(int w) { if (!M_BITMAPDATA) m_refData = new wxBitmapRefData; - + M_BITMAPDATA->m_width = w; } @@ -247,7 +282,7 @@ void wxBitmap::SetHeight(int h) { if (!M_BITMAPDATA) m_refData = new wxBitmapRefData; - + M_BITMAPDATA->m_height = h; } @@ -255,23 +290,28 @@ void wxBitmap::SetDepth(int d) { if (!M_BITMAPDATA) m_refData = new wxBitmapRefData; - + M_BITMAPDATA->m_depth = d; } +#if 0 + +// XXX void wxBitmap::SetQuality(int q) { if (!M_BITMAPDATA) m_refData = new wxBitmapRefData; - + M_BITMAPDATA->m_quality = q; } +#endif + void wxBitmap::SetOk(bool isOk) { if (!M_BITMAPDATA) m_refData = new wxBitmapRefData; - + M_BITMAPDATA->m_ok = isOk; } @@ -279,7 +319,7 @@ void wxBitmap::SetPalette(const wxPalette& palette) { if (!M_BITMAPDATA) m_refData = new wxBitmapRefData; - + M_BITMAPDATA->m_bitmapPalette = palette ; } @@ -287,70 +327,22 @@ void wxBitmap::SetMask(wxMask *mask) { if (!M_BITMAPDATA) m_refData = new wxBitmapRefData; - - M_BITMAPDATA->m_bitmapMask = mask ; -} - -void wxBitmap::AddHandler(wxBitmapHandler *handler) -{ - sm_handlers.Append(handler); -} -void wxBitmap::InsertHandler(wxBitmapHandler *handler) -{ - sm_handlers.Insert(handler); -} - -bool wxBitmap::RemoveHandler(const wxString& name) -{ - wxBitmapHandler *handler = FindHandler(name); - if ( handler ) - { - sm_handlers.DeleteObject(handler); - return TRUE; - } - else - return FALSE; + M_BITMAPDATA->m_bitmapMask = mask ; } -wxBitmapHandler *wxBitmap::FindHandler(const wxString& name) +wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const { - wxNode *node = sm_handlers.First(); - while ( node ) - { - wxBitmapHandler *handler = (wxBitmapHandler *)node->Data(); - if ( handler->GetName() == name ) - return handler; - node = node->Next(); - } - return NULL; -} + wxCHECK_MSG( Ok() && + (rect.x >= 0) && (rect.y >= 0) && + (rect.x+rect.width <= M_BMPDATA->m_width) && (rect.y+rect.height <= M_BMPDATA->m_height), + wxNullBitmap, wxT("invalid bitmap or bitmap region") ); -wxBitmapHandler *wxBitmap::FindHandler(const wxString& extension, long bitmapType) -{ - wxNode *node = sm_handlers.First(); - while ( node ) - { - wxBitmapHandler *handler = (wxBitmapHandler *)node->Data(); - if ( handler->GetExtension() == extension && - (bitmapType == -1 || handler->GetType() == bitmapType) ) - return handler; - node = node->Next(); - } - return NULL; -} + wxBitmap ret( rect.width, rect.height, 0 ); + wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") ); -wxBitmapHandler *wxBitmap::FindHandler(long bitmapType) -{ - wxNode *node = sm_handlers.First(); - while ( node ) - { - wxBitmapHandler *handler = (wxBitmapHandler *)node->Data(); - if (handler->GetType() == bitmapType) - return handler; - node = node->Next(); - } - return NULL; + // The remaining still TODO + return ret; } /* @@ -367,7 +359,7 @@ wxMask::wxMask() wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour) { m_pixmap = (WXPixmap) 0; - + Create(bitmap, colour); } @@ -376,7 +368,7 @@ wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour) wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex) { m_pixmap = (WXPixmap) 0; - + Create(bitmap, paletteIndex); } @@ -384,7 +376,7 @@ wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex) wxMask::wxMask(const wxBitmap& bitmap) { m_pixmap = (WXPixmap) 0; - + Create(bitmap); } @@ -424,24 +416,6 @@ bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap), const wxColour& WXUNUSED(c IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject) -bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap), void *WXUNUSED(data), long WXUNUSED(type), - int WXUNUSED(width), int WXUNUSED(height), int WXUNUSED(depth)) -{ - return FALSE; -} - -bool wxBitmapHandler::LoadFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), long WXUNUSED(type), - int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight)) -{ - return FALSE; -} - -bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), int WXUNUSED(type), - const wxPalette *WXUNUSED(palette)) -{ - return FALSE; -} - /* * Standard handlers */ @@ -456,31 +430,36 @@ public: m_extension = "xbm"; m_type = wxBITMAP_TYPE_XBM; }; - + virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags, - int desiredWidth, int desiredHeight); + int desiredWidth, int desiredHeight); }; + IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler, wxBitmapHandler) -bool wxXBMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags), - int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight)) +bool wxXBMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, + long WXUNUSED(flags), + int WXUNUSED(desiredWidth), + int WXUNUSED(desiredHeight)) { - M_BITMAPHANDLERDATA->m_freePixmap = TRUE; - + // M_BITMAPHANDLERDATA->m_freePixmap = TRUE; + if (!bitmap->GetRefData()) + bitmap->SetRefData( new wxBitmapRefData() ); + int hotX, hotY; unsigned int w, h; Pixmap pixmap; - + Display *dpy = (Display*) wxGetDisplay(); M_BITMAPDATA->m_display = (WXDisplay*) dpy; - + int value = XReadBitmapFile (dpy, RootWindow (dpy, DefaultScreen (dpy)), - (char*) (const char*) name, &w, &h, &pixmap, &hotX, &hotY); + wxConstCast(name.c_str(), char), &w, &h, &pixmap, &hotX, &hotY); M_BITMAPHANDLERDATA->m_width = w; M_BITMAPHANDLERDATA->m_height = h; M_BITMAPHANDLERDATA->m_depth = 1; M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap; - + if ((value == BitmapFileInvalid) || (value == BitmapOpenFailed) || (value == BitmapNoMemory)) @@ -490,7 +469,7 @@ bool wxXBMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long WXU } else M_BITMAPHANDLERDATA->m_ok = TRUE; - + return M_BITMAPHANDLERDATA->m_ok ; } @@ -504,25 +483,31 @@ public: m_extension = "xbm"; m_type = wxBITMAP_TYPE_XBM_DATA; }; - - virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1); + + virtual bool Create(wxBitmap *bitmap, void *data, long flags, + int width, int height, int depth = 1); }; IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler, wxBitmapHandler) -bool wxXBMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags), - int width, int height, int WXUNUSED(depth)) +bool wxXBMDataHandler::Create( wxBitmap *bitmap, void *data, + long WXUNUSED(flags), + int width, int height, int WXUNUSED(depth)) { + if (!bitmap->GetRefData()) + bitmap->SetRefData( new wxBitmapRefData() ); + M_BITMAPHANDLERDATA->m_width = width; M_BITMAPHANDLERDATA->m_height = height; M_BITMAPHANDLERDATA->m_depth = 1; - M_BITMAPHANDLERDATA->m_freePixmap = TRUE; - + // M_BITMAPHANDLERDATA->m_freePixmap = TRUE; + Display *dpy = (Display*) wxGetDisplay(); M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy; - + M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) XCreateBitmapFromData (dpy, RootWindow (dpy, DefaultScreen (dpy)), (char*) data, width, height); M_BITMAPHANDLERDATA->m_ok = (M_BITMAPHANDLERDATA->m_pixmap != (WXPixmap) 0) ; - + +#if 0 // code for wxControl. TODO: can we avoid doing this until we need it? // E.g. have CreateButtonPixmaps which is called on demand. XImage* image = (XImage *) XtMalloc (sizeof (XImage)); @@ -537,13 +522,13 @@ bool wxXBMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags image->bitmap_bit_order = LSBFirst; image->bitmap_pad = 8; image->bytes_per_line = (width + 7) >> 3; - + char tmp[128]; sprintf (tmp, "Im%x", (unsigned int) image); XmInstallImage (image, tmp); - + // Build our manually stipped pixmap. - + int bpl = (width + 7) / 8; char *data1 = new char[height * bpl]; char* bits = (char*) data; @@ -567,17 +552,20 @@ bool wxXBMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags insensImage->bitmap_bit_order = LSBFirst; insensImage->bitmap_pad = 8; insensImage->bytes_per_line = bpl; - + sprintf (tmp, "Not%x", (unsigned int)insensImage); XmInstallImage (insensImage, tmp); - + M_BITMAPHANDLERDATA->m_image = (WXImage*) image; M_BITMAPHANDLERDATA->m_insensImage = (WXImage*) insensImage; - +#endif + + + return TRUE; } -#if wxUSE_XPM +#if wxHAVE_LIB_XPM class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler { DECLARE_DYNAMIC_CLASS(wxXPMFileHandler) @@ -588,31 +576,38 @@ public: m_extension = "xpm"; m_type = wxBITMAP_TYPE_XPM; }; - + virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags, - int desiredWidth, int desiredHeight); - virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL); + int desiredWidth, int desiredHeight); + virtual bool SaveFile(const wxBitmap *bitmap, const wxString& name, + wxBitmapType type, const wxPalette *palette = NULL); }; IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler) -bool wxXPMFileHandler::LoadFile( wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags), - int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight) ) +bool wxXPMFileHandler::LoadFile( wxBitmap *bitmap, const wxString& name, + long WXUNUSED(flags), + int WXUNUSED(desiredWidth), + int WXUNUSED(desiredHeight) ) { + if (!bitmap->GetRefData()) + bitmap->SetRefData( new wxBitmapRefData() ); + Display *dpy = (Display*) wxGetDisplay(); M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy; - + XpmAttributes xpmAttr; Pixmap pixmap; Pixmap mask = 0; - + M_BITMAPHANDLERDATA->m_ok = FALSE; xpmAttr.valuemask = XpmReturnInfos | XpmCloseness; xpmAttr.closeness = 40000; int errorStatus = XpmReadFileToPixmap(dpy, - RootWindow(dpy, DefaultScreen(dpy)), (char*) (const char*) name, + RootWindow(dpy, DefaultScreen(dpy)), + wxConstCast(name.c_str(), char), &pixmap, &mask, &xpmAttr); - + if (errorStatus == XpmSuccess) { M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap; @@ -621,17 +616,17 @@ bool wxXPMFileHandler::LoadFile( wxBitmap *bitmap, const wxString& name, long WX M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask; M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask); } - + unsigned int depthRet; int xRet, yRet; unsigned int widthRet, heightRet, borderWidthRet; Window rootWindowRet; XGetGeometry(dpy, pixmap, &rootWindowRet, &xRet, &yRet, &widthRet, &heightRet, &borderWidthRet, &depthRet); - + M_BITMAPHANDLERDATA->m_width = xpmAttr.width; M_BITMAPHANDLERDATA->m_height = xpmAttr.height; - + /* if ( xpmAttr.npixels > 2 ) { @@ -641,13 +636,13 @@ bool wxXPMFileHandler::LoadFile( wxBitmap *bitmap, const wxString& name, long WX M_BITMAPHANDLERDATA->m_depth = 1; // mono } */ - + M_BITMAPHANDLERDATA->m_depth = depthRet; - - M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels; - + + // M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels; + XpmFreeAttributes(&xpmAttr); - + M_BITMAPHANDLERDATA->m_ok = TRUE; return TRUE; } else @@ -658,13 +653,15 @@ bool wxXPMFileHandler::LoadFile( wxBitmap *bitmap, const wxString& name, long WX } } -bool wxXPMFileHandler::SaveFile( wxBitmap *bitmap, const wxString& name, int WXUNUSED(type), - const wxPalette *WXUNUSED(palette)) +bool wxXPMFileHandler::SaveFile( const wxBitmap *bitmap, const wxString& name, + wxBitmapType WXUNUSED(type), + const wxPalette *WXUNUSED(palette)) { if (M_BITMAPHANDLERDATA->m_ok && M_BITMAPHANDLERDATA->m_pixmap) { Display *dpy = (Display*) M_BITMAPHANDLERDATA->m_display; - int errorStatus = XpmWriteFileFromPixmap(dpy, (char*) (const char*) name, + int errorStatus = XpmWriteFileFromPixmap(dpy, + wxConstCast(name.c_str(), char), (Pixmap) M_BITMAPHANDLERDATA->m_pixmap, (M_BITMAPHANDLERDATA->m_bitmapMask ? (Pixmap) M_BITMAPHANDLERDATA->m_bitmapMask->GetPixmap() : (Pixmap) 0), (XpmAttributes *) NULL); @@ -687,26 +684,32 @@ public: m_extension = "xpm"; m_type = wxBITMAP_TYPE_XPM_DATA; }; - - virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1); + + virtual bool Create(wxBitmap *bitmap, void *data, long flags, + int width, int height, int depth = 1); }; IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler) -bool wxXPMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags), +bool wxXPMDataHandler::Create( wxBitmap *bitmap, void *data, + long WXUNUSED(flags), int width, int height, int WXUNUSED(depth)) { + if (!bitmap->GetRefData()) + bitmap->SetRefData( new wxBitmapRefData() ); + M_BITMAPHANDLERDATA->m_width = width; M_BITMAPHANDLERDATA->m_height = height; M_BITMAPHANDLERDATA->m_depth = 1; - M_BITMAPHANDLERDATA->m_freePixmap = TRUE; - + // M_BITMAPHANDLERDATA->m_freePixmap = TRUE; + Display *dpy = (Display*) wxGetDisplay(); M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy; - + XpmAttributes xpmAttr; - + xpmAttr.valuemask = XpmReturnInfos; /* nothing yet, but get infos back */ - + +#if 0 XpmColorSymbol symbolicColors[4]; if (sg_Control && sg_Control->GetMainWidget()) { @@ -721,8 +724,9 @@ bool wxXPMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags xpmAttr.colorsymbols = symbolicColors; xpmAttr.valuemask |= XpmColorSymbols; // add flag } - - Pixmap pixmap; +#endif + + Pixmap pixmap = 0; Pixmap mask = 0; int ErrorStatus = XpmCreatePixmapFromData(dpy, RootWindow(dpy, DefaultScreen(dpy)), (char**) data, &pixmap, &mask, &xpmAttr); @@ -731,14 +735,14 @@ bool wxXPMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags // Set attributes M_BITMAPHANDLERDATA->m_width = xpmAttr.width; M_BITMAPHANDLERDATA->m_height = xpmAttr.height; - + unsigned int depthRet; int xRet, yRet; unsigned int widthRet, heightRet, borderWidthRet; Window rootWindowRet; XGetGeometry(dpy, pixmap, &rootWindowRet, &xRet, &yRet, &widthRet, &heightRet, &borderWidthRet, &depthRet); - + /* if ( xpmAttr.npixels > 2 ) { @@ -748,10 +752,10 @@ bool wxXPMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags M_BITMAPHANDLERDATA->m_depth = 1; // mono } */ - + M_BITMAPHANDLERDATA->m_depth = depthRet; - - M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels; + + // M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels; XpmFreeAttributes(&xpmAttr); M_BITMAPHANDLERDATA->m_ok = TRUE; M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap; @@ -769,116 +773,113 @@ bool wxXPMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags return M_BITMAPHANDLERDATA->m_ok ; } -#endif - -void wxBitmap::CleanUpHandlers() -{ - wxNode *node = sm_handlers.First(); - while ( node ) - { - wxBitmapHandler *handler = (wxBitmapHandler *)node->Data(); - wxNode *next = node->Next(); - delete handler; - delete node; - node = next; - } -} +#endif // wxHAVE_LIB_XPM void wxBitmap::InitStandardHandlers() { // Initialize all standard bitmap or derived class handlers here. AddHandler(new wxXBMFileHandler); AddHandler(new wxXBMDataHandler); - - // XPM is considered standard for Moif, although it can be omitted if absolutely - // necessary. -#if wxUSE_XPM + + // XPM is considered standard for Motif, although it can be omitted if + // libXpm is not installed +#if wxHAVE_LIB_XPM AddHandler(new wxXPMFileHandler); AddHandler(new wxXPMDataHandler); -#endif +#endif // wxHAVE_LIB_XPM } +#if 0 WXPixmap wxBitmap::GetLabelPixmap (WXWidget w) { - if (M_BITMAPDATA->m_image == (WXPixmap) 0) + if (!M_BITMAPDATA) + return (WXPixmap)NULL; + // if (M_BITMAPDATA->m_image == (WXPixmap) 0) return M_BITMAPDATA->m_pixmap; - + +#if 0 Display *dpy = (Display*) M_BITMAPDATA->m_display; - + #ifdef FOO /* If we do: if (labelPixmap) return labelPixmap; things can be wrong, because colors can have been changed. - + If we do: if (labelPixmap) XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ; we got BadDrawable if the pixmap is referenced by multiples widgets - + this is a catch22!! - - So, before doing thing really clean, I just do nothing; if the pixmap is - referenced by many widgets, Motif performs caching functions. - And if pixmap is referenced with multiples colors, we just have some - memory leaks... I hope we can deal with them... + + So, before doing thing really clean, I just do nothing; if the pixmap is + referenced by many widgets, Motif performs caching functions. + And if pixmap is referenced with multiples colors, we just have some + memory leaks... I hope we can deal with them... */ // Must be destroyed, because colours can have been changed! if (M_BITMAPDATA->m_labelPixmap) XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_labelPixmap); #endif - + char tmp[128]; sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image); - + Pixel fg, bg; Widget widget = (Widget) w; - + while (XmIsGadget ( widget )) widget = XtParent (widget); XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL); - + M_BITMAPDATA->m_labelPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg); - + return M_BITMAPDATA->m_labelPixmap; +#endif } WXPixmap wxBitmap::GetArmPixmap (WXWidget w) { - if (M_BITMAPDATA->m_image == (WXPixmap) 0) + // if (M_BITMAPDATA->m_image == (WXPixmap) 0) return M_BITMAPDATA->m_pixmap; - + +#if 0 Display *dpy = (Display*) M_BITMAPDATA->m_display; #ifdef FOO - See GetLabelPixmap () comment - // Must be destroyed, because colours can have been changed! - if (M_BITMAPDATA->m_armPixmap) - XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_armPixmap); + // See GetLabelPixmap () comment + + // Must be destroyed, because colours can have been changed! + if (M_BITMAPDATA->m_armPixmap) + XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_armPixmap); +#endif + + char tmp[128]; + sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image); + + Pixel fg, bg; + Widget widget = (Widget) w; + + XtVaGetValues (widget, XmNarmColor, &bg, NULL); + while (XmIsGadget (widget)) + widget = XtParent (widget); + XtVaGetValues (widget, XmNforeground, &fg, NULL); + + M_BITMAPDATA->m_armPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg); + + return M_BITMAPDATA->m_armPixmap; #endif - - char tmp[128]; - sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image); - - Pixel fg, bg; - Widget widget = (Widget) w; - - XtVaGetValues (widget, XmNarmColor, &bg, NULL); - while (XmIsGadget (widget)) - widget = XtParent (widget); - XtVaGetValues (widget, XmNforeground, &fg, NULL); - - M_BITMAPDATA->m_armPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg); - - return M_BITMAPDATA->m_armPixmap; } WXPixmap wxBitmap::GetInsensPixmap (WXWidget w) { Display *dpy = (Display*) M_BITMAPDATA->m_display; + if (!M_BITMAPDATA) + return (WXPixmap)NULL; if (M_BITMAPDATA->m_insensPixmap) return M_BITMAPDATA->m_insensPixmap; - + if (!w) { M_BITMAPDATA->m_insensPixmap = (WXPixmap) XCreateInsensitivePixmap(dpy, (Pixmap) M_BITMAPDATA->m_pixmap); @@ -887,130 +888,38 @@ WXPixmap wxBitmap::GetInsensPixmap (WXWidget w) else return M_BITMAPDATA->m_pixmap; } - - if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0) + + // if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0) return M_BITMAPDATA->m_pixmap; - + +#if 0 #ifdef FOO See GetLabelPixmap () comment // Must be destroyed, because colours can have been changed! if (M_BITMAPDATA->m_insensPixmap) XmDestroyPixmap (DefaultScreenOfDisplay (dpy), (Pixmap) M_BITMAPDATA->m_insensPixmap); #endif - - char tmp[128]; - sprintf (tmp, "Not%x", (unsigned int) M_BITMAPDATA->m_insensImage); - - Pixel fg, bg; - Widget widget = (Widget) w; - - while (XmIsGadget (widget)) - widget = XtParent (widget); - XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL); - - M_BITMAPDATA->m_insensPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg); - - return M_BITMAPDATA->m_insensPixmap; -} -// We may need this sometime... + char tmp[128]; + sprintf (tmp, "Not%x", (unsigned int) M_BITMAPDATA->m_insensImage); -/**************************************************************************** + Pixel fg, bg; + Widget widget = (Widget) w; - NAME - XCreateInsensitivePixmap - create a grayed-out copy of a pixmap - - SYNOPSIS - Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap ) - - DESCRIPTION - This function creates a grayed-out copy of the argument pixmap, suitable - for use as a XmLabel's XmNlabelInsensitivePixmap resource. - - RETURN VALUES - The return value is the new Pixmap id or zero on error. Errors include - a NULL display argument or an invalid Pixmap argument. - - ERRORS - If one of the XLib functions fail, it will produce a X error. The - default X error handler prints a diagnostic and calls exit(). - - SEE ALSO - XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3), - XFillRectangle(3), exit(2) - - AUTHOR - John R Veregge - john@puente.jpl.nasa.gov - Advanced Engineering and Prototyping Group (AEG) - Information Systems Technology Section (395) - Jet Propulsion Lab - Calif Institute of Technology - -*****************************************************************************/ - -Pixmap -XCreateInsensitivePixmap( Display *display, Pixmap pixmap ) + while (XmIsGadget (widget)) + widget = XtParent (widget); + XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL); -{ - static - char stipple_data[] = - { - 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, - 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, - 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, - 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA - }; - GC gc; - Pixmap ipixmap, stipple; - unsigned width, height, depth; - - Window window; /* These return values */ - unsigned border; /* from XGetGeometry() */ - int x, y; /* are not needed. */ - - ipixmap = 0; - - if ( NULL == display || 0 == pixmap ) - return ipixmap; - - if ( 0 == XGetGeometry( display, pixmap, &window, &x, &y, - &width, &height, &border, &depth ) - ) - return ipixmap; /* BadDrawable: probably an invalid pixmap */ - - /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap. - */ - stipple = XCreateBitmapFromData( display, pixmap, stipple_data, 16, 16 ); - if ( 0 != stipple ) - { - gc = XCreateGC( display, pixmap, (XtGCMask)0, (XGCValues*)NULL ); - if ( NULL != gc ) - { - /* Create an identical copy of the argument pixmap. - */ - ipixmap = XCreatePixmap( display, pixmap, width, height, depth ); - if ( 0 != ipixmap ) - { - /* Copy the argument pixmap into the new pixmap. - */ - XCopyArea( display, pixmap, ipixmap, - gc, 0, 0, width, height, 0, 0 ); - - /* Refill the new pixmap using the stipple algorithm/pixmap. - */ - XSetStipple( display, gc, stipple ); - XSetFillStyle( display, gc, FillStippled ); - XFillRectangle( display, ipixmap, gc, 0, 0, width, height ); - } - XFreeGC( display, gc ); - } - XFreePixmap( display, stipple ); - } - return ipixmap; + M_BITMAPDATA->m_insensPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg); + + return M_BITMAPDATA->m_insensPixmap; +#endif } +#endif // Creates a bitmap with transparent areas drawn in // the given colour. -wxBitmap wxCreateMaskedBitmap(wxBitmap& bitmap, wxColour& colour) +wxBitmap wxCreateMaskedBitmap(const wxBitmap& bitmap, wxColour& colour) { wxBitmap newBitmap(bitmap.GetWidth(), bitmap.GetHeight(), @@ -1019,12 +928,518 @@ wxBitmap wxCreateMaskedBitmap(wxBitmap& bitmap, wxColour& colour) wxMemoryDC srcDC; srcDC.SelectObject(bitmap); destDC.SelectObject(newBitmap); - + wxBrush brush(colour, wxSOLID); destDC.SetOptimization(FALSE); destDC.SetBackground(brush); destDC.Clear(); destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(), & srcDC, 0, 0, wxCOPY, TRUE); - + return newBitmap; } + + + + +//----------------------------------------------------------------------------- +// wxImage conversion routines +//----------------------------------------------------------------------------- + +/* + +Date: Wed, 05 Jan 2000 11:45:40 +0100 +From: Frits Boel +To: julian.smart@ukonline.co.uk +Subject: Patch for Motif ConvertToBitmap + +Hi Julian, + +I've been working on a wxWin application for image processing. From the +beginning, I was surprised by the (lack of) speed of ConvertToBitmap, +till I looked in the source code of image.cpp. I saw that converting a +wxImage to a bitmap with 8-bit pixels is done with comparing every pixel +to the 256 colors of the palet. A very time-consuming piece of code! + +Because I wanted a faster application, I've made a 'patch' for this. In +short: every pixel of the image is compared to a sorted list with +colors. If the color is found in the list, the palette entry is +returned; if the color is not found, the color palette is searched and +then the palette entry is returned and the color added to the sorted +list. + +Maybe there is another method for this, namely changing the palette +itself (if the colors are known, as is the case with tiffs with a +colormap). I did not look at this, maybe someone else did? + +The code of the patch is attached, have a look on it, and maybe you will +ship it with the next release of wxMotif? + +Regards, + +Frits Boel +Software engineer at Hubrecht Laboratory, The Netherlands. + +*/ + +class wxSearchColor +{ +public: + wxSearchColor( void ); + wxSearchColor( int size, XColor *colors ); + ~wxSearchColor( void ); + + int SearchColor( int r, int g, int b ); +private: + int AddColor( unsigned int value, int pos ); + + int size; + XColor *colors; + unsigned int *color; + int *entry; + + int bottom; + int top; +}; + +wxSearchColor::wxSearchColor( void ) +{ + size = 0; + colors = (XColor*) NULL; + color = (unsigned int *) NULL; + entry = (int*) NULL; + + bottom = 0; + top = 0; +} + +wxSearchColor::wxSearchColor( int size_, XColor *colors_ ) +{ + int i; + size = size_; + colors = colors_; + color = new unsigned int[size]; + entry = new int [size]; + + for (i = 0; i < size; i++ ) { + entry[i] = -1; + } + + bottom = top = ( size >> 1 ); +} + +wxSearchColor::~wxSearchColor( void ) +{ + if ( color ) delete[] color; + if ( entry ) delete[] entry; +} + +int wxSearchColor::SearchColor( int r, int g, int b ) +{ + unsigned int value = ( ( ( r * 256 ) + g ) * 256 ) + b; + int begin = bottom; + int end = top; + int middle = 0; + + while ( begin <= end ) { + + middle = ( begin + end ) >> 1; + + if ( value == color[middle] ) { + return( entry[middle] ); + } else if ( value < color[middle] ) { + end = middle - 1; + } else { + begin = middle + 1; + } + + } + + return AddColor( value, middle ); +} + +int wxSearchColor::AddColor( unsigned int value, int pos ) +{ + int i; + int pixel = -1; + int max = 3 * (65536); + for ( i = 0; i < 256; i++ ) { + int rdiff = ((value >> 8) & 0xFF00 ) - colors[i].red; + int gdiff = ((value ) & 0xFF00 ) - colors[i].green; + int bdiff = ((value << 8) & 0xFF00 ) - colors[i].blue; + int sum = abs (rdiff) + abs (gdiff) + abs (bdiff); + if (sum < max) { pixel = i; max = sum; } + } + + if ( entry[pos] < 0 ) { + color[pos] = value; + entry[pos] = pixel; + } else if ( value < color[pos] ) { + + if ( bottom > 0 ) { + for ( i = bottom; i < pos; i++ ) { + color[i-1] = color[i]; + entry[i-1] = entry[i]; + } + bottom--; + color[pos-1] = value; + entry[pos-1] = pixel; + } else if ( top < size-1 ) { + for ( i = top; i >= pos; i-- ) { + color[i+1] = color[i]; + entry[i+1] = entry[i]; + } + top++; + color[pos] = value; + entry[pos] = pixel; + } + + } else { + + if ( top < size-1 ) { + for ( i = top; i > pos; i-- ) { + color[i+1] = color[i]; + entry[i+1] = entry[i]; + } + top++; + color[pos+1] = value; + entry[pos+1] = pixel; + } else if ( bottom > 0 ) { + for ( i = bottom; i < pos; i++ ) { + color[i-1] = color[i]; + entry[i-1] = entry[i]; + } + bottom--; + color[pos] = value; + entry[pos] = pixel; + } + + } + + return( pixel ); +} + + +bool wxBitmap::CreateFromImage( const wxImage& image, int depth ) +{ + wxCHECK_MSG( image.Ok(), FALSE, wxT("invalid image") ) + wxCHECK_MSG( depth == -1, FALSE, wxT("invalid bitmap depth") ) + + m_refData = new wxBitmapRefData(); + + int width = image.GetWidth(); + int height = image.GetHeight(); + + SetHeight( height ); + SetWidth( width ); + + Display *dpy = (Display*) wxGetDisplay(); + Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) ); + int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) ); + + // Create image + + XImage *data_image = XCreateImage( dpy, vis, bpp, ZPixmap, 0, 0, width, height, 32, 0 ); + data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height ); + + Create( width, height, bpp ); + + // Create mask + + XImage *mask_image = (XImage*) NULL; + if (image.HasMask()) + { + mask_image = XCreateImage( dpy, vis, 1, ZPixmap, 0, 0, width, height, 32, 0 ); + mask_image->data = (char*) malloc( mask_image->bytes_per_line * mask_image->height ); + } + + // Retrieve depth info + + XVisualInfo vinfo_template; + XVisualInfo *vi; + + vinfo_template.visual = vis; + vinfo_template.visualid = XVisualIDFromVisual( vis ); + vinfo_template.depth = bpp; + int nitem = 0; + + vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, + &vinfo_template, &nitem ); + + wxCHECK_MSG( vi, FALSE, wxT("no visual") ); + + if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15; + if (bpp < 8) bpp = 8; + + // Render + + enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR }; + byte_order b_o = RGB; + + if (bpp >= 24) + { + if ((vi->red_mask > vi->green_mask) && (vi->green_mask > vi->blue_mask)) b_o = RGB; + else if ((vi->red_mask > vi->blue_mask) && (vi->blue_mask > vi->green_mask)) b_o = RGB; + else if ((vi->blue_mask > vi->red_mask) && (vi->red_mask > vi->green_mask)) b_o = BRG; + else if ((vi->blue_mask > vi->green_mask) && (vi->green_mask > vi->red_mask)) b_o = BGR; + else if ((vi->green_mask > vi->red_mask) && (vi->red_mask > vi->blue_mask)) b_o = GRB; + else if ((vi->green_mask > vi->blue_mask) && (vi->blue_mask > vi->red_mask)) b_o = GBR; + } + + XFree( vi ); + + int r_mask = image.GetMaskRed(); + int g_mask = image.GetMaskGreen(); + int b_mask = image.GetMaskBlue(); + + XColor colors[256]; + if (bpp == 8) + { + Colormap cmap = (Colormap) wxTheApp->GetMainColormap( dpy ); + + for (int i = 0; i < 256; i++) colors[i].pixel = i; + XQueryColors( dpy, cmap, colors, 256 ); + } + + wxSearchColor scolor( 256, colors ); + unsigned char* data = image.GetData(); + + bool hasMask = image.HasMask(); + + int index = 0; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + int r = data[index]; + index++; + int g = data[index]; + index++; + int b = data[index]; + index++; + + if (hasMask) + { + if ((r == r_mask) && (b == b_mask) && (g == g_mask)) + XPutPixel( mask_image, x, y, 0 ); + else + XPutPixel( mask_image, x, y, 1 ); + } + + switch (bpp) + { + case 8: + { +#if 0 // Old, slower code + int pixel = -1; + /* + if (wxTheApp->m_colorCube) + { + pixel = wxTheApp->m_colorCube + [ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ]; + } + else + { + */ + int max = 3 * (65536); + for (int i = 0; i < 256; i++) + { + int rdiff = (r << 8) - colors[i].red; + int gdiff = (g << 8) - colors[i].green; + int bdiff = (b << 8) - colors[i].blue; + int sum = abs (rdiff) + abs (gdiff) + abs (bdiff); + if (sum < max) { pixel = i; max = sum; } + } + /* + } + */ +#endif + + // And this is all to get the 'right' color... + int pixel = scolor.SearchColor( r, g, b ); + XPutPixel( data_image, x, y, pixel ); + break; + } + case 15: + { + int pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3); + XPutPixel( data_image, x, y, pixel ); + break; + } + case 16: + { + int pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3); + XPutPixel( data_image, x, y, pixel ); + break; + } + case 32: + case 24: + { + int pixel = 0; + switch (b_o) + { + case RGB: pixel = (r << 16) | (g << 8) | b; break; + case RBG: pixel = (r << 16) | (b << 8) | g; break; + case BRG: pixel = (b << 16) | (r << 8) | g; break; + case BGR: pixel = (b << 16) | (g << 8) | r; break; + case GRB: pixel = (g << 16) | (r << 8) | b; break; + case GBR: pixel = (g << 16) | (b << 8) | r; break; + } + XPutPixel( data_image, x, y, pixel ); + } + default: break; + } + } // for + } // for + + // Blit picture + + XGCValues gcvalues; + gcvalues.foreground = BlackPixel( dpy, DefaultScreen( dpy ) ); + GC gc = XCreateGC( dpy, RootWindow ( dpy, DefaultScreen(dpy) ), GCForeground, &gcvalues ); + XPutImage( dpy, (Drawable)GetPixmap(), gc, data_image, 0, 0, 0, 0, width, height ); + + XDestroyImage( data_image ); + XFreeGC( dpy, gc ); + + // Blit mask + if (image.HasMask()) + { + wxBitmap maskBitmap(width, height, 1); + + GC gcMask = XCreateGC( dpy, (Pixmap) maskBitmap.GetPixmap(), (XtGCMask) 0, (XGCValues*)NULL ); + XPutImage( dpy, (Drawable)maskBitmap.GetPixmap(), gcMask, mask_image, 0, 0, 0, 0, width, height ); + + XDestroyImage( mask_image ); + XFreeGC( dpy, gcMask ); + + wxMask* mask = new wxMask; + mask->SetPixmap(maskBitmap.GetPixmap()); + + SetMask(mask); + + maskBitmap.SetPixmapNull(); + } + + + return TRUE; +} + +wxImage wxBitmap::ConvertToImage() const +{ + wxImage image; + + wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") ); + + Display *dpy = (Display*) wxGetDisplay(); + Visual* vis = DefaultVisual( dpy, DefaultScreen( dpy ) ); + int bpp = DefaultDepth( dpy, DefaultScreen( dpy ) ); + + XImage *ximage = XGetImage( dpy, + (Drawable)GetPixmap(), + 0, 0, + GetWidth(), GetHeight(), + AllPlanes, ZPixmap ); + + wxCHECK_MSG( ximage, wxNullImage, wxT("couldn't create image") ); + + image.Create( GetWidth(), GetHeight() ); + char unsigned *data = image.GetData(); + + if (!data) + { + XDestroyImage( ximage ); + wxFAIL_MSG( wxT("couldn't create image") ); + return wxNullImage; + } + + /* + GdkImage *gdk_image_mask = (GdkImage*) NULL; + if (GetMask()) + { + gdk_image_mask = gdk_image_get( GetMask()->GetBitmap(), + 0, 0, + GetWidth(), GetHeight() ); + + image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable + } + */ + + // Retrieve depth info + + XVisualInfo vinfo_template; + XVisualInfo *vi; + + vinfo_template.visual = vis; + vinfo_template.visualid = XVisualIDFromVisual( vis ); + vinfo_template.depth = bpp; + int nitem = 0; + + vi = XGetVisualInfo( dpy, VisualIDMask|VisualDepthMask, &vinfo_template, &nitem ); + + wxCHECK_MSG( vi, wxNullImage, wxT("no visual") ); + + if ((bpp == 16) && (vi->red_mask != 0xf800)) bpp = 15; + + XFree( vi ); + + XColor colors[256]; + if (bpp == 8) + { + Colormap cmap = (Colormap)wxTheApp->GetMainColormap( dpy ); + + for (int i = 0; i < 256; i++) colors[i].pixel = i; + XQueryColors( dpy, cmap, colors, 256 ); + } + + long pos = 0; + for (int j = 0; j < GetHeight(); j++) + { + for (int i = 0; i < GetWidth(); i++) + { + int pixel = XGetPixel( ximage, i, j ); + if (bpp <= 8) + { + data[pos] = colors[pixel].red >> 8; + data[pos+1] = colors[pixel].green >> 8; + data[pos+2] = colors[pixel].blue >> 8; + } else if (bpp == 15) + { + data[pos] = (pixel >> 7) & 0xf8; + data[pos+1] = (pixel >> 2) & 0xf8; + data[pos+2] = (pixel << 3) & 0xf8; + } else if (bpp == 16) + { + data[pos] = (pixel >> 8) & 0xf8; + data[pos+1] = (pixel >> 3) & 0xfc; + data[pos+2] = (pixel << 3) & 0xf8; + } else + { + data[pos] = (pixel >> 16) & 0xff; + data[pos+1] = (pixel >> 8) & 0xff; + data[pos+2] = pixel & 0xff; + } + + /* + if (gdk_image_mask) + { + int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j ); + if (mask_pixel == 0) + { + data[pos] = 16; + data[pos+1] = 16; + data[pos+2] = 16; + } + } + */ + + pos += 3; + } + } + + XDestroyImage( ximage ); + /* + if (gdk_image_mask) gdk_image_destroy( gdk_image_mask ); + */ + + return image; +}