]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/carbon/bitmap.cpp
Commit patch [ 1559950 ] fix mem leaks in wx{Dir|File}Dialog
[wxWidgets.git] / src / mac / carbon / bitmap.cpp
index afc06f96ef090fba7d9b2b512899fdfe8678268f..4b2a1526b4aa3b4a7c4ab56bfa354e1f6dfee6d4 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        bitmap.cpp
+// Name:        src/mac/carbon/bitmap.cpp
 // Purpose:     wxBitmap
 // Author:      Stefan Csomor
 // Modified by:
 #include "wx/wxprec.h"
 
 #include "wx/bitmap.h"
-#include "wx/icon.h"
-#include "wx/log.h"
-#include "wx/image.h"
+
+#ifndef WX_PRECOMP
+    #include "wx/log.h"
+    #include "wx/dcmemory.h"
+    #include "wx/icon.h"
+    #include "wx/image.h"
+#endif
+
 #include "wx/metafile.h"
 #include "wx/xpmdecod.h"
 
@@ -31,7 +36,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
 #endif
 
 #include "wx/mac/uma.h"
-#include "wx/dcmemory.h"
 
 // Implementation Notes
 // --------------------
@@ -161,8 +165,8 @@ wxBitmapRefData::wxBitmapRefData( int w , int h , int d )
 
 bool wxBitmapRefData::Create( int w , int h , int d )
 {
-    m_width = w ;
-    m_height = ;
+    m_width = wxMax(1, w);
+    m_height = wxMax(1, h);
     m_depth = d ;
 
     m_bytesPerRow = w * 4 ;
@@ -363,7 +367,12 @@ IconRef wxBitmapRefData::GetIconRef()
                     *dest++ = b ;
 
                     if ( mask )
-                        *maskdest++ = *masksource++ ;
+                    {
+                        *maskdest++ = 0xFF - *masksource++ ;
+                        masksource++ ;
+                        masksource++ ;
+                        masksource++ ;
+                    }
                     else if ( hasAlpha )
                         *maskdest++ = a ;
                     else
@@ -387,9 +396,14 @@ IconRef wxBitmapRefData::GetIconRef()
             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 ) ;
@@ -398,8 +412,9 @@ IconRef wxBitmapRefData::GetIconRef()
         // we have to retain a reference, as Unregister will decrement it
         AcquireIconRef( m_iconRef ) ;
         UnregisterIconRef( 'WXNG' , (OSType) iconCounter ) ;
-        DisposeHandle( (Handle) iconFamily ) ;
         ++iconCounter ;
+#endif
+        DisposeHandle( (Handle) iconFamily ) ;
     }
 
     return m_iconRef ;
@@ -518,9 +533,9 @@ CGImageRef wxBitmapRefData::CGImageCreate() const
             for ( int y = 0 ; y < h ; ++y , sourcemaskstart += maskrowbytes)
             {
                 unsigned char *sourcemask = sourcemaskstart ;
-                for ( int x = 0 ; x < w ; ++x , sourcemask++ , destalpha += 4 )
+                for ( int x = 0 ; x < w ; ++x , sourcemask += 4 , destalpha += 4 )
                 {
-                    *destalpha = *sourcemask ;
+                    *destalpha = 0xFF - *sourcemask ;
                 }
             }
         }
@@ -797,7 +812,7 @@ wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits
                 bit = x % 8 ;
                 mask = 1 << bit ;
 
