]> git.saurik.com Git - wxWidgets.git/commitdiff
document that CanRead() and GetImageCount() functions of wxImageHandlers do NOT modif...
authorFrancesco Montorsi <f18m_cpp217828@yahoo.it>
Mon, 1 Jun 2009 11:43:36 +0000 (11:43 +0000)
committerFrancesco Montorsi <f18m_cpp217828@yahoo.it>
Mon, 1 Jun 2009 11:43:36 +0000 (11:43 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@60852 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

25 files changed:
include/wx/anidecod.h
include/wx/animdecod.h
include/wx/gifdecod.h
include/wx/imagbmp.h
include/wx/image.h
include/wx/imaggif.h
include/wx/imagtiff.h
include/wx/xpmdecod.h
interface/wx/image.h
interface/wx/stream.h
src/common/anidecod.cpp
src/common/gifdecod.cpp
src/common/imagbmp.cpp
src/common/image.cpp
src/common/imaggif.cpp
src/common/imagiff.cpp
src/common/imagjpeg.cpp
src/common/imagpcx.cpp
src/common/imagpng.cpp
src/common/imagpnm.cpp
src/common/imagtga.cpp
src/common/imagtiff.cpp
src/common/imagxpm.cpp
src/common/stream.cpp
src/common/xpmdecod.cpp

index 5d4a062be154aa8702be577bade363a6d94bc7ad..df5be1a60b11a72a7b940e810cc793d2e7f66829 100644 (file)
@@ -44,7 +44,7 @@ public:
     virtual wxColour GetTransparentColour(unsigned int frame) const;
 
     // implementation of wxAnimationDecoder's pure virtuals
-    virtual bool CanRead( wxInputStream& stream ) const;
+    
     virtual bool Load( wxInputStream& stream );
 
     bool ConvertToImage(unsigned int frame, wxImage *image) const;
@@ -55,6 +55,10 @@ public:
         { return wxANIMATION_TYPE_ANI; }
 
 private:
+    // wxAnimationDecoder pure virtual:
+    virtual bool DoCanRead( wxInputStream& stream ) const;
+            // modifies current stream position (see wxAnimationDecoder::CanRead)
+    
     // frames stored as wxImage(s): ANI files are meant to be used mostly for animated
     // cursors and thus they do not use any optimization to encode differences between
     // two frames: they are just a list of images to display sequentially.
index a4c864c365d09bfe3dc50429251a3735c5d469b8..e803953fe24efcb6faafa8672756e3952e3cf13e 100644 (file)
@@ -93,7 +93,28 @@ public:
     }
 
     virtual bool Load( wxInputStream& stream ) = 0;
-    virtual bool CanRead( wxInputStream& stream ) const = 0;
+    
+    bool CanRead( wxInputStream& stream ) const
+    {
+        // NOTE: this code is the same of wxImageHandler::CallDoCanRead
+        
+        if ( !stream.IsSeekable() )
+            return false;        // can't test unseekable stream
+
+        wxFileOffset posOld = stream.TellI();
+        bool ok = DoCanRead(stream);
+
+        // restore the old position to be able to test other formats and so on
+        if ( stream.SeekI(posOld) == wxInvalidOffset )
+        {
+            wxLogDebug(_T("Failed to rewind the stream in wxAnimationDecoder!"));
+
+            // reading would fail anyhow as we're not at the right position
+            return false;
+        }
+
+        return ok;
+    }
 
     virtual wxAnimationDecoder *Clone() const = 0;
     virtual wxAnimationType GetType() const = 0;
@@ -129,6 +150,12 @@ public:
     unsigned int GetFrameCount() const { return m_nFrames; }
 
 protected:
+    // checks the signature of the data in the given stream and returns true if it
+    // appears to be a valid animation format recognized by the animation decoder;
+    // this function should modify the stream current position without taking care
+    // of restoring it since CanRead() will do it.
+    virtual bool DoCanRead(wxInputStream& stream) const = 0;
+    
     wxSize m_szAnimation;
     unsigned int m_nFrames;
 
index 443af47c8b4fa13d3d522377f84d6209503c05bd..15208231576b9aad2211fba01162ae6ec1808277 100644 (file)
@@ -76,7 +76,6 @@ public:
     void Destroy();
 
     // implementation of wxAnimationDecoder's pure virtuals
-    virtual bool CanRead( wxInputStream& stream ) const;
     virtual bool Load( wxInputStream& stream )
         { return LoadGIF(stream) == wxGIF_OK; }
 
