• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
38 namespace WebCore {
39 
40 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
41 unsigned ImageSource::s_maxPixelsPerDecodedImage = 1024 * 1024;
42 #endif
43 
ImageSource(ImageSource::AlphaOption alphaOption,ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)44 ImageSource::ImageSource(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
45     : m_decoder(0)
46     , m_alphaOption(alphaOption)
47     , m_gammaAndColorProfileOption(gammaAndColorProfileOption)
48 {
49 }
50 
~ImageSource()51 ImageSource::~ImageSource()
52 {
53     clear(true);
54 }
55 
clear(bool destroyAll,size_t clearBeforeFrame,SharedBuffer * data,bool allDataReceived)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 
initialized() const70 bool ImageSource::initialized() const
71 {
72     return m_decoder;
73 }
74 
setData(SharedBuffer * data,bool allDataReceived)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 
filenameExtension() const93 String ImageSource::filenameExtension() const
94 {
95     return m_decoder ? m_decoder->filenameExtension() : String();
96 }
97 
isSizeAvailable()98 bool ImageSource::isSizeAvailable()
99 {
100     return m_decoder && m_decoder->isSizeAvailable();
101 }
102 
size() const103 IntSize ImageSource::size() const
104 {
105     return m_decoder ? m_decoder->size() : IntSize();
106 }
107 
frameSizeAtIndex(size_t index) const108 IntSize ImageSource::frameSizeAtIndex(size_t index) const
109 {
110     return m_decoder ? m_decoder->frameSizeAtIndex(index) : IntSize();
111 }
112 
getHotSpot(IntPoint &) const113 bool ImageSource::getHotSpot(IntPoint&) const
114 {
115     return false;
116 }
117 
bytesDecodedToDetermineProperties() const118 size_t ImageSource::bytesDecodedToDetermineProperties() const
119 {
120     return 0;
121 }
122 
repetitionCount()123 int ImageSource::repetitionCount()
124 {
125     return m_decoder ? m_decoder->repetitionCount() : cAnimationNone;
126 }
127 
frameCount() const128 size_t ImageSource::frameCount() const
129 {
130     return m_decoder ? m_decoder->frameCount() : 0;
131 }
132 
createFrameAtIndex(size_t index)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 
frameDurationAtIndex(size_t index)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 
frameHasAlphaAtIndex(size_t index)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 
frameIsCompleteAtIndex(size_t index)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