-                if ( linestart[index] & mask )
+                if ( !(linestart[index] & mask ) )
                 {
                     *destination++ = 0xFF ;
                     *destination++ = 0 ;
@@ -871,11 +886,11 @@ void wxBitmap::EndRawAccess()
 bool wxBitmap::CreateFromXpm(const char **bits)
 {
 #if wxUSE_IMAGE
-    wxCHECK_MSG( bits != NULL, false, wxT("invalid bitmap data") )
+    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);
 
@@ -931,17 +946,17 @@ wxBitmap wxBitmap::GetSubBitmap(const wxRect &rect) const
     if ( M_BITMAPDATA->m_bitmapMask )
     {
         wxMemoryBuffer maskbuf ;
-        int rowBytes = ( destwidth + 3 ) & 0xFFFFFFC ;
+        int rowBytes = ( destwidth * 4 + 3 ) & 0xFFFFFFC ;
         size_t maskbufsize = rowBytes * destheight ;
 
-        int sourcelinesize = M_BITMAPDATA->m_bitmapMask->GetBytesPerRow()  ;
+        int sourcelinesize = M_BITMAPDATA->m_bitmapMask->GetBytesPerRow() ;
         int destlinesize = rowBytes ;
 
         unsigned char *source = (unsigned char *) M_BITMAPDATA->m_bitmapMask->GetRawAccess() ;
         unsigned char *destdata = (unsigned char * ) maskbuf.GetWriteBuf( maskbufsize ) ;
         wxASSERT( (source != NULL) && (destdata != NULL) ) ;
 
-        source += rect.x + rect.y * sourcelinesize ;
+        source += rect.x * 4 + rect.y * sourcelinesize ;
         unsigned char *dest = destdata ;
 
         for (int yy = 0; yy < destheight; ++yy, source += sourcelinesize , dest += destlinesize)
@@ -1022,7 +1037,7 @@ bool wxBitmap::Create(void *data, wxBitmapType type, int width, int height, int
 
 wxBitmap::wxBitmap(const wxImage& image, int depth)
 {
-    wxCHECK_RET( image.Ok(), wxT("invalid image") )
+    wxCHECK_RET( image.Ok(), wxT("invalid image") );
 
     // width and height of the device-dependent bitmap
     int width = image.GetWidth();
@@ -1126,7 +1141,7 @@ wxImage wxBitmap::ConvertToImage() const
 
     // 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
+    // replaced with when it actually occurs in the bitmap
     static const int MASK_RED = 1;
     static const int MASK_GREEN = 2;
     static const int MASK_BLUE = 3;
@@ -1141,14 +1156,20 @@ wxImage wxBitmap::ConvertToImage() const
         for (int xx = 0; xx < width; xx++)
         {
             color = *((long*) source) ;
+#ifdef WORDS_BIGENDIAN
             a = ((color&0xFF000000) >> 24) ;
             r = ((color&0x00FF0000) >> 16) ;
             g = ((color&0x0000FF00) >> 8) ;
             b = (color&0x000000FF);
-
+#else
+            b = ((color&0xFF000000) >> 24) ;
+            g = ((color&0x00FF0000) >> 16) ;
+            r = ((color&0x0000FF00) >> 8) ;
+            a = (color&0x000000FF);
+#endif
             if ( hasMask )
             {
-                if ( *maskp++ == 0 )
+                if ( *maskp++ == 0xFF )
                 {
                     r = MASK_RED ;
                     g = MASK_GREEN ;
@@ -1156,6 +1177,10 @@ wxImage wxBitmap::ConvertToImage() const
                 }
                 else if ( r == MASK_RED && g == MASK_GREEN && b == MASK_BLUE )
                     b = MASK_BLUE_REPLACEMENT ;
+
+                maskp++ ;
+                maskp++ ;
+                maskp++ ;
             }
             else if ( hasAlpha )
                 *alpha++ = a ;
@@ -1177,8 +1202,8 @@ wxImage wxBitmap::ConvertToImage() const
 
 #endif //wxUSE_IMAGE
 
-bool wxBitmap::SaveFile(const wxString& filename, wxBitmapType type,
-                        const wxPalette *palette) const
+bool wxBitmap::SaveFile( const wxString& filename,
+    wxBitmapType type, const wxPalette *palette ) const
 {
     bool success = false;
     wxBitmapHandler *handler = FindHandler(type);
@@ -1327,31 +1352,32 @@ wxMask::wxMask()
 
 // Construct a mask from a bitmap and a colour indicating
 // the transparent area
-wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
+wxMask::wxMask( const wxBitmap& bitmap, const wxColour& colour )
 {
     Init() ;
-    Create(bitmap, colour);
+    Create( bitmap, colour );
 }
 
 // Construct a mask from a mono bitmap (copies the bitmap).
-wxMask::wxMask(const wxBitmap& bitmap)
+wxMask::wxMask( const wxBitmap& bitmap )
 {
     Init() ;
-    Create(bitmap);
+    Create( bitmap );
 }
 
 // Construct a mask from a mono bitmap (copies the bitmap).
+
 wxMask::wxMask( const wxMemoryBuffer& data, int width , int height , int bytesPerRow )
 {
     Init() ;
-    Create(data, width , height , bytesPerRow );
+    Create( data, width , height , bytesPerRow );
 }
 
 wxMask::~wxMask()
 {
     if ( m_maskBitmap )
     {
-        DisposeGWorld( (GWorldPtr) m_maskBitmap ) ;
+        DisposeGWorld( (GWorldPtr)m_maskBitmap ) ;
         m_maskBitmap = NULL ;
     }
 }
@@ -1367,23 +1393,27 @@ 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 QD colorizing will occur when blitting
+// The default ColorTable for k8IndexedGrayPixelFormat in Intel appears to be broken, so we'll use an non-indexed
+// bitmap mask instead; in order to keep the code simple, the change applies to PowerPC implementations as well
 
 void wxMask::RealizeNative()
 {
     if ( m_maskBitmap )
     {
-       DisposeGWorld(  (GWorldPtr) m_maskBitmap ) ;
+       DisposeGWorld( (GWorldPtr)m_maskBitmap ) ;
        m_maskBitmap = NULL ;
     }
 
     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 ) ) ;
+
+    OSStatus err = NewGWorldFromPtr(
+        (GWorldPtr*) &m_maskBitmap , k32ARGBPixelFormat , &rect , NULL , NULL , 0 ,
+        (char*) m_memBuf.GetData() , m_bytesPerRow ) ;
+    verify_noerr( err ) ;
 }
 
 // Create a mask from a mono bitmap (copies the bitmap).
+
 bool wxMask::Create(const wxMemoryBuffer& data,int width , int height , int bytesPerRow)
 {
     m_memBuf = data ;
@@ -1403,7 +1433,7 @@ bool wxMask::Create(const wxBitmap& bitmap)
 {
     m_width = bitmap.GetWidth() ;
     m_height = bitmap.GetHeight() ;
-    m_bytesPerRow = ( m_width + 3 ) & 0xFFFFFFC ;
+    m_bytesPerRow = ( m_width * 4 + 3 ) & 0xFFFFFFC ;
 
     size_t size = m_bytesPerRow * m_height ;
     unsigned char * destdatabase = (unsigned char*) m_memBuf.GetWriteBuf( size ) ;
@@ -1425,9 +1455,19 @@ bool wxMask::Create(const wxBitmap& bitmap)
             b = *srcdata++ ;
 
             if ( ( r + g + b ) > 0x10 )
-                *destdata++ = 0x00 ;
-            else
+            {
                 *destdata++ = 0xFF ;
+                *destdata++ = 0xFF ;
+                *destdata++ = 0xFF ;
+                *destdata++ = 0xFF ;
+            }
+            else
+            {
+                *destdata++ = 0x00 ;
+                *destdata++ = 0x00 ;
+                *destdata++ = 0x00 ;
+                *destdata++ = 0x00 ;
+            }
         }
     }
 
@@ -1443,7 +1483,7 @@ bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
 {
     m_width = bitmap.GetWidth() ;
     m_height = bitmap.GetHeight() ;
-    m_bytesPerRow = ( m_width + 3 ) & 0xFFFFFFC ;
+    m_bytesPerRow = ( m_width * 4 + 3 ) & 0xFFFFFFC ;
 
     size_t size = m_bytesPerRow * m_height ;
     unsigned char * destdatabase = (unsigned char*) m_memBuf.GetWriteBuf( size ) ;
@@ -1464,10 +1504,20 @@ bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
             g = *srcdata++ ;
             b = *srcdata++ ;
 
-            if ( colour == wxColour( r , g , b) )
-                *destdata++ = 0x00 ;
-            else
+            if ( colour == wxColour( r , g , b ) )
+            {
+                *destdata++ = 0xFF ;
+                *destdata++ = 0xFF ;
+                *destdata++ = 0xFF ;
                 *destdata++ = 0xFF ;
+            }
+            else
+            {
+                *destdata++ = 0x00 ;
+                *destdata++ = 0x00 ;
+                *destdata++ = 0x00 ;
+                *destdata++ = 0x00 ;
+            }
         }
     }
 
@@ -1525,6 +1575,7 @@ public:
     virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
           int desiredWidth, int desiredHeight);
 };
+
 IMPLEMENT_DYNAMIC_CLASS(wxPICTResourceHandler, wxBitmapHandler)
 
 
@@ -1539,6 +1590,7 @@ bool wxPICTResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, lon
     if ( thePict )
     {
         wxMetafile mf ;
+
         mf.SetHMETAFILE( (WXHMETAFILE) thePict ) ;
         bitmap->Create( mf.GetWidth() , mf.GetHeight() ) ;
         wxMemoryDC dc ;
@@ -1548,7 +1600,7 @@ bool wxPICTResourceHandler::LoadFile(wxBitmap *bitmap, const wxString& name, lon
 
         return true ;
     }
-#endif //wxUSE_METAFILE
+#endif
 
     return false ;
 }
@@ -1573,53 +1625,12 @@ void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp)
     data.m_height = GetHeight() ;
     data.m_stride = GetWidth() * 4 ;
 