@@ -88,6 +87,15 @@ public:
         { return wxANIMATION_TYPE_GIF; }
 
 private:
+    // wxAnimationDecoder pure virtual
+    virtual bool DoCanRead( wxInputStream& stream ) const;
+        // modifies current stream position (see wxAnimationDecoder::CanRead)
+
+    int getcode(wxInputStream& stream, int bits, int abfin);
+    wxGIFErrorCode dgif(wxInputStream& stream,
+                        GIFImage *img, int interl, int bits);
+
+    
     // array of all frames
     wxArrayPtrVoid m_frames;
 
@@ -98,10 +106,6 @@ private:
     unsigned char m_buffer[256];    // buffer for reading
     unsigned char *m_bufp;          // pointer to next byte in buffer
 
-    int getcode(wxInputStream& stream, int bits, int abfin);
-    wxGIFErrorCode dgif(wxInputStream& stream,
-                        GIFImage *img, int interl, int bits);
-
     wxDECLARE_NO_COPY_CLASS(wxGIFDecoder);
 };
 
index 1bcebe1d1817fbfaf96536c2cace2e27e901d942..b83c1df70028b191405a0bdd7963120b63c6cf63 100644 (file)
@@ -89,8 +89,9 @@ public:
     virtual bool SaveFile( wxImage *image, wxOutputStream& stream, bool verbose=true );
     virtual bool LoadFile( wxImage *image, wxInputStream& stream, bool verbose=true, int index=-1 );
     virtual bool DoLoadFile( wxImage *image, wxInputStream& stream, bool verbose, int index );
-    virtual int GetImageCount( wxInputStream& stream );
+    
 protected:
+    virtual int DoGetImageCount( wxInputStream& stream );
     virtual bool DoCanRead( wxInputStream& stream );
 #endif // wxUSE_STREAMS
 
@@ -145,8 +146,9 @@ public:
 #if wxUSE_STREAMS
     virtual bool SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSED(stream), bool WXUNUSED(verbose=true) ){return false ;}
     virtual bool LoadFile( wxImage *image, wxInputStream& stream, bool verbose=true, int index=-1 );
-    virtual int GetImageCount( wxInputStream& stream );
+
 protected:
+    virtual int DoGetImageCount( wxInputStream& stream );
     virtual bool DoCanRead( wxInputStream& stream );
 #endif // wxUSE_STREAMS
 
index 49ea7b2229c3ae6c7620aae07dfcf67f1e82450d..bf3e3e78fb12bfd9b26ed50d5e3861c01908585d 100644 (file)
@@ -97,10 +97,17 @@ public:
         { }
 
 #if wxUSE_STREAMS
-    virtual bool LoadFile( wxImage *image, wxInputStream& stream, bool verbose=true, int index=-1 );
-    virtual bool SaveFile( wxImage *image, wxOutputStream& stream, bool verbose=true );
-
-    virtual int GetImageCount( wxInputStream& stream );
+    // NOTE: LoadFile and SaveFile are not pure virtuals to allow derived classes
+    //       to implement only one of the two
+    virtual bool LoadFile( wxImage *WXUNUSED(image), wxInputStream& WXUNUSED(stream), 
+                           bool WXUNUSED(verbose)=true, int WXUNUSED(index)=-1 )
+        { return false; }
+    virtual bool SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSED(stream), 
+                           bool WXUNUSED(verbose)=true )
+        { return false; }
+
+    int GetImageCount( wxInputStream& stream );
+        // save the stream position, call DoGetImageCount() and restore the position
 
     bool CanRead( wxInputStream& stream ) { return CallDoCanRead(stream); }
     bool CanRead( const wxString& name );
@@ -125,6 +132,13 @@ public:
 
 protected:
 #if wxUSE_STREAMS
+    // NOTE: this function is allowed to change the current stream position
+    //       since GetImageCount() will take care of restoring it later
+    virtual int DoGetImageCount( wxInputStream& WXUNUSED(stream) ) 
+        { return 1; }       // default return value is 1 image
+    
+    // NOTE: this function is allowed to change the current stream position
+    //       since CallDoCanRead() will take care of restoring it later
     virtual bool DoCanRead( wxInputStream& stream ) = 0;
 
     // save the stream position, call DoCanRead() and restore the position
index 7912cf956f1f8f3aea9bc741433c8730c3e867c5..602c2e3233c37bb0e9c1473ac99c77f4acad7aa7 100644 (file)
@@ -35,8 +35,9 @@ public:
                           bool verbose = true, int index = -1);
     virtual bool SaveFile(wxImage *image, wxOutputStream& stream,
                           bool verbose=true);
