summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp')
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp92
1 files changed, 45 insertions, 47 deletions
diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
index 5b4b675..62d8b5b 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -27,17 +27,14 @@
#include "GIFImageDecoder.h"
#include "GIFImageReader.h"
-#if PLATFORM(CAIRO) || PLATFORM(QT) || PLATFORM(WX)
-
namespace WebCore {
-class GIFImageDecoderPrivate
-{
+class GIFImageDecoderPrivate {
public:
GIFImageDecoderPrivate(GIFImageDecoder* decoder = 0)
: m_reader(decoder)
+ , m_readOffset(0)
{
- m_readOffset = 0;
}
~GIFImageDecoderPrivate()
@@ -45,11 +42,11 @@ public:
m_reader.close();
}
- bool decode(const Vector<char>& data,
+ bool decode(SharedBuffer* data,
GIFImageDecoder::GIFQuery query = GIFImageDecoder::GIFFullQuery,
unsigned int haltFrame = -1)
{
- return m_reader.read((const unsigned char*)data.data() + m_readOffset, data.size() - m_readOffset,
+ return m_reader.read((const unsigned char*)data->data() + m_readOffset, data->size() - m_readOffset,
query,
haltFrame);
}
@@ -61,7 +58,8 @@ public:
bool isTransparent() const { return m_reader.frame_reader->is_transparent; }
- void getColorMap(unsigned char*& map, unsigned& size) const {
+ void getColorMap(unsigned char*& map, unsigned& size) const
+ {
if (m_reader.frame_reader->is_local_colormap_defined) {
map = m_reader.frame_reader->local_colormap;
size = (unsigned)m_reader.frame_reader->local_colormap_size;
@@ -86,8 +84,11 @@ private:
};
GIFImageDecoder::GIFImageDecoder()
-: m_frameCountValid(true), m_repetitionCount(cAnimationLoopOnce), m_reader(0)
-{}
+ : m_frameCountValid(true)
+ , m_repetitionCount(cAnimationLoopOnce)
+ , m_reader(0)
+{
+}
GIFImageDecoder::~GIFImageDecoder()
{
@@ -139,7 +140,10 @@ int GIFImageDecoder::frameCount()
// state, but for now we just crawl all the data. Note that this is no worse than what
// ImageIO does on Mac right now (it also crawls all the data again).
GIFImageDecoderPrivate reader;
- reader.decode(m_data->buffer(), GIFFrameCountQuery);
+ // This function may fail, but we want to keep any partial data it may
+ // have decoded, so don't mark it is invalid. If there is an overflow
+ // or some serious error, m_failed will have gotten set for us.
+ reader.decode(m_data.get(), GIFFrameCountQuery);
m_frameCountValid = true;
m_frameBufferCache.resize(reader.frameCount());
}
@@ -173,13 +177,12 @@ int GIFImageDecoder::repetitionCount() const
RGBA32Buffer* GIFImageDecoder::frameBufferAtIndex(size_t index)
{
- if (index >= frameCount())
+ if (index >= static_cast<size_t>(frameCount()))
return 0;
RGBA32Buffer& frame = m_frameBufferCache[index];
if (frame.status() != RGBA32Buffer::FrameComplete && m_reader)
- // Decode this frame.
- decode(GIFFullQuery, index+1);
+ decode(GIFFullQuery, index + 1); // Decode this frame.
return &frame;
}
@@ -239,7 +242,7 @@ void GIFImageDecoder::decode(GIFQuery query, unsigned haltAtFrame) const
if (m_failed)
return;
- m_failed = !m_reader->decode(m_data->buffer(), query, haltAtFrame);
+ m_failed = !m_reader->decode(m_data.get(), query, haltAtFrame);
if (m_failed) {
delete m_reader;
@@ -266,10 +269,10 @@ void GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
m_reader->frameWidth(), m_reader->frameHeight());
// Make sure the frameRect doesn't extend past the bottom-right of the buffer.
- if (frameRect.right() > m_size.width())
- frameRect.setWidth(m_size.width() - m_reader->frameXOffset());
- if (frameRect.bottom() > m_size.height())
- frameRect.setHeight(m_size.height() - m_reader->frameYOffset());
+ if (frameRect.right() > size().width())
+ frameRect.setWidth(size().width() - m_reader->frameXOffset());
+ if (frameRect.bottom() > size().height())
+ frameRect.setHeight(size().height() - m_reader->frameYOffset());
RGBA32Buffer* const buffer = &m_frameBufferCache[frameIndex];
buffer->setRect(frameRect);
@@ -287,14 +290,14 @@ void GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
// first frame specifies this method, it will get treated like
// DisposeOverwriteBgcolor below and reset to a completely empty image.)
const RGBA32Buffer* prevBuffer = &m_frameBufferCache[--frameIndex];
- ASSERT(prevBuffer->status() == RGBA32Buffer::FrameComplete);
RGBA32Buffer::FrameDisposalMethod prevMethod =
prevBuffer->disposalMethod();
- while ((frameIndex > 0) &&
- (prevMethod == RGBA32Buffer::DisposeOverwritePrevious)) {
+ while ((frameIndex > 0)
+ && (prevMethod == RGBA32Buffer::DisposeOverwritePrevious)) {
prevBuffer = &m_frameBufferCache[--frameIndex];
prevMethod = prevBuffer->disposalMethod();
}
+ ASSERT(prevBuffer->status() == RGBA32Buffer::FrameComplete);
if ((prevMethod == RGBA32Buffer::DisposeNotSpecified) ||
(prevMethod == RGBA32Buffer::DisposeKeep)) {
@@ -305,8 +308,8 @@ void GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
// We want to clear the previous frame to transparent, without
// affecting pixels in the image outside of the frame.
const IntRect& prevRect = prevBuffer->rect();
- if ((frameIndex == 0) ||
- prevRect.contains(IntRect(IntPoint(0, 0), m_size))) {
+ if ((frameIndex == 0)
+ || prevRect.contains(IntRect(IntPoint(0, 0), size()))) {
// Clearing the first frame, or a frame the size of the whole
// image, results in a completely empty image.
prepEmptyFrameBuffer(buffer);
@@ -321,7 +324,7 @@ void GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
buffer->setRGBA(*(currentRow + x), 0, 0, 0, 0);
}
if ((prevRect.width() > 0) && (prevRect.height() > 0))
- buffer->setHasAlpha(true);
+ buffer->setHasAlpha(true);
}
}
}
@@ -335,7 +338,7 @@ void GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
void GIFImageDecoder::prepEmptyFrameBuffer(RGBA32Buffer* buffer) const
{
- buffer->bytes().resize(m_size.width() * m_size.height());
+ buffer->bytes().resize(size().width() * size().height());
buffer->bytes().fill(0);
buffer->setHasAlpha(true);
}
@@ -353,8 +356,8 @@ void GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
initFrameBuffer(frameIndex);
// Do nothing for bogus data.
- if (rowBuffer == 0 || static_cast<int>(m_reader->frameYOffset() + rowNumber) >= m_size.height())
- return;
+ if (rowBuffer == 0 || static_cast<int>(m_reader->frameYOffset() + rowNumber) >= size().height())
+ return;
unsigned colorMapSize;
unsigned char* colorMap;
@@ -369,12 +372,12 @@ void GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
// within the overall image. The rows we are decoding are within this
// sub-rectangle. This means that if the GIF frame's sub-rectangle is (x,y,w,h) then row 0 is really row
// y, and each row goes from x to x+w.
- unsigned dstPos = (m_reader->frameYOffset() + rowNumber) * m_size.width() + m_reader->frameXOffset();
+ unsigned dstPos = (m_reader->frameYOffset() + rowNumber) * size().width() + m_reader->frameXOffset();
unsigned* dst = buffer.bytes().data() + dstPos;
- unsigned* dstEnd = dst + m_size.width() - m_reader->frameXOffset();
+ unsigned* dstEnd = dst + size().width() - m_reader->frameXOffset();
unsigned* currDst = dst;
unsigned char* currentRowByte = rowBuffer;
-
+
while (currentRowByte != rowEnd && currDst < dstEnd) {
if ((!m_reader->isTransparent() || *currentRowByte != m_reader->transparentPixel()) && *currentRowByte < colorMapSize) {
unsigned colorIndex = *currentRowByte * 3;
@@ -401,14 +404,14 @@ void GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
if (repeatCount > 1) {
// Copy the row |repeatCount|-1 times.
unsigned num = currDst - dst;
- unsigned size = num * sizeof(unsigned);
- unsigned width = m_size.width();
- unsigned* end = buffer.bytes().data() + width * m_size.height();
+ unsigned data_size = num * sizeof(unsigned);
+ unsigned width = size().width();
+ unsigned* end = buffer.bytes().data() + width * size().height();
currDst = dst + width;
for (unsigned i = 1; i < repeatCount; i++) {
if (currDst + num > end) // Protect against a buffer overrun from a bogus repeatCount.
break;
- memcpy(currDst, dst, size);
+ memcpy(currDst, dst, data_size);
currDst += width;
}
}
@@ -434,9 +437,9 @@ void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration,
if (!m_currentBufferSawAlpha) {
// The whole frame was non-transparent, so it's possible that the entire
// resulting buffer was non-transparent, and we can setHasAlpha(false).
- if (buffer.rect().contains(IntRect(IntPoint(0, 0), m_size))) {
+ if (buffer.rect().contains(IntRect(IntPoint(0, 0), size())))
buffer.setHasAlpha(false);
- } else if (frameIndex > 0) {
+ else if (frameIndex > 0) {
// Tricky case. This frame does not have alpha only if everywhere
// outside its rect doesn't have alpha. To know whether this is
// true, we check the start state of the frame -- if it doesn't have
@@ -446,9 +449,8 @@ void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration,
// don't affect the start state of this frame) the same way we do in
// initFrameBuffer().
const RGBA32Buffer* prevBuffer = &m_frameBufferCache[--frameIndex];
- while ((frameIndex > 0) &&
- (prevBuffer->disposalMethod() ==
- RGBA32Buffer::DisposeOverwritePrevious))
+ while ((frameIndex > 0)
+ && (prevBuffer->disposalMethod() == RGBA32Buffer::DisposeOverwritePrevious))
prevBuffer = &m_frameBufferCache[--frameIndex];
// Now, if we're at a DisposeNotSpecified or DisposeKeep frame, then
@@ -459,10 +461,8 @@ void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration,
// The only remaining case is a DisposeOverwriteBgcolor frame. If
// it had no alpha, and its rect is contained in the current frame's
// rect, we know the current frame has no alpha.
- if ((prevBuffer->disposalMethod() ==
- RGBA32Buffer::DisposeOverwriteBgcolor) &&
- !prevBuffer->hasAlpha() &&
- buffer.rect().contains(prevBuffer->rect()))
+ if ((prevBuffer->disposalMethod() == RGBA32Buffer::DisposeOverwriteBgcolor)
+ && !prevBuffer->hasAlpha() && buffer.rect().contains(prevBuffer->rect()))
buffer.setHasAlpha(false);
}
}
@@ -476,6 +476,4 @@ void GIFImageDecoder::gifComplete()
m_reader = 0;
}
-}
-
-#endif // PLATFORM(CAIRO)
+} // namespace WebCore