]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/gifdecod.cpp
fix wxDataObjectComposite::GetFormatCount and add some comments to explain the reason...
[wxWidgets.git] / src / common / gifdecod.cpp
index 5437982d7bd9b0d95a686fed617c6e4df237f380..1566f40bddff71423b3fbc74a9f67e6735bfec01 100644 (file)
@@ -24,6 +24,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include "wx/gifdecod.h"
 #include <stdlib.h>
 #include <string.h>
 #include "wx/gifdecod.h"
+#include "wx/scopedptr.h"
+#include "wx/scopeguard.h"
 
 
 
 
 
 
@@ -49,9 +51,11 @@ public:
     unsigned char *pal;             // palette
     unsigned int ncolours;          // number of colours
 
     unsigned char *pal;             // palette
     unsigned int ncolours;          // number of colours
 
-    DECLARE_NO_COPY_CLASS(GIFImage)
+    wxDECLARE_NO_COPY_CLASS(GIFImage);
 };
 
 };
 
+wxDECLARE_SCOPED_PTR(GIFImage, GIFImagePtr)
+wxDEFINE_SCOPED_PTR(GIFImage, GIFImagePtr)
 
 
 //---------------------------------------------------------------------------
 
 
 //---------------------------------------------------------------------------
@@ -118,6 +122,7 @@ bool wxGIFDecoder::ConvertToImage(unsigned int frame, wxImage *image) const
     // create the image
     wxSize sz = GetFrameSize(frame);
     image->Create(sz.GetWidth(), sz.GetHeight());
     // create the image
     wxSize sz = GetFrameSize(frame);
     image->Create(sz.GetWidth(), sz.GetHeight());
+    image->SetType(wxBITMAP_TYPE_GIF);
 
     if (!image->Ok())
         return false;
 
     if (!image->Ok())
         return false;
@@ -186,7 +191,7 @@ bool wxGIFDecoder::ConvertToImage(unsigned int frame, wxImage *image) const
 
 // Get data for current frame
 
 
 // Get data for current frame
 
-wxSize wxGIFDecoder::GetFrameSize(unsigned int frame) const 
+wxSize wxGIFDecoder::GetFrameSize(unsigned int frame) const
 {
     return wxSize(GetFrame(frame)->w, GetFrame(frame)->h);
 }
 {
     return wxSize(GetFrame(frame)->w, GetFrame(frame)->h);
 }
@@ -575,7 +580,8 @@ bool wxGIFDecoder::CanRead(wxInputStream &stream) const
     if ( !stream.Read(buf, WXSIZEOF(buf)) )
         return false;
 
     if ( !stream.Read(buf, WXSIZEOF(buf)) )
         return false;
 
-    stream.SeekI(-(wxFileOffset)WXSIZEOF(buf), wxFromCurrent);
+    if (stream.SeekI(-(wxFileOffset)WXSIZEOF(buf), wxFromCurrent) == wxInvalidOffset)
+        return false;       // this happens e.g. for non-seekable streams
 
     return memcmp(buf, "GIF", WXSIZEOF(buf)) == 0;
 }
 
     return memcmp(buf, "GIF", WXSIZEOF(buf)) == 0;
 }
@@ -593,7 +599,7 @@ bool wxGIFDecoder::CanRead(wxInputStream &stream) const
 wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream)
 {
     unsigned int  global_ncolors = 0;
 wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream)
 {
     unsigned int  global_ncolors = 0;
-    int           bits, interl, transparent, i;
+    int           bits, interl, i;
     wxAnimationDisposal disposal;
     long          size;
     long          delay;
     wxAnimationDisposal disposal;
     long          size;
     long          delay;
@@ -655,7 +661,7 @@ wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream)
     }
 
     // transparent colour, disposal method and delay default to unused
     }
 
     // transparent colour, disposal method and delay default to unused
-    transparent = -1;
+    int transparent = -1;
     disposal = wxANIM_UNSPECIFIED;
     delay = -1;
 
     disposal = wxANIM_UNSPECIFIED;
     delay = -1;
 
@@ -705,8 +711,7 @@ wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream)
                 delay = 10 * (buf[2] + 256 * buf[3]);
 
                 // read transparent colour index, if used
                 delay = 10 * (buf[2] + 256 * buf[3]);
 
                 // read transparent colour index, if used