-    virtual int GetImageCount(wxInputStream& stream);
+
 protected:
+    virtual int DoGetImageCount(wxInputStream& stream);
     virtual bool DoCanRead(wxInputStream& stream);
 #endif // wxUSE_STREAMS
 
index 75bfe80a14f050f1ad74fe15151e50255a6990e1..4beb66c6ce0948db55fce82ea838e4c7962cfce2 100644 (file)
@@ -34,8 +34,9 @@ public:
 #if wxUSE_STREAMS
     virtual bool LoadFile( wxImage *image, wxInputStream& stream, bool verbose=true, int index=-1 );
     virtual bool SaveFile( wxImage *image, wxOutputStream& stream, bool verbose=true );
-    virtual int GetImageCount( wxInputStream& stream );
+
 protected:
+    virtual int DoGetImageCount( wxInputStream& stream );
     virtual bool DoCanRead( wxInputStream& stream );
 #endif
 
index 00e33a728fa7fa18357095ac96157c4f9a789d32..1bd8f1c7f1c8ee300a0f42286f01ea957d425100 100644 (file)
@@ -30,15 +30,20 @@ public:
 
 #if wxUSE_STREAMS
     // Is the stream XPM file?
+    // NOTE: this function modifies the current stream position
     bool CanRead(wxInputStream& stream);
+    
     // Read XPM file from the stream, parse it and create image from it
     wxImage ReadFile(wxInputStream& stream);
 #endif
+
     // Read directly from XPM data (as passed to wxBitmap ctor):
     wxImage ReadData(const char* const* xpm_data);
+    
 #ifdef __BORLANDC__
     // needed for Borland 5.5
-    wxImage ReadData(char** xpm_data) { return ReadData(const_cast<const char* const*>(xpm_data)); }
+    wxImage ReadData(char** xpm_data) 
+        { return ReadData(const_cast<const char* const*>(xpm_data)); }
 #endif
 };
 
index 80c8100f2c4678f67802a2d64a5c355721125907..92cd47e91718c2adffb52ea47cb6ca28ded5b6b9 100644 (file)
@@ -83,6 +83,26 @@ public:
     */
     virtual ~wxImageHandler();
 
+    /**
+        Returns @true if this handler supports the image format contained in the
+        given stream.
+        
+        This function doesn't modify the current stream position (because it
+        restores the original position before returning; this however requires the
+        stream to be seekable; see wxStreamBase::IsSeekable).
+    */
+    bool CanRead( wxInputStream& stream );    
+
+    /**
+        Returns @true if this handler supports the image format contained in the
+        file with the given name.
+        
+        This function doesn't modify the current stream position (because it
+        restores the original position before returning; this however requires the
+        stream to be seekable; see wxStreamBase::IsSeekable).
+    */
+    bool CanRead( const wxString& filename );
+    
     /**
         Gets the preferred file extension associated with this handler.
 
@@ -106,7 +126,9 @@ public:
 
         @param stream
             Opened input stream for reading image data.
-            Currently, the stream must support seeking.
+            This function doesn't modify the current stream position (because it
+            restores the original position before returning; this however requires the
+            stream to be seekable; see wxStreamBase::IsSeekable).
 
         @return Number of available images. For most image handlers, this is 1
                 (exceptions are TIFF and ICO formats as well as animated GIFs
@@ -1574,9 +1596,20 @@ public:
     
     
     /**
-        Returns @true if the current image handlers can read this file
+        Returns @true if at least one of the available image handlers can read 
+        the file with the given name.
+        
+        See wxImageHandler::CanRead for more info.
     */
     static bool CanRead(const wxString& filename);
+    
+    /**
+        Returns @true if at least one of the available image handlers can read 
+        the data in the given stream.
+        
+        See wxImageHandler::CanRead for more info.
+    */
+    static bool CanRead(wxInputStream& stream);
 
     //@{
     /**
@@ -1586,8 +1619,10 @@ public:
 
         For the overload taking the parameter @a filename, that's the name
         of the file to query.
-        For the overload taking the parameter @a stream, that's the ppened input
-        stream with image data. Currently, the stream must support seeking.
+        For the overload taking the parameter @a stream, that's the opened input
+        stream with image data.
+        
+        See wxImageHandler::GetImageCount() for more info.
 
         The parameter @a type may be one of the following values:
         @li wxBITMAP_TYPE_BMP: Load a Windows bitmap file.
index 7900f3ef0b89db9ad42b517cbf3d165239655c29..51db34912d6111f88c1b7bd2816bbc62faf66b51 100644 (file)
@@ -76,7 +76,7 @@ public:
     virtual bool IsOk() const;
 
     /**
-        Returns @true if the streams supports seeking to arbitrary offsets.
+        Returns @true if the stream supports seeking to arbitrary offsets.
     */
     virtual bool IsSeekable() const;
 
