REGRESSION(r215211): [GTK] Several webgl related tests are failing
[WebKit-https.git] / Source / WebCore / platform / image-decoders / webp / WEBPImageDecoder.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "WEBPImageDecoder.h"
31
32 #if USE(WEBP)
33
34 // Backward emulation for earlier versions than 0.1.99.
35 #if (WEBP_DECODER_ABI_VERSION < 0x0163)
36 #define MODE_rgbA MODE_RGBA
37 #define MODE_bgrA MODE_BGRA
38 #endif
39
40 #if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN)
41 inline WEBP_CSP_MODE outputMode(bool hasAlpha) { return hasAlpha ? MODE_rgbA : MODE_RGBA; }
42 #else // LITTLE_ENDIAN, output BGRA pixels.
43 inline WEBP_CSP_MODE outputMode(bool hasAlpha) { return hasAlpha ? MODE_bgrA : MODE_BGRA; }
44 #endif
45
46 namespace WebCore {
47
48 WEBPImageDecoder::WEBPImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
49     : ImageDecoder(alphaOption, gammaAndColorProfileOption)
50     , m_decoder(0)
51     , m_hasAlpha(false)
52 {
53 }
54
55 WEBPImageDecoder::~WEBPImageDecoder()
56 {
57     clear();
58 }
59
60 void WEBPImageDecoder::clear()
61 {
62     if (m_decoder)
63         WebPIDelete(m_decoder);
64     m_decoder = 0;
65 }
66
67 ImageFrame* WEBPImageDecoder::frameBufferAtIndex(size_t index)
68 {
69     if (index)
70         return 0;
71
72     if (m_frameBufferCache.isEmpty())
73         m_frameBufferCache.resize(1);
74
75     ImageFrame& frame = m_frameBufferCache[0];
76     if (!frame.isComplete())
77         decode(false, isAllDataReceived());
78     return &frame;
79 }
80
81 bool WEBPImageDecoder::decode(bool onlySize, bool)
82 {
83     if (failed())
84         return false;
85
86     const uint8_t* dataBytes = reinterpret_cast<const uint8_t*>(m_data->data());
87     const size_t dataSize = m_data->size();
88
89     if (ImageDecoder::encodedDataStatus() < EncodedDataStatus::SizeAvailable) {
90         static const size_t imageHeaderSize = 30;
91         if (dataSize < imageHeaderSize)
92             return false;
93         int width, height;
94 #if (WEBP_DECODER_ABI_VERSION >= 0x0163)
95         WebPBitstreamFeatures features;
96         if (WebPGetFeatures(dataBytes, dataSize, &features) != VP8_STATUS_OK)
97             return setFailed();
98         width = features.width;
99         height = features.height;
100         m_hasAlpha = features.has_alpha;
101 #else
102         // Earlier version won't be able to display WebP files with alpha.
103         if (!WebPGetInfo(dataBytes, dataSize, &width, &height))
104             return setFailed();
105         m_hasAlpha = false;
106 #endif
107         if (!setSize(IntSize(width, height)))
108             return setFailed();
109     }
110
111     ASSERT(ImageDecoder::encodedDataStatus() >= EncodedDataStatus::SizeAvailable);
112     if (onlySize)
113         return true;
114
115     ASSERT(!m_frameBufferCache.isEmpty());
116     ImageFrame& buffer = m_frameBufferCache[0];
117     ASSERT(!buffer.isComplete());
118
119     if (buffer.isEmpty()) {
120         if (!buffer.initialize(size(), m_premultiplyAlpha))
121             return setFailed();
122         buffer.setDecoding(ImageFrame::Decoding::Partial);
123         buffer.setHasAlpha(m_hasAlpha);
124     }
125
126     if (!m_decoder) {
127         WEBP_CSP_MODE mode = outputMode(m_hasAlpha);
128         if (!m_premultiplyAlpha)
129             mode = outputMode(false);
130         int rowStride = size().width() * sizeof(RGBA32);
131         uint8_t* output = reinterpret_cast<uint8_t*>(buffer.backingStore()->pixelAt(0, 0));
132         int outputSize = size().height() * rowStride;
133         m_decoder = WebPINewRGB(mode, output, outputSize, rowStride);
134         if (!m_decoder)
135             return setFailed();
136     }
137
138     switch (WebPIUpdate(m_decoder, dataBytes, dataSize)) {
139     case VP8_STATUS_OK:
140         buffer.setDecoding(ImageFrame::Decoding::Complete);
141         clear();
142         return true;
143     case VP8_STATUS_SUSPENDED:
144         return false;
145     default:
146         clear();
147         return setFailed();
148     }
149 }
150
151 } // namespace WebCore
152
153 #endif