diff options
Diffstat (limited to 'WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp')
-rw-r--r-- | WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp | 92 |
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 |