X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e9576ca53db96b462ed4c0b4bdf47d64c40203e4..80a24267cbc17d85e278e1f10cdfdaea12199639:/src/mac/bitmap.cpp diff --git a/src/mac/bitmap.cpp b/src/mac/bitmap.cpp index 1e6255f551..65eb2eeb50 100644 --- a/src/mac/bitmap.cpp +++ b/src/mac/bitmap.cpp @@ -20,11 +20,74 @@ #include "wx/icon.h" #include "wx/log.h" +extern "C" +{ + #include "xpm.h" +} ; + #if !USE_SHARED_LIBRARIES IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject) IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject) #endif +#include + +CTabHandle wxMacCreateColorTable( int numColors ) +{ + CTabHandle newColors; /* Handle to the new color table */ + short index; /* Index into the table of colors */ + /* Allocate memory for the color table */ + newColors = (CTabHandle)NewHandleClear( sizeof (ColorTable) + + sizeof (ColorSpec) * (numColors - 1) ); + if (newColors != nil) + { + /* Initialize the fields */ + (**newColors).ctSeed = GetCTSeed(); + (**newColors).ctFlags = 0; + (**newColors).ctSize = numColors - 1; + /* Initialize the table of colors */ + } + return newColors ; +} + +void wxMacDestroyColorTable( CTabHandle colors ) +{ + DisposeHandle( (Handle) colors ) ; +} + +void wxMacSetColorTableEntry( CTabHandle newColors , int index , int red , int green , int blue ) +{ + (**newColors).ctTable[index].value = index; + (**newColors).ctTable[index].rgb.red = 0 ;// someRedValue; + (**newColors).ctTable[index].rgb.green = 0 ; // someGreenValue; + (**newColors).ctTable[index].rgb.blue = 0 ; // someBlueValue; +} + +GWorldPtr wxMacCreateGWorld( int height , int width , int depth ) +{ + OSErr err = noErr ; + GWorldPtr port ; + Rect rect = { 0 , 0 , width , height } ; + + if ( depth < 0 ) + { + depth = wxDisplayDepth() ; + } + + err = NewGWorld( &port , depth , &rect , NULL , NULL , 0 ) ; + if ( err == noErr ) + { + return port ; + } + return NULL ; +} + +void wxMacDestroyGWorld( GWorldPtr gw ) +{ + if ( gw ) + DisposeGWorld( gw ) ; +} + wxBitmapRefData::wxBitmapRefData() { m_ok = FALSE; @@ -34,17 +97,43 @@ wxBitmapRefData::wxBitmapRefData() m_quality = 0; m_numColors = 0; m_bitmapMask = NULL; + m_hBitmap = NULL ; + m_hPict = NULL ; + m_bitmapType = kMacBitmapTypeUnknownType ; } wxBitmapRefData::~wxBitmapRefData() { - /* - * TODO: delete the bitmap data here. - */ - - if (m_bitmapMask) - delete m_bitmapMask; + switch (m_bitmapType) + { + case kMacBitmapTypePict : + { + if ( m_hPict ) + { + KillPicture( m_hPict ) ; + m_hPict = NULL ; + } + } + break ; + case kMacBitmapTypeGrafWorld : + { + if ( m_hBitmap ) + { + wxMacDestroyGWorld( m_hBitmap ) ; + m_hBitmap = NULL ; + } + } + break ; + default : + // unkown type ? + break ; + } ; + + if (m_bitmapMask) + { + delete m_bitmapMask; m_bitmapMask = NULL; + } } wxList wxBitmap::sm_handlers; @@ -71,8 +160,59 @@ wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits M_BITMAPDATA->m_height = the_height ; M_BITMAPDATA->m_depth = no_bits ; M_BITMAPDATA->m_numColors = 0; - - /* TODO: create the bitmap from data */ + if ( no_bits == 1 ) + { + M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ; + M_BITMAPDATA->m_hBitmap = wxMacCreateGWorld( the_width , the_height , no_bits ) ; + M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ; + + CGrafPtr origPort ; + GDHandle origDevice ; + + GetGWorld( &origPort , &origDevice ) ; + SetGWorld( M_BITMAPDATA->m_hBitmap , NULL ) ; + LockPixels( GetGWorldPixMap( (CGrafPtr) M_BITMAPDATA->m_hBitmap ) ) ; + + // bits is a word aligned array + + unsigned char* linestart = (unsigned char*) bits ; + int linesize = ( the_width / 16 ) * 2 ; + if ( the_width % 16 ) + { + linesize += 2 ; + } ; + + RGBColor colors[2] = { + { 0xFFFF , 0xFFFF , 0xFFFF } , + { 0, 0 , 0 } + } ; + + for( int y = 0 ; y < the_height ; ++y , linestart += linesize ) + { + for( int x = 0 ; x < the_width ; ++x ) + { + int index = x / 8 ; + int bit = x % 8 ; + int mask = 1 << bit ; + if ( linestart[index] & mask ) + { + SetCPixel( x , y , &colors[1] ) ; + } + else + { + SetCPixel( x , y , &colors[0] ) ; + } + } + + } + UnlockPixels( GetGWorldPixMap( (CGrafPtr) M_BITMAPDATA->m_hBitmap ) ) ; + + SetGWorld( origPort , origDevice ) ; + } + else + { + //multicolor BITMAPs not yet implemented + } if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this); @@ -102,13 +242,10 @@ wxBitmap::wxBitmap(const wxString& filename, long type) wxTheBitmapList->AddBitmap(this); } -/* TODO: maybe allow creation from XPM -// Create from data wxBitmap::wxBitmap(const char **data) { (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0); } -*/ bool wxBitmap::Create(int w, int h, int d) { @@ -120,11 +257,19 @@ bool wxBitmap::Create(int w, int h, int d) M_BITMAPDATA->m_height = h; M_BITMAPDATA->m_depth = d; - /* TODO: create new bitmap */ - + M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ; + M_BITMAPDATA->m_hBitmap = wxMacCreateGWorld( w , h , d ) ; + M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ; return M_BITMAPDATA->m_ok; } +void wxBitmap::SetHBITMAP(WXHBITMAP bmp) +{ + M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ; + M_BITMAPDATA->m_hBitmap = bmp ; + M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ; +} + bool wxBitmap::LoadFile(const wxString& filename, long type) { UnRef(); @@ -296,18 +441,14 @@ wxBitmapHandler *wxBitmap::FindHandler(long bitmapType) wxMask::wxMask() { -/* TODO m_maskBitmap = 0; -*/ } // Construct a mask from a bitmap and a colour indicating // the transparent area wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour) { -/* TODO m_maskBitmap = 0; -*/ Create(bitmap, colour); } @@ -315,26 +456,24 @@ wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour) // the transparent area wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex) { -/* TODO m_maskBitmap = 0; -*/ - Create(bitmap, paletteIndex); } // Construct a mask from a mono bitmap (copies the bitmap). wxMask::wxMask(const wxBitmap& bitmap) { -/* TODO m_maskBitmap = 0; -*/ - Create(bitmap); } wxMask::~wxMask() { -// TODO: delete mask bitmap + if ( m_maskBitmap ) + { + wxMacDestroyGWorld( m_maskBitmap ) ; + m_maskBitmap = NULL ; + } } // Create a mask from a mono bitmap (copies the bitmap). @@ -356,8 +495,58 @@ bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex) // the transparent area bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour) { -// TODO - return FALSE; + if ( m_maskBitmap ) + { + wxMacDestroyGWorld( m_maskBitmap ) ; + m_maskBitmap = NULL ; + } + wxASSERT( ((wxBitmapRefData*) bitmap.GetRefData())->m_bitmapType == kMacBitmapTypeGrafWorld ) ; + // other types would require a temporary bitmap. not yet implemented + + if (!bitmap.Ok()) + { + return FALSE; + } + + m_maskBitmap = wxMacCreateGWorld( bitmap.GetWidth() , bitmap.GetHeight() , 1 ) ; + LockPixels( GetGWorldPixMap( (CGrafPtr) m_maskBitmap ) ) ; + LockPixels( GetGWorldPixMap( (CGrafPtr) ((wxBitmapRefData*) bitmap.GetRefData())->m_hBitmap ) ) ; + RGBColor maskColor = colour.GetPixel() ; + + // this is not very efficient, but I can't think + // of a better way of doing it + CGrafPtr origPort ; + GDHandle origDevice ; + + GetGWorld( &origPort , &origDevice ) ; + for (int w = 0; w < bitmap.GetWidth(); w++) + { + for (int h = 0; h < bitmap.GetHeight(); h++) + { + RGBColor colors[2] = { + { 0xFFFF , 0xFFFF , 0xFFFF } , + { 0, 0 , 0 } + } ; + + SetGWorld( ((wxBitmapRefData*) bitmap.GetRefData())->m_hBitmap , NULL ) ; + RGBColor col ; + GetCPixel( w , h , &col ) ; + SetGWorld( m_maskBitmap , NULL ) ; + if (col.red == maskColor.red && col.blue == maskColor.blue && col.green == maskColor.green) + { + SetCPixel( w , h , &colors[0] ) ; + } + else + { + SetCPixel( w , h , &colors[1] ) ; + } + } + } + UnlockPixels( GetGWorldPixMap( (CGrafPtr) m_maskBitmap ) ) ; + UnlockPixels( GetGWorldPixMap( ((wxBitmapRefData*) bitmap.GetRefData())->m_hBitmap ) ) ; + SetGWorld( origPort , origDevice ) ; + + return TRUE; } /* @@ -386,6 +575,52 @@ bool wxBitmapHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, * Standard handlers */ +class WXDLLEXPORT wxPICTResourceHandler: public wxBitmapHandler +{ + DECLARE_DYNAMIC_CLASS(wxPICTResourceHandler) +public: + inline wxPICTResourceHandler() + { + m_name = "Macintosh Pict resource"; + m_extension = ""; + m_type = wxBITMAP_TYPE_PICT_RESOURCE; + }; + + virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags, + int desiredWidth, int desiredHeight); +}; +IMPLEMENT_DYNAMIC_CLASS(wxPICTResourceHandler, wxBitmapHandler) + +bool wxPICTResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags, + int desiredWidth, int desiredHeight) +{ + Str255 theName ; + + strcpy( (char*) theName , name ) ; + c2pstr( (char*) theName ) ; + + PicHandle thePict = (PicHandle ) GetNamedResource( 'PICT' , theName ) ; + if ( thePict ) + { + PictInfo theInfo ; + + GetPictInfo( thePict , &theInfo , 0 , 0 , systemMethod , 0 ) ; + DetachResource( (Handle) thePict ) ; + M_BITMAPHANDLERDATA->m_bitmapType = kMacBitmapTypePict ; + M_BITMAPHANDLERDATA->m_hPict = thePict ; + M_BITMAPHANDLERDATA->m_width = theInfo.sourceRect.right - theInfo.sourceRect.left ; + M_BITMAPHANDLERDATA->m_height = theInfo.sourceRect.bottom - theInfo.sourceRect.top ; + + M_BITMAPHANDLERDATA->m_depth = theInfo.depth ; + M_BITMAPHANDLERDATA->m_ok = true ; + M_BITMAPHANDLERDATA->m_numColors = theInfo.uniqueColors ; +// M_BITMAPHANDLERDATA->m_bitmapPalette; +// M_BITMAPHANDLERDATA->m_quality; + return TRUE ; + } + return FALSE ; +} + /* TODO: bitmap handlers, a bit like this: class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler { @@ -404,6 +639,238 @@ public: IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler) */ +class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler +{ + DECLARE_DYNAMIC_CLASS(wxXPMFileHandler) +public: + inline wxXPMFileHandler(void) + { + m_name = "XPM bitmap file"; + m_extension = "xpm"; + m_type = wxBITMAP_TYPE_XPM; + }; + + virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags, + int desiredWidth = -1, int desiredHeight = -1); + virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL); +}; +IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler) + +bool wxXPMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags, + int desiredWidth, int desiredHeight) +{ +#if USE_XPM_IN_MSW + XImage *ximage; + XpmAttributes xpmAttr; + HDC dc; + + M_BITMAPHANDLERDATA->m_ok = FALSE; + dc = CreateCompatibleDC(NULL); + if (dc) + { + xpmAttr.valuemask = XpmReturnPixels; + int errorStatus = XpmReadFileToImage(&dc, WXSTRINGCAST name, &ximage, (XImage **) NULL, &xpmAttr); + DeleteDC(dc); + if (errorStatus == XpmSuccess) + { + M_BITMAPHANDLERDATA->m_hBitmap = (WXHBITMAP) ximage->bitmap; + + BITMAP bm; + GetObject((HBITMAP)M_BITMAPHANDLERDATA->m_hBitmap, sizeof(bm), (LPSTR) & bm); + + M_BITMAPHANDLERDATA->m_width = (bm.bmWidth); + M_BITMAPHANDLERDATA->m_height = (bm.bmHeight); + M_BITMAPHANDLERDATA->m_depth = (bm.bmPlanes * bm.bmBitsPixel); + M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels; + XpmFreeAttributes(&xpmAttr); + XImageFree(ximage); + + M_BITMAPHANDLERDATA->m_ok = TRUE; + return TRUE; + } + else + { + M_BITMAPHANDLERDATA->m_ok = FALSE; + return FALSE; + } + } +#endif + + return FALSE; +} + +bool wxXPMFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette) +{ +#if USE_XPM_IN_MSW + HDC dc = NULL; + + Visual *visual = NULL; + XImage ximage; + + dc = CreateCompatibleDC(NULL); + if (dc) + { + if (SelectObject(dc, (HBITMAP) M_BITMAPHANDLERDATA->m_hBitmap)) + { + + ximage.width = M_BITMAPHANDLERDATA->m_width; + ximage.height = M_BITMAPHANDLERDATA->m_height; + ximage.depth = M_BITMAPHANDLERDATA->m_depth; + ximage.bitmap = (void *)M_BITMAPHANDLERDATA->m_hBitmap; + int errorStatus = XpmWriteFileFromImage(&dc, WXSTRINGCAST name, + &ximage, (XImage *) NULL, (XpmAttributes *) NULL); + + if (dc) + DeleteDC(dc); + + if (errorStatus == XpmSuccess) + return TRUE; + else + return FALSE; + } else return FALSE; + } else return FALSE; +#else + return FALSE; +#endif +} + + +class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler +{ + DECLARE_DYNAMIC_CLASS(wxXPMDataHandler) +public: + inline wxXPMDataHandler(void) + { + m_name = "XPM bitmap data"; + 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); +}; +IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler) + +bool wxXPMDataHandler::Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth) +{ + XImage * ximage = NULL ; + XImage * xshapeimage = NULL ; + int ErrorStatus; + XpmAttributes xpmAttr; + + xpmAttr.valuemask = XpmReturnInfos; // get infos back + ErrorStatus = XpmCreateImageFromData( GetMainDevice() , (char **)data, + &ximage, &xshapeimage, &xpmAttr); + + if (ErrorStatus == XpmSuccess) + { + M_BITMAPHANDLERDATA->m_ok = FALSE; + M_BITMAPHANDLERDATA->m_numColors = 0; + M_BITMAPHANDLERDATA->m_hBitmap = ximage->gworldptr ; + + M_BITMAPHANDLERDATA->m_width = ximage->width; + M_BITMAPHANDLERDATA->m_height = ximage->height; + M_BITMAPHANDLERDATA->m_depth = ximage->depth; + M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels; + XpmFreeAttributes(&xpmAttr); + M_BITMAPHANDLERDATA->m_ok = TRUE; + ximage->gworldptr = NULL ; + XImageFree(ximage); // releases the malloc, but does not detroy + // the bitmap + M_BITMAPHANDLERDATA->m_bitmapType = kMacBitmapTypeGrafWorld ; + if ( xshapeimage != NULL ) + { + wxMask* m = new wxMask() ; + m->SetMaskBitmap( xshapeimage->gworldptr ) ; + M_BITMAPHANDLERDATA->m_bitmapMask = m ; + } + return TRUE; + } + else + { + M_BITMAPHANDLERDATA->m_ok = FALSE; + return FALSE; + } + return FALSE; +} + +class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler +{ + DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler) +public: + inline wxBMPResourceHandler() + { + m_name = "Windows bitmap resource"; + m_extension = ""; + m_type = wxBITMAP_TYPE_BMP_RESOURCE; + }; + + virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags, + int desiredWidth, int desiredHeight); +}; + +IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler) + +bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags, + int desiredWidth, int desiredHeight) +{ + // TODO: load colourmap. + // it's probably not found + wxLogError("Can't load bitmap '%s' from resources! Check .rc file.", name.c_str()); + + return FALSE; +} + +class WXDLLEXPORT wxBMPFileHandler: public wxBitmapHandler +{ + DECLARE_DYNAMIC_CLASS(wxBMPFileHandler) +public: + inline wxBMPFileHandler(void) + { + m_name = "Windows bitmap file"; + m_extension = "bmp"; + m_type = wxBITMAP_TYPE_BMP; + }; + + 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); +}; + +IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler) + +bool wxBMPFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags, + int desiredWidth, int desiredHeight) +{ +#if USE_IMAGE_LOADING_IN_MSW + wxPalette *palette = NULL; + bool success = FALSE; + success = (wxLoadIntoBitmap(WXSTRINGCAST name, bitmap, &palette) != 0); + if (!success && palette) + { + delete palette; + palette = NULL; + } + if (palette) + M_BITMAPHANDLERDATA->m_bitmapPalette = *palette; + return success; +#else + return FALSE; +#endif +} + +bool wxBMPFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *pal) +{ +#if USE_IMAGE_LOADING_IN_MSW + wxPalette *actualPalette = (wxPalette *)pal; + if (!actualPalette && (!M_BITMAPHANDLERDATA->m_bitmapPalette.IsNull())) + actualPalette = & (M_BITMAPHANDLERDATA->m_bitmapPalette); + return (wxSaveBitmap(WXSTRINGCAST name, bitmap, actualPalette) != 0); +#else + return FALSE; +#endif +} + + void wxBitmap::CleanUpHandlers() { wxNode *node = sm_handlers.First(); @@ -419,12 +886,10 @@ void wxBitmap::CleanUpHandlers() void wxBitmap::InitStandardHandlers() { -/* TODO: initialize all standard bitmap or derive class handlers here. - AddHandler(new wxBMPResourceHandler); - AddHandler(new wxBMPFileHandler); - AddHandler(new wxXPMFileHandler); - AddHandler(new wxXPMDataHandler); - AddHandler(new wxICOResourceHandler); - AddHandler(new wxICOFileHandler); -*/ + AddHandler( new wxPICTResourceHandler ) ; + AddHandler( new wxICONResourceHandler ) ; + AddHandler(new wxXPMFileHandler); + AddHandler(new wxXPMDataHandler); + AddHandler(new wxBMPResourceHandler); + AddHandler(new wxBMPFileHandler); }