-                if (buf[1] & 0x01)
-                    transparent = buf[4];
+                transparent = buf[1] & 0x01 ? buf[4] : -1;
 
                 // read disposal method
                 disposal = (wxAnimationDisposal)(((buf[1] & 0x1C) >> 2) - 1);
 
                 // read disposal method
                 disposal = (wxAnimationDisposal)(((buf[1] & 0x1C) >> 2) - 1);
@@ -716,12 +721,12 @@ wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream)
             {
                 while ((i = (unsigned char)stream.GetC()) != 0)
                 {
             {
                 while ((i = (unsigned char)stream.GetC()) != 0)
                 {
-                    if (stream.Eof() || (stream.LastRead() == 0))
+                    if (stream.Eof() || (stream.LastRead() == 0) ||
+                        stream.SeekI(i, wxFromCurrent) == wxInvalidOffset)
                     {
                         done = true;
                         break;
                     }
                     {
                         done = true;
                         break;
                     }
-                    stream.SeekI(i, wxFromCurrent);
                 }
             }
         }
                 }
             }
         }
@@ -730,22 +735,18 @@ wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream)
         if (type == 0x2C)
         {
             // allocate memory for IMAGEN struct
         if (type == 0x2C)
         {
             // allocate memory for IMAGEN struct
-            GIFImage *pimg = new GIFImage();
+            GIFImagePtr pimg(new GIFImage());
 
 
-            if (pimg == NULL)
-            {
-                Destroy();
+            wxScopeGuard guardDestroy = wxMakeObjGuard(*this, &wxGIFDecoder::Destroy);
+
+            if ( !pimg.get() )
                 return wxGIF_MEMERR;
                 return wxGIF_MEMERR;
-            }
 
             // fill in the data
             static const unsigned int idbSize = (2 + 2 + 2 + 2 + 1);
             stream.Read(buf, idbSize);
             if (stream.LastRead() != idbSize)
 
             // fill in the data
             static const unsigned int idbSize = (2 + 2 + 2 + 2 + 1);
             stream.Read(buf, idbSize);
             if (stream.LastRead() != idbSize)
-            {
-                Destroy();
                 return wxGIF_INVFORMAT;
                 return wxGIF_INVFORMAT;
-            }
 
             pimg->left = buf[0] + 256 * buf[1];
             pimg->top = buf[2] + 256 * buf[3];
 
             pimg->left = buf[0] + 256 * buf[1];
             pimg->top = buf[2] + 256 * buf[3];
@@ -756,12 +757,9 @@ wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream)
             pimg->w = buf[4] + 256 * buf[5];
             pimg->h = buf[6] + 256 * buf[7];
 
             pimg->w = buf[4] + 256 * buf[5];
             pimg->h = buf[6] + 256 * buf[7];
 
-            if (anim && ((pimg->w == 0) || (pimg->w > (unsigned int)m_szAnimation.GetWidth()) || 
-                        (pimg->h == 0) || (pimg->h > (unsigned int)m_szAnimation.GetHeight())))
-            {
-                Destroy();
+            if ( anim && ((pimg->w == 0) || (pimg->w > (unsigned int)m_szAnimation.GetWidth()) ||
+                  (pimg->h == 0) || (pimg->h > (unsigned int)m_szAnimation.GetHeight())) )
                 return wxGIF_INVFORMAT;
                 return wxGIF_INVFORMAT;
-            }
 
             interl = ((buf[8] & 0x40)? 1 : 0);
             size = pimg->w * pimg->h;
 
             interl = ((buf[8] & 0x40)? 1 : 0);
             size = pimg->w * pimg->h;
@@ -775,10 +773,7 @@ wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream)
             pimg->pal = (unsigned char *) malloc(768);
 
             if ((!pimg->p) || (!pimg->pal))
             pimg->pal = (unsigned char *) malloc(768);
 
             if ((!pimg->p) || (!pimg->pal))
