1 /* 2 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. 3 * Copyright (C) 2007 Alp Toker <alp.toker (at) collabora.co.uk> 4 * Copyright (C) 2008, Google Inc. All rights reserved. 5 * Copyright (C) 2007-2009 Torch Mobile, Inc 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "config.h" 30 #include "ImageSource.h" 31 32 #if PLATFORM(QT) 33 #include "ImageDecoderQt.h" 34 #else 35 #include "ImageDecoder.h" 36 #endif 37 38 namespace WebCore { 39 40 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) 41 unsigned ImageSource::s_maxPixelsPerDecodedImage = 1024 * 1024; 42 #endif 43 44 ImageSource::ImageSource(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) 45 : m_decoder(0) 46 , m_alphaOption(alphaOption) 47 , m_gammaAndColorProfileOption(gammaAndColorProfileOption) 48 { 49 } 50 51 ImageSource::~ImageSource() 52 { 53 clear(true); 54 } 55 56 void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived) 57 { 58 if (!destroyAll) { 59 if (m_decoder) 60 m_decoder->clearFrameBufferCache(clearBeforeFrame); 61 return; 62 } 63 64 delete m_decoder; 65 m_decoder = 0; 66 if (data) 67 setData(data, allDataReceived); 68 } 69 70 bool ImageSource::initialized() const 71 { 72 return m_decoder; 73 } 74 75 void ImageSource::setData(SharedBuffer* data, bool allDataReceived) 76 { 77 // Make the decoder by sniffing the bytes. 78 // This method will examine the data and instantiate an instance of the appropriate decoder plugin. 79 // If insufficient bytes are available to determine the image type, no decoder plugin will be 80 // made. 81 if (!m_decoder) { 82 m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data, m_alphaOption, m_gammaAndColorProfileOption)); 83 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) 84 if (m_decoder && s_maxPixelsPerDecodedImage) 85 m_decoder->setMaxNumPixels(s_maxPixelsPerDecodedImage); 86 #endif 87 } 88 89 if (m_decoder) 90 m_decoder->setData(data, allDataReceived); 91 } 92 93 String ImageSource::filenameExtension() const 94 { 95 return m_decoder ? m_decoder->filenameExtension() : String(); 96 } 97 98 bool ImageSource::isSizeAvailable() 99 { 100 return m_decoder && m_decoder->isSizeAvailable(); 101 } 102 103 IntSize ImageSource::size() const 104 { 105 return m_decoder ? m_decoder->size() : IntSize(); 106 } 107 108 IntSize ImageSource::frameSizeAtIndex(size_t index) const 109 { 110 return m_decoder ? m_decoder->frameSizeAtIndex(index) : IntSize(); 111 } 112 113 bool ImageSource::getHotSpot(IntPoint&) const 114 { 115 return false; 116 } 117 118 size_t ImageSource::bytesDecodedToDetermineProperties() const 119 { 120 return 0; 121 } 122 123 int ImageSource::repetitionCount() 124 { 125 return m_decoder ? m_decoder->repetitionCount() : cAnimationNone; 126 } 127 128 size_t ImageSource::frameCount() const 129 { 130 return m_decoder ? m_decoder->frameCount() : 0; 131 } 132 133 NativeImagePtr ImageSource::createFrameAtIndex(size_t index) 134 { 135 if (!m_decoder) 136 return 0; 137 138 ImageFrame* buffer = m_decoder->frameBufferAtIndex(index); 139 if (!buffer || buffer->status() == ImageFrame::FrameEmpty) 140 return 0; 141 142 // Zero-height images can cause problems for some ports. If we have an 143 // empty image dimension, just bail. 144 if (size().isEmpty()) 145 return 0; 146 147 // Return the buffer contents as a native image. For some ports, the data 148 // is already in a native container, and this just increments its refcount. 149 return buffer->asNewNativeImage(); 150 } 151 152 float ImageSource::frameDurationAtIndex(size_t index) 153 { 154 if (!m_decoder) 155 return 0; 156 157 ImageFrame* buffer = m_decoder->frameBufferAtIndex(index); 158 if (!buffer || buffer->status() == ImageFrame::FrameEmpty) 159 return 0; 160 161 // Many annoying ads specify a 0 duration to make an image flash as quickly as possible. 162 // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify 163 // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082> 164 // for more information. 165 const float duration = buffer->duration() / 1000.0f; 166 if (duration < 0.011f) 167 return 0.100f; 168 return duration; 169 } 170 171 bool ImageSource::frameHasAlphaAtIndex(size_t index) 172 { 173 // When a frame has not finished decoding, always mark it as having alpha. 174 // Ports that check the result of this function to determine their 175 // compositing op need this in order to not draw the undecoded portion as 176 // black. 177 // TODO: Perhaps we should ensure that each individual decoder returns true 178 // in this case. 179 return !frameIsCompleteAtIndex(index) 180 || m_decoder->frameBufferAtIndex(index)->hasAlpha(); 181 } 182 183 bool ImageSource::frameIsCompleteAtIndex(size_t index) 184 { 185 if (!m_decoder) 186 return false; 187 188 ImageFrame* buffer = m_decoder->frameBufferAtIndex(index); 189 return buffer && buffer->status() == ImageFrame::FrameComplete; 190 } 191 192 } 193