X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/72045d5768a126191a907bc640c28e81a11afdd6..769c3372a2bd68c45d1a4afc8462d3b7939decb1:/src/common/anidecod.cpp diff --git a/src/common/anidecod.cpp b/src/common/anidecod.cpp index 61cfb664d5..d0d0b6d75b 100644 --- a/src/common/anidecod.cpp +++ b/src/common/anidecod.cpp @@ -14,7 +14,9 @@ #pragma hdrstop #endif -#if wxUSE_STREAMS && wxUSE_GIF +#if wxUSE_STREAMS && wxUSE_ICO_CUR + +#include "wx/anidecod.h" #ifndef WX_PRECOMP #include "wx/palette.h" @@ -22,13 +24,10 @@ #include #include -#include "wx/anidecod.h" // static wxCURHandler wxANIDecoder::sm_handler; - - //--------------------------------------------------------------------------- // wxANIFrameInfo //--------------------------------------------------------------------------- @@ -36,20 +35,18 @@ wxCURHandler wxANIDecoder::sm_handler; class wxANIFrameInfo { public: - wxANIFrameInfo(size_t delay = 0, int idx = -1) + wxANIFrameInfo(unsigned int delay = 0, int idx = -1) { m_delay=delay; m_imageIndex=idx; } - size_t m_delay; + unsigned int m_delay; int m_imageIndex; }; -#include // this is a magic incantation which must be done! -WX_DEFINE_OBJARRAY(wxImageArray); - -#include // this is a magic incantation which must be done! -WX_DEFINE_OBJARRAY(wxANIFrameInfoArray); - +#include "wx/arrimpl.cpp" // this is a magic incantation which must be done! +WX_DEFINE_OBJARRAY(wxImageArray) +#include "wx/arrimpl.cpp" // this is a magic incantation which must be done! +WX_DEFINE_OBJARRAY(wxANIFrameInfoArray) //--------------------------------------------------------------------------- @@ -64,11 +61,11 @@ wxANIDecoder::~wxANIDecoder() { } -bool wxANIDecoder::ConvertToImage(size_t frame, wxImage *image) const +bool wxANIDecoder::ConvertToImage(unsigned int frame, wxImage *image) const { - size_t idx = m_info[frame].m_imageIndex; + unsigned int idx = m_info[frame].m_imageIndex; *image = m_images[idx]; // copy - return image->Ok(); + return image->IsOk(); } @@ -76,38 +73,50 @@ bool wxANIDecoder::ConvertToImage(size_t frame, wxImage *image) const // Data accessors //--------------------------------------------------------------------------- -wxSize wxANIDecoder::GetFrameSize(size_t WXUNUSED(frame)) const +wxSize wxANIDecoder::GetFrameSize(unsigned int WXUNUSED(frame)) const { // all frames are of the same size... return m_szAnimation; } -wxPoint wxANIDecoder::GetFramePosition(size_t WXUNUSED(frame)) const +wxPoint wxANIDecoder::GetFramePosition(unsigned int WXUNUSED(frame)) const { // all frames are of the same size... return wxPoint(0,0); } -wxAnimationDisposal wxANIDecoder::GetDisposalMethod(size_t WXUNUSED(frame)) const +wxAnimationDisposal wxANIDecoder::GetDisposalMethod(unsigned int WXUNUSED(frame)) const { // this disposal is implicit for all frames inside an ANI file return wxANIM_TOBACKGROUND; } -long wxANIDecoder::GetDelay(size_t frame) const +long wxANIDecoder::GetDelay(unsigned int frame) const { return m_info[frame].m_delay; } +wxColour wxANIDecoder::GetTransparentColour(unsigned int frame) const +{ + unsigned int idx = m_info[frame].m_imageIndex; + + if (!m_images[idx].HasMask()) + return wxNullColour; + + return wxColour(m_images[idx].GetMaskRed(), + m_images[idx].GetMaskGreen(), + m_images[idx].GetMaskBlue()); +} + //--------------------------------------------------------------------------- // ANI reading and decoding //--------------------------------------------------------------------------- -bool wxANIDecoder::CanRead(wxInputStream& stream) const +bool wxANIDecoder::DoCanRead(wxInputStream& stream) const { wxInt32 FCC1, FCC2; - wxUint32 datalen ; + wxUint32 datalen; wxInt32 riff32; memcpy( &riff32, "RIFF", 4 ); @@ -118,7 +127,11 @@ bool wxANIDecoder::CanRead(wxInputStream& stream) const wxInt32 anih32; memcpy( &anih32, "anih", 4 ); - stream.SeekI(0); + if ( stream.IsSeekable() && stream.SeekI(0) == wxInvalidOffset ) + { + return false; + } + if ( !stream.Read(&FCC1, 4) ) return false; @@ -134,7 +147,7 @@ bool wxANIDecoder::CanRead(wxInputStream& stream) const // we always have a data size: stream.Read(&datalen, 4); datalen = wxINT32_SWAP_ON_BE(datalen) ; - + // data should be padded to make even number of bytes if (datalen % 2 == 1) datalen ++ ; @@ -145,7 +158,8 @@ bool wxANIDecoder::CanRead(wxInputStream& stream) const } else { - stream.SeekI(stream.TellI() + datalen); + if ( stream.SeekI(stream.TellI() + datalen) == wxInvalidOffset ) + return false; } // try to read next data chunk: @@ -160,7 +174,7 @@ bool wxANIDecoder::CanRead(wxInputStream& stream) const } // the "anih" RIFF chunk -struct wxANIHeader +struct wxANIHeader { wxInt32 cbSizeOf; // Num bytes in AniHeader (36 bytes) wxInt32 cFrames; // Number of unique Icons in this cursor @@ -171,13 +185,32 @@ struct wxANIHeader wxInt32 cPlanes; // 1 wxInt32 JifRate; // Default Jiffies (1/60th of a second) if rate chunk not present. wxInt32 flags; // Animation Flag (see AF_ constants) + + // ANI files are always little endian so we need to swap bytes on big + // endian architectures +#ifdef WORDS_BIGENDIAN + void AdjustEndianness() + { + // this works because all our fields are wxInt32 and they must be + // packed without holes between them (if they're not, they wouldn't map + // to the file header!) + wxInt32 * const start = (wxInt32 *)this; + wxInt32 * const end = start + sizeof(wxANIHeader)/sizeof(wxInt32); + for ( wxInt32 *p = start; p != end; p++ ) + { + *p = wxINT32_SWAP_ALWAYS(*p); + } + } +#else + void AdjustEndianness() { } +#endif }; bool wxANIDecoder::Load( wxInputStream& stream ) { wxInt32 FCC1, FCC2; wxUint32 datalen; - size_t globaldelay=0; + unsigned int globaldelay=0; wxInt32 riff32; memcpy( &riff32, "RIFF", 4 ); @@ -192,8 +225,13 @@ bool wxANIDecoder::Load( wxInputStream& stream ) wxInt32 seq32; memcpy( &seq32, "seq ", 4 ); - stream.SeekI(0); - stream.Read(&FCC1, 4); + if ( stream.IsSeekable() && stream.SeekI(0) == wxInvalidOffset ) + { + return false; + } + + if ( !stream.Read(&FCC1, 4) ) + return false; if ( FCC1 != riff32 ) return false; @@ -204,10 +242,12 @@ bool wxANIDecoder::Load( wxInputStream& stream ) m_info.Clear(); // we have a riff file: - while ( stream.IsOk() ) + while ( !stream.Eof() ) { // we always have a data size: - stream.Read(&datalen, 4); + if (!stream.Read(&datalen, 4)) + return false; + datalen = wxINT32_SWAP_ON_BE(datalen); //data should be padded to make even number of bytes @@ -216,7 +256,8 @@ bool wxANIDecoder::Load( wxInputStream& stream ) // now either data or a FCC: if ( (FCC1 == riff32) || (FCC1 == list32) ) { - stream.Read(&FCC2, 4); + if (!stream.Read(&FCC2, 4)) + return false; } else if ( FCC1 == anih32 ) { @@ -227,17 +268,19 @@ bool wxANIDecoder::Load( wxInputStream& stream ) return false; // already parsed an ani header? struct wxANIHeader header; - stream.Read(&header, sizeof(wxANIHeader)); + if (!stream.Read(&header, sizeof(wxANIHeader))) + return false; + header.AdjustEndianness(); // we should have a global frame size m_szAnimation = wxSize(header.cx, header.cy); // save interesting info from the header m_nFrames = header.cSteps; // NB: not cFrames!! - if (m_nFrames==0) + if ( m_nFrames == 0 ) return false; - globaldelay = wxINT32_SWAP_ON_BE(header.JifRate) * 1000 / 60; + globaldelay = header.JifRate * 1000 / 60; m_images.Alloc(header.cFrames); m_info.Add(wxANIFrameInfo(), m_nFrames); @@ -247,11 +290,12 @@ bool wxANIDecoder::Load( wxInputStream& stream ) // did we already process the anih32 chunk? if (m_nFrames == 0) return false; // rate chunks should always be placed after anih chunk - + wxASSERT(m_info.GetCount() == m_nFrames); - for (size_t i=0; i