@@ -613,6 +613,11 @@ public:
     /**
         Changes the stream current position.
 
+        This operation in general is possible only for seekable streams 
+        (see wxStreamBase::IsSeekable()); non-seekable streams support only
+        seeking positive amounts in mode @c wxFromCurrent (this is implemented
+        by reading data and simply discarding it).
+
         @param pos
             Offset to seek to.
         @param mode
@@ -623,7 +628,9 @@ public:
     virtual wxFileOffset SeekI(wxFileOffset pos, wxSeekMode mode = wxFromStart);
 
     /**
-        Returns the current stream position.
+        Returns the current stream position or ::wxInvalidOffset if it's not
+        available (e.g. socket streams do not have a size nor a current stream
+        position).
     */
     virtual wxFileOffset TellI() const;
 
index 8ff307162305d3434f95ddc224f724fc3606f7d4..9d202672c66e6dd3f5c190c4830a221ed3542763 100644 (file)
@@ -113,10 +113,10 @@ wxColour wxANIDecoder::GetTransparentColour(unsigned int frame) const
 // 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 );
@@ -127,8 +127,6 @@ bool wxANIDecoder::CanRead(wxInputStream& stream) const
     wxInt32 anih32;
     memcpy( &anih32, "anih", 4 );
 
-    if ( stream.SeekI(0) == wxInvalidOffset )
-        return false;
     if ( !stream.Read(&FCC1, 4) )
         return false;
 
@@ -222,8 +220,6 @@ bool wxANIDecoder::Load( wxInputStream& stream )
     wxInt32 seq32;
     memcpy( &seq32, "seq ", 4 );
 
-    if ( stream.SeekI(0) == wxInvalidOffset)
-        return false;
     if ( !stream.Read(&FCC1, 4) )
         return false;
     if ( FCC1 != riff32 )
index 76450239a3894b512a9a11e600f15dd40d65ada2..27669b8d2a7b8271cccd565ff580b78da92d469e 100644 (file)
@@ -575,16 +575,13 @@ as an End of Information itself)
 // CanRead:
 //  Returns true if the file looks like a valid GIF, false otherwise.
 //
-bool wxGIFDecoder::CanRead(wxInputStream &stream) const
+bool wxGIFDecoder::DoCanRead(wxInputStream &stream) const
 {
     unsigned char buf[3];
 
     if ( !stream.Read(buf, WXSIZEOF(buf)) )
         return false;
 
-    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;
 }
 
