f6b765fe4d2f7ed56a180f61b45478cfa1a610aa
[WebKit-https.git] / Source / WebCore / platform / graphics / ImageSource.cpp
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
37 namespace WebCore {
38
39 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
40 unsigned ImageSource::s_maxPixelsPerDecodedImage = 1024 * 1024;
41 #endif
42
43 ImageSource::ImageSource(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
44     : m_decoder(0)
45     , m_alphaOption(alphaOption)
46     , m_gammaAndColorProfileOption(gammaAndColorProfileOption)
47 {
48 }
49
50 ImageSource::~ImageSource()
51 {
52     clear(true);
53 }
54
55 void 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
69 bool ImageSource::initialized() const
70 {
71     return m_decoder;
72 }
73
74 void 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
92 String ImageSource::filenameExtension() const
93 {
94     return m_decoder ? m_decoder->filenameExtension() : String();
95 }
96
97 bool ImageSource::isSizeAvailable()
98 {
99     return m_decoder && m_decoder->isSizeAvailable();
100 }
101
102 IntSize ImageSource::size(ImageOrientationDescription description) const
103 {
104     return frameSizeAtIndex(0, description);
105 }
106
107 IntSize 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
119 bool ImageSource::getHotSpot(IntPoint& hotSpot) const
120 {
121     return m_decoder ? m_decoder->hotSpot(hotSpot) : false;
122 }
123
124 size_t ImageSource::bytesDecodedToDetermineProperties() const
125 {
126     return 0;
127 }
128
129 int ImageSource::repetitionCount()
130 {
131     return m_decoder ? m_decoder->repetitionCount() : cAnimationNone;
132 }
133
134 size_t ImageSource::frameCount() const
135 {
136     return m_decoder ? m_decoder->frameCount() : 0;
137 }
138
139 PassNativeImagePtr 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
160 float 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
179 ImageOrientation ImageSource::orientationAtIndex(size_t) const
180 {
181     return m_decoder ? m_decoder->orientation() : DefaultImageOrientation;
182 }
183
184 bool ImageSource::frameHasAlphaAtIndex(size_t index)
185 {
186     if (!m_decoder)
187         return true;
188     return m_decoder->frameHasAlphaAtIndex(index);
189 }
190
191 bool 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
200 unsigned ImageSource::frameBytesAtIndex(size_t index) const
201 {
202     if (!m_decoder)
203         return 0;
204     return m_decoder->frameBytesAtIndex(index);
205 }
206
207 }