X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/53e8c532c641ea8285b436990ff6e29ddd8d0443..8fc754bf2bc32de45d85a519e7706fa122d42731:/src/mac/carbon/bitmap.cpp?ds=sidebyside diff --git a/src/mac/carbon/bitmap.cpp b/src/mac/carbon/bitmap.cpp index 02b7427a2c..bb3247be56 100644 --- a/src/mac/carbon/bitmap.cpp +++ b/src/mac/carbon/bitmap.cpp @@ -39,10 +39,10 @@ IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject ) #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, +// 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 @@ -51,200 +51,54 @@ IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject ) // 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 ) -{ - CGrafPtr origPort = NULL ; - GDHandle origDev = NULL ; - PicHandle pict = NULL ; - GWorldPtr wp = NULL ; - GWorldPtr mask = NULL ; - - GetGWorld( &origPort , &origDev ) ; - - wp = (GWorldPtr) bmp.GetHBITMAP( (WXHBITMAP*) &mask ) ; - - SetGWorld( wp , NULL ) ; - Rect portRect ; - GetPortBounds( wp , &portRect ) ; - pict = OpenPicture(&portRect); - - if(pict) - { - RGBColor white = { 0xffff ,0xffff , 0xffff } ; - RGBColor black = { 0x0000 ,0x0000 , 0x0000 } ; - RGBForeColor( &black ) ; - RGBBackColor( &white ) ; - - LockPixels( GetGWorldPixMap( wp ) ) ; - CopyBits(GetPortBitMapForCopyBits(wp), - GetPortBitMapForCopyBits(wp), - &portRect, - &portRect, - srcCopy,NULL); - UnlockPixels( GetGWorldPixMap( wp ) ) ; - ClosePicture(); - } - SetGWorld( origPort , origDev ) ; - - return pict; -} +#if wxUSE_BMPBUTTON void wxMacCreateBitmapButton( ControlButtonContentInfo*info , const wxBitmap& bitmap , int forceType ) { memset( info , 0 , sizeof(ControlButtonContentInfo) ) ; if ( bitmap.Ok() ) { - wxBitmapRefData * bmap = (wxBitmapRefData*) ( bitmap.GetRefData()) ; + wxBitmapRefData * bmap = bitmap.GetBitmapData() ; if ( bmap == NULL ) return ; - info->contentType = kControlContentIconRef ; - info->u.iconRef = wxMacCreateIconRef( bitmap ) ; - wxASSERT_MSG( info->u.iconRef , wxT("Converting to IconRef not possible") ) ; -#if wxMAC_USE_CORE_GRAPHICS - /* - // only on 10.4 more controls will accept a CGImage - + + 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 wxMAC_USE_CORE_GRAPHICS && 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 + { + info->contentType = kControlContentPictHandle ; + info->u.picture = bmap->GetPictHandle() ; + } } } @@ -252,7 +106,15 @@ void wxMacReleaseBitmapButton( ControlButtonContentInfo*info ) { if ( info->contentType == kControlContentIconRef ) { - ReleaseIconRef(info->u.iconRef) ; + 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 wxMAC_USE_CORE_GRAPHICS && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 else if ( info->contentType == kControlContentCGImageRef ) @@ -266,6 +128,8 @@ void wxMacReleaseBitmapButton( ControlButtonContentInfo*info ) } } +#endif //wxUSE_BMPBUTTON + #define M_BITMAPDATA ((wxBitmapRefData *)m_refData) void wxBitmapRefData::Init() @@ -278,6 +142,8 @@ void wxBitmapRefData::Init() #if wxMAC_USE_CORE_GRAPHICS m_cgImageRef = NULL ; #endif + m_iconRef = NULL ; + m_pictHandle = NULL ; m_hBitmap = NULL ; m_hMaskBitmap = NULL; m_maskBytesPerRow = NULL ; @@ -291,16 +157,16 @@ wxBitmapRefData::wxBitmapRefData() Init() ; } -wxBitmapRefData::wxBitmapRefData( int w , int h , int d ) +wxBitmapRefData::wxBitmapRefData( int w , int h , int d ) { Init() ; Create( w , h , d ) ; } -bool wxBitmapRefData::Create( int w , int h , int d ) +bool wxBitmapRefData::Create( int w , int h , int d ) { m_width = w ; - m_height = h ; + m_height = h ; m_depth = d ; m_bytesPerRow = w * 4 ; @@ -312,31 +178,31 @@ bool wxBitmapRefData::Create( int w , int h , int d ) 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 ) ) ; + (char*) data , m_bytesPerRow ) ) ; wxASSERT_MSG( m_hBitmap , wxT("Unable to create GWorld context") ) ; m_ok = ( m_hBitmap != NULL ) ; - return m_ok ; + return m_ok ; } void wxBitmapRefData::UseAlpha( bool use ) { if ( m_hasAlpha == use ) return ; - + m_hasAlpha = use ; if ( m_hasAlpha ) { int width = GetWidth() ; int height = GetHeight() ; - m_maskBytesPerRow = ( width + 3 ) & 0xFFFFFFC ; + m_maskBytesPerRow = ( width * 4 + 3 ) & 0xFFFFFFC ; size_t size = height * m_maskBytesPerRow ; unsigned char * data = (unsigned char * ) m_maskMemBuf.GetWriteBuf( size ) ; memset( data , 0 , size ) ; wxASSERT( m_hMaskBitmap == NULL ) ; Rect rect = { 0 , 0 , height , width } ; - verify_noerr( NewGWorldFromPtr( (GWorldPtr*) &m_hMaskBitmap , k8IndexedGrayPixelFormat , &rect , NULL , NULL , 0 , - (char*) data , m_maskBytesPerRow ) ) ; + 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 @@ -357,14 +223,16 @@ void *wxBitmapRefData::GetRawAccess() const return m_memBuf.GetData() ; } -void *wxBitmapRefData::BeginRawAccess() +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 + // we must destroy an existing cached image, as // the bitmap data may change now + wxASSERT_MSG( m_pictHandle == NULL && m_iconRef == NULL , + wxT("Currently, modifing bitmaps that are used in controls already is not supported") ) ; +#if wxMAC_USE_CORE_GRAPHICS if ( m_cgImageRef ) { CGImageRelease( m_cgImageRef ) ; @@ -384,8 +252,222 @@ void wxBitmapRefData::EndRawAccess() #endif } +bool wxBitmapRefData::HasNativeSize() +{ + int w = GetWidth() ; + int h = GetHeight() ; + int sz = wxMax( w , h ) ; -#if wxMAC_USE_CORE_GRAPHICS + if ( sz == 128 || sz == 48 || sz == 32 || sz == 16 ) + return true ; + return false ; +} + +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 ; + + 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 ; + } + + if ( dataType != 0 ) + { + // setup the header properly + + 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 = 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 ; + 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 ) ; + } + else + { + PicHandle pic = GetPictHandle() ; + SetIconFamilyData( iconFamily, 'PICT' , (Handle) pic ) ; + } + + // transform into IconRef + + static int iconCounter = 2 ; +#ifdef __WXDEBUG__ + OSStatus err = +#endif + 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 ) ; + DisposeHandle( (Handle) iconFamily ) ; + ++iconCounter ; + } + 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 } ; + + GetGWorld( &origPort , &origDev ) ; + + wp = GetHBITMAP( &mask ) ; + + RgnHandle clipRgn = NULL ; + + 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) { wxMemoryBuffer* membuf = (wxMemoryBuffer*) info ; @@ -406,7 +488,7 @@ CGImageRef wxBitmapRefData::CGImageCreate() const int h = m_height ; CGImageAlphaInfo alphaInfo = kCGImageAlphaNoneSkipFirst ; wxMemoryBuffer* membuf = NULL ; - + if ( m_bitmapMask ) { membuf = new wxMemoryBuffer( imageSize ) ; @@ -438,13 +520,13 @@ CGImageRef wxBitmapRefData::CGImageCreate() const 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); + 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 { @@ -456,7 +538,7 @@ CGImageRef wxBitmapRefData::CGImageCreate() const // we keep it for later use m_cgImageRef = image ; CGImageRetain( image ) ; - } + } return image ; } #endif @@ -468,7 +550,7 @@ GWorldPtr wxBitmapRefData::GetHBITMAP(GWorldPtr* mask) const { *mask = NULL ; if ( m_bitmapMask ) - *mask = (GWorldPtr) m_bitmapMask->GetHBITMAP() ; + *mask = (GWorldPtr) m_bitmapMask->GetHBITMAP() ; else if ( m_hasAlpha ) { #if !wxMAC_USE_CORE_GRAPHICS @@ -485,22 +567,26 @@ GWorldPtr wxBitmapRefData::GetHBITMAP(GWorldPtr* mask) const return m_hBitmap ; } -void wxBitmapRefData::UpdateAlphaMask() const +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 ) + for( int x = 0 ; x < w ; ++x , sourcemask += 4 ) { - *destalpha = *sourcemask ; + // we must have 24 bit depth for non quartz smooth alpha + *destalpha++ = 255 ; + *destalpha++ = 255 - *sourcemask ; + *destalpha++ = 255 - *sourcemask ; + *destalpha++ = 255 - *sourcemask ; } } } @@ -517,6 +603,16 @@ void wxBitmapRefData::Free() m_cgImageRef = NULL ; } #endif + if ( m_iconRef ) + { + ReleaseIconRef( m_iconRef ) ; + m_iconRef = NULL ; + } + if ( m_pictHandle ) + { + KillPicture( m_pictHandle ) ; + m_pictHandle = NULL ; + } if ( m_hBitmap ) { DisposeGWorld( MAC_WXHBITMAP(m_hBitmap) ) ; @@ -544,17 +640,21 @@ bool wxBitmap::CopyFromIcon(const wxIcon& icon) { int w = icon.GetWidth() ; int h = icon.GetHeight() ; + + Create( icon.GetWidth() , icon.GetHeight() ) ; + bool created = false ; + if ( w == h && ( w == 16 || w == 32 || w == 48 || w == 128 ) ) { IconFamilyHandle iconFamily = NULL ; Handle imagehandle = NewHandle(0) ; Handle maskhandle = NewHandle(0) ; - + OSType maskType = 0; OSType dataType = 0; - IconSelectorValue selector = 0 ; + IconSelectorValue selector = 0 ; if ( w == 128 ) { dataType = kThumbnail32BitData ; @@ -579,40 +679,46 @@ bool wxBitmap::CopyFromIcon(const wxIcon& icon) maskType = kSmall8BitMask ; selector = kSelectorSmall32Bit | kSelectorSmall8BitMask ; } - else - { - wxFAIL_MSG(wxT("Illegal icon size for conversion") ) ; - } OSStatus err = ( IconRefToIconFamily( MAC_WXHICON(icon.GetHICON()) , selector , &iconFamily ) ) ; - + err =( GetIconFamilyData( iconFamily , dataType , imagehandle ) ) ; err =( GetIconFamilyData( iconFamily , maskType , maskhandle ) ) ; - wxASSERT( GetHandleSize( imagehandle ) == w * 4 * h ) ; - wxASSERT( GetHandleSize( maskhandle ) == w * h ) ; - UseAlpha() ; - unsigned char *source = (unsigned char *) *imagehandle ; - unsigned char *sourcemask = (unsigned char *) *maskhandle ; - - unsigned char* destination = (unsigned char*) BeginRawAccess() ; - for ( int y = 0 ; y < h ; ++y ) + size_t imagehandlesize = GetHandleSize( imagehandle ) ; + size_t maskhandlesize = GetHandleSize( maskhandle ) ; + + if ( imagehandlesize != 0 && maskhandlesize != 0 ) { - for ( int x = 0 ; x < w ; ++x ) + wxASSERT( GetHandleSize( imagehandle ) == w * 4 * h ) ; + wxASSERT( GetHandleSize( maskhandle ) == w * h ) ; + UseAlpha() ; + unsigned char *source = (unsigned char *) *imagehandle ; + unsigned char *sourcemask = (unsigned char *) *maskhandle ; + + unsigned char* destination = (unsigned char*) BeginRawAccess() ; + for ( int y = 0 ; y < h ; ++y ) { - *destination++ = *sourcemask++ ; - source++ ; - *destination++ = *source++ ; - *destination++ = *source++ ; - *destination++ = *source++ ; + for ( int x = 0 ; x < w ; ++x ) + { + *destination++ = *sourcemask++ ; + source++ ; + *destination++ = *source++ ; + *destination++ = *source++ ; + *destination++ = *source++ ; + } } + EndRawAccess() ; + DisposeHandle( imagehandle ) ; + DisposeHandle( maskhandle ) ; + created = true ; } - EndRawAccess() ; - DisposeHandle( imagehandle ) ; - DisposeHandle( maskhandle ) ; + DisposeHandle( (Handle) iconFamily ) ; + } - else - { + + if ( !created ) + { wxMemoryDC dc ; dc.SelectObject( *this ) ; dc.DrawIcon( icon , 0 , 0 ) ; @@ -703,7 +809,7 @@ void* wxBitmap::GetRawAccess() const return M_BITMAPDATA->GetRawAccess() ; } -void* wxBitmap::BeginRawAccess() +void* wxBitmap::BeginRawAccess() { wxCHECK_MSG( Ok() , NULL , wxT("invalid bitmap") ) ; return M_BITMAPDATA->BeginRawAccess() ; @@ -717,15 +823,19 @@ void wxBitmap::EndRawAccess() bool wxBitmap::CreateFromXpm(const char **bits) { - wxCHECK_MSG( bits != NULL, FALSE, wxT("invalid bitmap data") ) +#if wxUSE_IMAGE + 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") ) + wxCHECK_MSG( img.Ok(), false, wxT("invalid bitmap data") ) *this = wxBitmap(img); - return TRUE; + return true; +#else + return false; +#endif } -#if wxMAC_USE_CORE_GRAPHICS +#ifdef __WXMAC_OSX__ WXCGIMAGEREF wxBitmap::CGImageCreate() const { wxCHECK_MSG( Ok(), NULL , wxT("invalid bitmap") ) ; @@ -762,7 +872,7 @@ wxBitmap wxBitmap::GetSubBitmap(const wxRect &rect) const } } ret.EndRawAccess() ; - + if ( M_BITMAPDATA->m_bitmapMask ) { wxMemoryBuffer maskbuf ; @@ -815,11 +925,13 @@ bool wxBitmap::LoadFile(const wxString& filename, wxBitmapType type) } else { +#if wxUSE_IMAGE wxImage loadimage(filename, type); if (loadimage.Ok()) { *this = loadimage; return true; } +#endif } wxLogWarning(wxT("no bitmap handler for type %d defined."), type); return false; @@ -836,12 +948,14 @@ bool wxBitmap::Create(void *data, wxBitmapType type, int width, int height, int if ( handler == NULL ) { wxLogWarning(wxT("no bitmap handler for type %d defined."), type); - return FALSE; + return false; } return handler->Create(this, data, type, width, height, depth); } +#if wxUSE_IMAGE + wxBitmap::wxBitmap(const wxImage& image, int depth) { wxCHECK_RET( image.Ok(), wxT("invalid image") ) @@ -850,12 +964,12 @@ wxBitmap::wxBitmap(const wxImage& image, int depth) int width = image.GetWidth(); int height = image.GetHeight(); - m_refData = new wxBitmapRefData( width , height , depth ) ;; + m_refData = new wxBitmapRefData( width , height , depth ) ; // Create picture bool hasAlpha = false ; - + if ( image.HasMask() ) { // takes precedence, don't mix with alpha info @@ -864,10 +978,10 @@ wxBitmap::wxBitmap(const wxImage& image, int depth) { hasAlpha = image.HasAlpha() ; } - + if ( hasAlpha ) UseAlpha() ; - + unsigned char* destination = (unsigned char*) BeginRawAccess() ; register unsigned char* data = image.GetData(); @@ -924,6 +1038,7 @@ wxImage wxBitmap::ConvertToImage() const bool hasAlpha = false ; bool hasMask = false ; + int maskBytesPerRow = 0 ; unsigned char *alpha = NULL ; unsigned char *mask = NULL ; if ( HasAlpha() ) @@ -935,6 +1050,7 @@ wxImage wxBitmap::ConvertToImage() const { hasMask = true ; mask = (unsigned char*) GetMask()->GetRawAccess() ; + maskBytesPerRow = GetMask()->GetBytesPerRow() ; } if ( hasAlpha ) @@ -943,7 +1059,7 @@ wxImage wxBitmap::ConvertToImage() const alpha = image.GetAlpha() ; } int index = 0; - + // The following masking algorithm is the same as well in msw/gtk: // the colour used as transparent one in wxImage and the one it is // replaced with when it really occurs in the bitmap @@ -952,8 +1068,9 @@ wxImage wxBitmap::ConvertToImage() const static const int MASK_BLUE = 3; static const int MASK_BLUE_REPLACEMENT = 2; - for (int yy = 0; yy < height; yy++) + for (int yy = 0; yy < height; yy++ , mask += maskBytesPerRow ) { + unsigned char * maskp = mask ; for (int xx = 0; xx < width; xx++) { long color = *((long*) source) ; @@ -963,17 +1080,14 @@ wxImage wxBitmap::ConvertToImage() const unsigned char b = (color&0x000000FF); if ( hasMask ) { - if ( *mask++ == 0 ) + if ( *maskp++ == 0 ) { - if ( r == MASK_RED && g == MASK_GREEN && b == MASK_BLUE ) - b = MASK_BLUE_REPLACEMENT ; - else - { - r = MASK_RED ; - g = MASK_GREEN ; - b = MASK_BLUE ; - } + r = MASK_RED ; + g = MASK_GREEN ; + b = MASK_BLUE ; } + else if ( r == MASK_RED && g == MASK_GREEN && b == MASK_BLUE ) + b = MASK_BLUE_REPLACEMENT ; } else if ( hasAlpha ) *alpha++ = a ; @@ -990,25 +1104,29 @@ wxImage wxBitmap::ConvertToImage() const return image; } +#endif //wxUSE_IMAGE bool wxBitmap::SaveFile(const wxString& filename, wxBitmapType type, const wxPalette *palette) const { + bool success = false; wxBitmapHandler *handler = FindHandler(type); if ( handler ) { - return handler->SaveFile(this, filename, type, palette); + success = handler->SaveFile(this, filename, type, palette); } else { +#if wxUSE_IMAGE wxImage image = ConvertToImage(); - - return image.SaveFile(filename, type); + success = image.SaveFile(filename, type); +#else + wxLogWarning(wxT("no bitmap handler for type %d defined."), type); +#endif } - wxLogWarning(wxT("no bitmap handler for type %d defined."), type); - return false; + return success; } bool wxBitmap::Ok() const @@ -1173,7 +1291,7 @@ wxMask::~wxMask() } } -void wxMask::Init() +void wxMask::Init() { m_width = m_height = m_bytesPerRow = 0 ; m_maskBitmap = NULL ; @@ -1184,7 +1302,10 @@ void *wxMask::GetRawAccess() const return m_memBuf.GetData() ; } -void wxMask::RealizeNative() +// this can be a k8IndexedGrayPixelFormat GWorld, because it never stores other values than black or white +// so no rainbox colors will be created by QD when blitting + +void wxMask::RealizeNative() { if ( m_maskBitmap ) { @@ -1193,7 +1314,7 @@ void wxMask::RealizeNative() } Rect rect = { 0 , 0 , m_height , m_width } ; verify_noerr( NewGWorldFromPtr( (GWorldPtr*) &m_maskBitmap , k8IndexedGrayPixelFormat , &rect , NULL , NULL , 0 , - (char*) m_memBuf.GetData() , m_bytesPerRow ) ) ; + (char*) m_memBuf.GetData() , m_bytesPerRow ) ) ; } // Create a mask from a mono bitmap (copies the bitmap). @@ -1235,7 +1356,7 @@ bool wxMask::Create(const wxBitmap& bitmap) } m_memBuf.UngetWriteBuf( size ) ; RealizeNative() ; - return TRUE; + return true; } // Create a mask from a bitmap and a colour indicating @@ -1267,7 +1388,7 @@ bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour) } m_memBuf.UngetWriteBuf( size ) ; RealizeNative() ; - return TRUE; + return true; } WXHBITMAP wxMask::GetHBITMAP() const @@ -1285,18 +1406,18 @@ wxBitmapHandler::~wxBitmapHandler() bool wxBitmapHandler::Create(wxBitmap *bitmap, void *data, long type, int width, int height, int depth) { - return FALSE; + return false; } bool wxBitmapHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags, int desiredWidth, int desiredHeight) { - return FALSE; + return false; } bool wxBitmapHandler::SaveFile(const wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette) { - return FALSE; + return false; } // ---------------------------------------------------------------------------- @@ -1337,10 +1458,10 @@ bool wxPICTResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, lo dc.SelectObject( *bitmap ) ; mf.Play( &dc ) ; dc.SelectObject( wxNullBitmap ) ; - return TRUE ; + return true ; } #endif //wxUSE_METAFILE - return FALSE ; + return false ; }