index 6f3a298d18eed65e66b51db3336e4f7512b5565f..9693a0d85e03d972882eb8fbf0e61b5d9d40edab 100644 (file)
@@ -641,7 +641,9 @@ bool wxBMPHandler::DoLoadDib(wxImage * image, int width, int height,
      */
     if ( IsBmp )
     {
-        if (stream.SeekI(bmpOffset) == wxInvalidOffset)
+        // NOTE: seeking a positive amount in wxFromCurrent mode allows us to
+        //       load even non-seekable streams (see wxInputStream::SeekI docs)!
+        if (stream.SeekI(bmpOffset, wxFromCurrent) == wxInvalidOffset)
             return false;
         //else: icon, just carry on
     }
@@ -899,15 +901,9 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream,
     wxInt32         dbuf[4];
     wxInt8          bbuf[4];
 
-    wxFileOffset offset = 0; // keep gcc quiet
     if ( IsBmp )
     {
         // read the header off the .BMP format file
-
-        offset = stream.TellI();
-        if (offset == wxInvalidOffset)
-            offset = 0;
-
         stream.Read(bbuf, 2);
         stream.Read(dbuf, 16);
     }
@@ -918,7 +914,7 @@ bool wxBMPHandler::LoadDib(wxImage *image, wxInputStream& stream,
     #if 0 // unused
         wxInt32 size = wxINT32_SWAP_ON_BE(dbuf[0]);
     #endif
-    offset = offset + wxINT32_SWAP_ON_BE(dbuf[2]);
+    wxFileOffset offset = wxINT32_SWAP_ON_BE(dbuf[2]);
 
     stream.Read(dbuf, 4 * 2);
     int width = wxINT32_SWAP_ON_BE((int)dbuf[0]);
@@ -1021,7 +1017,7 @@ bool wxBMPHandler::DoCanRead(wxInputStream& stream)
 {
     unsigned char hdr[2];
 
-    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
+    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )     // it's ok to modify the stream position here
         return false;
 
     // do we have the BMP file signature?
@@ -1259,8 +1255,6 @@ bool wxICOHandler::SaveFile(wxImage *image,
 bool wxICOHandler::LoadFile(wxImage *image, wxInputStream& stream,
                             bool verbose, int index)
 {
-    if (stream.SeekI(0) == wxInvalidOffset)
-        return false;
     return DoLoadFile(image, stream, verbose, index);
 }
 
@@ -1272,9 +1266,9 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream,
 
     ICONDIR IconDir;
 
-    wxFileOffset iPos = stream.TellI();
     stream.Read(&IconDir, sizeof(IconDir));
     wxUint16 nIcons = wxUINT16_SWAP_ON_BE(IconDir.idCount);
+    
     // nType is 1 for Icons, 2 for Cursors:
     wxUint16 nType = wxUINT16_SWAP_ON_BE(IconDir.idType);
 
@@ -1285,9 +1279,13 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream,
     int colmax = 0;
     int iSel = wxNOT_FOUND;
 
-    for (int i = 0; i < nIcons; i++ )
+    // remember how many bytes we read from the stream:
+    wxFileOffset offset = sizeof(IconDir);
+    
+    for (unsigned int i = 0; i < nIcons; i++ )
     {
-        stream.Read(pCurrentEntry, sizeof(ICONDIRENTRY));
+        offset += stream.Read(pCurrentEntry, sizeof(ICONDIRENTRY)).LastRead();
+        
         // bHeight and bColorCount are wxUint8
         if ( pCurrentEntry->bWidth >= wMax )
         {
@@ -1301,6 +1299,7 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream,
                 colmax = pCurrentEntry->bColorCount;
             }
         }
+        
         pCurrentEntry++;
     }
 
@@ -1320,8 +1319,13 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream,
     {
         // seek to selected icon:
         pCurrentEntry = pIconDirEntry + iSel;
-        if (stream.SeekI(iPos + wxUINT32_SWAP_ON_BE(pCurrentEntry->dwImageOffset), wxFromStart) == wxInvalidOffset)
+        
+        // NOTE: seeking a positive amount in wxFromCurrent mode allows us to
+        //       load even non-seekable streams (see wxInputStream::SeekI docs)!
+        if (stream.SeekI(wxUINT32_SWAP_ON_BE(pCurrentEntry->dwImageOffset) - offset, 
+                         wxFromCurrent) == wxInvalidOffset)
             return false;
+        
         bResult = LoadDib(image, stream, true, IsBmp);
         bool bIsCursorType = (this->GetType() == wxBITMAP_TYPE_CUR) || (this->GetType() == wxBITMAP_TYPE_ANI);
         if ( bResult && bIsCursorType && nType == 2 )
@@ -1331,30 +1335,27 @@ bool wxICOHandler::DoLoadFile(wxImage *image, wxInputStream& stream,
             image->SetOption(wxIMAGE_OPTION_CUR_HOTSPOT_Y, wxUINT16_SWAP_ON_BE(pCurrentEntry->wBitCount));
         }
     }
-    delete[] pIconDirEntry;
+    
+    delete [] pIconDirEntry;
+    
     return bResult;
 }
 
-int wxICOHandler::GetImageCount(wxInputStream& stream)
+int wxICOHandler::DoGetImageCount(wxInputStream& stream)
 {
     ICONDIR IconDir;
-    wxFileOffset iPos = stream.TellI();
-    if (stream.SeekI(0) == wxInvalidOffset)
-        return 0;
+
     if (stream.Read(&IconDir, sizeof(IconDir)).LastRead() != sizeof(IconDir))
+             // it's ok to modify the stream position here
         return 0;
-    wxUint16 nIcons = wxUINT16_SWAP_ON_BE(IconDir.idCount);
-    if (stream.SeekI(iPos) == wxInvalidOffset)
-        return 0;
-    return (int)nIcons;
+    
+    return (int)wxUINT16_SWAP_ON_BE(IconDir.idCount);
 }
 
 bool wxICOHandler::DoCanRead(wxInputStream& stream)
 {
-    if (stream.SeekI(0) == wxInvalidOffset)
-        return false;
     unsigned char hdr[4];
-    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
+    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )     // it's ok to modify the stream position here
         return false;
 
     // hdr[2] is one for an icon and two for a cursor
@@ -1374,10 +1375,8 @@ IMPLEMENT_DYNAMIC_CLASS(wxCURHandler, wxICOHandler)
 
 bool wxCURHandler::DoCanRead(wxInputStream& stream)
 {
-    if (stream.SeekI(0) == wxInvalidOffset)
-        return false;
     unsigned char hdr[4];
-    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
+    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )     // it's ok to modify the stream position here
         return false;
 
     // hdr[2] is one for an icon and two for a cursor
@@ -1408,12 +1407,13 @@ bool wxANIHandler::DoCanRead(wxInputStream& stream)
 {
     wxANIDecoder decod;
     return decod.CanRead(stream);
+             // it's ok to modify the stream position here
 }
 
-int wxANIHandler::GetImageCount(wxInputStream& stream)
+int wxANIHandler::DoGetImageCount(wxInputStream& stream)
 {
     wxANIDecoder decoder;
-    if (!decoder.Load(stream))
+    if (!decoder.Load(stream))  // it's ok to modify the stream position here
         return wxNOT_FOUND;
 
     return decoder.GetFrameCount();
index cbe275bc19a3c2dd3e9c71a4703175dbe79049a3..d8cbaa2cfda7ff4a85b3de10ff94a156f8a8983c 100644 (file)
@@ -2658,19 +2658,27 @@ void wxImage::RotateHue(double angle)
 IMPLEMENT_ABSTRACT_CLASS(wxImageHandler,wxObject)
 
 #if wxUSE_STREAMS
-bool wxImageHandler::LoadFile( wxImage *WXUNUSED(image), wxInputStream& WXUNUSED(stream), bool WXUNUSED(verbose), int WXUNUSED(index) )
+int wxImageHandler::GetImageCount( wxInputStream& stream )
 {
-    return false;
-}
+    // NOTE: this code is the same of wxAnimationDecoder::CanRead and
+    //       wxImageHandler::CallDoCanRead
 
-bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), wxOutputStream& WXUNUSED(stream), bool WXUNUSED(verbose) )
-{
-    return false;
-}
+    if ( !stream.IsSeekable() )
+        return false;        // can't test unseekable stream
 
