+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 } ;
+ 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") ) ;
+
+ 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 } ;
+ 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") ) ;
+ m_maskMemBuf.UngetWriteBuf(size) ;
+
+#if !wxMAC_USE_CORE_GRAPHICS
+ UpdateAlphaMask() ;
+#endif
+ }
+ else
+ {
+ DisposeGWorld( m_hMaskBitmap ) ;
+ 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()
+{
+ if ( m_iconRef == NULL )
+ {
+ // Create Icon Family Handle
+
+ IconFamilyHandle iconFamily = NULL ;
+
+#ifdef WORDS_BIGENDIAN
+ iconFamily = (IconFamilyHandle) NewHandle( 8 ) ;
+ (**iconFamily).resourceType = kIconFamilyType ;
+ (**iconFamily).resourceSize = sizeof(OSType) + sizeof(Size);
+#else
+ // test this solution on big endian as well
+ iconFamily = (IconFamilyHandle) NewHandle( 0 ) ;
+#endif
+
+ int w = GetWidth() ;
+ int h = GetHeight() ;
+ int sz = wxMax( w , h ) ;
+
+ OSType dataType = 0 ;
+ OSType maskType = 0 ;
+
+ switch (sz)
+ {
+ case 128:
+ dataType = kThumbnail32BitData ;
+ maskType = kThumbnail8BitMask ;
+ break;
+
+ case 48:
+ dataType = kHuge32BitData ;
+ maskType = kHuge8BitMask ;
+ break;
+
+ case 32:
+ dataType = kLarge32BitData ;
+ maskType = kLarge8BitMask ;
+ break;
+
+ case 16:
+ dataType = kSmall32BitData ;
+ maskType = kSmall8BitMask ;
+ break;
+
+ default:
+ break;
+ }
+
+ if ( dataType != 0 )
+ {
+ // setup the header properly
+
+ Handle data = NULL ;
+ Handle maskdata = NULL ;
+ unsigned char * maskptr = NULL ;
+ unsigned char * ptr = NULL ;
+ size_t datasize, masksize ;
+
+ datasize = sz * sz * 4 ;
+ data = NewHandle( datasize ) ;
+ HLock( data ) ;
+ ptr = (unsigned char*) *data ;
+ memset( ptr , 0, datasize ) ;
+
+ masksize = sz * sz ;
+ maskdata = NewHandle( masksize ) ;
+ HLock( maskdata ) ;
+ maskptr = (unsigned char*) *maskdata ;
+ memset( maskptr , 0 , masksize ) ;
+
+ bool hasAlpha = HasAlpha() ;
+ wxMask *mask = m_bitmapMask ;
+ unsigned char * source = (unsigned char*) GetRawAccess() ;
+ unsigned char * masksource = mask ? (unsigned char*) mask->GetRawAccess() : NULL ;
+
+ for ( int y = 0 ; y < h ; ++y )
+ {
+ unsigned char * dest = ptr + y * sz * 4 ;
+ unsigned char * maskdest = maskptr + y * sz ;
+ unsigned char a, r, g, b;
+
+ for ( int x = 0 ; x < w ; ++x )
+ {
+ a = *source ++ ;
+ r = *source ++ ;
+ g = *source ++ ;
+ b = *source ++ ;
+
+ *dest++ = 0 ;
+ *dest++ = r ;
+ *dest++ = g ;
+ *dest++ = b ;
+
+ if ( mask )
+ {
+ *maskdest++ = 0xFF - *masksource++ ;
+ masksource++ ;
+ masksource++ ;
+ masksource++ ;
+ }
+ else if ( hasAlpha )
+ *maskdest++ = a ;
+ else
+ *maskdest++ = 0xFF ;
+ }
+ }
+
+ OSStatus err = SetIconFamilyData( iconFamily, dataType , data ) ;
+ wxASSERT_MSG( err == noErr , wxT("Error when adding bitmap") ) ;
+
+ err = SetIconFamilyData( iconFamily, maskType , maskdata ) ;
+ wxASSERT_MSG( err == noErr , wxT("Error when adding mask") ) ;
+
+ HUnlock( data ) ;
+ HUnlock( maskdata ) ;
+ DisposeHandle( data ) ;
+ DisposeHandle( maskdata ) ;
+ }
+ else
+ {
+ PicHandle pic = GetPictHandle() ;
+ SetIconFamilyData( iconFamily, 'PICT' , (Handle) pic ) ;
+ }
+ // transform into IconRef
+#if defined( __WXMAC_OSX__ ) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2
+ // cleaner version existing from 10.3 upwards
+ HLock((Handle) iconFamily);
+ OSStatus err = GetIconRefFromIconFamilyPtr( *iconFamily, GetHandleSize((Handle) iconFamily), &m_iconRef );
+ HUnlock((Handle) iconFamily);
+ wxASSERT_MSG( err == noErr , wxT("Error when constructing icon ref") );
+#else
+ static int iconCounter = 2 ;
+
+ OSStatus err = RegisterIconRefFromIconFamily( 'WXNG' , (OSType) iconCounter, iconFamily, &m_iconRef ) ;
+ wxASSERT_MSG( err == noErr , wxT("Error when adding bitmap") ) ;
+
+ // we have to retain a reference, as Unregister will decrement it
+ AcquireIconRef( m_iconRef ) ;
+ UnregisterIconRef( 'WXNG' , (OSType) iconCounter ) ;
+ ++iconCounter ;
+#endif
+ DisposeHandle( (Handle) iconFamily ) ;
+ }
+
+ return m_iconRef ;
+}
+
+PicHandle wxBitmapRefData::GetPictHandle()
+{
+ if ( m_pictHandle == NULL )
+ {
+ CGrafPtr origPort = NULL ;
+ GDHandle origDev = NULL ;
+ GWorldPtr wp = NULL ;
+ GWorldPtr mask = NULL ;
+ int height = GetHeight() ;
+ int width = GetWidth() ;
+
+ Rect rect = { 0 , 0 , height , width } ;
+ RgnHandle clipRgn = NULL ;
+
+ GetGWorld( &origPort , &origDev ) ;
+ wp = GetHBITMAP( &mask ) ;
+
+ if ( mask )
+ {
+ GWorldPtr monoworld ;
+ clipRgn = NewRgn() ;
+ OSStatus err = NewGWorld( &monoworld , 1 , &rect , NULL , NULL , 0 ) ;
+ verify_noerr(err) ;
+ LockPixels( GetGWorldPixMap( monoworld ) ) ;
+ LockPixels( GetGWorldPixMap( mask ) ) ;
+ SetGWorld( monoworld , NULL ) ;
+
+ RGBColor white = { 0xffff , 0xffff , 0xffff } ;
+ RGBColor black = { 0x0000 , 0x0000 , 0x0000 } ;
+ RGBForeColor( &black ) ;
+ RGBBackColor( &white ) ;
+
+ CopyBits(GetPortBitMapForCopyBits(mask),
+ GetPortBitMapForCopyBits(monoworld),
+ &rect,
+ &rect,
+ srcCopy, NULL);
+ BitMapToRegion( clipRgn , (BitMap*) *GetGWorldPixMap( monoworld ) ) ;
+
+ UnlockPixels( GetGWorldPixMap( monoworld ) ) ;
+ UnlockPixels( GetGWorldPixMap( mask ) ) ;
+ DisposeGWorld( monoworld ) ;
+ }
+
+ SetGWorld( wp , NULL ) ;
+ Rect portRect ;
+ GetPortBounds( wp , &portRect ) ;
+ m_pictHandle = OpenPicture(&portRect);
+
+ if (m_pictHandle)
+ {
+ RGBColor white = { 0xffff , 0xffff , 0xffff } ;
+ RGBColor black = { 0x0000 , 0x0000 , 0x0000 } ;
+
+ RGBForeColor( &black ) ;
+ RGBBackColor( &white ) ;
+
+ if ( clipRgn )
+ SetClip( clipRgn ) ;
+
+ LockPixels( GetGWorldPixMap( wp ) ) ;
+ CopyBits(GetPortBitMapForCopyBits(wp),
+ GetPortBitMapForCopyBits(wp),
+ &portRect,
+ &portRect,
+ srcCopy,clipRgn);
+ UnlockPixels( GetGWorldPixMap( wp ) ) ;
+ ClosePicture();
+ }
+
+ SetGWorld( origPort , origDev ) ;
+ if ( clipRgn )
+ DisposeRgn( clipRgn ) ;
+ }
+
+ return m_pictHandle ;
+}
+
+#ifdef __WXMAC_OSX__
+void wxMacMemoryBufferReleaseProc(void *info, const void *data, size_t size)