1/* 2 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. 3 * Copyright (C) 2007 Alp Toker <alp.toker@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 38namespace WebCore { 39 40ImageSource::ImageSource() 41 : m_decoder(0) 42{ 43} 44 45ImageSource::~ImageSource() 46{ 47 clear(true); 48} 49 50void 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 64bool ImageSource::initialized() const 65{ 66 return m_decoder; 67} 68 69void 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 90String ImageSource::filenameExtension() const 91{ 92 return m_decoder ? m_decoder->filenameExtension() : String(); 93} 94 95bool ImageSource::isSizeAvailable() 96{ 97 return m_decoder && m_decoder->isSizeAvailable(); 98} 99 100IntSize ImageSource::size() const 101{ 102 return m_decoder ? m_decoder->size() : IntSize(); 103} 104 105IntSize ImageSource::frameSizeAtIndex(size_t index) const 106{ 107 return m_decoder ? m_decoder->frameSizeAtIndex(index) : IntSize(); 108} 109 110int ImageSource::repetitionCount() 111{ 112 return m_decoder ? m_decoder->repetitionCount() : cAnimationNone; 113} 114 115size_t ImageSource::frameCount() const 116{ 117 return m_decoder ? m_decoder->frameCount() : 0; 118} 119 120NativeImagePtr 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 139float 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 157bool 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 169bool 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