-int wxImageHandler::GetImageCount( wxInputStream& WXUNUSED(stream) )
-{
-    return 1;
+    wxFileOffset posOld = stream.TellI();
+    int n = DoGetImageCount(stream);
+
+    // restore the old position to be able to test other formats and so on
+    if ( stream.SeekI(posOld) == wxInvalidOffset )
+    {
+        wxLogDebug(_T("Failed to rewind the stream in wxImageHandler!"));
+
+        // reading would fail anyhow as we're not at the right position
+        return false;
+    }
+
+    return n;
 }
 
 bool wxImageHandler::CanRead( const wxString& name )
@@ -2688,13 +2696,13 @@ bool wxImageHandler::CanRead( const wxString& name )
 
 bool wxImageHandler::CallDoCanRead(wxInputStream& stream)
 {
-    wxFileOffset posOld = stream.TellI();
-    if ( posOld == wxInvalidOffset )
-    {
-        // can't test unseekable stream
-        return false;
-    }
+    // NOTE: this code is the same of wxAnimationDecoder::CanRead and
+    //       wxImageHandler::GetImageCount
+    
+    if ( !stream.IsSeekable() )
+        return false;        // can't test unseekable stream
 
+    wxFileOffset posOld = stream.TellI();
     bool ok = DoCanRead(stream);
 
     // restore the old position to be able to test other formats and so on
index 7b241bd6e19ac143aa056601b4d0b91803db9286..cd81463b498d8b88d3fbe0c53c23230ecff6d703 100644 (file)
@@ -98,14 +98,18 @@ bool wxGIFHandler::DoCanRead( wxInputStream& stream )
 {
     wxGIFDecoder decod;
     return decod.CanRead(stream);
+         // it's ok to modify the stream position here
 }
 
-int wxGIFHandler::GetImageCount( wxInputStream& stream )
+int wxGIFHandler::DoGetImageCount( wxInputStream& stream )
 {
     wxGIFDecoder decod;
     wxGIFErrorCode error = decod.LoadGIF(stream);
     if ( (error != wxGIF_OK) && (error != wxGIF_TRUNCATED) )
         return -1;
+    
+    // NOTE: this function modifies the current stream position but it's ok
+    //       (see wxImageHandler::GetImageCount)
 
     return decod.GetFrameCount();
 }
index 9fd15214d4adeeed246f67ad998720204256c314..2ea52b1403699a6de3a619bfe624f4c10e22d5fc 100644 (file)
@@ -98,7 +98,10 @@ public:
     // constructor, destructor, etc.
     wxIFFDecoder(wxInputStream *s);
     ~wxIFFDecoder() { Destroy(); }
+    
+    // NOTE: this function modifies the current stream position
     bool CanRead();
+    
     int ReadIFF();
     bool ConvertToImage(wxImage *image) const;
 };