-            {
-                Destroy();
                 return wxGIF_MEMERR;
                 return wxGIF_MEMERR;
-            }
 
             // load local color map if available, else use global map
             if ((buf[8] & 0x80) == 0x80)
 
             // load local color map if available, else use global map
             if ((buf[8] & 0x80) == 0x80)
@@ -788,10 +783,7 @@ wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream)
                 stream.Read(pimg->pal, numBytes);
                 pimg->ncolours = local_ncolors;
                 if (stream.LastRead() != numBytes)
                 stream.Read(pimg->pal, numBytes);
                 pimg->ncolours = local_ncolors;
                 if (stream.LastRead() != numBytes)
-                {
-                    Destroy();
                     return wxGIF_INVFORMAT;
                     return wxGIF_INVFORMAT;
-                }
             }
             else
             {
             }
             else
             {
@@ -802,21 +794,17 @@ wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream)
             // get initial code size from first byte in raster data
             bits = (unsigned char)stream.GetC();
             if (bits == 0)
             // get initial code size from first byte in raster data
             bits = (unsigned char)stream.GetC();
             if (bits == 0)
-            {
-                Destroy();
                 return wxGIF_INVFORMAT;
                 return wxGIF_INVFORMAT;
-            }
 
             // decode image
 
             // decode image
-            wxGIFErrorCode result = dgif(stream, pimg, interl, bits);
+            wxGIFErrorCode result = dgif(stream, pimg.get(), interl, bits);
             if (result != wxGIF_OK)
             if (result != wxGIF_OK)
-            {
-                Destroy();
                 return result;
                 return result;
-            }
+
+            guardDestroy.Dismiss();
 
             // add the image to our frame array
 
             // add the image to our frame array
-            m_frames.Add((void*)pimg);
+            m_frames.Add(pimg.release());
             m_nFrames++;
 
             // if this is not an animated GIF, exit after first image
             m_nFrames++;
 
             // if this is not an animated GIF, exit after first image
@@ -847,12 +835,12 @@ wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream)
             // skip all data
             while ((i = (unsigned char)stream.GetC()) != 0)
             {
             // skip all data
             while ((i = (unsigned char)stream.GetC()) != 0)
             {
-                if (stream.Eof() || (stream.LastRead() == 0))
+                if (stream.Eof() || (stream.LastRead() == 0) ||
+                    stream.SeekI(i, wxFromCurrent) == wxInvalidOffset)
                 {
                     Destroy();
                     return wxGIF_INVFORMAT;
                 }
                 {
                     Destroy();
                     return wxGIF_INVFORMAT;
                 }
-                stream.SeekI(i, wxFromCurrent);
             }
         }
         else if (type == 0x2C)
             }
         }
         else if (type == 0x2C)
@@ -871,7 +859,11 @@ wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream)
             {
                 unsigned int local_ncolors = 2 << (buf[8] & 0x07);
                 wxFileOffset numBytes = 3 * local_ncolors;
             {
                 unsigned int local_ncolors = 2 << (buf[8] & 0x07);
                 wxFileOffset numBytes = 3 * local_ncolors;
-                stream.SeekI(numBytes, wxFromCurrent);
+                if (stream.SeekI(numBytes, wxFromCurrent) == wxInvalidOffset)
+                {
+                    Destroy();
+                    return wxGIF_INVFORMAT;
+                }
             }
 
             // initial code size
             }
 
             // initial code size
@@ -885,12 +877,12 @@ wxGIFErrorCode wxGIFDecoder::LoadGIF(wxInputStream& stream)
             // skip all data
             while ((i = (unsigned char)stream.GetC()) != 0)
             {
             // skip all data
             while ((i = (unsigned char)stream.GetC()) != 0)
             {
-                if (stream.Eof() || (stream.LastRead() == 0))
+                if (stream.Eof() || (stream.LastRead() == 0) ||
+                    stream.SeekI(i, wxFromCurrent) == wxInvalidOffset)
                 {
                     Destroy();
                     return wxGIF_INVFORMAT;
                 }
                 {
                     Destroy();
                     return wxGIF_INVFORMAT;
                 }
-                stream.SeekI(i, wxFromCurrent);
             }
         }
         else if ((type != 0x3B) && (type != 00)) // testing
             }
         }
         else if ((type != 0x3B) && (type != 00)) // testing