summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/image-decoders/png
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/image-decoders/png')
-rw-r--r--WebCore/platform/image-decoders/png/PNGImageDecoder.cpp112
-rw-r--r--WebCore/platform/image-decoders/png/PNGImageDecoder.h5
2 files changed, 50 insertions, 67 deletions
diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
index ad79fc8..35c8af0 100644
--- a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2006 Apple Computer, Inc.
* Copyright (C) 2007-2009 Torch Mobile, Inc.
+ * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
*
* Portions are Copyright (C) 2001 mozilla.org
*
@@ -39,7 +40,6 @@
#include "config.h"
#include "PNGImageDecoder.h"
#include "png.h"
-#include "assert.h"
namespace WebCore {
@@ -76,6 +76,8 @@ public:
, m_decodingSizeOnly(false)
, m_interlaceBuffer(0)
, m_hasAlpha(0)
+ , m_hasFinishedDecoding(false)
+ , m_currentBufferSize(0)
{
m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning);
m_info = png_create_info_struct(m_png);
@@ -93,9 +95,14 @@ public:
delete []m_interlaceBuffer;
m_interlaceBuffer = 0;
m_readOffset = 0;
+ m_hasFinishedDecoding = false;
}
- void decode(const Vector<char>& data, bool sizeOnly)
+ unsigned currentBufferSize() const { return m_currentBufferSize; }
+
+ void setComplete() { m_hasFinishedDecoding = true; }
+
+ void decode(const SharedBuffer& data, bool sizeOnly)
{
m_decodingSizeOnly = sizeOnly;
@@ -105,13 +112,17 @@ public:
return;
}
- // Go ahead and assume we consumed all the data. If we consume less, the
- // callback will adjust our read offset accordingly. Do not attempt to adjust the
- // offset after png_process_data returns.
- unsigned offset = m_readOffset;
- unsigned remaining = data.size() - m_readOffset;
- m_readOffset = data.size();
- png_process_data(m_png, m_info, (png_bytep)(data.data()) + offset, remaining);
+ 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)
+ return;
+ }
+ if (!m_hasFinishedDecoding && decoder->isAllDataReceived())
+ decoder->pngComplete();
}
bool decodingSizeOnly() const { return m_decodingSizeOnly; }
@@ -134,16 +145,16 @@ private:
png_infop m_info;
png_bytep m_interlaceBuffer;
bool m_hasAlpha;
+ bool m_hasFinishedDecoding;
+ unsigned m_currentBufferSize;
};
PNGImageDecoder::PNGImageDecoder()
- : m_reader(0)
{
}
PNGImageDecoder::~PNGImageDecoder()
{
- delete m_reader;
}
// Take the data and store it.
@@ -157,7 +168,7 @@ void PNGImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
// Create the PNG reader.
if (!m_reader && !m_failed)
- m_reader = new PNGImageReader(this);
+ m_reader.set(new PNGImageReader(this));
}
// Whether or not the size information has been decoded yet.
@@ -190,12 +201,10 @@ void PNGImageDecoder::decode(bool sizeOnly)
if (m_failed)
return;
- m_reader->decode(m_data->buffer(), sizeOnly);
+ m_reader->decode(*m_data, sizeOnly);
- if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) {
- delete m_reader;
- m_reader = 0;
- }
+ if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete))
+ m_reader.clear();
}
void decodingFailed(png_structp png, png_const_charp errorMsg)
@@ -224,8 +233,8 @@ void PNGImageDecoder::decodingFailed()
void PNGImageDecoder::headerAvailable()
{
- png_structp png = reader()->pngPtr();
- png_infop info = reader()->infoPtr();
+ png_structp png = m_reader->pngPtr();
+ png_infop info = m_reader->infoPtr();
png_uint_32 width = png->width;
png_uint_32 height = png->height;
@@ -243,9 +252,7 @@ void PNGImageDecoder::headerAvailable()
longjmp(png->jmpbuf, 1);
return;
}
-#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
prepareScaleDataIfNecessary();
-#endif
}
int bitDepth, colorType, interlaceType, compressionType, filterType, channels;
@@ -292,13 +299,13 @@ void PNGImageDecoder::headerAvailable()
// Update our info now
png_read_update_info(png, info);
channels = png_get_channels(png, info);
- assert(channels == 3 || channels == 4);
+ ASSERT(channels == 3 || channels == 4);
- reader()->setHasAlpha(channels == 4);
+ m_reader->setHasAlpha(channels == 4);
- if (reader()->decodingSizeOnly()) {
+ if (m_reader->decodingSizeOnly()) {
// If we only needed the size, halt the reader.
- reader()->setReadOffset(m_data->size() - png->buffer_size);
+ m_reader->setReadOffset(m_reader->currentBufferSize() - png->buffer_size);
png->buffer_size = 0;
}
}
@@ -317,16 +324,9 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
// Initialize the framebuffer if needed.
RGBA32Buffer& buffer = m_frameBufferCache[0];
if (buffer.status() == RGBA32Buffer::FrameEmpty) {
-#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
- int width = m_scaled ? m_scaledColumns.size() : size().width();
- int height = m_scaled ? m_scaledRows.size() : size().height();
-#else
- int width = size().width();
- int height = size().height();
-#endif
- if (!buffer.setSize(width, height)) {
- static_cast<PNGImageDecoder*>(png_get_progressive_ptr(reader()->pngPtr()))->decodingFailed();
- longjmp(reader()->pngPtr()->jmpbuf, 1);
+ 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;
}
buffer.setStatus(RGBA32Buffer::FramePartial);
@@ -335,8 +335,8 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
// For PNGs, the frame always fills the entire image.
buffer.setRect(IntRect(IntPoint(), size()));
- if (reader()->pngPtr()->interlaced)
- reader()->createInterlaceBuffer((reader()->hasAlpha() ? 4 : 3) * size().width() * size().height());
+ if (m_reader->pngPtr()->interlaced)
+ m_reader->createInterlaceBuffer((m_reader->hasAlpha() ? 4 : 3) * size().width() * size().height());
}
if (rowBuffer == 0)
@@ -370,11 +370,11 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
* old row and the new row.
*/
- png_structp png = reader()->pngPtr();
- bool hasAlpha = reader()->hasAlpha();
+ png_structp png = m_reader->pngPtr();
+ bool hasAlpha = m_reader->hasAlpha();
unsigned colorChannels = hasAlpha ? 4 : 3;
png_bytep row;
- png_bytep interlaceBuffer = reader()->interlaceBuffer();
+ png_bytep interlaceBuffer = m_reader->interlaceBuffer();
if (interlaceBuffer) {
row = interlaceBuffer + (rowIndex * colorChannels * size().width());
png_progressive_combine_row(png, row, rowBuffer);
@@ -383,33 +383,15 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex,
row = rowBuffer;
// Copy the data into our buffer.
-#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
- if (m_scaled) {
- int destY = scaledY(rowIndex);
- if (destY < 0)
- return;
- int columns = m_scaledColumns.size();
- bool sawAlpha = buffer.hasAlpha();
- for (int x = 0; x < columns; ++x) {
- png_bytep pixel = row + m_scaledColumns[x] * 4;
- unsigned alpha = pixel[3];
- buffer.setRGBA(x, destY, pixel[0], pixel[1], pixel[2], alpha);
- if (!sawAlpha && alpha < 255) {
- sawAlpha = true;
- buffer.setHasAlpha(true);
- }
- }
+ int width = scaledSize().width();
+ int destY = scaledY(rowIndex);
+ if (destY < 0)
return;
- }
-#endif
- int width = size().width();
bool sawAlpha = buffer.hasAlpha();
for (int x = 0; x < width; x++) {
- unsigned red = *row++;
- unsigned green = *row++;
- unsigned blue = *row++;
- unsigned alpha = (hasAlpha ? *row++ : 255);
- buffer.setRGBA(x, rowIndex, red, green, blue, alpha);
+ png_bytep pixel = row + (m_scaled ? m_scaledColumns[x] : x) * colorChannels;
+ unsigned alpha = hasAlpha ? pixel[3] : 255;
+ buffer.setRGBA(x, destY, pixel[0], pixel[1], pixel[2], alpha);
if (!sawAlpha && alpha < 255) {
sawAlpha = true;
buffer.setHasAlpha(true);
@@ -424,6 +406,8 @@ void pngComplete(png_structp png, png_infop info)
void PNGImageDecoder::pngComplete()
{
+ m_reader->setComplete();
+
if (m_frameBufferCache.isEmpty())
return;
diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.h b/WebCore/platform/image-decoders/png/PNGImageDecoder.h
index 3c0535b..07a0b3a 100644
--- a/WebCore/platform/image-decoders/png/PNGImageDecoder.h
+++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.h
@@ -27,6 +27,7 @@
#define PNGImageDecoder_h
#include "ImageDecoder.h"
+#include <wtf/OwnPtr.h>
namespace WebCore {
@@ -50,8 +51,6 @@ namespace WebCore {
void decode(bool sizeOnly = false);
- PNGImageReader* reader() { return m_reader; }
-
// Callbacks from libpng
void decodingFailed();
void headerAvailable();
@@ -59,7 +58,7 @@ namespace WebCore {
void pngComplete();
private:
- PNGImageReader* m_reader;
+ OwnPtr<PNGImageReader> m_reader;
};
} // namespace WebCore