@@ -234,9 +237,6 @@ bool wxIFFDecoder::CanRead()
     if ( !m_f->Read(buf, WXSIZEOF(buf)) )
         return false;
 
-    if ( m_f->SeekI(-(wxFileOffset)WXSIZEOF(buf), wxFromCurrent) == wxInvalidOffset )
-        return false;
-
     return (memcmp(buf, "FORM", 4) == 0) && (memcmp(buf+8, "ILBM", 4) == 0);
 }
 
@@ -787,6 +787,7 @@ bool wxIFFHandler::DoCanRead(wxInputStream& stream)
     wxIFFDecoder decod(&stream);
 
     return decod.CanRead();
+         // it's ok to modify the stream position here
 }
 
 #endif // wxUSE_STREAMS
index f14027cb78d4bd0ed122b7e051eef07a2e646759..a06f0dd8f2c15fbd7ed831e4c851c9ea0f64039b 100644 (file)
@@ -479,7 +479,7 @@ bool wxJPEGHandler::DoCanRead( wxInputStream& stream )
 {
     unsigned char hdr[2];
 
-    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
+    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )     // it's ok to modify the stream position here
         return false;
 
     return hdr[0] == 0xFF && hdr[1] == 0xD8;
index 05f1d66a5e5c9fc9df5d475e8f35d63b3df316bb..71f3b1e7a5a42a43034218f36da0469511855d29 100644 (file)
@@ -487,7 +487,7 @@ bool wxPCXHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbos
 
 bool wxPCXHandler::DoCanRead( wxInputStream& stream )
 {
-    unsigned char c = stream.GetC();
+    unsigned char c = stream.GetC();     // it's ok to modify the stream position here
     if ( !stream )
         return false;
 
index 474221ae11d3fff2ae44becff4ec4a1281e54aff..528168a609cf1d23eac9bc8f24bb07c8c3ef21b6 100644 (file)
@@ -302,7 +302,7 @@ bool wxPNGHandler::DoCanRead( wxInputStream& stream )
 {
     unsigned char hdr[4];
 
-    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
+    if ( !stream.Read(hdr, WXSIZEOF(hdr)) )     // it's ok to modify the stream position here
         return false;
 
     return memcmp(hdr, "\211PNG", WXSIZEOF(hdr)) == 0;
index 85fbdc08a9b45991ff8b825284cea2129d3694c9..2b3e75f979aa7196b205d3396700e6c2a4acd074 100644 (file)
@@ -180,6 +180,7 @@ bool wxPNMHandler::DoCanRead( wxInputStream& stream )
 {
     Skip_Comment(stream);
 
+    // it's ok to modify the stream position here
     if ( stream.GetC() == 'P' )
     {
         switch ( stream.GetC() )
index 9fd65003a77f746bde9e7c32670edfb26c04537a..d98ff01800d68f6438c64b9d0df388f9e94c69c3 100644 (file)
@@ -741,7 +741,7 @@ bool wxTGAHandler::DoCanRead(wxInputStream& stream)
 {
     // read the fixed-size TGA headers
     unsigned char hdr[HDR_SIZE];
-    stream.Read(hdr, HDR_SIZE);
+    stream.Read(hdr, HDR_SIZE);     // it's ok to modify the stream position here
 
     // Check wether we can read the file or not.
 
index 91b70afbae6ff882f50e4f2d2d86a59d22073cd1..fed6679246e0c79b02b03c8c8a541b8bfc165f38 100644 (file)
@@ -413,7 +413,7 @@ bool wxTIFFHandler::LoadFile( wxImage *image, wxInputStream& stream, bool verbos
     return true;
 }
 
-int wxTIFFHandler::GetImageCount( wxInputStream& stream )
+int wxTIFFHandler::DoGetImageCount( wxInputStream& stream )
 {
     TIFF *tif = TIFFwxOpen( stream, "image", "r" );
 
@@ -426,6 +426,9 @@ int wxTIFFHandler::GetImageCount( wxInputStream& stream )
     } while (TIFFReadDirectory(tif));
 
     TIFFClose( tif );
+    
+    // NOTE: this function modifies the current stream position but it's ok
+    //       (see wxImageHandler::GetImageCount)
 
     return dircount;
 }
@@ -587,7 +590,7 @@ bool wxTIFFHandler::DoCanRead( wxInputStream& stream )
 {
     unsigned char hdr[2];
 
-    if ( !stream.Read(&hdr[0], WXSIZEOF(hdr)) )
+    if ( !stream.Read(&hdr[0], WXSIZEOF(hdr)) )     // it's ok to modify the stream position here
         return false;
 
     return (hdr[0] == 'I' && hdr[1] == 'I') ||
index 3f1caeaf46a07610a520c1b70674ffc7341f767e..2850e770e61d616ea871e434897134934b43cddd 100644 (file)
@@ -218,6 +218,7 @@ bool wxXPMHandler::DoCanRead(wxInputStream& stream)
 {
     wxXPMDecoder decoder;
     return decoder.CanRead(stream);
+         // it's ok to modify the stream position here
 }
 
 #endif  // wxUSE_STREAMS
index 8d8a42c870ffe4c9b7daf21fc100e05b26aacb1a..357499b047b628290380437b2c2e806b272f1109 100644 (file)
@@ -916,13 +916,48 @@ wxFileOffset wxInputStream::SeekI(wxFileOffset pos, wxSeekMode mode)
 {
     // RR: This code is duplicated in wxBufferedInputStream. This is
     // not really a good design, but buffered stream are different
-    // from all other in that they handle two stream-related objects,
+    // from all others in that they handle two stream-related objects:
     // the stream buffer and parent stream.
 
     // I don't know whether it should be put as well in wxFileInputStream::OnSysSeek
     if (m_lasterror==wxSTREAM_EOF)
         m_lasterror=wxSTREAM_NO_ERROR;
 
+    // avoid unnecessary seek operations (optimization)
+    wxFileOffset currentPos = TellI(), size = GetLength();
+    if ((mode == wxFromStart && currentPos == pos) ||
+        (mode == wxFromCurrent && pos == 0) ||
+        (mode == wxFromEnd && size != wxInvalidOffset && currentPos == size-pos))
+        return currentPos;
+
+    if (!IsSeekable() && mode == wxFromCurrent && pos > 0)
+    {
+        // rather than seeking, we can just read data and discard it;
+        // this allows to forward-seek also non-seekable streams!
+        char buf[BUF_TEMP_SIZE];
+        size_t bytes_read;
+
+        // read chunks of BUF_TEMP_SIZE bytes until we reach the new position
+        for ( ; pos >= BUF_TEMP_SIZE; pos -= bytes_read)
+        {
+            bytes_read = Read(buf, WXSIZEOF(buf)).LastRead();
+            if ( m_lasterror != wxSTREAM_NO_ERROR )
+                return wxInvalidOffset;
+            
+            wxASSERT(bytes_read == WXSIZEOF(buf));
+        }
+        
+        // read the last 'pos' bytes
+        bytes_read = Read(buf, (size_t)pos).LastRead();
+        if ( m_lasterror != wxSTREAM_NO_ERROR )
+            return wxInvalidOffset;
+        
+        wxASSERT(bytes_read == (size_t)pos);
+        
+        // we should now have seeked to the right position...
+        return TellI();
+    }
+
     /* RR: A call to SeekI() will automatically invalidate any previous
        call to Ungetch(), otherwise it would be possible to SeekI() to
        one position, unread some bytes there, SeekI() to another position
index 54e54c5221e5aeabe90011754f6e19d01793b815..82a415f69624fe8f7d7efe9663860b40d6afbc9b 100644 (file)
@@ -122,9 +122,6 @@ bool wxXPMDecoder::CanRead(wxInputStream& stream)
     if ( !stream.Read(buf, WXSIZEOF(buf)) )
         return false;
 
-    if (stream.SeekI(-(wxFileOffset)WXSIZEOF(buf), wxFromCurrent) == wxInvalidOffset)
-        return false;
-
     return memcmp(buf, "/* XPM */", WXSIZEOF(buf)) == 0;
 }