You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
514 lines
20 KiB
514 lines
20 KiB
6 years ago
|
diff -up webkitgtk-2.20.2/Source/cmake/FindWebP.cmake.no_webp_demux webkitgtk-2.20.2/Source/cmake/FindWebP.cmake
|
||
|
--- webkitgtk-2.20.2/Source/cmake/FindWebP.cmake.no_webp_demux 2018-02-19 08:45:33.000000000 +0100
|
||
|
+++ webkitgtk-2.20.2/Source/cmake/FindWebP.cmake 2018-05-11 08:36:41.026235222 +0200
|
||
|
@@ -33,34 +33,20 @@ find_package(PkgConfig)
|
||
|
pkg_check_modules(PC_WEBP QUIET libwebp)
|
||
|
|
||
|
# Look for the header file.
|
||
|
-find_path(WEBP_INCLUDE_DIR
|
||
|
+find_path(WEBP_INCLUDE_DIRS
|
||
|
NAMES webp/decode.h
|
||
|
HINTS ${PC_WEBP_INCLUDEDIR} ${PC_WEBP_INCLUDE_DIRS}
|
||
|
)
|
||
|
-list(APPEND WEBP_INCLUDE_DIRS ${WEBP_INCLUDE_DIR})
|
||
|
mark_as_advanced(WEBP_INCLUDE_DIRS)
|
||
|
|
||
|
# Look for the library.
|
||
|
find_library(
|
||
|
- WEBP_LIBRARY
|
||
|
+ WEBP_LIBRARIES
|
||
|
NAMES webp
|
||
|
HINTS ${PC_WEBP_LIBDIR} ${PC_WEBP_LIBRARY_DIRS}
|
||
|
)
|
||
|
-list(APPEND WEBP_LIBRARIES ${WEBP_LIBRARY})
|
||
|
mark_as_advanced(WEBP_LIBRARIES)
|
||
|
|
||
|
-find_path(WEBP_DEMUX_INCLUDE_DIR
|
||
|
- NAMES webp/demux.h
|
||
|
- HINTS ${PC_WEBP_INCLUDEDIR} ${PC_WEBP_INCLUDE_DIRS}
|
||
|
-)
|
||
|
-list(APPEND WEBP_INCLUDE_DIRS ${WEBP_DEMUX_INCLUDE_DIR})
|
||
|
-
|
||
|
-find_library(WEBP_DEMUX_LIBRARY
|
||
|
- NAMES webpdemux
|
||
|
- HINTS ${PC_WEBP_LIBDIR} ${PC_WEBP_LIBRARY_DIRS}
|
||
|
-)
|
||
|
-list(APPEND WEBP_LIBRARIES ${WEBP_DEMUX_LIBRARY})
|
||
|
-
|
||
|
include(FindPackageHandleStandardArgs)
|
||
|
find_package_handle_standard_args(WebP REQUIRED_VARS WEBP_INCLUDE_DIRS WEBP_LIBRARIES
|
||
|
FOUND_VAR WEBP_FOUND)
|
||
|
diff -up webkitgtk-2.20.2/Source/WebCore/platform/graphics/ImageBackingStore.h.no_webp_demux webkitgtk-2.20.2/Source/WebCore/platform/graphics/ImageBackingStore.h
|
||
|
--- webkitgtk-2.20.2/Source/WebCore/platform/graphics/ImageBackingStore.h.no_webp_demux 2018-02-19 08:45:32.000000000 +0100
|
||
|
+++ webkitgtk-2.20.2/Source/WebCore/platform/graphics/ImageBackingStore.h 2018-05-11 08:36:41.027235218 +0200
|
||
|
@@ -147,6 +147,7 @@ public:
|
||
|
setPixel(pixelAt(x, y), r, g, b, a);
|
||
|
}
|
||
|
|
||
|
+#if ENABLE(APNG)
|
||
|
void blendPixel(RGBA32* dest, unsigned r, unsigned g, unsigned b, unsigned a)
|
||
|
{
|
||
|
if (!a)
|
||
|
@@ -172,6 +173,7 @@ public:
|
||
|
else
|
||
|
*dest = makeUnPremultipliedRGBA(r, g, b, a);
|
||
|
}
|
||
|
+#endif
|
||
|
|
||
|
static bool isOverSize(const IntSize& size)
|
||
|
{
|
||
|
diff -up webkitgtk-2.20.2/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp.no_webp_demux webkitgtk-2.20.2/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
|
||
|
--- webkitgtk-2.20.2/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp.no_webp_demux 2018-02-19 08:45:32.000000000 +0100
|
||
|
+++ webkitgtk-2.20.2/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp 2018-05-11 09:19:25.756550925 +0200
|
||
|
@@ -31,49 +31,47 @@
|
||
|
|
||
|
#if USE(WEBP)
|
||
|
|
||
|
-namespace WebCore {
|
||
|
+// Backward emulation for earlier versions than 0.1.99.
|
||
|
+#if (WEBP_DECODER_ABI_VERSION < 0x0163)
|
||
|
+#define MODE_rgbA MODE_RGBA
|
||
|
+#define MODE_bgrA MODE_BGRA
|
||
|
+#endif
|
||
|
+
|
||
|
+#if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN)
|
||
|
+inline WEBP_CSP_MODE outputMode(bool hasAlpha) { return hasAlpha ? MODE_rgbA : MODE_RGBA; }
|
||
|
+#else // LITTLE_ENDIAN, output BGRA pixels.
|
||
|
+inline WEBP_CSP_MODE outputMode(bool hasAlpha) { return hasAlpha ? MODE_bgrA : MODE_BGRA; }
|
||
|
+#endif
|
||
|
|
||
|
-// Convenience function to improve code readability, as WebPDemuxGetFrame is +1 based.
|
||
|
-bool webpFrameAtIndex(WebPDemuxer* demuxer, size_t index, WebPIterator* webpFrame)
|
||
|
-{
|
||
|
- return WebPDemuxGetFrame(demuxer, index + 1, webpFrame);
|
||
|
-}
|
||
|
+namespace WebCore {
|
||
|
|
||
|
WEBPImageDecoder::WEBPImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
|
||
|
: ScalableImageDecoder(alphaOption, gammaAndColorProfileOption)
|
||
|
+ , m_decoder(0)
|
||
|
+ , m_hasAlpha(false)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
-WEBPImageDecoder::~WEBPImageDecoder() = default;
|
||
|
-
|
||
|
-void WEBPImageDecoder::setData(SharedBuffer& data, bool allDataReceived)
|
||
|
+WEBPImageDecoder::~WEBPImageDecoder()
|
||
|
{
|
||
|
- if (failed())
|
||
|
- return;
|
||
|
-
|
||
|
- // We need to ensure that the header is parsed everytime new data arrives, as the number
|
||
|
- // of frames may change until we have the complete data. If the size has not been obtained
|
||
|
- // yet, the call to ScalableImageDecoder::setData() will call parseHeader() and set
|
||
|
- // m_headerParsed to true, so the call to parseHeader() at the end won't do anything. If the size
|
||
|
- // is available, then parseHeader() is only called once.
|
||
|
- m_headerParsed = false;
|
||
|
- ScalableImageDecoder::setData(data, allDataReceived);
|
||
|
- parseHeader();
|
||
|
+ clear();
|
||
|
}
|
||
|
|
||
|
-RepetitionCount WEBPImageDecoder::repetitionCount() const
|
||
|
+void WEBPImageDecoder::clear()
|
||
|
{
|
||
|
- if (failed())
|
||
|
- return RepetitionCountOnce;
|
||
|
-
|
||
|
- return m_repetitionCount ? m_repetitionCount : RepetitionCountInfinite;
|
||
|
+ if (m_decoder)
|
||
|
+ WebPIDelete(m_decoder);
|
||
|
+ m_decoder = 0;
|
||
|
}
|
||
|
|
||
|
ImageFrame* WEBPImageDecoder::frameBufferAtIndex(size_t index)
|
||
|
{
|
||
|
- if (index >= frameCount())
|
||
|
+ if (index)
|
||
|
return 0;
|
||
|
|
||
|
+ if (m_frameBufferCache.isEmpty())
|
||
|
+ m_frameBufferCache.grow(1);
|
||
|
+
|
||
|
// The size of m_frameBufferCache may be smaller than the index requested. This can happen
|
||
|
// because new data may have arrived with a bigger frameCount, but decode() hasn't been called
|
||
|
// yet, which is the one that resizes the cache.
|
||
|
@@ -85,275 +83,73 @@ ImageFrame* WEBPImageDecoder::frameBuffe
|
||
|
return &m_frameBufferCache[index];
|
||
|
}
|
||
|
|
||
|
-size_t WEBPImageDecoder::findFirstRequiredFrameToDecode(size_t frameIndex, WebPDemuxer* demuxer)
|
||
|
-{
|
||
|
- // The first frame doesn't depend on any other.
|
||
|
- if (!frameIndex)
|
||
|
- return 0;
|
||
|
-
|
||
|
- // Go backwards and find the first complete frame.
|
||
|
- size_t firstIncompleteFrame = frameIndex;
|
||
|
- for (; firstIncompleteFrame; --firstIncompleteFrame) {
|
||
|
- if (m_frameBufferCache[firstIncompleteFrame - 1].isComplete())
|
||
|
- break;
|
||
|
- }
|
||
|
-
|
||
|
- // Check if there are any independent frames between firstIncompleteFrame and frameIndex.
|
||
|
- for (size_t firstIndependentFrame = frameIndex; firstIndependentFrame > firstIncompleteFrame ; --firstIndependentFrame) {
|
||
|
- WebPIterator webpFrame;
|
||
|
- if (!webpFrameAtIndex(demuxer, firstIndependentFrame, &webpFrame))
|
||
|
- continue;
|
||
|
-
|
||
|
- IntRect frameRect(webpFrame.x_offset, webpFrame.y_offset, webpFrame.width, webpFrame.height);
|
||
|
- if (!frameRect.contains({ { }, size() }))
|
||
|
- continue;
|
||
|
-
|
||
|
- // This frame covers the whole area and doesn't have alpha, so it can be rendered without
|
||
|
- // dependencies.
|
||
|
- if (!webpFrame.has_alpha)
|
||
|
- return firstIndependentFrame;
|
||
|
-
|
||
|
- // This frame covers the whole area and its disposalMethod is RestoreToBackground, which means
|
||
|
- // that the next frame will be rendered on top of a transparent background, and can be decoded
|
||
|
- // without dependencies. This can only be checked for frames prior to frameIndex.
|
||
|
- if (firstIndependentFrame < frameIndex && m_frameBufferCache[firstIndependentFrame].disposalMethod() == ImageFrame::DisposalMethod::RestoreToBackground)
|
||
|
- return firstIndependentFrame + 1;
|
||
|
- }
|
||
|
-
|
||
|
- return firstIncompleteFrame;
|
||
|
-}
|
||
|
-
|
||
|
-void WEBPImageDecoder::decode(size_t frameIndex, bool allDataReceived)
|
||
|
+bool WEBPImageDecoder::decode(bool onlySize, bool)
|
||
|
{
|
||
|
if (failed())
|
||
|
- return;
|
||
|
-
|
||
|
- // This can be executed both in the main thread (when not using async decoding) or in the decoding thread.
|
||
|
- // When executed in the decoding thread, a call to setData() from the main thread may change the data
|
||
|
- // the WebPDemuxer is using, leaving it in an inconsistent state, so we need to protect the data.
|
||
|
- RefPtr<SharedBuffer> protectedData(m_data);
|
||
|
- WebPData inputData = { reinterpret_cast<const uint8_t*>(protectedData->data()), protectedData->size() };
|
||
|
- WebPDemuxState demuxerState;
|
||
|
- WebPDemuxer* demuxer = WebPDemuxPartial(&inputData, &demuxerState);
|
||
|
- if (!demuxer) {
|
||
|
- setFailed();
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- m_frameBufferCache.resize(m_frameCount);
|
||
|
-
|
||
|
- // It is a fatal error if all data is received and we have decoded all frames available but the file is truncated.
|
||
|
- if (frameIndex >= m_frameBufferCache.size() - 1 && allDataReceived && demuxer && demuxerState != WEBP_DEMUX_DONE) {
|
||
|
- WebPDemuxDelete(demuxer);
|
||
|
- setFailed();
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- for (size_t i = findFirstRequiredFrameToDecode(frameIndex, demuxer); i <= frameIndex; i++)
|
||
|
- decodeFrame(i, demuxer);
|
||
|
+ return false;
|
||
|
|
||
|
- WebPDemuxDelete(demuxer);
|
||
|
-}
|
||
|
+ const uint8_t* dataBytes = reinterpret_cast<const uint8_t*>(m_data->data());
|
||
|
+ const size_t dataSize = m_data->size();
|
||
|
|
||
|
-void WEBPImageDecoder::decodeFrame(size_t frameIndex, WebPDemuxer* demuxer)
|
||
|
-{
|
||
|
- if (failed())
|
||
|
- return;
|
||
|
+ if (ScalableImageDecoder::encodedDataStatus() < EncodedDataStatus::SizeAvailable) {
|
||
|
+ static const size_t imageHeaderSize = 30;
|
||
|
+ if (dataSize < imageHeaderSize)
|
||
|
+ return false;
|
||
|
+ int width, height;
|
||
|
+#if (WEBP_DECODER_ABI_VERSION >= 0x0163)
|
||
|
+ WebPBitstreamFeatures features;
|
||
|
+ if (WebPGetFeatures(dataBytes, dataSize, &features) != VP8_STATUS_OK)
|
||
|
+ return setFailed();
|
||
|
+ width = features.width;
|
||
|
+ height = features.height;
|
||
|
+ m_hasAlpha = features.has_alpha;
|
||
|
+#else
|
||
|
+ // Earlier version won't be able to display WebP files with alpha.
|
||
|
+ if (!WebPGetInfo(dataBytes, dataSize, &width, &height))
|
||
|
+ return setFailed();
|
||
|
+ m_hasAlpha = false;
|
||
|
+#endif
|
||
|
+ if (!setSize(IntSize(width, height)))
|
||
|
+ return setFailed();
|
||
|
+ }
|
||
|
+
|
||
|
+ ASSERT(ScalableImageDecoder::encodedDataStatus() >= EncodedDataStatus::SizeAvailable);
|
||
|
+ if (onlySize)
|
||
|
+ return true;
|
||
|
|
||
|
- WebPIterator webpFrame;
|
||
|
- if (!webpFrameAtIndex(demuxer, frameIndex, &webpFrame))
|
||
|
- return;
|
||
|
-
|
||
|
- const uint8_t* dataBytes = reinterpret_cast<const uint8_t*>(webpFrame.fragment.bytes);
|
||
|
- size_t dataSize = webpFrame.fragment.size;
|
||
|
- bool blend = webpFrame.blend_method == WEBP_MUX_BLEND ? true : false;
|
||
|
-
|
||
|
- ASSERT(m_frameBufferCache.size() > frameIndex);
|
||
|
- ImageFrame& buffer = m_frameBufferCache[frameIndex];
|
||
|
- buffer.setDuration(Seconds::fromMilliseconds(webpFrame.duration));
|
||
|
- buffer.setDisposalMethod(webpFrame.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ? ImageFrame::DisposalMethod::RestoreToBackground : ImageFrame::DisposalMethod::DoNotDispose);
|
||
|
+ ASSERT(!m_frameBufferCache.isEmpty());
|
||
|
+ ImageFrame& buffer = m_frameBufferCache[0];
|
||
|
ASSERT(!buffer.isComplete());
|
||
|
|
||
|
- if (buffer.isInvalid() && !initFrameBuffer(frameIndex, &webpFrame)) {
|
||
|
- setFailed();
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- WebPDecBuffer decoderBuffer;
|
||
|
- WebPInitDecBuffer(&decoderBuffer);
|
||
|
- decoderBuffer.colorspace = MODE_RGBA;
|
||
|
- decoderBuffer.u.RGBA.stride = webpFrame.width * sizeof(RGBA32);
|
||
|
- decoderBuffer.u.RGBA.size = decoderBuffer.u.RGBA.stride * webpFrame.height;
|
||
|
- decoderBuffer.is_external_memory = 1;
|
||
|
- std::unique_ptr<unsigned char[]> p(new uint8_t[decoderBuffer.u.RGBA.size]());
|
||
|
- decoderBuffer.u.RGBA.rgba = p.get();
|
||
|
- if (!decoderBuffer.u.RGBA.rgba) {
|
||
|
- setFailed();
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- WebPIDecoder* decoder = WebPINewDecoder(&decoderBuffer);
|
||
|
- if (!decoder) {
|
||
|
- setFailed();
|
||
|
- return;
|
||
|
+ if (buffer.isInvalid()) {
|
||
|
+ if (!buffer.initialize(size(), m_premultiplyAlpha))
|
||
|
+ return setFailed();
|
||
|
+ buffer.setDecodingStatus(DecodingStatus::Partial);
|
||
|
+ buffer.setHasAlpha(m_hasAlpha);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!m_decoder) {
|
||
|
+ WEBP_CSP_MODE mode = outputMode(m_hasAlpha);
|
||
|
+ if (!m_premultiplyAlpha)
|
||
|
+ mode = outputMode(false);
|
||
|
+ int rowStride = size().width() * sizeof(RGBA32);
|
||
|
+ uint8_t* output = reinterpret_cast<uint8_t*>(buffer.backingStore()->pixelAt(0, 0));
|
||
|
+ int outputSize = size().height() * rowStride;
|
||
|
+ m_decoder = WebPINewRGB(mode, output, outputSize, rowStride);
|
||
|
+ if (!m_decoder)
|
||
|
+ return setFailed();
|
||
|
}
|
||
|
|
||
|
- switch (WebPIUpdate(decoder, dataBytes, dataSize)) {
|
||
|
+ switch (WebPIUpdate(m_decoder, dataBytes, dataSize)) {
|
||
|
case VP8_STATUS_OK:
|
||
|
- applyPostProcessing(frameIndex, decoder, decoderBuffer, blend);
|
||
|
buffer.setDecodingStatus(DecodingStatus::Complete);
|
||
|
- break;
|
||
|
+ clear();
|
||
|
+ return true;
|
||
|
case VP8_STATUS_SUSPENDED:
|
||
|
- if (!isAllDataReceived()) {
|
||
|
- applyPostProcessing(frameIndex, decoder, decoderBuffer, blend);
|
||
|
- buffer.setDecodingStatus(DecodingStatus::Partial);
|
||
|
- break;
|
||
|
- }
|
||
|
- // Fallthrough.
|
||
|
- default:
|
||
|
- setFailed();
|
||
|
- }
|
||
|
-
|
||
|
- WebPIDelete(decoder);
|
||
|
-}
|
||
|
-
|
||
|
-bool WEBPImageDecoder::initFrameBuffer(size_t frameIndex, const WebPIterator* webpFrame)
|
||
|
-{
|
||
|
- if (frameIndex >= frameCount())
|
||
|
return false;
|
||
|
-
|
||
|
- ImageFrame& buffer = m_frameBufferCache[frameIndex];
|
||
|
-
|
||
|
- // Initialize the frame rect in our buffer.
|
||
|
- IntRect frameRect(webpFrame->x_offset, webpFrame->y_offset, webpFrame->width, webpFrame->height);
|
||
|
-
|
||
|
- // Make sure the frameRect doesn't extend outside the buffer.
|
||
|
- frameRect.intersect({ { }, size() });
|
||
|
-
|
||
|
- if (!frameIndex || !m_frameBufferCache[frameIndex - 1].backingStore()) {
|
||
|
- // This frame doesn't rely on any previous data.
|
||
|
- if (!buffer.initialize(size(), m_premultiplyAlpha))
|
||
|
- return false;
|
||
|
- } else {
|
||
|
- const ImageFrame& prevBuffer = m_frameBufferCache[frameIndex - 1];
|
||
|
- ASSERT(prevBuffer.isComplete());
|
||
|
-
|
||
|
- // Preserve the last frame as the starting state for this frame.
|
||
|
- if (!prevBuffer.backingStore() || !buffer.initialize(*prevBuffer.backingStore()))
|
||
|
- return false;
|
||
|
-
|
||
|
- if (prevBuffer.disposalMethod() == ImageFrame::DisposalMethod::RestoreToBackground) {
|
||
|
- // We want to clear the previous frame to transparent, without
|
||
|
- // affecting pixels in the image outside of the frame.
|
||
|
- const IntRect& prevRect = prevBuffer.backingStore()->frameRect();
|
||
|
- buffer.backingStore()->clearRect(prevRect);
|
||
|
- }
|
||
|
- }
|
||
|
-
|
||
|
- buffer.setHasAlpha(webpFrame->has_alpha);
|
||
|
- buffer.backingStore()->setFrameRect(frameRect);
|
||
|
-
|
||
|
- return true;
|
||
|
-}
|
||
|
-
|
||
|
-void WEBPImageDecoder::applyPostProcessing(size_t frameIndex, WebPIDecoder* decoder, WebPDecBuffer& decoderBuffer, bool blend)
|
||
|
-{
|
||
|
- ImageFrame& buffer = m_frameBufferCache[frameIndex];
|
||
|
- int decodedWidth = 0;
|
||
|
- int decodedHeight = 0;
|
||
|
- if (!WebPIDecGetRGB(decoder, &decodedHeight, &decodedWidth, 0, 0))
|
||
|
- return; // See also https://bugs.webkit.org/show_bug.cgi?id=74062
|
||
|
- if (decodedHeight <= 0)
|
||
|
- return;
|
||
|
-
|
||
|
- const IntRect& frameRect = buffer.backingStore()->frameRect();
|
||
|
- ASSERT_WITH_SECURITY_IMPLICATION(decodedWidth == frameRect.width());
|
||
|
- ASSERT_WITH_SECURITY_IMPLICATION(decodedHeight <= frameRect.height());
|
||
|
- const int left = frameRect.x();
|
||
|
- const int top = frameRect.y();
|
||
|
-
|
||
|
- for (int y = 0; y < decodedHeight; y++) {
|
||
|
- const int canvasY = top + y;
|
||
|
- for (int x = 0; x < decodedWidth; x++) {
|
||
|
- const int canvasX = left + x;
|
||
|
- RGBA32* address = buffer.backingStore()->pixelAt(canvasX, canvasY);
|
||
|
- uint8_t* pixel = decoderBuffer.u.RGBA.rgba + (y * frameRect.width() + x) * sizeof(RGBA32);
|
||
|
- if (blend && (pixel[3] < 255))
|
||
|
- buffer.backingStore()->blendPixel(address, pixel[0], pixel[1], pixel[2], pixel[3]);
|
||
|
- else
|
||
|
- buffer.backingStore()->setPixel(address, pixel[0], pixel[1], pixel[2], pixel[3]);
|
||
|
- }
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
-void WEBPImageDecoder::parseHeader()
|
||
|
-{
|
||
|
- if (m_headerParsed)
|
||
|
- return;
|
||
|
-
|
||
|
- m_headerParsed = true;
|
||
|
-
|
||
|
- const unsigned webpHeaderSize = 30; // RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8_FRAME_HEADER_SIZE
|
||
|
- if (m_data->size() < webpHeaderSize)
|
||
|
- return; // Await VP8X header so WebPDemuxPartial succeeds.
|
||
|
-
|
||
|
- WebPData inputData = { reinterpret_cast<const uint8_t*>(m_data->data()), m_data->size() };
|
||
|
- WebPDemuxState demuxerState;
|
||
|
- WebPDemuxer* demuxer = WebPDemuxPartial(&inputData, &demuxerState);
|
||
|
- if (!demuxer) {
|
||
|
- setFailed();
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- m_frameCount = WebPDemuxGetI(demuxer, WEBP_FF_FRAME_COUNT);
|
||
|
- if (!m_frameCount) {
|
||
|
- WebPDemuxDelete(demuxer);
|
||
|
- return; // Wait until the encoded image frame data arrives.
|
||
|
- }
|
||
|
-
|
||
|
- int width = WebPDemuxGetI(demuxer, WEBP_FF_CANVAS_WIDTH);
|
||
|
- int height = WebPDemuxGetI(demuxer, WEBP_FF_CANVAS_HEIGHT);
|
||
|
- if (!isSizeAvailable() && !setSize(IntSize(width, height))) {
|
||
|
- WebPDemuxDelete(demuxer);
|
||
|
- return;
|
||
|
- }
|
||
|
-
|
||
|
- m_formatFlags = WebPDemuxGetI(demuxer, WEBP_FF_FORMAT_FLAGS);
|
||
|
- if (!(m_formatFlags & ANIMATION_FLAG))
|
||
|
- m_repetitionCount = WebCore::RepetitionCountNone;
|
||
|
- else {
|
||
|
- // Since we have parsed at least one frame, even if partially,
|
||
|
- // the global animation (ANIM) properties have been read since
|
||
|
- // an ANIM chunk must precede the ANMF frame chunks.
|
||
|
- m_repetitionCount = WebPDemuxGetI(demuxer, WEBP_FF_LOOP_COUNT);
|
||
|
- ASSERT(m_repetitionCount == (m_repetitionCount & 0xffff)); // Loop count is always <= 16 bits.
|
||
|
- if (!m_repetitionCount)
|
||
|
- m_repetitionCount = WebCore::RepetitionCountInfinite;
|
||
|
- }
|
||
|
-
|
||
|
- WebPDemuxDelete(demuxer);
|
||
|
-}
|
||
|
-
|
||
|
-void WEBPImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame)
|
||
|
-{
|
||
|
- if (m_frameBufferCache.isEmpty())
|
||
|
- return;
|
||
|
-
|
||
|
- // We don't want to delete the last frame in the cache, as is may be needed for
|
||
|
- // decoding when new data arrives. See GIFImageDecoder for the full explanation.
|
||
|
- clearBeforeFrame = std::min(clearBeforeFrame, m_frameBufferCache.size() - 1);
|
||
|
-
|
||
|
- // Also from GIFImageDecoder: We need to preserve frames such that:
|
||
|
- // * We don't clear |clearBeforeFrame|.
|
||
|
- // * 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.
|
||
|
- //
|
||
|
- // In WEBP every frame depends on the previous one or none. That means that frames after clearBeforeFrame
|
||
|
- // won't need any frame before them to render, so we can clear them all.
|
||
|
- for (int i = clearBeforeFrame - 1; i >= 0; i--) {
|
||
|
- ImageFrame& buffer = m_frameBufferCache[i];
|
||
|
- if (!buffer.isInvalid())
|
||
|
- buffer.clear();
|
||
|
+ default:
|
||
|
+ clear();
|
||
|
+ return setFailed();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
diff -up webkitgtk-2.20.2/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h.no_webp_demux webkitgtk-2.20.2/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h
|
||
|
--- webkitgtk-2.20.2/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h.no_webp_demux 2018-02-19 08:45:32.000000000 +0100
|
||
|
+++ webkitgtk-2.20.2/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h 2018-05-11 08:36:41.029235210 +0200
|
||
|
@@ -33,7 +33,6 @@
|
||
|
#if USE(WEBP)
|
||
|
|
||
|
#include "webp/decode.h"
|
||
|
-#include "webp/demux.h"
|
||
|
|
||
|
namespace WebCore {
|
||
|
|
||
|
@@ -47,26 +46,19 @@ public:
|
||
|
virtual ~WEBPImageDecoder();
|
||
|
|
||
|
String filenameExtension() const override { return ASCIILiteral("webp"); }
|
||
|
- void setData(SharedBuffer&, bool) final;
|
||
|
ImageFrame* frameBufferAtIndex(size_t index) override;
|
||
|
- RepetitionCount repetitionCount() const override;
|
||
|
- size_t frameCount() const override { return m_frameCount; }
|
||
|
- void clearFrameBufferCache(size_t) override;
|
||
|
|
||
|
private:
|
||
|
WEBPImageDecoder(AlphaOption, GammaAndColorProfileOption);
|
||
|
- void tryDecodeSize(bool) override { parseHeader(); }
|
||
|
- void decode(size_t, bool);
|
||
|
- void decodeFrame(size_t, WebPDemuxer*);
|
||
|
- void parseHeader();
|
||
|
- bool initFrameBuffer(size_t, const WebPIterator*);
|
||
|
- void applyPostProcessing(size_t, WebPIDecoder*, WebPDecBuffer&, bool);
|
||
|
- size_t findFirstRequiredFrameToDecode(size_t, WebPDemuxer*);
|
||
|
-
|
||
|
- int m_repetitionCount { 0 };
|
||
|
- size_t m_frameCount { 0 };
|
||
|
- int m_formatFlags { 0 };
|
||
|
- bool m_headerParsed { false };
|
||
|
+ void tryDecodeSize(bool allDataReceived) override { decode(true, allDataReceived); }
|
||
|
+
|
||
|
+ bool decode(bool onlySize, bool allDataReceived);
|
||
|
+
|
||
|
+ WebPIDecoder* m_decoder;
|
||
|
+ bool m_hasAlpha;
|
||
|
+
|
||
|
+ void applyColorProfile(const uint8_t*, size_t, ImageFrame&) { };
|
||
|
+ void clear();
|
||
|
};
|
||
|
|
||
|
} // namespace WebCore
|