diff options
author | Mike Reed <> | 2009-03-24 22:38:28 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-24 22:38:28 -0700 |
commit | ec1dd9995d33d4d707adc024a3d0e4bef6e48cee (patch) | |
tree | 056526d13b762b590549dfb861fec74d1104a7d6 /WebCore/platform/image-decoders | |
parent | 22c08561df8d32fc8c44f0beac60967002e4862f (diff) | |
download | external_webkit-ec1dd9995d33d4d707adc024a3d0e4bef6e48cee.zip external_webkit-ec1dd9995d33d4d707adc024a3d0e4bef6e48cee.tar.gz external_webkit-ec1dd9995d33d4d707adc024a3d0e4bef6e48cee.tar.bz2 |
Automated import from //branches/master/...@142337,142337
Diffstat (limited to 'WebCore/platform/image-decoders')
-rw-r--r-- | WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp | 55 | ||||
-rw-r--r-- | WebCore/platform/image-decoders/skia/ImageDecoder.h | 10 |
2 files changed, 48 insertions, 17 deletions
diff --git a/WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp index 38bfa97..2d77943 100644 --- a/WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp +++ b/WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp @@ -193,6 +193,7 @@ void GIFImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame) // can be asked to clear more frames than we currently have. if (m_frameBufferCache.isEmpty()) return; // Nothing to do. + // The "-1" here is tricky. It does not mean that |clearBeforeFrame| is the // last frame we wish to preserve, but rather that we never want to clear // the very last frame in the cache: it's empty (so clearing it is @@ -203,21 +204,36 @@ void GIFImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame) // this case. clearBeforeFrame = std::min(clearBeforeFrame, m_frameBufferCache.size() - 1); const Vector<RGBA32Buffer>::iterator end(m_frameBufferCache.begin() + clearBeforeFrame); - for (Vector<RGBA32Buffer>::iterator i(m_frameBufferCache.begin()); i != end; ++i) { - if (i->status() == RGBA32Buffer::FrameEmpty) - continue; // Nothing to do. - - // The layout of frames is: - // [empty frames][complete frames][partial frame][empty frames] - // ...where each of these groups may be empty. We should not clear a - // partial frame since that's what's being decoded right now, and we - // also should not clear the last complete frame, since it may be needed - // when constructing the next frame. Note that "i + 1" is safe since - // i < end < m_frameBufferCache.end(). - if ((i->status() == RGBA32Buffer::FramePartial) || ((i + 1)->status() != RGBA32Buffer::FrameComplete)) - break; - - i->clear(); + + // We need to preserve frames such that: + // * We don't clear |end| + // * We don't clear the frame we're currently decoding + // * We don't clear any frame from which a future initFrameBuffer() call + // will copy bitmap data + // All other frames can be cleared. Because of the constraints on when + // ImageSource::clear() can be called (see ImageSource.h), we're guaranteed + // not to have non-empty frames after the frame we're currently decoding. + // So, scan backwards from |end| as follows: + // * If the frame is empty, we're still past any frames we care about. + // * If the frame is complete, but is DisposeOverwritePrevious, we'll + // skip over it in future initFrameBuffer() calls. We can clear it + // unless it's |end|, and keep scanning. For any other disposal method, + // stop scanning, as we've found the frame initFrameBuffer() will need + // next. + // * If the frame is partial, we're decoding it, so don't clear it; if it + // has a disposal method other than DisposeOverwritePrevious, stop + // scanning, as we'll only need this frame when decoding the next one. + Vector<RGBA32Buffer>::iterator i(end); + for (; (i != m_frameBufferCache.begin()) && ((i->status() == RGBA32Buffer::FrameEmpty) || (i->disposalMethod() == RGBA32Buffer::DisposeOverwritePrevious)); --i) { + if ((i->status() == RGBA32Buffer::FrameComplete) && (i != end)) + i->clear(); + } + + // Now |i| holds the last frame we need to preserve; clear prior frames. + for (Vector<RGBA32Buffer>::iterator j(m_frameBufferCache.begin()); j != i; ++j) { + ASSERT(j->status() != RGBA32Buffer::FramePartial); + if (j->status() != RGBA32Buffer::FrameEmpty) + j->clear(); } } @@ -278,7 +294,6 @@ bool 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) @@ -286,6 +301,7 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) prevBuffer = &m_frameBufferCache[--frameIndex]; prevMethod = prevBuffer->disposalMethod(); } + ASSERT(prevBuffer->status() == RGBA32Buffer::FrameComplete); if ((prevMethod == RGBA32Buffer::DisposeNotSpecified) || (prevMethod == RGBA32Buffer::DisposeKeep)) { @@ -310,6 +326,9 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) // Unnecessary (but safe); see comments on the similar call above. buffer->setHasAlpha(prevBuffer->hasAlpha()); SkBitmap& bitmap = buffer->bitmap(); +#ifdef ANDROID_ANIMATED_GIF + SkAutoLockPixels alp(bitmap); +#endif for (int y = prevRect.y(); y < prevRect.bottom(); ++y) { for (int x = prevRect.x(); x < prevRect.right(); ++x) buffer->setRGBA(bitmap.getAddr32(x, y), 0, 0, 0, 0); @@ -361,6 +380,10 @@ void GIFImageDecoder::haveDecodedRow(unsigned frameIndex, if (!colorMap) return; +#ifdef ANDROID_ANIMATED_GIF + // Lock the pixels properly. Should be submitted back to webkit. + SkAutoLockPixels alp(buffer.bitmap()); +#endif // The buffers that we draw are the entire image's width and height, so a final output frame is // width * height RGBA32 values in size. // diff --git a/WebCore/platform/image-decoders/skia/ImageDecoder.h b/WebCore/platform/image-decoders/skia/ImageDecoder.h index 9988a3e..b983315 100644 --- a/WebCore/platform/image-decoders/skia/ImageDecoder.h +++ b/WebCore/platform/image-decoders/skia/ImageDecoder.h @@ -39,6 +39,9 @@ #include <wtf/Vector.h> #include "SkBitmap.h" +#ifdef ANDROID_ANIMATED_GIF +#include "SkColor.h" +#endif namespace WebCore { @@ -169,7 +172,7 @@ namespace WebCore { bmp.setConfig(SkBitmap::kARGB_8888_Config, width, height); if (!bmp.allocPixels()) return false; // Allocation failure, maybe the bitmap was too big. - + // Clear the image. bmp.eraseARGB(0, 0, 0, 0); @@ -199,6 +202,10 @@ namespace WebCore { static void setRGBA(uint32_t* dest, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { // We store this data pre-multiplied. +#ifdef ANDROID_ANIMATED_GIF + // Chrome should take this change as well. + *dest = SkPreMultiplyARGB(a, r, g, b); +#else if (a == 0) *dest = 0; else { @@ -210,6 +217,7 @@ namespace WebCore { } *dest = (a << 24 | r << 16 | g << 8 | b); } +#endif } void setRGBA(int x, int y, uint8_t r, uint8_t g, uint8_t b, uint8_t a) |