1/* 2 * Copyright (C) 2006 Apple 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 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 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#include "ImageDecoder.h" 33 34#include "ImageOrientation.h" 35#include "NotImplemented.h" 36 37namespace WebCore { 38 39#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) 40unsigned ImageSource::s_maxPixelsPerDecodedImage = 1024 * 1024; 41#endif 42 43ImageSource::ImageSource(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) 44 : m_decoder(0) 45 , m_alphaOption(alphaOption) 46 , m_gammaAndColorProfileOption(gammaAndColorProfileOption) 47{ 48} 49 50ImageSource::~ImageSource() 51{ 52 clear(true); 53} 54 55void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived) 56{ 57 if (!destroyAll) { 58 if (m_decoder) 59 m_decoder->clearFrameBufferCache(clearBeforeFrame); 60 return; 61 } 62 63 delete m_decoder; 64 m_decoder = 0; 65 if (data) 66 setData(data, allDataReceived); 67} 68 69bool ImageSource::initialized() const 70{ 71 return m_decoder; 72} 73 74void ImageSource::setData(SharedBuffer* data, bool allDataReceived) 75{ 76 // Make the decoder by sniffing the bytes. 77 // This method will examine the data and instantiate an instance of the appropriate decoder plugin. 78 // If insufficient bytes are available to determine the image type, no decoder plugin will be 79 // made. 80 if (!m_decoder) { 81 m_decoder = static_cast<NativeImageDecoderPtr>(NativeImageDecoder::create(*data, m_alphaOption, m_gammaAndColorProfileOption)); 82#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) 83 if (m_decoder && s_maxPixelsPerDecodedImage) 84 m_decoder->setMaxNumPixels(s_maxPixelsPerDecodedImage); 85#endif 86 } 87 88 if (m_decoder) 89 m_decoder->setData(data, allDataReceived); 90} 91 92String ImageSource::filenameExtension() const 93{ 94 return m_decoder ? m_decoder->filenameExtension() : String(); 95} 96 97bool ImageSource::isSizeAvailable() 98{ 99 return m_decoder && m_decoder->isSizeAvailable(); 100} 101 102IntSize ImageSource::size(ImageOrientationDescription description) const 103{ 104 return frameSizeAtIndex(0, description); 105} 106 107IntSize ImageSource::frameSizeAtIndex(size_t index, ImageOrientationDescription description) const 108{ 109 if (!m_decoder) 110 return IntSize(); 111 112 IntSize size = m_decoder->frameSizeAtIndex(index); 113 if ((description.respectImageOrientation() == RespectImageOrientation) && m_decoder->orientation().usesWidthAsHeight()) 114 return IntSize(size.height(), size.width()); 115 116 return size; 117} 118 119bool ImageSource::getHotSpot(IntPoint& hotSpot) const 120{ 121 return m_decoder ? m_decoder->hotSpot(hotSpot) : false; 122} 123 124size_t ImageSource::bytesDecodedToDetermineProperties() const 125{ 126 return 0; 127} 128 129int ImageSource::repetitionCount() 130{ 131 return m_decoder ? m_decoder->repetitionCount() : cAnimationNone; 132} 133 134size_t ImageSource::frameCount() const 135{ 136 return m_decoder ? m_decoder->frameCount() : 0; 137} 138 139PassNativeImagePtr ImageSource::createFrameAtIndex(size_t index, float* scale) 140{ 141 UNUSED_PARAM(scale); 142 143 if (!m_decoder) 144 return 0; 145 146 ImageFrame* buffer = m_decoder->frameBufferAtIndex(index); 147 if (!buffer || buffer->status() == ImageFrame::FrameEmpty) 148 return 0; 149 150 // Zero-height images can cause problems for some ports. If we have an 151 // empty image dimension, just bail. 152 if (size().isEmpty()) 153 return 0; 154 155 // Return the buffer contents as a native image. For some ports, the data 156 // is already in a native container, and this just increments its refcount. 157 return buffer->asNewNativeImage(); 158} 159 160float ImageSource::frameDurationAtIndex(size_t index) 161{ 162 if (!m_decoder) 163 return 0; 164 165 ImageFrame* buffer = m_decoder->frameBufferAtIndex(index); 166 if (!buffer || buffer->status() == ImageFrame::FrameEmpty) 167 return 0; 168 169 // Many annoying ads specify a 0 duration to make an image flash as quickly as possible. 170 // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify 171 // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082> 172 // for more information. 173 const float duration = buffer->duration() / 1000.0f; 174 if (duration < 0.011f) 175 return 0.100f; 176 return duration; 177} 178 179ImageOrientation ImageSource::orientationAtIndex(size_t) const 180{ 181 return m_decoder ? m_decoder->orientation() : DefaultImageOrientation; 182} 183 184bool ImageSource::frameHasAlphaAtIndex(size_t index) 185{ 186 if (!m_decoder) 187 return true; 188 return m_decoder->frameHasAlphaAtIndex(index); 189} 190 191bool ImageSource::frameIsCompleteAtIndex(size_t index) 192{ 193 if (!m_decoder) 194 return false; 195 196 ImageFrame* buffer = m_decoder->frameBufferAtIndex(index); 197 return buffer && buffer->status() == ImageFrame::FrameComplete; 198} 199 200unsigned ImageSource::frameBytesAtIndex(size_t index) const 201{ 202 if (!m_decoder) 203 return 0; 204 return m_decoder->frameBytesAtIndex(index); 205} 206 207} 208