1 /*
2 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
3 * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "config.h"
28 #include "BitmapImage.h"
29
30 #include "FloatRect.h"
31 #include "ImageObserver.h"
32 #include "IntRect.h"
33 #include "MIMETypeRegistry.h"
34 #include "PlatformString.h"
35 #include "Timer.h"
36 #include <wtf/CurrentTime.h>
37 #include <wtf/Vector.h>
38
39 namespace WebCore {
40
frameBytes(const IntSize & frameSize)41 static int frameBytes(const IntSize& frameSize)
42 {
43 return frameSize.width() * frameSize.height() * 4;
44 }
45
BitmapImage(ImageObserver * observer)46 BitmapImage::BitmapImage(ImageObserver* observer)
47 : Image(observer)
48 , m_currentFrame(0)
49 , m_frames(0)
50 , m_frameTimer(0)
51 , m_repetitionCount(cAnimationNone)
52 , m_repetitionCountStatus(Unknown)
53 , m_repetitionsComplete(0)
54 , m_desiredFrameStartTime(0)
55 , m_isSolidColor(false)
56 , m_checkedForSolidColor(false)
57 , m_animationFinished(false)
58 , m_allDataReceived(false)
59 , m_haveSize(false)
60 , m_sizeAvailable(false)
61 , m_hasUniformFrameSize(true)
62 , m_decodedSize(0)
63 , m_haveFrameCount(false)
64 , m_frameCount(0)
65 {
66 initPlatformData();
67 }
68
~BitmapImage()69 BitmapImage::~BitmapImage()
70 {
71 invalidatePlatformData();
72 stopAnimation();
73 }
74
destroyDecodedData(bool destroyAll)75 void BitmapImage::destroyDecodedData(bool destroyAll)
76 {
77 int framesCleared = 0;
78 const size_t clearBeforeFrame = destroyAll ? m_frames.size() : m_currentFrame;
79 for (size_t i = 0; i < clearBeforeFrame; ++i) {
80 // The underlying frame isn't actually changing (we're just trying to
81 // save the memory for the framebuffer data), so we don't need to clear
82 // the metadata.
83 if (m_frames[i].clear(false))
84 ++framesCleared;
85 }
86
87 destroyMetadataAndNotify(framesCleared);
88
89 m_source.clear(destroyAll, clearBeforeFrame, data(), m_allDataReceived);
90 return;
91 }
92
destroyDecodedDataIfNecessary(bool destroyAll)93 void BitmapImage::destroyDecodedDataIfNecessary(bool destroyAll)
94 {
95 // Animated images >5MB are considered large enough that we'll only hang on
96 // to one frame at a time.
97 static const unsigned cLargeAnimationCutoff = 5242880;
98 if (m_frames.size() * frameBytes(m_size) > cLargeAnimationCutoff)
99 destroyDecodedData(destroyAll);
100 }
101
destroyMetadataAndNotify(int framesCleared)102 void BitmapImage::destroyMetadataAndNotify(int framesCleared)
103 {
104 m_isSolidColor = false;
105 invalidatePlatformData();
106
107 const int deltaBytes = framesCleared * -frameBytes(m_size);
108 m_decodedSize += deltaBytes;
109 if (deltaBytes && imageObserver())
110 imageObserver()->decodedSizeChanged(this, deltaBytes);
111 }
112
cacheFrame(size_t index)113 void BitmapImage::cacheFrame(size_t index)
114 {
115 size_t numFrames = frameCount();
116 ASSERT(m_decodedSize == 0 || numFrames > 1);
117
118 if (m_frames.size() < numFrames)
119 m_frames.grow(numFrames);
120
121 m_frames[index].m_frame = m_source.createFrameAtIndex(index);
122 if (numFrames == 1 && m_frames[index].m_frame)
123 checkForSolidColor();
124
125 m_frames[index].m_haveMetadata = true;
126 m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index);
127 if (repetitionCount(false) != cAnimationNone)
128 m_frames[index].m_duration = m_source.frameDurationAtIndex(index);
129 m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);
130
131 const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size);
132 if (frameSize != m_size)
133 m_hasUniformFrameSize = false;
134 if (m_frames[index].m_frame) {
135 const int deltaBytes = frameBytes(frameSize);
136 m_decodedSize += deltaBytes;
137 if (imageObserver())
138 imageObserver()->decodedSizeChanged(this, deltaBytes);
139 }
140 }
141
size() const142 IntSize BitmapImage::size() const
143 {
144 if (m_sizeAvailable && !m_haveSize) {
145 m_size = m_source.size();
146 m_haveSize = true;
147 }
148 return m_size;
149 }
150
currentFrameSize() const151 IntSize BitmapImage::currentFrameSize() const
152 {
153 if (!m_currentFrame || m_hasUniformFrameSize)
154 return size();
155 return m_source.frameSizeAtIndex(m_currentFrame);
156 }
157
dataChanged(bool allDataReceived)158 bool BitmapImage::dataChanged(bool allDataReceived)
159 {
160 // Because we're modifying the current frame, clear its (now possibly
161 // inaccurate) metadata as well.
162 destroyMetadataAndNotify((!m_frames.isEmpty() && m_frames[m_frames.size() - 1].clear(true)) ? 1 : 0);
163
164 // Feed all the data we've seen so far to the image decoder.
165 m_allDataReceived = allDataReceived;
166 m_source.setData(data(), allDataReceived);
167
168 // Clear the frame count.
169 m_haveFrameCount = false;
170
171 m_hasUniformFrameSize = true;
172
173 // Image properties will not be available until the first frame of the file
174 // reaches kCGImageStatusIncomplete.
175 return isSizeAvailable();
176 }
177
filenameExtension() const178 String BitmapImage::filenameExtension() const
179 {
180 return m_source.filenameExtension();
181 }
182
frameCount()183 size_t BitmapImage::frameCount()
184 {
185 if (!m_haveFrameCount) {
186 m_haveFrameCount = true;
187 m_frameCount = m_source.frameCount();
188 }
189 return m_frameCount;
190 }
191
isSizeAvailable()192 bool BitmapImage::isSizeAvailable()
193 {
194 if (m_sizeAvailable)
195 return true;
196
197 m_sizeAvailable = m_source.isSizeAvailable();
198
199 return m_sizeAvailable;
200 }
201
frameAtIndex(size_t index)202 NativeImagePtr BitmapImage::frameAtIndex(size_t index)
203 {
204 if (index >= frameCount())
205 return 0;
206
207 if (index >= m_frames.size() || !m_frames[index].m_frame)
208 cacheFrame(index);
209
210 return m_frames[index].m_frame;
211 }
212
frameIsCompleteAtIndex(size_t index)213 bool BitmapImage::frameIsCompleteAtIndex(size_t index)
214 {
215 if (index >= frameCount())
216 return true;
217
218 if (index >= m_frames.size() || !m_frames[index].m_haveMetadata)
219 cacheFrame(index);
220
221 return m_frames[index].m_isComplete;
222 }
223
frameDurationAtIndex(size_t index)224 float BitmapImage::frameDurationAtIndex(size_t index)
225 {
226 if (index >= frameCount())
227 return 0;
228
229 if (index >= m_frames.size() || !m_frames[index].m_haveMetadata)
230 cacheFrame(index);
231
232 return m_frames[index].m_duration;
233 }
234
frameHasAlphaAtIndex(size_t index)235 bool BitmapImage::frameHasAlphaAtIndex(size_t index)
236 {
237 if (index >= frameCount())
238 return true;
239
240 if (index >= m_frames.size() || !m_frames[index].m_haveMetadata)
241 cacheFrame(index);
242
243 return m_frames[index].m_hasAlpha;
244 }
245
repetitionCount(bool imageKnownToBeComplete)246 int BitmapImage::repetitionCount(bool imageKnownToBeComplete)
247 {
248 if ((m_repetitionCountStatus == Unknown) || ((m_repetitionCountStatus == Uncertain) && imageKnownToBeComplete)) {
249 // Snag the repetition count. If |imageKnownToBeComplete| is false, the
250 // repetition count may not be accurate yet for GIFs; in this case the
251 // decoder will default to cAnimationLoopOnce, and we'll try and read
252 // the count again once the whole image is decoded.
253 m_repetitionCount = m_source.repetitionCount();
254 m_repetitionCountStatus = (imageKnownToBeComplete || m_repetitionCount == cAnimationNone) ? Certain : Uncertain;
255 }
256 return m_repetitionCount;
257 }
258
shouldAnimate()259 bool BitmapImage::shouldAnimate()
260 {
261 return (repetitionCount(false) != cAnimationNone && !m_animationFinished && imageObserver());
262 }
263
startAnimation(bool catchUpIfNecessary)264 void BitmapImage::startAnimation(bool catchUpIfNecessary)
265 {
266 #ifdef ANDROID_ANIMATED_GIF
267 // We can't ever seem to keep up, so always let us just show the next frame
268 catchUpIfNecessary = false;
269 #endif
270 if (m_frameTimer || !shouldAnimate() || frameCount() <= 1)
271 return;
272
273 // Determine time for next frame to start. By ignoring paint and timer lag
274 // in this calculation, we make the animation appear to run at its desired
275 // rate regardless of how fast it's being repainted.
276 const double currentDuration = frameDurationAtIndex(m_currentFrame);
277 const double time = currentTime();
278 if (m_desiredFrameStartTime == 0) {
279 m_desiredFrameStartTime = time + currentDuration;
280 } else {
281 m_desiredFrameStartTime += currentDuration;
282
283 // When an animated image is more than five minutes out of date, the
284 // user probably doesn't care about resyncing and we could burn a lot of
285 // time looping through frames below. Just reset the timings.
286 const double cAnimationResyncCutoff = 5 * 60;
287 if ((time - m_desiredFrameStartTime) > cAnimationResyncCutoff)
288 m_desiredFrameStartTime = time + currentDuration;
289 }
290
291 // Don't advance the animation to an incomplete frame.
292 size_t nextFrame = (m_currentFrame + 1) % frameCount();
293 if (!m_allDataReceived && !frameIsCompleteAtIndex(nextFrame))
294 return;
295
296 // Don't advance past the last frame if we haven't decoded the whole image
297 // yet and our repetition count is potentially unset. The repetition count
298 // in a GIF can potentially come after all the rest of the image data, so
299 // wait on it.
300 if (!m_allDataReceived && repetitionCount(false) == cAnimationLoopOnce && m_currentFrame >= (frameCount() - 1))
301 return;
302
303 // The image may load more slowly than it's supposed to animate, so that by
304 // the time we reach the end of the first repetition, we're well behind.
305 // Clamp the desired frame start time in this case, so that we don't skip
306 // frames (or whole iterations) trying to "catch up". This is a tradeoff:
307 // It guarantees users see the whole animation the second time through and
308 // don't miss any repetitions, and is closer to what other browsers do; on
309 // the other hand, it makes animations "less accurate" for pages that try to
310 // sync an image and some other resource (e.g. audio), especially if users
311 // switch tabs (and thus stop drawing the animation, which will pause it)
312 // during that initial loop, then switch back later.
313 if (nextFrame == 0 && m_repetitionsComplete == 0 && m_desiredFrameStartTime < time)
314 m_desiredFrameStartTime = time;
315
316 if (!catchUpIfNecessary || time < m_desiredFrameStartTime) {
317 // Haven't yet reached time for next frame to start; delay until then.
318 m_frameTimer = new Timer<BitmapImage>(this, &BitmapImage::advanceAnimation);
319 m_frameTimer->startOneShot(std::max(m_desiredFrameStartTime - time, 0.));
320 } else {
321 // We've already reached or passed the time for the next frame to start.
322 // See if we've also passed the time for frames after that to start, in
323 // case we need to skip some frames entirely. Remember not to advance
324 // to an incomplete frame.
325 for (size_t frameAfterNext = (nextFrame + 1) % frameCount(); frameIsCompleteAtIndex(frameAfterNext); frameAfterNext = (nextFrame + 1) % frameCount()) {
326 // Should we skip the next frame?
327 double frameAfterNextStartTime = m_desiredFrameStartTime + frameDurationAtIndex(nextFrame);
328 if (time < frameAfterNextStartTime)
329 break;
330
331 // Yes; skip over it without notifying our observers.
332 if (!internalAdvanceAnimation(true))
333 return;
334 m_desiredFrameStartTime = frameAfterNextStartTime;
335 nextFrame = frameAfterNext;
336 }
337
338 // Draw the next frame immediately. Note that m_desiredFrameStartTime
339 // may be in the past, meaning the next time through this function we'll
340 // kick off the next advancement sooner than this frame's duration would
341 // suggest.
342 if (internalAdvanceAnimation(false)) {
343 // The image region has been marked dirty, but once we return to our
344 // caller, draw() will clear it, and nothing will cause the
345 // animation to advance again. We need to start the timer for the
346 // next frame running, or the animation can hang. (Compare this
347 // with when advanceAnimation() is called, and the region is dirtied
348 // while draw() is not in the callstack, meaning draw() gets called
349 // to update the region and thus startAnimation() is reached again.)
350 // NOTE: For large images with slow or heavily-loaded systems,
351 // throwing away data as we go (see destroyDecodedData()) means we
352 // can spend so much time re-decoding data above that by the time we
353 // reach here we're behind again. If we let startAnimation() run
354 // the catch-up code again, we can get long delays without painting
355 // as we race the timer, or even infinite recursion. In this
356 // situation the best we can do is to simply change frames as fast
357 // as possible, so force startAnimation() to set a zero-delay timer
358 // and bail out if we're not caught up.
359 startAnimation(false);
360 }
361 }
362 }
363
stopAnimation()364 void BitmapImage::stopAnimation()
365 {
366 // This timer is used to animate all occurrences of this image. Don't invalidate
367 // the timer unless all renderers have stopped drawing.
368 delete m_frameTimer;
369 m_frameTimer = 0;
370 }
371
resetAnimation()372 void BitmapImage::resetAnimation()
373 {
374 stopAnimation();
375 m_currentFrame = 0;
376 m_repetitionsComplete = 0;
377 m_desiredFrameStartTime = 0;
378 m_animationFinished = false;
379
380 // For extremely large animations, when the animation is reset, we just throw everything away.
381 destroyDecodedDataIfNecessary(true);
382 }
383
advanceAnimation(Timer<BitmapImage> *)384 void BitmapImage::advanceAnimation(Timer<BitmapImage>*)
385 {
386 internalAdvanceAnimation(false);
387 // At this point the image region has been marked dirty, and if it's
388 // onscreen, we'll soon make a call to draw(), which will call
389 // startAnimation() again to keep the animation moving.
390 }
391
internalAdvanceAnimation(bool skippingFrames)392 bool BitmapImage::internalAdvanceAnimation(bool skippingFrames)
393 {
394 // Stop the animation.
395 stopAnimation();
396
397 // See if anyone is still paying attention to this animation. If not, we don't
398 // advance and will remain suspended at the current frame until the animation is resumed.
399 if (!skippingFrames && imageObserver()->shouldPauseAnimation(this))
400 return false;
401
402 ++m_currentFrame;
403 bool advancedAnimation = true;
404 bool destroyAll = false;
405 if (m_currentFrame >= frameCount()) {
406 ++m_repetitionsComplete;
407
408 // Get the repetition count again. If we weren't able to get a
409 // repetition count before, we should have decoded the whole image by
410 // now, so it should now be available.
411 if (repetitionCount(true) && m_repetitionsComplete >= m_repetitionCount) {
412 m_animationFinished = true;
413 m_desiredFrameStartTime = 0;
414 --m_currentFrame;
415 advancedAnimation = false;
416 } else {
417 m_currentFrame = 0;
418 destroyAll = true;
419 }
420 }
421 destroyDecodedDataIfNecessary(destroyAll);
422
423 // We need to draw this frame if we advanced to it while not skipping, or if
424 // while trying to skip frames we hit the last frame and thus had to stop.
425 if (skippingFrames != advancedAnimation)
426 imageObserver()->animationAdvanced(this);
427 return advancedAnimation;
428 }
429
430 }
431