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 "core/platform/graphics/chromium/DeferredImageDecoder.h" 28 29 #include "core/platform/graphics/chromium/ImageFrameGenerator.h" 30 #include "core/platform/graphics/chromium/LazyDecodingPixelRef.h" 31 #include "wtf/OwnPtr.h" 32 #include "wtf/PassOwnPtr.h" 33 34 namespace WebCore { 35 36 namespace { 37 38 // URI label for a lazily decoded SkPixelRef. 39 const char labelLazyDecoded[] = "lazy"; 40 41 } // namespace 42 43 bool DeferredImageDecoder::s_enabled = false; 44 45 DeferredImageDecoder::DeferredImageDecoder(PassOwnPtr<ImageDecoder> actualDecoder) 46 : m_allDataReceived(false) 47 , m_actualDecoder(actualDecoder) 48 , m_orientation(DefaultImageOrientation) 49 , m_repetitionCount(cAnimationNone) 50 { 51 } 52 53 DeferredImageDecoder::~DeferredImageDecoder() 54 { 55 } 56 57 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorOption) 58 { 59 OwnPtr<ImageDecoder> actualDecoder = ImageDecoder::create(data, alphaOption, gammaAndColorOption); 60 return actualDecoder ? adoptPtr(new DeferredImageDecoder(actualDecoder.release())) : nullptr; 61 } 62 63 PassOwnPtr<DeferredImageDecoder> DeferredImageDecoder::createForTesting(PassOwnPtr<ImageDecoder> decoder) 64 { 65 return adoptPtr(new DeferredImageDecoder(decoder)); 66 } 67 68 bool DeferredImageDecoder::isLazyDecoded(const SkBitmap& bitmap) 69 { 70 return bitmap.pixelRef() 71 && bitmap.pixelRef()->getURI() 72 && !memcmp(bitmap.pixelRef()->getURI(), labelLazyDecoded, sizeof(labelLazyDecoded)); 73 } 74 75 SkBitmap DeferredImageDecoder::createResizedLazyDecodingBitmap(const SkBitmap& bitmap, const SkISize& scaledSize, const SkIRect& scaledSubset) 76 { 77 LazyDecodingPixelRef* pixelRef = static_cast<LazyDecodingPixelRef*>(bitmap.pixelRef()); 78 79 int rowBytes = 0; 80 rowBytes = SkBitmap::ComputeRowBytes(SkBitmap::kARGB_8888_Config, scaledSize.width()); 81 82 SkBitmap resizedBitmap; 83 resizedBitmap.setConfig(SkBitmap::kARGB_8888_Config, scaledSubset.width(), scaledSubset.height(), rowBytes); 84 85 // FIXME: This code has the potential problem that multiple 86 // LazyDecodingPixelRefs are created even though they share the same 87 // scaled size and ImageFrameGenerator. 88 resizedBitmap.setPixelRef(new LazyDecodingPixelRef(pixelRef->frameGenerator(), scaledSize, pixelRef->frameIndex(), scaledSubset))->unref(); 89 90 // See comments in createLazyDecodingBitmap(). 91 resizedBitmap.setImmutable(); 92 return resizedBitmap; 93 } 94 95 void DeferredImageDecoder::setEnabled(bool enabled) 96 { 97 s_enabled = enabled; 98 } 99 100 String DeferredImageDecoder::filenameExtension() const 101 { 102 return m_actualDecoder ? m_actualDecoder->filenameExtension() : m_filenameExtension; 103 } 104 105 ImageFrame* DeferredImageDecoder::frameBufferAtIndex(size_t index) 106 { 107 prepareLazyDecodedFrames(); 108 if (index < m_lazyDecodedFrames.size()) { 109 // ImageFrameGenerator has the latest known alpha state. There will 110 // be a performance boost if this frame is opaque. 111 m_lazyDecodedFrames[index]->setHasAlpha(m_frameGenerator->hasAlpha(index)); 112 return m_lazyDecodedFrames[index].get(); 113 } 114 if (m_actualDecoder) 115 return m_actualDecoder->frameBufferAtIndex(index); 116 return 0; 117 } 118 119 void DeferredImageDecoder::setData(SharedBuffer* data, bool allDataReceived) 120 { 121 if (m_actualDecoder) { 122 m_data = data; 123 m_allDataReceived = allDataReceived; 124 m_actualDecoder->setData(data, allDataReceived); 125 prepareLazyDecodedFrames(); 126 } 127 128 if (m_frameGenerator) 129 m_frameGenerator->setData(data, allDataReceived); 130 } 131 132 bool DeferredImageDecoder::isSizeAvailable() 133 { 134 // m_actualDecoder is 0 only if image decoding is deferred and that 135 // means image header decoded successfully and size is available. 136 return m_actualDecoder ? m_actualDecoder->isSizeAvailable() : true; 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: Frame 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 const bool isSingleFrame = m_actualDecoder->repetitionCount() == cAnimationNone || (m_allDataReceived && m_actualDecoder->frameCount() == 1u); 215 m_frameGenerator = ImageFrameGenerator::create(SkISize::Make(m_size.width(), m_size.height()), m_data, m_allDataReceived, !isSingleFrame); 216 } 217 218 void DeferredImageDecoder::prepareLazyDecodedFrames() 219 { 220 if (!s_enabled 221 || !m_actualDecoder 222 || !m_actualDecoder->isSizeAvailable() 223 || m_actualDecoder->filenameExtension() == "ico") 224 return; 225 226 activateLazyDecoding(); 227 228 const size_t previousSize = m_lazyDecodedFrames.size(); 229 m_lazyDecodedFrames.resize(m_actualDecoder->frameCount()); 230 for (size_t i = previousSize; i < m_lazyDecodedFrames.size(); ++i) { 231 OwnPtr<ImageFrame> frame(adoptPtr(new ImageFrame())); 232 frame->setSkBitmap(createLazyDecodingBitmap(i)); 233 frame->setDuration(m_actualDecoder->frameDurationAtIndex(i)); 234 frame->setStatus(m_actualDecoder->frameIsCompleteAtIndex(i) ? ImageFrame::FrameComplete : ImageFrame::FramePartial); 235 m_lazyDecodedFrames[i] = frame.release(); 236 } 237 238 // The last lazy decoded frame created from previous call might be 239 // incomplete so update its state. 240 if (previousSize) 241 m_lazyDecodedFrames[previousSize - 1]->setStatus(m_actualDecoder->frameIsCompleteAtIndex(previousSize - 1) ? ImageFrame::FrameComplete : ImageFrame::FramePartial); 242 243 if (m_allDataReceived) { 244 m_repetitionCount = m_actualDecoder->repetitionCount(); 245 m_actualDecoder.clear(); 246 m_data = nullptr; 247 } 248 } 249 250 SkBitmap DeferredImageDecoder::createLazyDecodingBitmap(size_t index) 251 { 252 SkISize fullSize = SkISize::Make(m_actualDecoder->size().width(), m_actualDecoder->size().height()); 253 ASSERT(!fullSize.isEmpty()); 254 255 SkIRect fullRect = SkIRect::MakeSize(fullSize); 256 257 // Creates a lazily decoded SkPixelRef that references the entire image without scaling. 258 SkBitmap bitmap; 259 bitmap.setConfig(SkBitmap::kARGB_8888_Config, fullSize.width(), fullSize.height()); 260 bitmap.setPixelRef(new LazyDecodingPixelRef(m_frameGenerator, fullSize, index, fullRect))->unref(); 261 262 // Use the URI to identify this as a lazily decoded SkPixelRef of type LazyDecodingPixelRef. 263 // FIXME: It would be more useful to give the actual image URI. 264 bitmap.pixelRef()->setURI(labelLazyDecoded); 265 266 // Inform the bitmap that we will never change the pixels. This is a performance hint 267 // subsystems that may try to cache this bitmap (e.g. pictures, pipes, gpu, pdf, etc.) 268 bitmap.setImmutable(); 269 270 return bitmap; 271 } 272 273 bool DeferredImageDecoder::hotSpot(IntPoint& hotSpot) const 274 { 275 // TODO: Implement. 276 return m_actualDecoder ? m_actualDecoder->hotSpot(hotSpot) : false; 277 } 278 279 } // namespace WebCore 280