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 "third_party/skia/include/core/SkImageInfo.h"
32#include "wtf/PassOwnPtr.h"
33
34namespace blink {
35
36namespace {
37
38// URI label for SkDiscardablePixelRef.
39const char labelDiscardable[] = "discardable";
40
41} // namespace
42
43bool DeferredImageDecoder::s_enabled = false;
44
45DeferredImageDecoder::DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecoder)
46    : m_allDataReceived(false)
47    , m_lastDataSize(0)
48    , m_dataChanged(false)
49    , m_actualDecoder(actualDecoder)
50    , m_orientation(DefaultImageOrientation)
51    , m_repetitionCount(cAnimationNone)
52    , m_hasColorProfile(false)
53{
54}
55
56DeferredImageDecoder::~DeferredImageDecoder()
57{
58}
59
60PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorOption)
61{
62    OwnPtr<ImageDecoder> actualDecoder = ImageDecoder::create(data, alphaOption, gammaAndColorOption);
63    return actualDecoder ? adoptPtr(new DeferredImageDecoder(actualDecoder.release())) : nullptr;
64}
65
66PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::createForTesting(PassOwnPtr<ImageDecoder> decoder)
67{
68    return adoptPtr(new DeferredImageDecoder(decoder));
69}
70
71bool DeferredImageDecoder::isLazyDecoded(const SkBitmap& bitmap)
72{
73    return bitmap.pixelRef()
74        && bitmap.pixelRef()->getURI()
75        && !memcmp(bitmap.pixelRef()->getURI(), labelDiscardable, sizeof(labelDiscardable));
76}
77
78void DeferredImageDecoder::setEnabled(bool enabled)
79{
80    s_enabled = enabled;
81}
82
83bool DeferredImageDecoder::enabled()
84{
85    return s_enabled;
86}
87
88String DeferredImageDecoder::filenameExtension() const
89{
90    return m_actualDecoder ? m_actualDecoder->filenameExtension() : m_filenameExtension;
91}
92
93ImageFrame* DeferredImageDecoder::frameBufferAtIndex(size_t index)
94{
95    prepareLazyDecodedFrames();
96    if (index < m_lazyDecodedFrames.size()) {
97        // ImageFrameGenerator has the latest known alpha state. There will
98        // be a performance boost if this frame is opaque.
99        m_lazyDecodedFrames[index]->setHasAlpha(m_frameGenerator->hasAlpha(index));
100        return m_lazyDecodedFrames[index].get();
101    }
102    if (m_actualDecoder)
103        return m_actualDecoder->frameBufferAtIndex(index);
104    return 0;
105}
106
107void DeferredImageDecoder::setData(SharedBuffer& data, bool allDataReceived)
108{
109    if (m_actualDecoder) {
110        const bool firstData = !m_data;
111        const bool moreData = data.size() > m_lastDataSize;
112        m_dataChanged = firstData || moreData;
113        m_data = RefPtr<SharedBuffer>(data);
114        m_lastDataSize = data.size();
115        m_allDataReceived = allDataReceived;
116        m_actualDecoder->setData(&data, allDataReceived);
117        prepareLazyDecodedFrames();
118    }
119
120    if (m_frameGenerator)
121        m_frameGenerator->setData(&data, allDataReceived);
122}
123
124bool DeferredImageDecoder::isSizeAvailable()
125{
126    // m_actualDecoder is 0 only if image decoding is deferred and that means
127    // the image header decoded successfully and the size is available.
128    return m_actualDecoder ? m_actualDecoder->isSizeAvailable() : true;
129}
130
131bool DeferredImageDecoder::hasColorProfile() const
132{
133    return m_actualDecoder ? m_actualDecoder->hasColorProfile() : m_hasColorProfile;
134}
135
136IntSize DeferredImageDecoder::size() const
137{
138    return m_actualDecoder ? m_actualDecoder->size() : m_size;
139}
140
141IntSize DeferredImageDecoder::frameSizeAtIndex(size_t index) const
142{
143    // FIXME: LocalFrame size is assumed to be uniform. This might not be true for
144    // future supported codecs.
145    return m_actualDecoder ? m_actualDecoder->frameSizeAtIndex(index) : m_size;
146}
147
148size_t DeferredImageDecoder::frameCount()
149{
150    return m_actualDecoder ? m_actualDecoder->frameCount() : m_lazyDecodedFrames.size();
151}
152
153int DeferredImageDecoder::repetitionCount() const
154{
155    return m_actualDecoder ? m_actualDecoder->repetitionCount() : m_repetitionCount;
156}
157
158size_t DeferredImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame)
159{
160    // If image decoding is deferred then frame buffer cache is managed by
161    // the compositor and this call is ignored.
162    return m_actualDecoder ? m_actualDecoder->clearCacheExceptFrame(clearExceptFrame) : 0;
163}
164
165bool DeferredImageDecoder::frameHasAlphaAtIndex(size_t index) const
166{
167    if (m_actualDecoder)
168        return m_actualDecoder->frameHasAlphaAtIndex(index);
169    if (!m_frameGenerator->isMultiFrame())
170        return m_frameGenerator->hasAlpha(index);
171    return true;
172}
173
174bool DeferredImageDecoder::frameIsCompleteAtIndex(size_t index) const
175{
176    if (m_actualDecoder)
177        return m_actualDecoder->frameIsCompleteAtIndex(index);
178    if (index < m_lazyDecodedFrames.size())
179        return m_lazyDecodedFrames[index]->status() == ImageFrame::FrameComplete;
180    return false;
181}
182
183float DeferredImageDecoder::frameDurationAtIndex(size_t index) const
184{
185    if (m_actualDecoder)
186        return m_actualDecoder->frameDurationAtIndex(index);
187    if (index < m_lazyDecodedFrames.size())
188        return m_lazyDecodedFrames[index]->duration();
189    return 0;
190}
191
192unsigned DeferredImageDecoder::frameBytesAtIndex(size_t index) const
193{
194    // If frame decoding is deferred then it is not managed by MemoryCache
195    // so return 0 here.
196    return m_frameGenerator ? 0 : m_actualDecoder->frameBytesAtIndex(index);
197}
198
199ImageOrientation DeferredImageDecoder::orientation() const
200{
201    return m_actualDecoder ? m_actualDecoder->orientation() : m_orientation;
202}
203
204void DeferredImageDecoder::activateLazyDecoding()
205{
206    if (m_frameGenerator)
207        return;
208    m_size = m_actualDecoder->size();
209    m_orientation = m_actualDecoder->orientation();
210    m_filenameExtension = m_actualDecoder->filenameExtension();
211    m_hasColorProfile = m_actualDecoder->hasColorProfile();
212    const bool isSingleFrame = m_actualDecoder->repetitionCount() == cAnimationNone || (m_allDataReceived && m_actualDecoder->frameCount() == 1u);
213    m_frameGenerator = ImageFrameGenerator::create(SkISize::Make(m_actualDecoder->decodedSize().width(), m_actualDecoder->decodedSize().height()), m_data, m_allDataReceived, !isSingleFrame);
214}
215
216void DeferredImageDecoder::prepareLazyDecodedFrames()
217{
218    if (!s_enabled
219        || !m_actualDecoder
220        || !m_actualDecoder->isSizeAvailable()
221        || m_actualDecoder->filenameExtension() == "ico")
222        return;
223
224    activateLazyDecoding();
225
226    const size_t previousSize = m_lazyDecodedFrames.size();
227    m_lazyDecodedFrames.resize(m_actualDecoder->frameCount());
228
229    // We have encountered a broken image file. Simply bail.
230    if (m_lazyDecodedFrames.size() < previousSize)
231        return;
232
233    for (size_t i = previousSize; i < m_lazyDecodedFrames.size(); ++i) {
234        OwnPtr<ImageFrame> frame(adoptPtr(new ImageFrame()));
235        frame->setSkBitmap(createBitmap(i));
236        frame->setDuration(m_actualDecoder->frameDurationAtIndex(i));
237        frame->setStatus(m_actualDecoder->frameIsCompleteAtIndex(i) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
238        m_lazyDecodedFrames[i] = frame.release();
239    }
240
241    // The last lazy decoded frame created from previous call might be
242    // incomplete so update its state.
243    if (previousSize) {
244        const size_t lastFrame = previousSize - 1;
245        m_lazyDecodedFrames[lastFrame]->setStatus(m_actualDecoder->frameIsCompleteAtIndex(lastFrame) ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
246
247        // If data has changed then create a new bitmap. This forces
248        // Skia to decode again.
249        if (m_dataChanged) {
250            m_dataChanged = false;
251            m_lazyDecodedFrames[lastFrame]->setSkBitmap(createBitmap(lastFrame));
252        }
253    }
254
255    if (m_allDataReceived) {
256        m_repetitionCount = m_actualDecoder->repetitionCount();
257        m_actualDecoder.clear();
258        m_data = nullptr;
259    }
260}
261
262// Creates a SkBitmap that is backed by SkDiscardablePixelRef.
263SkBitmap DeferredImageDecoder::createBitmap(size_t index)
264{
265    IntSize decodedSize = m_actualDecoder->decodedSize();
266    ASSERT(decodedSize.width() > 0);
267    ASSERT(decodedSize.height() > 0);
268
269#if SK_B32_SHIFT // Little-endian RGBA pixels. (Android)
270    const SkColorType colorType = kRGBA_8888_SkColorType;
271#else
272    const SkColorType colorType = kBGRA_8888_SkColorType;
273#endif
274    const SkImageInfo info = SkImageInfo::Make(decodedSize.width(), decodedSize.height(), colorType, kPremul_SkAlphaType);
275
276    SkBitmap bitmap;
277    DecodingImageGenerator* generator = new DecodingImageGenerator(m_frameGenerator, info, index);
278    bool installed = SkInstallDiscardablePixelRef(generator, &bitmap);
279    ASSERT_UNUSED(installed, installed);
280    bitmap.pixelRef()->setURI(labelDiscardable);
281    generator->setGenerationId(bitmap.getGenerationID());
282    return bitmap;
283}
284
285bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const
286{
287    // TODO: Implement.
288    return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false;
289}
290
291} // namespace blink
292