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 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 57 DeferredImageDecoder::~DeferredImageDecoder() 58 { 59 } 60 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 67 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::createForTesting(PassOwnPtr<ImageDecoder> decoder) 68 { 69 return adoptPtr(new DeferredImageDecoder(decoder)); 70 } 71 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 79 void DeferredImageDecoder::setEnabled(bool enabled) 80 { 81 s_enabled = enabled; 82 if (enabled) 83 ImageDecodingStore::setImageCachingEnabled(false); 84 } 85 86 bool DeferredImageDecoder::enabled() 87 { 88 return s_enabled; 89 } 90 91 String DeferredImageDecoder::filenameExtension() const 92 { 93 return m_actualDecoder ? m_actualDecoder->filenameExtension() : m_filenameExtension; 94 } 95 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 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 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 134 bool DeferredImageDecoder::hasColorProfile() const 135 { 136 return m_actualDecoder ? m_actualDecoder->hasColorProfile() : m_hasColorProfile; 137 } 138 139 IntSize DeferredImageDecoder::size() const 140 { 141 return m_actualDecoder ? m_actualDecoder->size() : m_size; 142 } 143 144 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 151 size_t DeferredImageDecoder::frameCount() 152 { 153 return m_actualDecoder ? m_actualDecoder->frameCount() : m_lazyDecodedFrames.size(); 154 } 155 156 int DeferredImageDecoder::repetitionCount() const 157 { 158 return m_actualDecoder ? m_actualDecoder->repetitionCount() : m_repetitionCount; 159 } 160 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 168 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 177 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 186 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 195 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 202 ImageOrientation DeferredImageDecoder::orientation() const 203 { 204 return m_actualDecoder ? m_actualDecoder->orientation() : m_orientation; 205 } 206 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 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. 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 291 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