diff options
Diffstat (limited to 'WebCore/platform/image-decoders/png')
-rw-r--r-- | WebCore/platform/image-decoders/png/PNGImageDecoder.cpp | 112 | ||||
-rw-r--r-- | WebCore/platform/image-decoders/png/PNGImageDecoder.h | 5 |
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 |