summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/image-decoders/gif
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/image-decoders/gif')
-rw-r--r--Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp150
-rw-r--r--Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.h42
-rw-r--r--Source/WebCore/platform/image-decoders/gif/GIFImageReader.cpp23
-rw-r--r--Source/WebCore/platform/image-decoders/gif/GIFImageReader.h17
4 files changed, 116 insertions, 116 deletions
diff --git a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
index 07304769c..f8c9893ce 100644
--- a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
+++ b/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -28,14 +28,11 @@
#include "GIFImageReader.h"
#include <limits>
-#include <wtf/PassOwnPtr.h>
namespace WebCore {
-GIFImageDecoder::GIFImageDecoder(ImageSource::AlphaOption alphaOption,
- ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
+GIFImageDecoder::GIFImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
: ImageDecoder(alphaOption, gammaAndColorProfileOption)
- , m_repetitionCount(cAnimationLoopOnce)
{
}
@@ -43,14 +40,14 @@ GIFImageDecoder::~GIFImageDecoder()
{
}
-void GIFImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
+void GIFImageDecoder::setData(SharedBuffer& data, bool allDataReceived)
{
if (failed())
return;
ImageDecoder::setData(data, allDataReceived);
if (m_reader)
- m_reader->setData(data);
+ m_reader->setData(&data);
}
bool GIFImageDecoder::isSizeAvailable()
@@ -61,25 +58,25 @@ bool GIFImageDecoder::isSizeAvailable()
return ImageDecoder::isSizeAvailable();
}
-bool GIFImageDecoder::setSize(unsigned width, unsigned height)
+bool GIFImageDecoder::setSize(const IntSize& size)
{
- if (ImageDecoder::isSizeAvailable() && size() == IntSize(width, height))
+ if (ImageDecoder::isSizeAvailable() && this->size() == size)
return true;
- if (!ImageDecoder::setSize(width, height))
+ if (!ImageDecoder::setSize(size))
return false;
prepareScaleDataIfNecessary();
return true;
}
-size_t GIFImageDecoder::frameCount()
+size_t GIFImageDecoder::frameCount() const
{
- decode(std::numeric_limits<unsigned>::max(), GIFFrameCountQuery);
+ const_cast<GIFImageDecoder*>(this)->decode(std::numeric_limits<unsigned>::max(), GIFFrameCountQuery);
return m_frameBufferCache.size();
}
-int GIFImageDecoder::repetitionCount() const
+RepetitionCount GIFImageDecoder::repetitionCount() const
{
// This value can arrive at any point in the image data stream. Most GIFs
// in the wild declare it near the beginning of the file, so it usually is
@@ -106,7 +103,7 @@ int GIFImageDecoder::repetitionCount() const
// later in the stream. It is also possible that no frames are in the
// stream. In these cases we should just loop once.
if (failed() || (m_reader && (!m_reader->imagesCount())))
- m_repetitionCount = cAnimationLoopOnce;
+ m_repetitionCount = RepetitionCountOnce;
else if (m_reader && m_reader->loopCount() != cLoopCountNotSeen)
m_repetitionCount = m_reader->loopCount();
return m_repetitionCount;
@@ -118,14 +115,14 @@ ImageFrame* GIFImageDecoder::frameBufferAtIndex(size_t index)
return 0;
ImageFrame& frame = m_frameBufferCache[index];
- if (frame.status() != ImageFrame::FrameComplete)
+ if (!frame.isComplete())
decode(index + 1, GIFFullQuery);
return &frame;
}
bool GIFImageDecoder::setFailed()
{
- m_reader.clear();
+ m_reader = nullptr;
return ImageDecoder::setFailed();
}
@@ -136,6 +133,10 @@ void GIFImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame)
if (m_frameBufferCache.isEmpty())
return; // Nothing to do.
+ // Lock the decodelock here, as we are going to destroy the GIFImageReader and doing so while
+ // there's an ongoing decode will cause a crash.
+ LockHolder locker(m_decodeLock);
+
// 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
@@ -157,26 +158,30 @@ void GIFImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame)
// 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
+ // * If the frame is complete, but is DisposalMethod::RestoreToPrevious, 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
+ // has a disposal method other than DisposalMethod::RestoreToPrevious, stop
// scanning, as we'll only need this frame when decoding the next one.
Vector<ImageFrame>::iterator i(end);
- for (; (i != m_frameBufferCache.begin()) && ((i->status() == ImageFrame::FrameEmpty) || (i->disposalMethod() == ImageFrame::DisposeOverwritePrevious)); --i) {
- if ((i->status() == ImageFrame::FrameComplete) && (i != end))
- i->clearPixelData();
+ for (; (i != m_frameBufferCache.begin()) && (i->isEmpty() || (i->disposalMethod() == ImageFrame::DisposalMethod::RestoreToPrevious)); --i) {
+ if (i->isComplete() && (i != end))
+ i->clear();
}
// Now |i| holds the last frame we need to preserve; clear prior frames.
for (Vector<ImageFrame>::iterator j(m_frameBufferCache.begin()); j != i; ++j) {
- ASSERT(j->status() != ImageFrame::FramePartial);
- if (j->status() != ImageFrame::FrameEmpty)
- j->clearPixelData();
+ ASSERT(!j->isPartial());
+ if (j->isEmpty())
+ j->clear();
}
+
+ // When some frames are cleared, the reader is out of sync, since the caller might ask for any frame not
+ // necessarily in the order expected by the reader. See https://bugs.webkit.org/show_bug.cgi?id=159089.
+ m_reader = nullptr;
}
bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, const Vector<unsigned char>& rowBuffer, size_t width, size_t rowNumber, unsigned repeatCount, bool writeTransparentPixels)
@@ -210,16 +215,16 @@ bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, const Vector<unsigned
// Initialize the frame if necessary.
ImageFrame& buffer = m_frameBufferCache[frameIndex];
- if (((buffer.status() == ImageFrame::FrameEmpty) && !initFrameBuffer(frameIndex)) || !buffer.hasPixelData())
+ if ((buffer.isEmpty() && !initFrameBuffer(frameIndex)) || !buffer.hasBackingStore())
return false;
- ImageFrame::PixelData* currentAddress = buffer.getAddr(xBegin, yBegin);
+ RGBA32* currentAddress = buffer.backingStore()->pixelAt(xBegin, yBegin);
// Write one row's worth of data into the frame.
for (int x = xBegin; x < xEnd; ++x) {
const unsigned char sourceValue = rowBuffer[(m_scaled ? m_scaledColumns[x] : x) - frameContext->xOffset];
if ((!frameContext->isTransparent || (sourceValue != frameContext->tpixel)) && (sourceValue < colorMapSize)) {
const size_t colorIndex = static_cast<size_t>(sourceValue) * 3;
- buffer.setRGBA(currentAddress, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255);
+ buffer.backingStore()->setPixel(currentAddress, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255);
} else {
m_currentBufferSawAlpha = true;
// We may or may not need to write transparent pixels to the buffer.
@@ -230,34 +235,36 @@ bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, const Vector<unsigned
// beyond the first, or the initial passes will "show through" the
// later ones.
if (writeTransparentPixels)
- buffer.setRGBA(currentAddress, 0, 0, 0, 0);
+ buffer.backingStore()->setPixel(currentAddress, 0, 0, 0, 0);
}
++currentAddress;
}
// Tell the frame to copy the row data if need be.
if (repeatCount > 1)
- buffer.copyRowNTimes(xBegin, xEnd, yBegin, yEnd);
+ buffer.backingStore()->repeatFirstRow(IntRect(xBegin, yBegin, xEnd - xBegin , yEnd - yBegin));
return true;
}
-bool GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, ImageFrame::FrameDisposalMethod disposalMethod)
+bool GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, ImageFrame::DisposalMethod disposalMethod)
{
// Initialize the frame if necessary. Some GIFs insert do-nothing frames,
// in which case we never reach haveDecodedRow() before getting here.
ImageFrame& buffer = m_frameBufferCache[frameIndex];
- if ((buffer.status() == ImageFrame::FrameEmpty) && !initFrameBuffer(frameIndex))
+ if (buffer.isEmpty() && !initFrameBuffer(frameIndex))
return false; // initFrameBuffer() has already called setFailed().
- buffer.setStatus(ImageFrame::FrameComplete);
+ buffer.setDecoding(ImageFrame::Decoding::Complete);
buffer.setDuration(frameDuration);
buffer.setDisposalMethod(disposalMethod);
if (!m_currentBufferSawAlpha) {
+ IntRect rect = buffer.backingStore()->frameRect();
+
// 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.originalFrameRect().contains(IntRect(IntPoint(), scaledSize())))
+ if (rect.contains(IntRect(IntPoint(), scaledSize())))
buffer.setHasAlpha(false);
else if (frameIndex) {
// Tricky case. This frame does not have alpha only if everywhere
@@ -265,22 +272,23 @@ bool GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration,
// true, we check the start state of the frame -- if it doesn't have
// alpha, we're safe.
//
- // First skip over prior DisposeOverwritePrevious frames (since they
+ // First skip over prior DisposalMethod::RestoreToPrevious frames (since they
// don't affect the start state of this frame) the same way we do in
// initFrameBuffer().
const ImageFrame* prevBuffer = &m_frameBufferCache[--frameIndex];
- while (frameIndex && (prevBuffer->disposalMethod() == ImageFrame::DisposeOverwritePrevious))
+ while (frameIndex && (prevBuffer->disposalMethod() == ImageFrame::DisposalMethod::RestoreToPrevious))
prevBuffer = &m_frameBufferCache[--frameIndex];
- // Now, if we're at a DisposeNotSpecified or DisposeKeep frame, then
+ // Now, if we're at a DisposalMethod::Unspecified or DisposalMethod::DoNotDispose frame, then
// we can say we have no alpha if that frame had no alpha. But
// since in initFrameBuffer() we already copied that frame's alpha
// state into the current frame's, we need do nothing at all here.
//
- // The only remaining case is a DisposeOverwriteBgcolor frame. If
+ // The only remaining case is a DisposalMethod::RestoreToBackground 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() == ImageFrame::DisposeOverwriteBgcolor) && !prevBuffer->hasAlpha() && buffer.originalFrameRect().contains(prevBuffer->originalFrameRect()))
+ IntRect prevRect = prevBuffer->backingStore()->frameRect();
+ if ((prevBuffer->disposalMethod() == ImageFrame::DisposalMethod::RestoreToBackground) && !prevBuffer->hasAlpha() && rect.contains(prevRect))
buffer.setHasAlpha(false);
}
}
@@ -294,7 +302,7 @@ void GIFImageDecoder::gifComplete()
// going to be.
repetitionCount();
- m_reader.clear();
+ m_reader = nullptr;
}
void GIFImageDecoder::decode(unsigned haltAtFrame, GIFQuery query)
@@ -302,9 +310,10 @@ void GIFImageDecoder::decode(unsigned haltAtFrame, GIFQuery query)
if (failed())
return;
+ LockHolder locker(m_decodeLock);
if (!m_reader) {
- m_reader = adoptPtr(new GIFImageReader(this));
- m_reader->setData(m_data);
+ m_reader = std::make_unique<GIFImageReader>(this);
+ m_reader->setData(m_data.get());
}
if (query == GIFSizeQuery) {
@@ -318,10 +327,7 @@ void GIFImageDecoder::decode(unsigned haltAtFrame, GIFQuery query)
return;
}
- const size_t oldSize = m_frameBufferCache.size();
m_frameBufferCache.resize(m_reader->imagesCount());
- for (size_t i = oldSize; i < m_reader->imagesCount(); ++i)
- m_frameBufferCache[i].setPremultiplyAlpha(m_premultiplyAlpha);
if (query == GIFFrameCountQuery)
return;
@@ -342,66 +348,68 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
// Initialize the frame rect in our buffer.
const GIFFrameContext* frameContext = m_reader->frameContext();
IntRect frameRect(frameContext->xOffset, frameContext->yOffset, frameContext->width, frameContext->height);
-
- // Make sure the frameRect doesn't extend outside the buffer.
- if (frameRect.maxX() > size().width())
- frameRect.setWidth(size().width() - frameContext->xOffset);
- if (frameRect.maxY() > size().height())
- frameRect.setHeight(size().height() - frameContext->yOffset);
-
ImageFrame* const buffer = &m_frameBufferCache[frameIndex];
- int left = upperBoundScaledX(frameRect.x());
- int right = lowerBoundScaledX(frameRect.maxX(), left);
- int top = upperBoundScaledY(frameRect.y());
- int bottom = lowerBoundScaledY(frameRect.maxY(), top);
- buffer->setOriginalFrameRect(IntRect(left, top, right - left, bottom - top));
if (!frameIndex) {
// This is the first frame, so we're not relying on any previous data.
- if (!buffer->setSize(scaledSize().width(), scaledSize().height()))
+ if (!buffer->initialize(scaledSize(), m_premultiplyAlpha))
return setFailed();
} else {
// The starting state for this frame depends on the previous frame's
// disposal method.
//
- // Frames that use the DisposeOverwritePrevious method are effectively
+ // Frames that use the DisposalMethod::RestoreToPrevious method are effectively
// no-ops in terms of changing the starting state of a frame compared to
// the starting state of the previous frame, so skip over them. (If the
// first frame specifies this method, it will get treated like
- // DisposeOverwriteBgcolor below and reset to a completely empty image.)
+ // DisposalMethod::RestoreToBackground below and reset to a completely empty image.)
const ImageFrame* prevBuffer = &m_frameBufferCache[--frameIndex];
- ImageFrame::FrameDisposalMethod prevMethod = prevBuffer->disposalMethod();
- while (frameIndex && (prevMethod == ImageFrame::DisposeOverwritePrevious)) {
+ ImageFrame::DisposalMethod prevMethod = prevBuffer->disposalMethod();
+ while (frameIndex && (prevMethod == ImageFrame::DisposalMethod::RestoreToPrevious)) {
prevBuffer = &m_frameBufferCache[--frameIndex];
prevMethod = prevBuffer->disposalMethod();
}
- ASSERT(prevBuffer->status() == ImageFrame::FrameComplete);
- if ((prevMethod == ImageFrame::DisposeNotSpecified) || (prevMethod == ImageFrame::DisposeKeep)) {
+ ASSERT(prevBuffer->isComplete());
+
+ if ((prevMethod == ImageFrame::DisposalMethod::Unspecified) || (prevMethod == ImageFrame::DisposalMethod::DoNotDispose)) {
// Preserve the last frame as the starting state for this frame.
- if (!buffer->copyBitmapData(*prevBuffer))
+ if (!prevBuffer->backingStore() || !buffer->initialize(*prevBuffer->backingStore()))
return setFailed();
} else {
// We want to clear the previous frame to transparent, without
// affecting pixels in the image outside of the frame.
- const IntRect& prevRect = prevBuffer->originalFrameRect();
+ IntRect prevRect = prevBuffer->backingStore()->frameRect();
const IntSize& bufferSize = scaledSize();
if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) {
// Clearing the first frame, or a frame the size of the whole
// image, results in a completely empty image.
- if (!buffer->setSize(bufferSize.width(), bufferSize.height()))
+ if (!buffer->initialize(bufferSize, m_premultiplyAlpha))
return setFailed();
} else {
// Copy the whole previous buffer, then clear just its frame.
- if (!buffer->copyBitmapData(*prevBuffer))
+ if (!prevBuffer->backingStore() || !buffer->initialize(*prevBuffer->backingStore()))
return setFailed();
- buffer->zeroFillFrameRect(prevRect);
+ buffer->backingStore()->clearRect(prevRect);
+ buffer->setHasAlpha(true);
}
}
}
+ // Make sure the frameRect doesn't extend outside the buffer.
+ if (frameRect.maxX() > size().width())
+ frameRect.setWidth(size().width() - frameContext->xOffset);
+ if (frameRect.maxY() > size().height())
+ frameRect.setHeight(size().height() - frameContext->yOffset);
+
+ int left = upperBoundScaledX(frameRect.x());
+ int right = lowerBoundScaledX(frameRect.maxX(), left);
+ int top = upperBoundScaledY(frameRect.y());
+ int bottom = lowerBoundScaledY(frameRect.maxY(), top);
+ buffer->backingStore()->setFrameRect(IntRect(left, top, right - left, bottom - top));
+
// Update our status to be partially complete.
- buffer->setStatus(ImageFrame::FramePartial);
+ buffer->setDecoding(ImageFrame::Decoding::Partial);
// Reset the alpha pixel tracker for this frame.
m_currentBufferSawAlpha = false;
diff --git a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.h b/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
index f9e1b84d3..56a4010cc 100644
--- a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
+++ b/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -23,41 +23,40 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef GIFImageDecoder_h
-#define GIFImageDecoder_h
+#pragma once
#include "ImageDecoder.h"
-#include <wtf/OwnPtr.h>
+#include <wtf/Lock.h>
class GIFImageReader;
namespace WebCore {
// This class decodes the GIF image format.
- class GIFImageDecoder : public ImageDecoder {
+ class GIFImageDecoder final : public ImageDecoder {
public:
- GIFImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
+ GIFImageDecoder(AlphaOption, GammaAndColorProfileOption);
virtual ~GIFImageDecoder();
enum GIFQuery { GIFFullQuery, GIFSizeQuery, GIFFrameCountQuery };
// ImageDecoder
- virtual String filenameExtension() const { return "gif"; }
- virtual void setData(SharedBuffer* data, bool allDataReceived);
- virtual bool isSizeAvailable();
- virtual bool setSize(unsigned width, unsigned height);
- virtual size_t frameCount();
- virtual int repetitionCount() const;
- virtual ImageFrame* frameBufferAtIndex(size_t index);
+ String filenameExtension() const override { return "gif"; }
+ void setData(SharedBuffer& data, bool allDataReceived) override;
+ bool isSizeAvailable() override;
+ bool setSize(const IntSize&) override;
+ size_t frameCount() const override;
+ RepetitionCount repetitionCount() const override;
+ ImageFrame* frameBufferAtIndex(size_t index) override;
// CAUTION: setFailed() deletes |m_reader|. Be careful to avoid
// accessing deleted memory, especially when calling this from inside
// GIFImageReader!
- virtual bool setFailed();
- virtual void clearFrameBufferCache(size_t clearBeforeFrame);
+ bool setFailed() override;
+ void clearFrameBufferCache(size_t clearBeforeFrame) override;
// Callbacks from the GIF reader.
bool haveDecodedRow(unsigned frameIndex, const Vector<unsigned char>& rowBuffer, size_t width, size_t rowNumber, unsigned repeatCount, bool writeTransparentPixels);
- bool frameComplete(unsigned frameIndex, unsigned frameDuration, ImageFrame::FrameDisposalMethod disposalMethod);
+ bool frameComplete(unsigned frameIndex, unsigned frameDuration, ImageFrame::DisposalMethod);
void gifComplete();
private:
@@ -73,10 +72,9 @@ namespace WebCore {
bool initFrameBuffer(unsigned frameIndex);
bool m_currentBufferSawAlpha;
- mutable int m_repetitionCount;
- OwnPtr<GIFImageReader> m_reader;
+ mutable RepetitionCount m_repetitionCount { RepetitionCountOnce };
+ std::unique_ptr<GIFImageReader> m_reader;
+ Lock m_decodeLock;
};
} // namespace WebCore
-
-#endif
diff --git a/Source/WebCore/platform/image-decoders/gif/GIFImageReader.cpp b/Source/WebCore/platform/image-decoders/gif/GIFImageReader.cpp
index b21bbf65c..0965859fe 100644
--- a/Source/WebCore/platform/image-decoders/gif/GIFImageReader.cpp
+++ b/Source/WebCore/platform/image-decoders/gif/GIFImageReader.cpp
@@ -21,7 +21,7 @@
*
* Contributor(s):
* Chris Saari <saari@netscape.com>
- * Apple Computer
+ * Apple Inc.
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -77,7 +77,6 @@ mailing address.
#include <string.h>
#include "GIFImageDecoder.h"
-#include "ImageSource.h"
using WebCore::GIFImageDecoder;
@@ -322,9 +321,9 @@ bool GIFFrameContext::decode(const unsigned char* data, size_t length, WebCore::
if (!isDataSizeDefined() || !isHeaderDefined())
return true;
- m_lzwContext = adoptPtr(new GIFLZWContext(client, this));
+ m_lzwContext = std::make_unique<GIFLZWContext>(client, this);
if (!m_lzwContext->prepareToDecode()) {
- m_lzwContext.clear();
+ m_lzwContext = nullptr;
return false;
}
@@ -346,7 +345,7 @@ bool GIFFrameContext::decode(const unsigned char* data, size_t length, WebCore::
// There will be no more decoding for this frame so it's time to cleanup.
if (isComplete()) {
*frameDecoded = true;
- m_lzwContext.clear();
+ m_lzwContext = nullptr;
}
return true;
}
@@ -447,7 +446,7 @@ bool GIFImageReader::parse(size_t dataPosition, size_t len, bool parseSizeOnly)
// CALLBACK: Inform the decoderplugin of our size.
// Note: A subsequent frame might have dimensions larger than the "screen" dimensions.
- if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight))
+ if (m_client && !m_client->setSize(WebCore::IntSize(m_screenWidth, m_screenHeight)))
return false;
m_screenBgcolor = currentComponent[5];
@@ -568,14 +567,14 @@ bool GIFImageReader::parse(size_t dataPosition, size_t len, bool parseSizeOnly)
// We ignore the "user input" bit.
- // NOTE: This relies on the values in the FrameDisposalMethod enum
+ // NOTE: This relies on the values in the DisposalMethod enum
// matching those in the GIF spec!
int disposalMethod = ((*currentComponent) >> 2) & 0x7;
- currentFrame->disposalMethod = static_cast<WebCore::ImageFrame::FrameDisposalMethod>(disposalMethod);
+ currentFrame->disposalMethod = static_cast<WebCore::ImageFrame::DisposalMethod>(disposalMethod);
// Some specs say that disposal method 3 is "overwrite previous", others that setting
// the third bit of the field (i.e. method 4) is. We map both to the same value.
if (disposalMethod == 4)
- currentFrame->disposalMethod = WebCore::ImageFrame::DisposeOverwritePrevious;
+ currentFrame->disposalMethod = WebCore::ImageFrame::DisposalMethod::RestoreToPrevious;
currentFrame->delayTime = GETINT16(currentComponent + 1) * 10;
GETN(1, GIFConsumeBlock);
break;
@@ -624,7 +623,7 @@ bool GIFImageReader::parse(size_t dataPosition, size_t len, bool parseSizeOnly)
// Zero loop count is infinite animation loop request.
if (!m_loopCount)
- m_loopCount = WebCore::cAnimationLoopInfinite;
+ m_loopCount = WebCore::RepetitionCountInfinite;
GETN(1, GIFNetscapeExtensionBlock);
} else if (netscapeExtension == 2) {
@@ -664,7 +663,7 @@ bool GIFImageReader::parse(size_t dataPosition, size_t len, bool parseSizeOnly)
yOffset = 0;
// CALLBACK: Inform the decoderplugin of our size.
- if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight))
+ if (m_client && !m_client->setSize(WebCore::IntSize(m_screenWidth, m_screenHeight)))
return false;
}
@@ -781,7 +780,7 @@ void GIFImageReader::setRemainingBytes(size_t remainingBytes)
void GIFImageReader::addFrameIfNecessary()
{
if (m_frames.isEmpty() || m_frames.last()->isComplete())
- m_frames.append(adoptPtr(new GIFFrameContext(m_frames.size())));
+ m_frames.append(std::make_unique<GIFFrameContext>(m_frames.size()));
}
// FIXME: Move this method to close to doLZW().
diff --git a/Source/WebCore/platform/image-decoders/gif/GIFImageReader.h b/Source/WebCore/platform/image-decoders/gif/GIFImageReader.h
index bda8997d9..40b1d69f1 100644
--- a/Source/WebCore/platform/image-decoders/gif/GIFImageReader.h
+++ b/Source/WebCore/platform/image-decoders/gif/GIFImageReader.h
@@ -35,15 +35,12 @@
*
* ***** END LICENSE BLOCK ***** */
-#ifndef GIFImageReader_h
-#define GIFImageReader_h
+#pragma once
// Define ourselves as the clientPtr. Mozilla just hacked their C++ callback class into this old C decoder,
// so we will too.
#include "GIFImageDecoder.h"
#include "SharedBuffer.h"
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
#define MAX_LZW_BITS 12
@@ -157,7 +154,7 @@ public:
unsigned width;
unsigned height;
int tpixel; // Index of transparent pixel.
- WebCore::ImageFrame::FrameDisposalMethod disposalMethod; // Restore to background, leave in place, etc.
+ WebCore::ImageFrame::DisposalMethod disposalMethod; // Restore to background, leave in place, etc.
size_t localColormapPosition; // Per-image colormap.
int localColormapSize; // Size of local colormap array.
int datasize;
@@ -176,7 +173,7 @@ public:
, width(0)
, height(0)
, tpixel(0)
- , disposalMethod(WebCore::ImageFrame::DisposeNotSpecified)
+ , disposalMethod(WebCore::ImageFrame::DisposalMethod::Unspecified)
, localColormapPosition(0)
, localColormapSize(0)
, datasize(0)
@@ -215,7 +212,7 @@ public:
}
private:
- OwnPtr<GIFLZWContext> m_lzwContext;
+ std::unique_ptr<GIFLZWContext> m_lzwContext;
Vector<GIFLZWBlock> m_lzwBlocks; // LZW blocks for this frame.
size_t m_currentLzwBlock;
bool m_isComplete;
@@ -248,7 +245,7 @@ public:
{
}
- void setData(PassRefPtr<WebCore::SharedBuffer> data) { m_data = data; }
+ void setData(WebCore::SharedBuffer* data) { m_data = data; }
// FIXME: haltAtFrame should be size_t.
bool decode(WebCore::GIFImageDecoder::GIFQuery, unsigned haltAtFrame);
@@ -319,11 +316,9 @@ private:
int m_globalColormapSize; // Size of global colormap array.
int m_loopCount; // Netscape specific extension block to control the number of animation loops a GIF renders.
- Vector<OwnPtr<GIFFrameContext> > m_frames;
+ Vector<std::unique_ptr<GIFFrameContext> > m_frames;
size_t m_currentDecodingFrame;
RefPtr<WebCore::SharedBuffer> m_data;
bool m_parseCompleted;
};
-
-#endif