+#include "wx/mac/uma.h"
+
+// Implementation Notes
+// --------------------
+//
+// we are always working with a 32 bit deep pixel buffer
+// under QuickDraw its alpha parts are going to be ignored in the GWorld,
+// therefore we have a separate GWorld there for blitting the mask in
+
+// under Quartz then content is transformed into a CGImageRef representing the same data
+// which can be transferred to the GPU by the OS for fast rendering
+
+// we don't dare use premultiplied alpha yet
+#define wxMAC_USE_PREMULTIPLIED_ALPHA 0
+
+#if wxUSE_BMPBUTTON
+
+void wxMacCreateBitmapButton( ControlButtonContentInfo*info , const wxBitmap& bitmap , int forceType )
+{
+ memset( info , 0 , sizeof(ControlButtonContentInfo) ) ;
+ if ( bitmap.Ok() )
+ {
+ wxBitmapRefData * bmap = bitmap.GetBitmapData() ;
+ if ( bmap == NULL )
+ return ;
+
+ if ( ( bmap->HasNativeSize() && forceType == 0 ) || forceType == kControlContentIconRef )
+ {
+ wxBitmap scaleBmp ;
+ wxBitmapRefData* bmp = bmap ;
+
+ if ( !bmap->HasNativeSize() )
+ {
+ // as PICT conversion will only result in a 16x16 icon, let's attempt
+ // a few scales for better results
+
+ int w = bitmap.GetWidth() ;
+ int h = bitmap.GetHeight() ;
+ int sz = wxMax( w , h ) ;
+ if ( sz == 24 || sz == 64 )
+ {
+ scaleBmp = wxBitmap( bitmap.ConvertToImage().Scale( w * 2 , h * 2 ) ) ;
+ bmp = scaleBmp.GetBitmapData() ;
+ }
+ }
+
+ info->contentType = kControlContentIconRef ;
+ info->u.iconRef = bmp->GetIconRef() ;
+ AcquireIconRef( info->u.iconRef ) ;
+ }
+#if defined( __WXMAC_OSX__ ) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
+ else if ( forceType == kControlContentCGImageRef )
+ {
+ info->contentType = kControlContentCGImageRef ;
+ info->u.imageRef = (CGImageRef) bmap->CGImageCreate() ;
+ }
+#endif
+ else
+ {
+#ifndef __LP64__
+ info->contentType = kControlContentPictHandle ;
+ info->u.picture = bmap->GetPictHandle() ;
+#endif
+ }
+ }
+}
+
+void wxMacReleaseBitmapButton( ControlButtonContentInfo*info )
+{
+ if ( info->contentType == kControlContentIconRef )
+ {
+ ReleaseIconRef( info->u.iconRef ) ;
+ }
+ else if ( info->contentType == kControlNoContent )
+ {
+ // there's no bitmap at all, fall through silently
+ }
+ else if ( info->contentType == kControlContentPictHandle )
+ {
+ // owned by the bitmap, no release here
+ }
+#if defined( __WXMAC_OSX__ ) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
+ else if ( info->contentType == kControlContentCGImageRef )
+ {
+ CGImageRelease( info->u.imageRef ) ;
+ }
+#endif
+ else
+ {
+ wxFAIL_MSG(wxT("Unexpected bitmap type") ) ;
+ }
+}
+
+#endif //wxUSE_BMPBUTTON
+
+#define M_BITMAPDATA ((wxBitmapRefData *)m_refData)
+
+void wxBitmapRefData::Init()
+{
+ m_width = 0 ;
+ m_height = 0 ;
+ m_depth = 0 ;
+ m_ok = false ;
+ m_bitmapMask = NULL ;
+
+#ifdef __WXMAC_OSX__
+ m_cgImageRef = NULL ;
+#endif
+
+ m_iconRef = NULL ;
+ m_pictHandle = NULL ;
+ m_hBitmap = NULL ;
+ m_hMaskBitmap = NULL;
+ m_maskBytesPerRow = 0 ;
+
+ m_rawAccessCount = 0 ;
+ m_hasAlpha = false;
+}
+
+wxBitmapRefData::wxBitmapRefData(const wxBitmapRefData &tocopy)
+{
+ Init();
+ Create(tocopy.m_width, tocopy.m_height, tocopy.m_depth);
+
+ if (tocopy.m_bitmapMask)
+ m_bitmapMask = new wxMask(*tocopy.m_bitmapMask);
+
+ unsigned char* dest = (unsigned char*)GetRawAccess();
+ unsigned char* source = (unsigned char*)tocopy.GetRawAccess();
+ size_t numbytes = tocopy.m_width * tocopy.m_height * 4;
+
+ for (size_t i=0; i<numbytes; i++)
+ {
+ *dest++ = *source++;
+ }
+
+ UseAlpha(tocopy.m_hasAlpha);
+
+ // TODO: Copy palette?
+}
+
+wxBitmapRefData::wxBitmapRefData()
+{
+ Init() ;
+}
+
+wxBitmapRefData::wxBitmapRefData( int w , int h , int d )
+{
+ Init() ;
+ Create( w , h , d ) ;
+}
+
+bool wxBitmapRefData::Create( int w , int h , int d )
+{
+ m_width = wxMax(1, w);
+ m_height = wxMax(1, h);
+ m_depth = d ;
+
+ m_bytesPerRow = w * 4 ;
+ size_t size = m_bytesPerRow * h ;
+ void* data = m_memBuf.GetWriteBuf( size ) ;
+ memset( data , 0 , size ) ;
+ m_memBuf.UngetWriteBuf( size ) ;
+
+ m_hBitmap = NULL ;
+ Rect rect = { 0 , 0 , m_height , m_width } ;
+#ifndef __LP64__
+ verify_noerr( NewGWorldFromPtr( (GWorldPtr*) &m_hBitmap , k32ARGBPixelFormat , &rect , NULL , NULL , 0 ,
+ (char*) data , m_bytesPerRow ) ) ;
+ wxASSERT_MSG( m_hBitmap , wxT("Unable to create GWorld context") ) ;
+#endif
+ m_ok = ( m_hBitmap != NULL ) ;
+
+ return m_ok ;
+}
+
+void wxBitmapRefData::UseAlpha( bool use )
+{
+ if ( m_hasAlpha == use )
+ return ;
+
+ m_hasAlpha = use ;
+ if ( m_hasAlpha )
+ {
+ wxASSERT( m_hMaskBitmap == NULL ) ;
+
+ int width = GetWidth() ;
+ int height = GetHeight() ;
+ m_maskBytesPerRow = ( width * 4 + 3 ) & 0xFFFFFFC ;
+ size_t size = height * m_maskBytesPerRow ;
+ unsigned char * data = (unsigned char * ) m_maskMemBuf.GetWriteBuf( size ) ;
+ wxASSERT( data != NULL ) ;
+
+ memset( data , 0 , size ) ;
+ Rect rect = { 0 , 0 , height , width } ;
+#ifndef __LP64__
+ verify_noerr( NewGWorldFromPtr( (GWorldPtr*) &m_hMaskBitmap , k32ARGBPixelFormat , &rect , NULL , NULL , 0 ,
+ (char*) data , m_maskBytesPerRow ) ) ;
+ wxASSERT_MSG( m_hMaskBitmap , wxT("Unable to create GWorld context for alpha mask") ) ;
+#endif
+ m_maskMemBuf.UngetWriteBuf(size) ;
+
+#if !wxMAC_USE_CORE_GRAPHICS
+ UpdateAlphaMask() ;
+#endif
+ }
+ else
+ {
+#ifndef __LP64__
+ DisposeGWorld( m_hMaskBitmap ) ;
+#endif
+ m_hMaskBitmap = NULL ;
+ m_maskBytesPerRow = 0 ;
+ }
+}
+
+void *wxBitmapRefData::GetRawAccess() const
+{
+ wxCHECK_MSG( Ok(), NULL , wxT("invalid bitmap") ) ;
+ return m_memBuf.GetData() ;
+}
+
+void *wxBitmapRefData::BeginRawAccess()
+{
+ wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") ) ;
+ wxASSERT( m_rawAccessCount == 0 ) ;
+ wxASSERT_MSG( m_pictHandle == NULL && m_iconRef == NULL ,
+ wxT("Currently, modifing bitmaps that are used in controls already is not supported") ) ;
+
+ ++m_rawAccessCount ;
+
+#ifdef __WXMAC_OSX__
+ // we must destroy an existing cached image, as
+ // the bitmap data may change now
+ if ( m_cgImageRef )
+ {
+ CGImageRelease( m_cgImageRef ) ;
+ m_cgImageRef = NULL ;
+ }
+#endif
+
+ return m_memBuf.GetData() ;
+}
+
+void wxBitmapRefData::EndRawAccess()
+{
+ wxCHECK_RET( Ok() , wxT("invalid bitmap") ) ;
+ wxASSERT( m_rawAccessCount == 1 ) ;
+
+ --m_rawAccessCount ;
+
+#if !wxMAC_USE_CORE_GRAPHICS
+ UpdateAlphaMask() ;
+#endif
+}
+
+bool wxBitmapRefData::HasNativeSize()
+{
+ int w = GetWidth() ;
+ int h = GetHeight() ;
+ int sz = wxMax( w , h ) ;
+
+ return ( sz == 128 || sz == 48 || sz == 32 || sz == 16 );
+}
+
+IconRef wxBitmapRefData::GetIconRef()