summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/image-decoders
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2010-04-27 16:31:00 +0100
committerSteve Block <steveblock@google.com>2010-05-11 14:42:12 +0100
commitdcc8cf2e65d1aa555cce12431a16547e66b469ee (patch)
tree92a8d65cd5383bca9749f5327fb5e440563926e6 /WebCore/platform/image-decoders
parentccac38a6b48843126402088a309597e682f40fe6 (diff)
downloadexternal_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.zip
external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.gz
external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.bz2
Merge webkit.org at r58033 : Initial merge by git
Change-Id: If006c38561af287c50cd578d251629b51e4d8cd1
Diffstat (limited to 'WebCore/platform/image-decoders')
-rw-r--r--WebCore/platform/image-decoders/ImageDecoder.h30
-rw-r--r--WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp11
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp51
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageReader.cpp4
-rw-r--r--WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp30
-rw-r--r--WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp52
-rw-r--r--WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h1
-rw-r--r--WebCore/platform/image-decoders/png/PNGImageDecoder.cpp66
-rw-r--r--WebCore/platform/image-decoders/png/PNGImageDecoder.h8
10 files changed, 110 insertions, 145 deletions
diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h
index 002395b..b063db2 100644
--- a/WebCore/platform/image-decoders/ImageDecoder.h
+++ b/WebCore/platform/image-decoders/ImageDecoder.h
@@ -214,10 +214,10 @@ namespace WebCore {
public:
ImageDecoder()
: m_scaled(false)
- , m_failed(false)
, m_sizeAvailable(false)
- , m_isAllDataReceived(false)
, m_maxNumPixels(-1)
+ , m_isAllDataReceived(false)
+ , m_failed(false)
{
}
@@ -236,6 +236,8 @@ namespace WebCore {
virtual void setData(SharedBuffer* data, bool allDataReceived)
{
+ if (failed())
+ return;
m_data = data;
m_isAllDataReceived = allDataReceived;
}
@@ -277,10 +279,8 @@ namespace WebCore {
// be set and the caller should immediately stop decoding.
virtual bool setSize(unsigned width, unsigned height)
{
- if (isOverSize(width, height)) {
- m_failed = true;
- return false;
- }
+ if (isOverSize(width, height))
+ return setFailed();
m_size = IntSize(width, height);
m_sizeAvailable = true;
return true;
@@ -303,8 +303,16 @@ namespace WebCore {
// transparency.
virtual bool supportsAlpha() const { return true; }
+ // Sets the "decode failure" flag. For caller convenience (since so
+ // many callers want to return false after calling this), returns false
+ // to enable easy tailcalling.
+ virtual bool setFailed()
+ {
+ m_failed = true;
+ return false;
+ }
+
bool failed() const { return m_failed; }
- void setFailed() { m_failed = true; }
// Wipe out frames in the frame buffer cache before |clearBeforeFrame|,
// assuming this can be done without breaking decoding. Different
@@ -327,11 +335,10 @@ namespace WebCore {
int scaledY(int origY, int searchStart = 0);
RefPtr<SharedBuffer> m_data; // The encoded data.
+ Vector<RGBA32Buffer> m_frameBufferCache;
+ bool m_scaled;
Vector<int> m_scaledColumns;
Vector<int> m_scaledRows;
- bool m_scaled;
- Vector<RGBA32Buffer> m_frameBufferCache;
- bool m_failed;
private:
// Some code paths compute the size of the image as "width * height * 4"
@@ -347,8 +354,9 @@ namespace WebCore {
IntSize m_size;
bool m_sizeAvailable;
- bool m_isAllDataReceived;
int m_maxNumPixels;
+ bool m_isAllDataReceived;
+ bool m_failed;
};
} // namespace WebCore
diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
index fb9f9f2..a6d36ef 100644
--- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
@@ -57,7 +57,7 @@ void BMPImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
bool BMPImageDecoder::isSizeAvailable()
{
- if (!ImageDecoder::isSizeAvailable() && !failed())
+ if (!ImageDecoder::isSizeAvailable())
decode(true);
return ImageDecoder::isSizeAvailable();
@@ -72,7 +72,7 @@ RGBA32Buffer* BMPImageDecoder::frameBufferAtIndex(size_t index)
m_frameBufferCache.resize(1);
RGBA32Buffer* buffer = &m_frameBufferCache.first();
- if (buffer->status() != RGBA32Buffer::FrameComplete && !failed())
+ if (buffer->status() != RGBA32Buffer::FrameComplete)
decode(false);
return buffer;
}
@@ -131,12 +131,7 @@ bool BMPImageDecoder::processFileHeader(size_t* imgDataOffset)
BITMAPARRAY = 0x4241, // "BA"
*/
};
- if (fileType != BMAP) {
- setFailed();
- return false;
- }
-
- return true;
+ return (fileType == BMAP) || setFailed();
}
} // namespace WebCore
diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
index 807d57c..5965ae4 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -42,26 +42,32 @@ GIFImageDecoder::~GIFImageDecoder()
void GIFImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
{
- if (m_failed)
+ if (failed())
return;
ImageDecoder::setData(data, allDataReceived);
// We need to rescan the frame count, as the new data may have changed it.
m_alreadyScannedThisDataForFrameCount = false;
-
- if (!m_reader && !m_failed)
- m_reader.set(new GIFImageReader(this));
}
bool GIFImageDecoder::isSizeAvailable()
{
- if (!ImageDecoder::isSizeAvailable() && !failed() && m_reader)
+ if (!ImageDecoder::isSizeAvailable())
decode(0, GIFSizeQuery);
return ImageDecoder::isSizeAvailable();
}
+bool GIFImageDecoder::setSize(unsigned width, unsigned height)
+{
+ if (!ImageDecoder::setSize(width, height))
+ return false;
+
+ prepareScaleDataIfNecessary();
+ return true;
+}
+
size_t GIFImageDecoder::frameCount()
{
if (!m_alreadyScannedThisDataForFrameCount) {
@@ -108,8 +114,8 @@ RGBA32Buffer* GIFImageDecoder::frameBufferAtIndex(size_t index)
return 0;
RGBA32Buffer& frame = m_frameBufferCache[index];
- if (frame.status() != RGBA32Buffer::FrameComplete && m_reader)
- decode(index + 1, GIFFullQuery); // Decode this frame.
+ if (frame.status() != RGBA32Buffer::FrameComplete)
+ decode(index + 1, GIFFullQuery);
return &frame;
}
@@ -163,15 +169,6 @@ void GIFImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame)
}
}
-bool GIFImageDecoder::sizeNowAvailable(unsigned width, unsigned height)
-{
- if (!setSize(width, height))
- return false;
-
- prepareScaleDataIfNecessary();
- return true;
-}
-
void GIFImageDecoder::decodingHalted(unsigned bytesLeft)
{
m_readOffset = m_data->size() - bytesLeft;
@@ -291,12 +288,16 @@ void GIFImageDecoder::gifComplete()
void GIFImageDecoder::decode(unsigned haltAtFrame, GIFQuery query)
{
- if (m_failed)
+ if (failed())
return;
- m_failed = !m_reader->read((const unsigned char*)m_data->data() + m_readOffset, m_data->size() - m_readOffset, query, haltAtFrame);
+ if (!m_reader)
+ m_reader.set(new GIFImageReader(this));
+
+ if (!m_reader->read((const unsigned char*)m_data->data() + m_readOffset, m_data->size() - m_readOffset, query, haltAtFrame))
+ setFailed();
- if (m_failed)
+ if (failed())
m_reader.clear();
}
@@ -321,10 +322,8 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
if (!frameIndex) {
// This is the first frame, so we're not relying on any previous data.
- if (!buffer->setSize(scaledSize().width(), scaledSize().height())) {
- m_failed = true;
- return false;
- }
+ if (!buffer->setSize(scaledSize().width(), scaledSize().height()))
+ return setFailed();
} else {
// The starting state for this frame depends on the previous frame's
// disposal method.
@@ -353,10 +352,8 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) {
// Clearing the first frame, or a frame the size of the whole
// image, results in a completely empty image.
- if (!buffer->setSize(bufferSize.width(), bufferSize.height())) {
- m_failed = true;
- return false;
- }
+ if (!buffer->setSize(bufferSize.width(), bufferSize.height()))
+ return setFailed();
} else {
// Copy the whole previous buffer, then clear just its frame.
buffer->copyBitmapData(*prevBuffer);
diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
index 0aa5387..28a9a59 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
+++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
@@ -45,13 +45,13 @@ namespace WebCore {
virtual String filenameExtension() const { return "gif"; }
virtual void setData(SharedBuffer* data, bool allDataReceived);
virtual bool isSizeAvailable();
+ virtual bool setSize(unsigned width, unsigned height);
virtual size_t frameCount();
virtual int repetitionCount() const;
virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
virtual void clearFrameBufferCache(size_t clearBeforeFrame);
// Callbacks from the GIF reader.
- bool sizeNowAvailable(unsigned width, unsigned height);
void decodingHalted(unsigned bytesLeft);
bool haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, unsigned repeatCount, bool writeTransparentPixels);
void frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod);
diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp
index 755a48d..677853e 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp
+++ b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp
@@ -519,7 +519,7 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len,
screen_height = GETINT16(q + 2);
// CALLBACK: Inform the decoderplugin of our size.
- if (clientptr && !clientptr->sizeNowAvailable(screen_width, screen_height))
+ if (clientptr && !clientptr->setSize(screen_width, screen_height))
return false;
screen_bgcolor = q[5];
@@ -746,7 +746,7 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len,
y_offset = 0;
// CALLBACK: Inform the decoderplugin of our size.
- if (clientptr && !clientptr->sizeNowAvailable(screen_width, screen_height))
+ if (clientptr && !clientptr->setSize(screen_width, screen_height))
return false;
}
diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
index 1a202bc..325c506 100644
--- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
@@ -88,14 +88,9 @@ IntSize ICOImageDecoder::frameSizeAtIndex(size_t index) const
bool ICOImageDecoder::setSize(unsigned width, unsigned height)
{
- if (m_frameSize.isEmpty())
- return ImageDecoder::setSize(width, height);
-
// The size calculated inside the BMPImageReader had better match the one in
// the icon directory.
- if (IntSize(width, height) != m_frameSize)
- setFailed();
- return !failed();
+ return m_frameSize.isEmpty() ? ImageDecoder::setSize(width, height) : ((IntSize(width, height) == m_frameSize) || setFailed());
}
size_t ICOImageDecoder::frameCount()
@@ -193,15 +188,10 @@ bool ICOImageDecoder::decodeAtIndex(size_t index)
}
// Fail if the size the PNGImageDecoder calculated does not match the size
// in the directory.
- if (m_pngDecoders[index]->isSizeAvailable() && (m_pngDecoders[index]->size() != dirEntry.m_size)) {
- setFailed();
- return false;
- }
+ if (m_pngDecoders[index]->isSizeAvailable() && (m_pngDecoders[index]->size() != dirEntry.m_size))
+ return setFailed();
m_frameBufferCache[index] = *m_pngDecoders[index]->frameBufferAtIndex(0);
- if (!m_pngDecoders[index]->failed())
- return true;
- setFailed();
- return false;
+ return !m_pngDecoders[index]->failed() || setFailed();
}
bool ICOImageDecoder::processDirectory()
@@ -220,10 +210,8 @@ bool ICOImageDecoder::processDirectory()
ICON = 1,
CURSOR = 2,
};
- if (((fileType != ICON) && (fileType != CURSOR)) || (!idCount)) {
- setFailed();
- return false;
- }
+ if (((fileType != ICON) && (fileType != CURSOR)) || (!idCount))
+ return setFailed();
// Enlarge member vectors to hold all the entries.
m_dirEntries.resize(idCount);
@@ -244,10 +232,8 @@ bool ICOImageDecoder::processDirectoryEntries()
// Make sure the specified image offsets are past the end of the directory
// entries.
for (IconDirectoryEntries::iterator i(m_dirEntries.begin()); i != m_dirEntries.end(); ++i) {
- if (i->m_imageOffset < m_decodedOffset) {
- setFailed();
- return false;
- }
+ if (i->m_imageOffset < m_decodedOffset)
+ return setFailed();
}
// Arrange frames in decreasing quality order.
diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
index 9ed20b6..3d9fb8e 100644
--- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
@@ -131,7 +131,8 @@ public:
close();
}
- void close() {
+ void close()
+ {
decoder_source_mgr* src = (decoder_source_mgr*)m_info.src;
if (src)
fastFree(src);
@@ -140,13 +141,14 @@ public:
jpeg_destroy_decompress(&m_info);
}
- void skipBytes(long num_bytes) {
+ void skipBytes(long numBytes)
+ {
decoder_source_mgr* src = (decoder_source_mgr*)m_info.src;
- long bytesToSkip = std::min(num_bytes, (long)src->pub.bytes_in_buffer);
+ long bytesToSkip = std::min(numBytes, (long)src->pub.bytes_in_buffer);
src->pub.bytes_in_buffer -= (size_t)bytesToSkip;
src->pub.next_input_byte += bytesToSkip;
- m_bytesToSkip = std::max(num_bytes - bytesToSkip, static_cast<long>(0));
+ m_bytesToSkip = std::max(numBytes - bytesToSkip, static_cast<long>(0));
}
bool decode(const Vector<char>& data, bool onlySize)
@@ -192,7 +194,6 @@ public:
m_info.out_color_space = JCS_CMYK;
break;
default:
- m_state = JPEG_ERROR;
return false;
}
@@ -212,10 +213,8 @@ public:
m_state = JPEG_START_DECOMPRESS;
// We can fill in the size now that the header is available.
- if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) {
- m_state = JPEG_ERROR;
+ if (!m_decoder->setSize(m_info.image_width, m_info.image_height))
return false;
- }
if (m_decodingSizeOnly) {
// We can stop here. Reduce our buffer length and available
@@ -316,7 +315,8 @@ public:
break;
case JPEG_ERROR:
- break;
+ // We can get here if the constructor failed.
+ return m_decoder->setFailed();
}
return true;
@@ -380,20 +380,9 @@ JPEGImageDecoder::~JPEGImageDecoder()
{
}
-void JPEGImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
-{
- if (m_failed)
- return;
-
- ImageDecoder::setData(data, allDataReceived);
-
- if (!m_reader && !m_failed)
- m_reader.set(new JPEGImageReader(this));
-}
-
bool JPEGImageDecoder::isSizeAvailable()
{
- if (!ImageDecoder::isSizeAvailable() && !failed() && m_reader)
+ if (!ImageDecoder::isSizeAvailable())
decode(true);
return ImageDecoder::isSizeAvailable();
@@ -417,7 +406,7 @@ RGBA32Buffer* JPEGImageDecoder::frameBufferAtIndex(size_t index)
m_frameBufferCache.resize(1);
RGBA32Buffer& frame = m_frameBufferCache[0];
- if (frame.status() != RGBA32Buffer::FrameComplete && m_reader)
+ if (frame.status() != RGBA32Buffer::FrameComplete)
decode(false);
return &frame;
}
@@ -430,10 +419,8 @@ bool JPEGImageDecoder::outputScanlines()
// Initialize the framebuffer if needed.
RGBA32Buffer& buffer = m_frameBufferCache[0];
if (buffer.status() == RGBA32Buffer::FrameEmpty) {
- if (!buffer.setSize(scaledSize().width(), scaledSize().height())) {
- m_failed = true;
- return false;
- }
+ if (!buffer.setSize(scaledSize().width(), scaledSize().height()))
+ return setFailed();
buffer.setStatus(RGBA32Buffer::FramePartial);
buffer.setHasAlpha(false);
@@ -474,8 +461,7 @@ bool JPEGImageDecoder::outputScanlines()
buffer.setRGBA(x, destY, jsample[0] * k / 255, jsample[1] * k / 255, jsample[2] * k / 255, 0xFF);
} else {
ASSERT_NOT_REACHED();
- m_failed = true;
- return false;
+ return setFailed();
}
}
}
@@ -495,12 +481,16 @@ void JPEGImageDecoder::jpegComplete()
void JPEGImageDecoder::decode(bool onlySize)
{
- if (m_failed)
+ if (failed())
return;
- m_failed = !m_reader->decode(m_data->buffer(), onlySize);
+ if (!m_reader)
+ m_reader.set(new JPEGImageReader(this));
+
+ if (!m_reader->decode(m_data->buffer(), onlySize))
+ setFailed();
- if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete))
+ if (failed() || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete))
m_reader.clear();
}
diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
index 2a95dbe..45e14bc 100644
--- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
+++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
@@ -42,7 +42,6 @@ namespace WebCore {
// ImageDecoder
virtual String filenameExtension() const { return "jpg"; }
- virtual void setData(SharedBuffer* data, bool allDataReceived);
virtual bool isSizeAvailable();
virtual bool setSize(unsigned width, unsigned height);
virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
index 36f818f..de01d55 100644
--- a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -54,7 +54,6 @@ const unsigned long cMaxPNGSize = 1000000UL;
// Called if the decoding of the image fails.
static void PNGAPI decodingFailed(png_structp png, png_const_charp)
{
- static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->decodingFailed();
longjmp(png->jmpbuf, 1);
}
@@ -96,7 +95,6 @@ public:
, m_decodingSizeOnly(false)
, m_interlaceBuffer(0)
, m_hasAlpha(false)
- , m_hasFinishedDecoding(false)
, m_currentBufferSize(0)
{
m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning);
@@ -117,33 +115,34 @@ public:
delete[] m_interlaceBuffer;
m_interlaceBuffer = 0;
m_readOffset = 0;
- m_hasFinishedDecoding = false;
}
unsigned currentBufferSize() const { return m_currentBufferSize; }
- void setComplete() { m_hasFinishedDecoding = true; }
-
void decode(const SharedBuffer& data, bool sizeOnly)
{
m_decodingSizeOnly = sizeOnly;
+ PNGImageDecoder* decoder = static_cast<PNGImageDecoder*>(png_get_progressive_ptr(m_png));
// We need to do the setjmp here. Otherwise bad things will happen.
if (setjmp(m_png->jmpbuf)) {
close();
+ decoder->setFailed();
return;
}
- PNGImageDecoder* decoder = static_cast<PNGImageDecoder*>(png_get_progressive_ptr(m_png));
const char* segment;
while (unsigned segmentLength = data.getSomeData(segment, m_readOffset)) {
m_readOffset += segmentLength;
m_currentBufferSize = m_readOffset;
png_process_data(m_png, m_info, reinterpret_cast<png_bytep>(const_cast<char*>(segment)), segmentLength);
- if ((sizeOnly && decoder->isSizeAvailable()) || m_hasFinishedDecoding)
+ // We explicitly specify the superclass isSizeAvailable() because we
+ // merely want to check if we've managed to set the size, not
+ // (recursively) trigger additional decoding if we haven't.
+ if (sizeOnly ? decoder->ImageDecoder::isSizeAvailable() : decoder->isComplete())
return;
}
- if (!m_hasFinishedDecoding && decoder->isAllDataReceived())
+ if (!decoder->isComplete() && decoder->isAllDataReceived())
decoder->pngComplete();
}
@@ -165,7 +164,6 @@ private:
png_infop m_info;
png_bytep m_interlaceBuffer;
bool m_hasAlpha;
- bool m_hasFinishedDecoding;
unsigned m_currentBufferSize;
};
@@ -177,24 +175,23 @@ PNGImageDecoder::~PNGImageDecoder()
{
}
-void PNGImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
-{
- if (m_failed)
- return;
-
- ImageDecoder::setData(data, allDataReceived);
-
- if (!m_reader && !m_failed)
- m_reader.set(new PNGImageReader(this));
-}
bool PNGImageDecoder::isSizeAvailable()
{
- if (!ImageDecoder::isSizeAvailable() && !failed() && m_reader)
+ if (!ImageDecoder::isSizeAvailable())
decode(true);
return ImageDecoder::isSizeAvailable();
}
+bool PNGImageDecoder::setSize(unsigned width, unsigned height)
+{
+ if (!ImageDecoder::setSize(width, height))
+ return false;
+
+ prepareScaleDataIfNecessary();
+ return true;
+}
+
RGBA32Buffer* PNGImageDecoder::frameBufferAtIndex(size_t index)
{
if (index)
@@ -204,17 +201,11 @@ RGBA32Buffer* PNGImageDecoder::frameBufferAtIndex(size_t index)
m_frameBufferCache.resize(1);
RGBA32Buffer& frame = m_frameBufferCache[0];
- if (frame.status() != RGBA32Buffer::FrameComplete && m_reader)
- // Decode this frame.
+ if (frame.status() != RGBA32Buffer::FrameComplete)
decode(false);
return &frame;
}
-void PNGImageDecoder::decodingFailed()
-{
- m_failed = true;
-}
-
void PNGImageDecoder::headerAvailable()
{
png_structp png = m_reader->pngPtr();
@@ -224,19 +215,14 @@ void PNGImageDecoder::headerAvailable()
// Protect against large images.
if (png->width > cMaxPNGSize || png->height > cMaxPNGSize) {
- m_failed = true;
longjmp(png->jmpbuf, 1);
return;
}
// We can fill in the size now that the header is available.
- if (!ImageDecoder::isSizeAvailable()) {
- if (!setSize(width, height)) {
- // Size unreasonable, bail out.
- longjmp(png->jmpbuf, 1);
- return;
- }
- prepareScaleDataIfNecessary();
+ if (!setSize(width, height)) {
+ longjmp(png->jmpbuf, 1);
+ return;
}
int bitDepth, colorType, interlaceType, compressionType, filterType, channels;
@@ -299,7 +285,6 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
RGBA32Buffer& buffer = m_frameBufferCache[0];
if (buffer.status() == RGBA32Buffer::FrameEmpty) {
if (!buffer.setSize(scaledSize().width(), scaledSize().height())) {
- static_cast<PNGImageDecoder*>(png_get_progressive_ptr(m_reader->pngPtr()))->decodingFailed();
longjmp(m_reader->pngPtr()->jmpbuf, 1);
return;
}
@@ -374,20 +359,21 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
void PNGImageDecoder::pngComplete()
{
- m_reader->setComplete();
-
if (!m_frameBufferCache.isEmpty())
m_frameBufferCache.first().setStatus(RGBA32Buffer::FrameComplete);
}
void PNGImageDecoder::decode(bool onlySize)
{
- if (m_failed)
+ if (failed())
return;
+ if (!m_reader)
+ m_reader.set(new PNGImageReader(this));
+
m_reader->decode(*m_data, onlySize);
- if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete))
+ if (failed() || isComplete())
m_reader.clear();
}
diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.h b/WebCore/platform/image-decoders/png/PNGImageDecoder.h
index ba0e19a..3f0602c 100644
--- a/WebCore/platform/image-decoders/png/PNGImageDecoder.h
+++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.h
@@ -41,16 +41,20 @@ namespace WebCore {
// ImageDecoder
virtual String filenameExtension() const { return "png"; }
- virtual void setData(SharedBuffer* data, bool allDataReceived);
virtual bool isSizeAvailable();
+ virtual bool setSize(unsigned width, unsigned height);
virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
// Callbacks from libpng
- void decodingFailed();
void headerAvailable();
void rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int interlacePass);
void pngComplete();
+ bool isComplete() const
+ {
+ return !m_frameBufferCache.isEmpty() && (m_frameBufferCache.first().status() == RGBA32Buffer::FrameComplete);
+ }
+
private:
// Decodes the image. If |onlySize| is true, stops decoding after
// calculating the image size.