+#include "wx/dcmemory.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 premultiplied alpha yet
+#define wxMAC_USE_PREMULTIPLIED_ALPHA 0
+
+IconFamilyHandle wxMacCreateIconFamily(const wxBitmap& bitmap)
+{
+ wxBitmap bmp = bitmap ;
+ // setup the header properly
+
+ IconFamilyHandle iconFamily = (IconFamilyHandle) NewHandle(8) ;
+ (**iconFamily).resourceType = kIconFamilyType ;
+ (**iconFamily).resourceSize = sizeof(OSType) + sizeof(Size);
+
+ int w = bmp.GetWidth() ;
+ int h = bmp.GetHeight() ;
+ int sz = wxMax( w , h ) ;
+
+ OSType dataType ;
+ OSType maskType ;
+
+ if ( sz == 64 )
+ {
+ bmp = wxBitmap( bitmap.ConvertToImage().Scale( 128 , 128 ) ) ;
+ sz = 128 ;
+ h = w = 128 ;
+ }
+ else if ( sz == 24 )
+ {
+ bmp = wxBitmap( bitmap.ConvertToImage().Scale( 48 , 48 ) ) ;
+ sz = 48 ;
+ h = w = 48 ;
+ }
+
+ if ( sz == 128 )
+ {
+ dataType = kThumbnail32BitData ;
+ maskType = kThumbnail8BitMask ;
+ }
+ else if ( sz == 48 )
+ {
+ dataType = kHuge32BitData ;
+ maskType = kHuge8BitMask ;
+ }
+ else if ( sz == 32 )
+ {
+ dataType = kLarge32BitData ;
+ maskType = kLarge8BitMask ;
+ }
+ else if ( sz == 16 )
+ {
+ dataType = kSmall32BitData ;
+ maskType = kSmall8BitMask ;
+ }
+ else
+ {
+ return NULL ;
+ }
+
+ Handle data = NULL ;
+ Handle maskdata = NULL ;
+ unsigned char * maskptr = NULL ;
+ unsigned char * ptr = NULL ;
+ size_t size ;
+ size_t masksize ;
+
+ size = sz * sz * 4 ;
+ data = NewHandle( size) ;
+ HLock( data ) ;
+ ptr = (unsigned char*) *data ;
+ memset( ptr , 0, size ) ;
+
+ masksize = sz * sz ;
+ maskdata = NewHandle( masksize ) ;
+ HLock( maskdata ) ;
+ maskptr = (unsigned char*) *maskdata ;
+ memset( maskptr , 0 , masksize ) ;
+
+ bool hasAlpha = bmp.HasAlpha() ;
+ wxMask *mask = bmp.GetMask() ;
+ unsigned char * source = (unsigned char*) bmp.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 ;
+ for ( int x = 0 ; x < w ; ++x )
+ {
+ unsigned char a = *source ++ ;
+ unsigned char r = *source ++ ;
+ unsigned char g = *source ++ ;
+ unsigned char b = *source ++ ;
+
+ *dest++ = 0 ;
+ *dest++ = r ;
+ *dest++ = g ;
+ *dest++ = b ;
+
+ if ( mask )
+ *maskdest++ = *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 ) ;
+ return iconFamily ;
+}
+
+IconRef wxMacCreateIconRef(const wxBitmap& bmp)
+{
+ IconFamilyHandle iconFamily = wxMacCreateIconFamily( bmp ) ;
+ if ( iconFamily == NULL )
+ return NULL ;
+
+ IconRef iconRef ;
+ static int iconCounter = 2 ;
+
+ OSStatus err = RegisterIconRefFromIconFamily( 'WXNG' , (OSType) iconCounter, iconFamily, &iconRef ) ;
+ UInt16 owners ;
+ err = GetIconRefOwners(iconRef , &owners ) ;
+
+ wxASSERT_MSG( err == noErr , wxT("Error when adding bitmap") ) ;
+ // we have to retain a reference, as Unregister will decrement it
+ AcquireIconRef( iconRef ) ;
+ UnregisterIconRef( 'WXNG' , (OSType) iconCounter ) ;
+ DisposeHandle( (Handle) iconFamily ) ;
+ ++iconCounter ;
+
+ return iconRef ;
+}
+
+PicHandle wxMacCreatePicHandle( const wxBitmap &bmp )