X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/df21986cb7d7d33a8c28a2c60930532a7a53233c..45cf8535da51328702d0cab63636bc13bca4a620:/src/mac/carbon/bitmap.cpp?ds=sidebyside diff --git a/src/mac/carbon/bitmap.cpp b/src/mac/carbon/bitmap.cpp index 28c71c4336..24cb80549f 100644 --- a/src/mac/carbon/bitmap.cpp +++ b/src/mac/carbon/bitmap.cpp @@ -51,188 +51,52 @@ IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject ) // we don't dare premultiplied alpha yet #define wxMAC_USE_PREMULTIPLIED_ALPHA 0 -IconFamilyHandle wxMacCreateIconFamily(const wxBitmap& bmp) -{ - // 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 ) ; - if ( sz > 128 ) - { - wxFAIL_MSG( wxT("Currently only 128 pixels wide images are supported") ) ; - } - - Handle data = NULL ; - Handle maskdata = NULL ; - unsigned char * maskptr = NULL ; - unsigned char * ptr = NULL ; - size_t size ; - size_t masksize ; - OSType dataType ; - OSType maskType ; - - bool hasAlpha = bmp.HasAlpha() ; - wxMask *mask = bmp.GetMask() ; - // thumbnail is 128 x 128 with 32 bits per pixel - - if ( sz > 48 ) - { - sz = 128 ; - dataType = kThumbnail32BitData ; - maskType = kThumbnail8BitMask ; - } - else if ( sz > 32 ) - { - sz = 48 ; - dataType = kHuge32BitData ; - maskType = kHuge8BitMask ; - } - else if ( sz > 16 ) - { - sz = 32 ; - dataType = kLarge32BitData ; - maskType = kLarge8BitMask ; - } - else - { - sz = 16 ; - dataType = kSmall32BitData ; - maskType = kSmall8BitMask ; - } - - 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 ) ; - - 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 ) ; - 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; -} - 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 ) ; - + + 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 - /* - // only on 10.4 more controls will accept a CGImage - + else if ( forceType == kControlContentCGImageRef ) + { info->contentType = kControlContentCGImageRef ; info->u.imageRef = (CGImageRef) bmap->CGImageCreate() ; - */ + } #endif + else + { + info->contentType = kControlContentPictHandle ; + info->u.picture = bmap->GetPictHandle() ; + } } } @@ -240,7 +104,11 @@ void wxMacReleaseBitmapButton( ControlButtonContentInfo*info ) { if ( info->contentType == kControlContentIconRef ) { - ReleaseIconRef(info->u.iconRef) ; + ReleaseIconRef( info->u.iconRef ) ; + } + 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 ) @@ -254,6 +122,7 @@ void wxMacReleaseBitmapButton( ControlButtonContentInfo*info ) } } +#define M_BITMAPDATA ((wxBitmapRefData *)m_refData) void wxBitmapRefData::Init() { @@ -265,6 +134,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 ; @@ -316,13 +187,13 @@ void wxBitmapRefData::UseAlpha( bool use ) { 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 , + 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) ; @@ -349,9 +220,11 @@ 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 ) ; @@ -371,6 +244,215 @@ void wxBitmapRefData::EndRawAccess() #endif } +bool wxBitmapRefData::HasNativeSize() +{ + int w = GetWidth() ; + int h = GetHeight() ; + int sz = wxMax( w , h ) ; + + 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 ; + + iconFamily = (IconFamilyHandle) NewHandle(8) ; + (**iconFamily).resourceType = kIconFamilyType ; + (**iconFamily).resourceSize = sizeof(OSType) + sizeof(Size); + + 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 + { + iconFamily = (IconFamilyHandle) NewHandle(8) ; + (**iconFamily).resourceType = kIconFamilyType ; + (**iconFamily).resourceSize = sizeof(OSType) + sizeof(Size); + PicHandle pic = GetPictHandle() ; + SetIconFamilyData( iconFamily, 'PICT' , (Handle) pic ) ; + } + + // transform into IconRef + + 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 ) ; + 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 ; +} #if wxMAC_USE_CORE_GRAPHICS void wxMacMemoryBufferReleaseProc(void *info, const void *data, size_t size) @@ -485,9 +567,13 @@ void wxBitmapRefData::UpdateAlphaMask() const 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 ; } } } @@ -504,6 +590,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) ) ; @@ -531,17 +627,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 ; - OSType dataType ; - IconSelectorValue selector ; + OSType maskType = 0; + OSType dataType = 0; + IconSelectorValue selector = 0 ; if ( w == 128 ) { dataType = kThumbnail32BitData ; @@ -566,39 +666,44 @@ 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 ) ; } - EndRawAccess() ; - DisposeHandle( imagehandle ) ; - DisposeHandle( maskhandle ) ; + DisposeHandle( (Handle) iconFamily ) ; + } - else + + if ( !created ) { wxMemoryDC dc ; dc.SelectObject( *this ) ; @@ -954,12 +1059,12 @@ wxImage wxBitmap::ConvertToImage() const { if ( r == MASK_RED && g == MASK_GREEN && b == MASK_BLUE ) b = MASK_BLUE_REPLACEMENT ; - } - else - { - r = MASK_RED ; - g = MASK_GREEN ; - b = MASK_BLUE ; + else + { + r = MASK_RED ; + g = MASK_GREEN ; + b = MASK_BLUE ; + } } } else if ( hasAlpha ) @@ -1024,11 +1129,15 @@ int wxBitmap::GetDepth() const return M_BITMAPDATA->GetDepth(); } +#if WXWIN_COMPATIBILITY_2_4 + int wxBitmap::GetQuality() const { return 0; } +#endif + wxMask *wxBitmap::GetMask() const { wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") ); @@ -1067,10 +1176,14 @@ void wxBitmap::SetDepth(int d) M_BITMAPDATA->SetDepth(d); } +#if WXWIN_COMPATIBILITY_2_4 + void wxBitmap::SetQuality(int WXUNUSED(quality)) { } +#endif + void wxBitmap::SetOk(bool isOk) { if (!M_BITMAPDATA) @@ -1163,6 +1276,9 @@ void *wxMask::GetRawAccess() const return m_memBuf.GetData() ; } +// 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 ) @@ -1298,9 +1414,11 @@ public: }; IMPLEMENT_DYNAMIC_CLASS(wxPICTResourceHandler, wxBitmapHandler) + bool wxPICTResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags, int desiredWidth, int desiredHeight) { +#if wxUSE_METAFILE Str255 theName ; wxMacStringToPascal( name , theName ) ; @@ -1316,9 +1434,11 @@ bool wxPICTResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, lo dc.SelectObject( wxNullBitmap ) ; return TRUE ; } +#endif //wxUSE_METAFILE return FALSE ; } + void wxBitmap::InitStandardHandlers() { AddHandler(new wxPICTResourceHandler) ;