Home | History | Annotate | Download | only in graphics
      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