+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 ) ;
+ ++m_rawAccessCount ;
+#if wxMAC_USE_CORE_GRAPHICS
+ // 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
+}
+
+
+#if wxMAC_USE_CORE_GRAPHICS
+void wxMacMemoryBufferReleaseProc(void *info, const void *data, size_t size)
+{
+ wxMemoryBuffer* membuf = (wxMemoryBuffer*) info ;
+ wxASSERT( data == membuf->GetData() ) ;
+ delete membuf ;
+}
+
+CGImageRef wxBitmapRefData::CGImageCreate() const
+{
+ wxASSERT( m_ok ) ;
+ wxASSERT( m_rawAccessCount >= 0 ) ;
+ CGImageRef image ;
+ if ( m_rawAccessCount > 0 || m_cgImageRef == NULL )
+ {
+ size_t imageSize = m_width * m_height * 4 ;
+ void * dataBuffer = m_memBuf.GetData() ;
+ int w = m_width ;
+ int h = m_height ;
+ CGImageAlphaInfo alphaInfo = kCGImageAlphaNoneSkipFirst ;
+ wxMemoryBuffer* membuf = NULL ;
+
+ if ( m_bitmapMask )
+ {
+ membuf = new wxMemoryBuffer( imageSize ) ;
+ memcpy( membuf->GetData() , dataBuffer , imageSize ) ;
+ unsigned char *sourcemaskstart = (unsigned char *) m_bitmapMask->GetRawAccess() ;
+ int maskrowbytes = m_bitmapMask->GetBytesPerRow() ;
+ unsigned char *destalpha = (unsigned char *) membuf->GetData() ;
+ alphaInfo = kCGImageAlphaFirst ;
+ for ( int y = 0 ; y < h ; ++y , sourcemaskstart += maskrowbytes)
+ {
+ unsigned char *sourcemask = sourcemaskstart ;
+ for( int x = 0 ; x < w ; ++x , sourcemask++ , destalpha += 4 )
+ {
+ *destalpha = *sourcemask ;
+ }
+ }
+ }
+ else if ( m_hasAlpha )
+ {
+#if wxMAC_USE_PREMULTIPLIED_ALPHA
+ alphaInfo = kCGImageAlphaPremultipliedFirst ;
+#else
+ alphaInfo = kCGImageAlphaFirst ;
+#endif
+ membuf = new wxMemoryBuffer( m_memBuf ) ;
+ }
+ else
+ {
+ membuf = new wxMemoryBuffer( m_memBuf ) ;
+ }
+ CGColorSpaceRef colorSpace = wxMacGetGenericRGBColorSpace();
+ CGDataProviderRef dataProvider =
+ CGDataProviderCreateWithData( membuf , (const void *)membuf->GetData() , imageSize,
+ wxMacMemoryBufferReleaseProc );
+ image =
+ ::CGImageCreate( w, h, 8 , 32 , 4 * m_width , colorSpace, alphaInfo ,
+ dataProvider, NULL , false , kCGRenderingIntentDefault );
+ CGDataProviderRelease( dataProvider);
+ }
+ else
+ {
+ image = m_cgImageRef ;
+ CGImageRetain( image ) ;
+ }
+ if ( m_rawAccessCount == 0 && m_cgImageRef == NULL)
+ {
+ // we keep it for later use
+ m_cgImageRef = image ;
+ CGImageRetain( image ) ;
+ }
+ return image ;
+}
+#endif
+
+GWorldPtr wxBitmapRefData::GetHBITMAP(GWorldPtr* mask) const
+{
+ wxCHECK_MSG( Ok(), NULL, wxT("invalid bitmap") );
+ if ( mask )
+ {
+ *mask = NULL ;
+ if ( m_bitmapMask )
+ *mask = (GWorldPtr) m_bitmapMask->GetHBITMAP() ;
+ else if ( m_hasAlpha )
+ {
+#if !wxMAC_USE_CORE_GRAPHICS
+ if ( m_rawAccessCount > 0 )
+ UpdateAlphaMask() ;
+#else
+ // this structure is not kept in synch when using CG, so if someone
+ // is really accessing the Graphports, we have to sync it
+ UpdateAlphaMask() ;
+#endif
+ *mask = m_hMaskBitmap ;
+ }
+ }
+ return m_hBitmap ;
+}
+
+void wxBitmapRefData::UpdateAlphaMask() const
+{
+ if ( m_hasAlpha )
+ {
+ unsigned char *sourcemask = (unsigned char *) GetRawAccess() ;
+ unsigned char *destalphabase = (unsigned char *) m_maskMemBuf.GetData() ;
+
+ int h = GetHeight() ;
+ int w = GetWidth() ;
+
+ for ( int y = 0 ; y < h ; ++y , destalphabase += m_maskBytesPerRow )
+ {
+ unsigned char* destalpha = destalphabase ;
+ for( int x = 0 ; x < w ; ++x , sourcemask += 4, ++destalpha )
+ {
+ *destalpha = *sourcemask ;
+ }
+ }
+ }
+}
+
+void wxBitmapRefData::Free()
+{
+ wxASSERT_MSG( m_rawAccessCount == 0 , wxT("Bitmap still selected when destroyed") ) ;
+
+#if wxMAC_USE_CORE_GRAPHICS
+ if ( m_cgImageRef )
+ {
+ CGImageRelease( m_cgImageRef ) ;
+ m_cgImageRef = NULL ;
+ }
+#endif
+ if ( m_hBitmap )
+ {
+ DisposeGWorld( MAC_WXHBITMAP(m_hBitmap) ) ;
+ m_hBitmap = NULL ;
+ }
+ if ( m_hMaskBitmap )
+ {
+ DisposeGWorld( MAC_WXHBITMAP(m_hMaskBitmap) ) ;
+ m_hMaskBitmap = NULL ;
+ }
+
+ if (m_bitmapMask)
+ {
+ delete m_bitmapMask;
+ m_bitmapMask = NULL;
+ }
+}
+
+wxBitmapRefData::~wxBitmapRefData()
+{
+ Free() ;
+}