X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5fde6fcc9b551340a194ae4c726db5ab64b5c594..89ebf1c919fbd662b2b9440573cf7d268023419c:/src/mac/carbon/bitmap.cpp diff --git a/src/mac/carbon/bitmap.cpp b/src/mac/carbon/bitmap.cpp index 5cc2a537fd..95bc8f1612 100644 --- a/src/mac/carbon/bitmap.cpp +++ b/src/mac/carbon/bitmap.cpp @@ -10,37 +10,33 @@ ///////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ +#pragma implementation "bitmapbase.h" #pragma implementation "bitmap.h" #endif -#include "wx/wx.h" -#include "wx/setup.h" -#include "wx/utils.h" -#include "wx/palette.h" +#include "wx/defs.h" + #include "wx/bitmap.h" #include "wx/icon.h" #include "wx/log.h" - -extern "C" -{ -#ifdef __UNIX__ - #include "xpm/xpm.h" -#else - #include "xpm.h" -#endif -} ; +#include "wx/image.h" +#include "wx/xpmdecod.h" #if !USE_SHARED_LIBRARIES IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject) IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject) +IMPLEMENT_ABSTRACT_CLASS(wxBitmapBase , wxGDIObject ) +IMPLEMENT_ABSTRACT_CLASS(wxBitmapHandlerBase, wxObject ) #endif -#ifdef __UNIX__ +#ifdef __DARWIN__ #include #else #include #endif +#include "wx/mac/uma.h" + CTabHandle wxMacCreateColorTable( int numColors ) { CTabHandle newColors; /* Handle to the new color table */ @@ -97,95 +93,204 @@ void wxMacDestroyGWorld( GWorldPtr gw ) DisposeGWorld( gw ) ; } -PicHandle wxMacCreatePict(GWorldPtr wp, GWorldPtr mask) +#define kDefaultRes 0x00480000 /* Default resolution is 72 DPI; Fixed type */ + +OSErr SetupCIconHandlePixMap( CIconHandle icon , short depth , Rect *bounds , CTabHandle colors ) { - CGrafPtr origPort ; - GDHandle origDev ; + CTabHandle newColors; /* Color table used for the off-screen PixMap */ + Ptr offBaseAddr; /* Pointer to the off-screen pixel image */ + OSErr error; /* Returns error code */ + short bytesPerRow; /* Number of bytes per row in the PixMap */ - PicHandle pict; // this is the Picture we give back - RGBColor gray = { 0xCCCC ,0xCCCC , 0xCCCC } ; - RGBColor white = { 0xffff ,0xffff , 0xffff } ; - RGBColor black = { 0x0000 ,0x0000 , 0x0000 } ; + error = noErr; + newColors = nil; + offBaseAddr = nil; - unsigned char *maskimage = NULL ; - Rect portRect ; - GetPortBounds( wp , &portRect ) ; - int width = portRect.right - portRect.left ; - int height = portRect.bottom - portRect.top ; + bytesPerRow = ((depth * (bounds->right - bounds->left) + 31) / 32) * 4; - LockPixels( GetGWorldPixMap( wp ) ) ; - GetGWorld( &origPort , &origDev ) ; + /* Clone the clut if indexed color; allocate a dummy clut if direct color*/ + if (depth <= 8) + { + newColors = colors; + error = HandToHand((Handle *) &newColors); + } + else + { + newColors = (CTabHandle) NewHandle(sizeof(ColorTable) - + sizeof(CSpecArray)); + error = MemError(); + } + if (error == noErr) + { + /* Allocate pixel image; long integer multiplication avoids overflow */ + (**icon).iconData = NewHandle((unsigned long) bytesPerRow * (bounds->bottom - + bounds->top)); + if ((**icon).iconData != nil) + { + /* Initialize fields common to indexed and direct PixMaps */ + (**icon).iconPMap.baseAddr = 0; /* Point to image */ + (**icon).iconPMap.rowBytes = bytesPerRow | /* MSB set for PixMap */ + 0x8000; + (**icon).iconPMap.bounds = *bounds; /* Use given bounds */ + (**icon).iconPMap.pmVersion = 0; /* No special stuff */ + (**icon).iconPMap.packType = 0; /* Default PICT pack */ + (**icon).iconPMap.packSize = 0; /* Always zero in mem */ + (**icon).iconPMap.hRes = kDefaultRes; /* 72 DPI default res */ + (**icon).iconPMap.vRes = kDefaultRes; /* 72 DPI default res */ + (**icon).iconPMap.pixelSize = depth; /* Set # bits/pixel */ + + /* Initialize fields specific to indexed and direct PixMaps */ + if (depth <= 8) + { + /* PixMap is indexed */ + (**icon).iconPMap.pixelType = 0; /* Indicates indexed */ + (**icon).iconPMap.cmpCount = 1; /* Have 1 component */ + (**icon).iconPMap.cmpSize = depth; /* Component size=depth */ + (**icon).iconPMap.pmTable = newColors; /* Handle to CLUT */ + } + else + { + /* PixMap is direct */ + (**icon).iconPMap.pixelType = RGBDirect; /* Indicates direct */ + (**icon).iconPMap.cmpCount = 3; /* Have 3 components */ + if (depth == 16) + (**icon).iconPMap.cmpSize = 5; /* 5 bits/component */ + else + (**icon).iconPMap.cmpSize = 8; /* 8 bits/component */ + (**newColors).ctSeed = 3 * (**icon).iconPMap.cmpSize; + (**newColors).ctFlags = 0; + (**newColors).ctSize = 0; + (**icon).iconPMap.pmTable = newColors; + } + } + else + error = MemError(); + } + else + newColors = nil; - if ( mask ) - { - maskimage = (unsigned char*) malloc( width * height ) ; - SetGWorld( mask , NULL ) ; - LockPixels( GetGWorldPixMap( mask ) ) ; - for ( int y = 0 ; y < height ; y++ ) - { - for( int x = 0 ; x < width ; x++ ) - { - RGBColor col ; - - GetCPixel( x + portRect.left , y + portRect.top , &col ) ; - maskimage[y*width + x] = ( col.red == 0 ) ; // for monochrome masks - } - } - UnlockPixels( GetGWorldPixMap( mask ) ) ; - } + /* If no errors occured, return a handle to the new off-screen PixMap */ + if (error != noErr) + { + if (newColors != nil) + DisposeCTable(newColors); + } - SetGWorld( wp , NULL ) ; + /* Return the error code */ + return error; +} - pict = OpenPicture(&portRect); // open a picture, this disables drawing - if(!pict) - return NULL; +CIconHandle wxMacCreateCIcon(GWorldPtr image , GWorldPtr mask , short dstDepth , short iconSize ) +{ + GWorldPtr saveWorld; + GDHandle saveHandle; - if ( maskimage ) - { - RGBForeColor( &black ) ; - RGBBackColor( &white ) ; - PenMode(transparent); + GetGWorld(&saveWorld,&saveHandle); // save Graphics env state + SetGWorld(image,nil); - for ( int y = 0 ; y < height ; ++y ) - { - for( int x = 0 ; x < width ; ++x ) - { - if ( maskimage[y*width + x] ) - { - RGBColor col ; + Rect frame = { 0 , 0 , iconSize , iconSize } ; + Rect imageBounds = frame ; + GetPortBounds( image , &imageBounds ) ; - GetCPixel( x + portRect.left , y + portRect.top , &col ) ; - SetCPixel( x + portRect.left , y + portRect.top , &col ) ; - } - else { - // With transparency set this sets a blank pixel not a white one - SetCPixel( x + portRect.left , y + portRect.top , &white); - } - } - } - free( maskimage ) ; - maskimage = NULL ; - } - else - { - RGBBackColor( &gray ) ; - EraseRect(&portRect); - RGBForeColor( &black ) ; - RGBBackColor( &white ) ; - - CopyBits(GetPortBitMapForCopyBits(wp), /* src PixMap - we copy image over - * itself - */ - GetPortBitMapForCopyBits(wp), // dst PixMap - no drawing occurs - &portRect, // srcRect - it will be recorded and compressed - - &portRect, // dstRect - into the picture that is open - - srcCopy,NULL); // copyMode and no clip region - } - ClosePicture(); // We are done recording the picture - UnlockPixels( GetGWorldPixMap( wp ) ) ; - SetGWorld( origPort , origDev ) ; + int bwSize = iconSize / 8 * iconSize ; + CIconHandle icon = (CIconHandle) NewHandleClear( sizeof ( CIcon ) + 2 * bwSize) ; + HLock((Handle)icon) ; + SetupCIconHandlePixMap( icon , dstDepth , &frame,GetCTable(dstDepth)) ; + HLock( (**icon).iconData ) ; + (**icon).iconPMap.baseAddr = *(**icon).iconData ; - return pict; // return our groovy pict handle + LockPixels(GetGWorldPixMap(image)); + + CopyBits(GetPortBitMapForCopyBits(image), + (BitMapPtr)&((**icon).iconPMap), + &imageBounds, + &imageBounds, + srcCopy | ditherCopy, nil); + + + UnlockPixels(GetGWorldPixMap(image)); + HUnlock( (**icon).iconData ) ; + + (**icon).iconMask.rowBytes = iconSize / 8 ; + (**icon).iconMask.bounds = frame ; + + (**icon).iconBMap.rowBytes = iconSize / 8 ; + (**icon).iconBMap.bounds = frame ; + (**icon).iconMask.baseAddr = (char*) &(**icon).iconMaskData ; + (**icon).iconBMap.baseAddr = (char*) &(**icon).iconMaskData + bwSize ; + + if ( mask ) + { + LockPixels(GetGWorldPixMap(mask) ) ; + CopyBits(GetPortBitMapForCopyBits(mask) , + &(**icon).iconBMap , &imageBounds , &imageBounds, srcCopy , nil ) ; + CopyBits(GetPortBitMapForCopyBits(mask) , + &(**icon).iconMask , &imageBounds , &imageBounds, srcCopy , nil ) ; + UnlockPixels(GetGWorldPixMap( mask ) ) ; + } + else + { + LockPixels(GetGWorldPixMap(image)); + CopyBits(GetPortBitMapForCopyBits(image) , + &(**icon).iconBMap , &imageBounds , &imageBounds, srcCopy , nil ) ; + CopyBits(GetPortBitMapForCopyBits(image) , + &(**icon).iconMask , &imageBounds , &imageBounds, srcCopy , nil ) ; + UnlockPixels(GetGWorldPixMap(image)); + } + + (**icon).iconMask.baseAddr = NULL ; + (**icon).iconBMap.baseAddr = NULL ; + (**icon).iconPMap.baseAddr = NULL ; + HUnlock((Handle)icon) ; + SetGWorld(saveWorld,saveHandle); + + return icon; +} + +PicHandle wxMacCreatePict(GWorldPtr wp, GWorldPtr mask) +{ + CGrafPtr origPort ; + GDHandle origDev ; + + PicHandle pict; + + RGBColor white = { 0xffff ,0xffff , 0xffff } ; + RGBColor black = { 0x0000 ,0x0000 , 0x0000 } ; + + GetGWorld( &origPort , &origDev ) ; + + RgnHandle clipRgn = NULL ; + + if ( mask ) + { + clipRgn = NewRgn() ; + LockPixels( GetGWorldPixMap( mask ) ) ; + BitMapToRegion( clipRgn , (BitMap*) *GetGWorldPixMap( mask ) ) ; + UnlockPixels( GetGWorldPixMap( mask ) ) ; + } + + SetGWorld( wp , NULL ) ; + Rect portRect ; + GetPortBounds( wp , &portRect ) ; + + pict = OpenPicture(&portRect); + if(pict) + { + RGBForeColor( &black ) ; + RGBBackColor( &white ) ; + + LockPixels( GetGWorldPixMap( wp ) ) ; + CopyBits(GetPortBitMapForCopyBits(wp), + GetPortBitMapForCopyBits(wp), + &portRect, + &portRect, + srcCopy,clipRgn); + UnlockPixels( GetGWorldPixMap( wp ) ) ; + ClosePicture(); + } + SetGWorld( origPort , origDev ) ; + return pict; } wxBitmapRefData::wxBitmapRefData() @@ -197,46 +302,67 @@ wxBitmapRefData::wxBitmapRefData() m_quality = 0; m_numColors = 0; m_bitmapMask = NULL; - m_hBitmap = NULL ; - m_hPict = NULL ; - m_bitmapType = kMacBitmapTypeUnknownType ; + m_hBitmap = NULL ; + m_hPict = NULL ; + m_hIcon = NULL ; + m_bitmapType = kMacBitmapTypeUnknownType ; } -wxBitmapRefData::~wxBitmapRefData() +// TODO move this do a public function of Bitmap Ref +static void DisposeBitmapRefData(wxBitmapRefData *data) { - switch (m_bitmapType) + switch (data->m_bitmapType) { case kMacBitmapTypePict : { - if ( m_hPict ) + if ( data->m_hPict ) { - KillPicture( m_hPict ) ; - m_hPict = NULL ; + KillPicture( data->m_hPict ) ; + data->m_hPict = NULL ; } } break ; case kMacBitmapTypeGrafWorld : { - if ( m_hBitmap ) + if ( data->m_hBitmap ) { - wxMacDestroyGWorld( m_hBitmap ) ; - m_hBitmap = NULL ; + wxMacDestroyGWorld( data->m_hBitmap ) ; + data->m_hBitmap = NULL ; } } break ; + case kMacBitmapTypeIcon : + if ( data->m_hIcon ) + { + DisposeCIcon( data->m_hIcon ) ; + data->m_hIcon = NULL ; + } + default : // unkown type ? break ; } - if (m_bitmapMask) + if (data->m_bitmapMask) { - delete m_bitmapMask; - m_bitmapMask = NULL; + delete data->m_bitmapMask; + data->m_bitmapMask = NULL; } } -wxList wxBitmap::sm_handlers; +wxBitmapRefData::~wxBitmapRefData() +{ + DisposeBitmapRefData( this ) ; +} + +wxList wxBitmapBase::sm_handlers; + + +bool wxBitmap::CopyFromIcon(const wxIcon& icon) +{ + Ref(icon) ; + return true; +} wxBitmap::wxBitmap() { @@ -260,73 +386,61 @@ 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; - 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 ) ; + 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( M_BITMAPDATA->m_hBitmap ) ) ; - -#ifdef __UNIX__ - // bits is a word aligned array?? Don't think so - // bits is a char array on MAC OS X however using the benefit of the - // doubt I replaced references to 16 with sizeof(unsigned char)*8 - unsigned char* linestart = (unsigned char*) bits ; - int linesize = ( the_width / (sizeof(unsigned char) * 8)) ; - if ( the_width % (sizeof(unsigned char) * 8) ) { - linesize += sizeof(unsigned char); - } -#else - // bits is a word aligned array - - unsigned char* linestart = (unsigned char*) bits ; - int linesize = ( the_width / 16 ) * 2 ; - if ( the_width % 16 ) - { - linesize += 2 ; - } -#endif - - 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( M_BITMAPDATA->m_hBitmap ) ) ; + CGrafPtr origPort ; + GDHandle origDevice ; - SetGWorld( origPort , origDevice ) ; - } - else - { - wxFAIL_MSG(wxT("multicolor BITMAPs not yet implemented")); - } - - if ( wxTheBitmapList ) + GetGWorld( &origPort , &origDevice ) ; + SetGWorld( M_BITMAPDATA->m_hBitmap , NULL ) ; + LockPixels( GetGWorldPixMap( M_BITMAPDATA->m_hBitmap ) ) ; + + // bits is a char array + + unsigned char* linestart = (unsigned char*) bits ; + int linesize = ( the_width / (sizeof(unsigned char) * 8)) ; + if ( the_width % (sizeof(unsigned char) * 8) ) { + linesize += sizeof(unsigned char); + } + + 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( M_BITMAPDATA->m_hBitmap ) ) ; + + SetGWorld( origPort , origDevice ) ; + } + else + { + wxFAIL_MSG(wxT("multicolor BITMAPs not yet implemented")); + } + + if ( wxTheBitmapList ) { wxTheBitmapList->AddBitmap(this); + } } wxBitmap::wxBitmap(int w, int h, int d) @@ -337,7 +451,7 @@ wxBitmap::wxBitmap(int w, int h, int d) 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); @@ -345,22 +459,33 @@ wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth) wxTheBitmapList->AddBitmap(this); } -wxBitmap::wxBitmap(const wxString& filename, long type) +wxBitmap::wxBitmap(const wxString& filename, wxBitmapType type) { - LoadFile(filename, (int)type); + LoadFile(filename, type); if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this); } -wxBitmap::wxBitmap(const char **data) +bool wxBitmap::CreateFromXpm(const char **bits) { - (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0); + wxCHECK_MSG( bits != NULL, FALSE, wxT("invalid bitmap data") ) + wxXPMDecoder decoder; + wxImage img = decoder.ReadData(bits); + wxCHECK_MSG( img.Ok(), FALSE, wxT("invalid bitmap data") ) + *this = wxBitmap(img); + if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this); + return TRUE; } -wxBitmap::wxBitmap(char **data) +wxBitmap::wxBitmap(const char **bits) { - (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0); + (void) CreateFromXpm(bits); +} + +wxBitmap::wxBitmap(char **bits) +{ + (void) CreateFromXpm((const char **)bits); } wxBitmap wxBitmap::GetSubBitmap(const wxRect &rect) const @@ -428,7 +553,7 @@ wxBitmap wxBitmap::GetSubBitmap(const wxRect &rect) const RGBColor color; bitmap = GetHBITMAP(); - subbitmap = wxMacCreateGWorld(rect.width, rect.height, GetDepth()); + subbitmap = ref->m_hBitmap ; LockPixels(GetGWorldPixMap(bitmap)); LockPixels(GetGWorldPixMap(subbitmap)); @@ -444,7 +569,6 @@ wxBitmap wxBitmap::GetSubBitmap(const wxRect &rect) const } UnlockPixels(GetGWorldPixMap(bitmap)); UnlockPixels(GetGWorldPixMap(subbitmap)); - ret.SetHBITMAP(subbitmap); } } SetGWorld( origPort, origDevice ); @@ -464,7 +588,7 @@ bool wxBitmap::Create(int w, int h, int d) M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ; M_BITMAPDATA->m_hBitmap = wxMacCreateGWorld( w , h , d ) ; - M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ; + M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ; return M_BITMAPDATA->m_ok; } @@ -477,29 +601,38 @@ int wxBitmap::GetBitmapType() const void wxBitmap::SetHBITMAP(WXHBITMAP bmp) { + DisposeBitmapRefData( M_BITMAPDATA ) ; + M_BITMAPDATA->m_bitmapType = kMacBitmapTypeGrafWorld ; M_BITMAPDATA->m_hBitmap = bmp ; - M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ; + M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_hBitmap != NULL ) ; } -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); + if ( handler ) + { + m_refData = new wxBitmapRefData; - return FALSE; + return handler->LoadFile(this, filename, type, -1, -1); } - - return handler->LoadFile(this, filename, type, -1, -1); + else + { + wxImage loadimage(filename, type); + if (loadimage.Ok()) { + *this = loadimage; + return true; + } + } + wxLogWarning("no bitmap handler for type %d defined.", type); + return false; } -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(); @@ -516,17 +649,171 @@ bool wxBitmap::Create(void *data, long type, int width, int height, int depth) return handler->Create(this, data, type, width, height, depth); } -bool wxBitmap::SaveFile(const wxString& filename, int type, const wxPalette *palette) +wxBitmap::wxBitmap(const wxImage& image, int depth) { - wxBitmapHandler *handler = FindHandler(type); + wxCHECK_RET( image.Ok(), wxT("invalid image") ) + wxCHECK_RET( depth == -1, wxT("invalid bitmap depth") ) - if ( handler == NULL ) { - wxLogWarning("no bitmap handler for type %d defined.", type); + m_refData = new wxBitmapRefData(); + + if (wxTheBitmapList) wxTheBitmapList->AddBitmap(this); - return FALSE; - } + // width and height of the device-dependent bitmap + int width = image.GetWidth(); + int height = image.GetHeight(); + + // Create picture + + Create( width , height , 32 ) ; + + CGrafPtr origPort ; + GDHandle origDevice ; + + PixMapHandle pixMap = GetGWorldPixMap(GetHBITMAP()) ; + LockPixels( pixMap ); - return handler->SaveFile(this, filename, type, palette); + GetGWorld( &origPort , &origDevice ) ; + SetGWorld( GetHBITMAP() , NULL ) ; + + // Render image + RGBColor colorRGB ; + + register unsigned char* data = image.GetData(); + char* destinationBase = GetPixBaseAddr( pixMap ); + register unsigned char* destination = (unsigned char*) destinationBase ; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + *destination++ = 0 ; + *destination++ = *data++ ; + *destination++ = *data++ ; + *destination++ = *data++ ; + } + destinationBase += ((**pixMap).rowBytes & 0x7fff); + destination = (unsigned char*) destinationBase ; + } + if ( image.HasMask() ) + { + data = image.GetData(); + + wxColour maskcolor(image.GetMaskRed(), image.GetMaskGreen(), image.GetMaskBlue()); + RGBColor white = { 0xffff, 0xffff, 0xffff }; + RGBColor black = { 0 , 0 , 0 }; + wxBitmap maskBitmap ; + + maskBitmap.Create( width, height, 1); + LockPixels( GetGWorldPixMap(maskBitmap.GetHBITMAP()) ); + SetGWorld(maskBitmap.GetHBITMAP(), NULL); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + if ( data[0] == image.GetMaskRed() && data[1] == image.GetMaskGreen() && data[2] == image.GetMaskBlue() ) + { + SetCPixel(x,y, &white); + } + else { + SetCPixel(x,y, &black); + } + data += 3 ; + } + } // for height + SetGWorld(GetHBITMAP(), NULL); + SetMask(new wxMask( maskBitmap )); + UnlockPixels( GetGWorldPixMap(maskBitmap.GetHBITMAP()) ); + } + + UnlockPixels( GetGWorldPixMap(GetHBITMAP()) ); + SetGWorld( origPort, origDevice ); +} + +wxImage wxBitmap::ConvertToImage() const +{ + wxImage image; + + wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") ); + + // create an wxImage object + int width = GetWidth(); + int height = GetHeight(); + image.Create( width, height ); + + unsigned char *data = image.GetData(); + + wxCHECK_MSG( data, wxNullImage, wxT("Could not allocate data for image") ); + + WXHBITMAP origPort; + GDHandle origDevice; + int index; + RGBColor color; + // background color set to RGB(16,16,16) in consistent with wxGTK + unsigned char mask_r=16, mask_g=16, mask_b=16; + SInt16 r,g,b; + wxMask *mask = GetMask(); + + GetGWorld( &origPort, &origDevice ); + LockPixels(GetGWorldPixMap(GetHBITMAP())); + SetGWorld( GetHBITMAP(), NULL); + + // Copy data into image + index = 0; + for (int yy = 0; yy < height; yy++) + { + for (int xx = 0; xx < width; xx++) + { + GetCPixel(xx,yy, &color); + r = ((color.red ) >> 8); + g = ((color.green ) >> 8); + b = ((color.blue ) >> 8); + data[index ] = r; + data[index + 1] = g; + data[index + 2] = b; + if (mask) + { + if (mask->PointMasked(xx,yy)) + { + data[index ] = mask_r; + data[index + 1] = mask_g; + data[index + 2] = mask_b; + } + } + index += 3; + } + } + if (mask) + { + image.SetMaskColour( mask_r, mask_g, mask_b ); + image.SetMask( true ); + } + + // Free resources + UnlockPixels(GetGWorldPixMap(GetHBITMAP())); + SetGWorld(origPort, origDevice); + + return image; +} + + +bool wxBitmap::SaveFile(const wxString& filename, wxBitmapType type, + const wxPalette *palette) const +{ + wxBitmapHandler *handler = FindHandler(type); + + if ( handler ) + { + return handler->SaveFile(this, filename, type, palette); + } + else + { + wxImage image = ConvertToImage(); + + return image.SaveFile(filename, type); + } + + wxLogWarning("no bitmap handler for type %d defined.", type); + return false; } bool wxBitmap::Ok() const @@ -629,6 +916,10 @@ void wxBitmap::SetMask(wxMask *mask) if (!M_BITMAPDATA) m_refData = new wxBitmapRefData; + // Remove existing mask if there is one. + if (M_BITMAPDATA->m_bitmapMask) + delete M_BITMAPDATA->m_bitmapMask; + M_BITMAPDATA->m_bitmapMask = mask ; } @@ -680,7 +971,7 @@ PicHandle wxBitmap::GetPict() const if( mask ) { -#ifdef __UNIX__ +#ifdef __DARWIN__ RGBColor trans = white; #else RGBBackColor( &gray ); @@ -766,27 +1057,27 @@ wxBitmapHandler *wxBitmap::FindHandler(const wxString& name) return NULL; } -wxBitmapHandler *wxBitmap::FindHandler(const wxString& extension, long bitmapType) +wxBitmapHandler *wxBitmap::FindHandler(const wxString& extension, wxBitmapType type) { wxNode *node = sm_handlers.First(); while ( node ) { wxBitmapHandler *handler = (wxBitmapHandler *)node->Data(); if ( handler->GetExtension() == extension && - (bitmapType == -1 || handler->GetType() == bitmapType) ) + (type == -1 || handler->GetType() == type) ) return handler; node = node->Next(); } return NULL; } -wxBitmapHandler *wxBitmap::FindHandler(long bitmapType) +wxBitmapHandler *wxBitmap::FindHandler(wxBitmapType type) { wxNode *node = sm_handlers.First(); while ( node ) { wxBitmapHandler *handler = (wxBitmapHandler *)node->Data(); - if (handler->GetType() == bitmapType) + if (handler->GetType() == type) return handler; node = node->Next(); } @@ -960,13 +1251,13 @@ bool wxBitmapHandler::Create(wxBitmap *bitmap, void *data, long type, int width, return FALSE; } -bool wxBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long type, +bool wxBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags, int desiredWidth, int desiredHeight) { return FALSE; } -bool wxBitmapHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette) +bool wxBitmapHandler::SaveFile(const wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette) { return FALSE; } @@ -1025,178 +1316,9 @@ bool wxPICTResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, lo return FALSE ; } -/* TODO: bitmap handlers, a bit like this: -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) -*/ - -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; -} +#if 0 // The following is an example for creating a bitmap handler +// TODO: bitmap handlers, a bit like this: class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler { DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler) @@ -1211,69 +1333,9 @@ public: 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() { @@ -1290,10 +1352,6 @@ void wxBitmap::CleanUpHandlers() void wxBitmap::InitStandardHandlers() { - AddHandler( new wxPICTResourceHandler ) ; - AddHandler( new wxICONResourceHandler ) ; - AddHandler(new wxXPMFileHandler); - AddHandler(new wxXPMDataHandler); - AddHandler(new wxBMPResourceHandler); - AddHandler(new wxBMPFileHandler); + AddHandler(new wxPICTResourceHandler) ; + AddHandler(new wxICONResourceHandler) ; }