-    return GetRawAccess() ;
+    return BeginRawAccess() ;
 }
 
 void wxBitmap::UngetRawData(wxPixelDataBase& dataBase)
 {
-    if ( !Ok() )
-        return;
-
-    // TODO : if we have some information about the API we should check
-    // this code looks strange...
-
-    if ( !M_BITMAPDATA->HasAlpha() )
-        return;
-
-    wxAlphaPixelData& data = (wxAlphaPixelData&)dataBase;
-    int w = data.GetWidth();
-    int h = data.GetHeight();
-
-    wxBitmap bmpMask( GetWidth(), GetHeight(), 32 );
-    wxAlphaPixelData dataMask( bmpMask, data.GetOrigin(), wxSize( w, h ) );
-    wxAlphaPixelData::Iterator pMask( dataMask ), p( data );
-
-    for ( int y = 0; y < h; y++ )
-    {
-        wxAlphaPixelData::Iterator rowStartMask = pMask;
-        wxAlphaPixelData::Iterator rowStart = p;
-
-        for ( int x = 0; x < w; x++ )
-        {
-            const wxAlphaPixelData::Iterator::ChannelType alpha = p.Alpha();
-
-            pMask.Red() = alpha;
-            pMask.Green() = alpha;
-            pMask.Blue() = alpha;
-
-            ++p;
-            ++pMask;
-        }
-
-        p = rowStart;
-        p.OffsetY( data, 1 );
-
-        pMask = rowStartMask;
-        pMask.OffsetY( dataMask, 1 );
-    }
-
-    SetMask( new wxMask( bmpMask ) );
+    EndRawAccess() ;
 }
 
 void wxBitmap::UseAlpha()