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 ImageSource::ImageSource() 41 : m_decoder(0) 42 { 43 } 44 45 ImageSource::~ImageSource() 46 { 47 clear(true); 48 } 49 50 void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived) 51 { 52 if (!destroyAll) { 53 if (m_decoder) 54 m_decoder->clearFrameBufferCache(clearBeforeFrame); 55 return; 56 } 57 58 delete m_decoder; 59 m_decoder = 0; 60 if (data) 61 setData(data, allDataReceived); 62 } 63 64 bool ImageSource::initialized() const 65 { 66 return m_decoder; 67 } 68 69 void ImageSource::setData(SharedBuffer* data, bool allDataReceived) 70 { 71 // Make the decoder by sniffing the bytes. 72 // This method will examine the data and instantiate an instance of the appropriate decoder plugin. 73 // If insufficient bytes are available to determine the image type, no decoder plugin will be 74 // made. 75 if (!m_decoder) { 76 m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data)); 77 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) 78 #ifndef IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS 79 #define IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS (1024 * 1024) 80 #endif 81 if (m_decoder) 82 m_decoder->setMaxNumPixels(IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS); 83 #endif 84 } 85 86 if (m_decoder) 87 m_decoder->setData(data, allDataReceived); 88 } 89 90 String ImageSource::filenameExtension() const 91 { 92 return m_decoder ? m_decoder->filenameExtension() : String(); 93 } 94 95 bool ImageSource::isSizeAvailable() 96 { 97 return m_decoder && m_decoder->isSizeAvailable(); 98 } 99 100 IntSize ImageSource::size() const 101 { 102 return m_decoder ? m_decoder->size() : IntSize(); 103 } 104 105 IntSize ImageSource::frameSizeAtIndex(size_t index) const 106 { 107 return m_decoder ? m_decoder->frameSizeAtIndex(index) : IntSize(); 108 } 109 110 int ImageSource::repetitionCount() 111 { 112 return m_decoder ? m_decoder->repetitionCount() : cAnimationNone; 113 } 114 115 size_t ImageSource::frameCount() const 116 { 117 return m_decoder ? m_decoder->frameCount() : 0; 118 } 119 120 NativeImagePtr ImageSource::createFrameAtIndex(size_t index) 121 { 122 if (!m_decoder) 123 return 0; 124 125 RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index); 126 if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty) 127 return 0; 128 129 // Zero-height images can cause problems for some ports. If we have an 130 // empty image dimension, just bail. 131 if (size().isEmpty()) 132 return 0; 133 134 // Return the buffer contents as a native image. For some ports, the data 135 // is already in a native container, and this just increments its refcount. 136 return buffer->asNewNativeImage(); 137 } 138 139 float ImageSource::frameDurationAtIndex(size_t index) 140 { 141 if (!m_decoder) 142 return 0; 143 144 RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index); 145 if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty) 146 return 0; 147 148 // Many annoying ads specify a 0 duration to make an image flash as quickly 149 // as possible. We follow WinIE's behavior and use a duration of 100 ms 150 // for any frames that specify a duration of <= 50 ms. See 151 // <http://bugs.webkit.org/show_bug.cgi?id=14413> or Radar 4051389 for 152 // more. 153 const float duration = buffer->duration() / 1000.0f; 154 return (duration < 0.051f) ? 0.100f : duration; 155 } 156 157 bool ImageSource::frameHasAlphaAtIndex(size_t index) 158 { 159 // When a frame has not finished decoding, always mark it as having alpha. 160 // Ports that check the result of this function to determine their 161 // compositing op need this in order to not draw the undecoded portion as 162 // black. 163 // TODO: Perhaps we should ensure that each individual decoder returns true 164 // in this case. 165 return !frameIsCompleteAtIndex(index) 166 || m_decoder->frameBufferAtIndex(index)->hasAlpha(); 167 } 168 169 bool ImageSource::frameIsCompleteAtIndex(size_t index) 170 { 171 if (!m_decoder) 172 return false; 173 174 RGBA32Buffer* buffer = m_decoder->frameBufferAtIndex(index); 175 return buffer && buffer->status() == RGBA32Buffer::FrameComplete; 176 } 177 178 } 179