1 /*
2 * Copyright (C) 2012 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 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "platform/graphics/DeferredImageDecoder.h"
28
29 #include "platform/graphics/DecodingImageGenerator.h"
30 #include "platform/graphics/ImageDecodingStore.h"
31 #include "platform/graphics/LazyDecodingPixelRef.h"
32 #include "third_party/skia/include/core/SkImageInfo.h"
33 #include "wtf/PassOwnPtr.h"
34
35 namespace WebCore {
36
37 namespace {
38
39 // URI label for SkDiscardablePixelRef.
40 const char labelDiscardable[] = "discardable";
41
42 } // namespace
43
44 bool DeferredImageDecoder::s_enabled = false;
45
DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecoder)46 DeferredImageDecoder::DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecoder)
47 : m_allDataReceived(false)
48 , m_lastDataSize(0)
49 , m_dataChanged(false)
50 , m_actualDecoder(actualDecoder)
51 , m_orientation(DefaultImageOrientation)
52 , m_repetitionCount(cAnimationNone)
53 , m_hasColorProfile(false)
54 {
55 }
56
~DeferredImageDecoder()57 DeferredImageDecoder::~DeferredImageDecoder()
58 {
59 }
60
create(const SharedBuffer & data,ImageSource::AlphaOption alphaOption,ImageSource::GammaAndColorProfileOption gammaAndColorOption)61 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorOption)
62 {
63 OwnPtr<ImageDecoder> actualDecoder = ImageDecoder::create(data, alphaOption, gammaAndColorOption);
64 return actualDecoder ? adoptPtr(new DeferredImageDecoder(actualDecoder.release())) : nullptr;
65 }
66
createForTesting(PassOwnPtr<ImageDecoder> decoder)67 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::createForTesting(PassOwnPtr<ImageDecoder> decoder)
68 {
69 return adoptPtr(new DeferredImageDecoder(decoder));
70 }
71
isLazyDecoded(const SkBitmap & bitmap)72 bool DeferredImageDecoder::isLazyDecoded(const SkBitmap& bitmap)
73 {
74 return bitmap.pixelRef()
75 && bitmap.pixelRef()->getURI()
76 && !memcmp(bitmap.pixelRef()->getURI(), labelDiscardable, sizeof(labelDiscardable));
77 }
78
setEnabled(bool enabled)79 void DeferredImageDecoder::setEnabled(bool enabled)
80 {
81 s_enabled = enabled;
82 if (enabled)
83 ImageDecodingStore::setImageCachingEnabled(false);
84 }
85
enabled()86 bool DeferredImageDecoder::enabled()
87 {
88 return s_enabled;
89 }
90
filenameExtension() const91 String DeferredImageDecoder::filenameExtension() const
92 {
93 return m_actualDecoder ? m_actualDecoder->filenameExtension() : m_filenameExtension;
94 }
95
frameBufferAtIndex(size_t index)96 ImageFrame* DeferredImageDecoder::frameBufferAtIndex(size_t index)
97 {
98 prepareLazyDecodedFrames();
99 if (index < m_lazyDecodedFrames.size()) {
100 // ImageFrameGenerator has the latest known alpha state. There will
101 // be a performance boost if this frame is opaque.
102 m_lazyDecodedFrames[index]->setHasAlpha(m_frameGenerator->hasAlpha(index));
103 return m_lazyDecodedFrames[index].get();
104 }
105 if (m_actualDecoder)
106 return m_actualDecoder->frameBufferAtIndex(index);
107 return 0;
108 }
109
setData(SharedBuffer & data,bool allDataReceived)110 void DeferredImageDecoder::setData(SharedBuffer& data, bool allDataReceived)
111 {
112 if (m_actualDecoder) {
113 const bool firstData = !m_data;
114 const bool moreData = data.size() > m_lastDataSize;
115 m_dataChanged = firstData || moreData;
116 m_data = RefPtr<SharedBuffer>(data);
117 m_lastDataSize = data.size();
118 m_allDataReceived = allDataReceived;
119 m_actualDecoder->setData(&data, allDataReceived);
120 prepareLazyDecodedFrames();
121 }
122
123 if (m_frameGenerator)
124 m_frameGenerator->setData(&data, allDataReceived);
125 }
126
isSizeAvailable()127 bool DeferredImageDecoder::isSizeAvailable()
128 {
129 // m_actualDecoder is 0 only if image decoding is deferred and that
130 // means image header decoded successfully and size is available.
131 return m_actualDecoder ? m_actualDecoder->isSizeAvailable() : true;
132 }
133
hasColorProfile() const134 bool DeferredImageDecoder::hasColorProfile() const
135 {
136 return m_actualDecoder ? m_actualDecoder->hasColorProfile() : m_hasColorProfile;
137 }
138
size() const139 IntSize DeferredImageDecoder::size() const
140 {
141 return m_actualDecoder ? m_actualDecoder->size() : m_size;
142 }
143
frameSizeAtIndex(size_t index) const144 IntSize DeferredImageDecoder::frameSizeAtIndex(size_t index) const
145 {
146 // FIXME: LocalFrame size is assumed to be uniform. This might not be true for
147 // future supported codecs.
148 return m_actualDecoder ? m_actualDecoder->frameSizeAtIndex(index) : m_size;
149 }
150
frameCount()151 size_t DeferredImageDecoder::frameCount()
152 {
153 return m_actualDecoder ? m_actualDecoder->frameCount() : m_lazyDecodedFrames.size();
154 }
155
repetitionCount() const156 int DeferredImageDecoder::repetitionCount() const
157 {
158 return m_actualDecoder ? m_actualDecoder->repetitionCount() : m_repetitionCount;
159 }
160
clearCacheExceptFrame(size_t clearExceptFrame)161 size_t DeferredImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame)
162 {
163 // If image decoding is deferred then frame buffer cache is managed by
164 // the compositor and this call is ignored.
165 return m_actualDecoder ? m_actualDecoder->clearCacheExceptFrame(clearExceptFrame) : 0;
166 }
167
frameHasAlphaAtIndex(size_t index) const168 bool DeferredImageDecoder::frameHasAlphaAtIndex(size_t index) const
169 {
170 if (m_actualDecoder)
171 return m_actualDecoder->frameHasAlphaAtIndex(index);
172 if (!m_frameGenerator->isMultiFrame())
173 return m_frameGenerator->hasAlpha(index);
174 return true;
175 }
176
frameIsCompleteAtIndex(size_t index) const177 bool DeferredImageDecoder::frameIsCompleteAtIndex(size_t index) const
178 {
179 if (m_actualDecoder)
180 return m_actualDecoder->frameIsCompleteAtIndex(index);
181 if (index < m_lazyDecodedFrames.size())
182 return m_lazyDecodedFrames[index]->status() == ImageFrame::FrameComplete;
183 return false;
184 }
185
frameDurationAtIndex(size_t index) const186 float DeferredImageDecoder::frameDurationAtIndex(size_t index) const
187 {
188 if (m_actualDecoder)
189 return m_actualDecoder->frameDurationAtIndex(index);
190 if (index < m_lazyDecodedFrames.size())
191 return m_lazyDecodedFrames[index]->duration();
192 return 0;
193 }
194
frameBytesAtIndex(size_t index) const195 unsigned DeferredImageDecoder::frameBytesAtIndex(size_t index) const
196 {
197 // If frame decoding is deferred then it is not managed by MemoryCache
198 // so return 0 here.
199 return m_frameGenerator ? 0 : m_actualDecoder->frameBytesAtIndex(index);
200 }
201
orientation() const202 ImageOrientation DeferredImageDecoder::orientation() const
203 {
204 return m_actualDecoder ? m_actualDecoder->orientation() : m_orientation;
205 }
206
activateLazyDecoding()207 void DeferredImageDecoder::activateLazyDecoding()
208 {
209 if (m_frameGenerator)
210 return;
211 m_size = m_actualDecoder->size();
212 m_orientation = m_actualDecoder->orientation();
213 m_filenameExtension = m_actualDecoder->filenameExtension();
214 m_hasColorProfile = m_actualDecoder->hasColorProfile();
215 const bool isSingleFrame = m_actualDecoder->repetitionCount() == cAnimationNone || (m_allDataReceived && m_actualDecoder->frameCount() == 1u);
216 m_frameGenerator = ImageFrameGenerator::create(SkISize::Make(m_actualDecoder->decodedSize().width(), m_actualDecoder->decodedSize().height()), m_data, m_allDataReceived, !isSingleFrame);
217 }
218
prepareLazyDecodedFrames()219 void DeferredImageDecoder::prepareLazyDecodedFrames()
220 {
221 if (!s_enabled
222 || !m_actualDecoder
223 || !m_actualDecoder->isSizeAvailable()
224 || m_actualDecoder->filenameExtension() == "ico")
225 return;
226
227 activateLazyDecoding();
228
229 const size_t previousSize = m_lazyDecodedFrames.size();
230 m_lazyDecodedFrames.resize(m_actualDecoder->frameCount());
231
232 // We have encountered a broken image file. Simply bail.
233 if (m_lazyDecodedFrames.size() < previousSize)
234 return;
235
236 for (size_t i = previousSize; i < m_lazyDecodedFrames.size(); ++i) {
237 OwnPtr<ImageFrame> frame(adoptPtr(new ImageFrame()));
238 frame->setSkBitmap(createBitmap(i));
239 frame->setDuration(m_actualDecoder->frameDurationAtIndex(i));
240 frame->setStatus(m_actualDecoder->frameIsCompleteAtIndex(i) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
241 m_lazyDecodedFrames[i] = frame.release();
242 }
243
244 // The last lazy decoded frame created from previous call might be
245 // incomplete so update its state.
246 if (previousSize) {
247 const size_t lastFrame = previousSize - 1;
248 m_lazyDecodedFrames[lastFrame]->setStatus(m_actualDecoder->frameIsCompleteAtIndex(lastFrame) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
249
250 // If data has changed then create a new bitmap. This forces
251 // Skia to decode again.
252 if (m_dataChanged) {
253 m_dataChanged = false;
254 m_lazyDecodedFrames[lastFrame]->setSkBitmap(createBitmap(lastFrame));
255 }
256 }
257
258 if (m_allDataReceived) {
259 m_repetitionCount = m_actualDecoder->repetitionCount();
260 m_actualDecoder.clear();
261 m_data = nullptr;
262 }
263 }
264
265 // Creates a SkBitmap that is backed by SkDiscardablePixelRef.
createBitmap(size_t index)266 SkBitmap DeferredImageDecoder::createBitmap(size_t index)
267 {
268 IntSize decodedSize = m_actualDecoder->decodedSize();
269 ASSERT(decodedSize.width() > 0);
270 ASSERT(decodedSize.height() > 0);
271
272 SkImageInfo info;
273 info.fWidth = decodedSize.width();
274 info.fHeight = decodedSize.height();
275 #if SK_B32_SHIFT // Little-endian RGBA pixels. (Android)
276 info.fColorType = kRGBA_8888_SkColorType;
277 #else
278 info.fColorType = kBGRA_8888_SkColorType;
279 #endif
280 info.fAlphaType = kPremul_SkAlphaType;
281
282 SkBitmap bitmap;
283 DecodingImageGenerator* generator = new DecodingImageGenerator(m_frameGenerator, info, index);
284 bool installed = SkInstallDiscardablePixelRef(generator, &bitmap);
285 ASSERT_UNUSED(installed, installed);
286 bitmap.pixelRef()->setURI(labelDiscardable);
287 generator->setGenerationId(bitmap.getGenerationID());
288 return bitmap;
289 }
290
hotSpot(IntPoint & hotSpot) const291 bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const
292 {
293 // TODO: Implement.
294 return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false;
295 }
296
297 } // namespace WebCore
298