document that CanRead() and GetImageCount() functions of wxImageHandlers do NOT modify the current stream position and that they require seekable streams; rename current GetImageCount() functions to DoGetImageCount() and put save-and-restore stream position logic in GetImageCount(); add comments in the various DoCanRead() and in DoGetImageCount() where the stream position is modified; remove unneeded SeekI(0) calls from DoCanRead() and DoGetImageCount() functions: they didn't allow to load images from non-seekable streams; implement forward-seeking in wxInputStream::SeekI() also for non-seekable streams

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@60852 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Francesco Montorsi
2009-06-01 11:43:36 +00:00
parent 1f51673bb8
commit 8faef7ccbc
25 changed files with 236 additions and 93 deletions

View 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.

View 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;

View 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);
};

View 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

View 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 );
// 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; }
virtual int GetImageCount( wxInputStream& stream );
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

View 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

View 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

View 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
};

View 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,10 +1596,21 @@ 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);
//@{
/**
If the image file contains more than one image and the image handler is
@@ -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.

View 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;

View 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 )

View 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;
}

View 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();

View 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

View File

@@ -98,15 +98,19 @@ 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();
}

View 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

View 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;

View 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;

View 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;

View 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() )

View 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.

View 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" );
@@ -427,6 +427,9 @@ int wxTIFFHandler::GetImageCount( wxInputStream& stream )
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') ||

View 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

View 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

View 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;
}