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 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 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 "GraphicsContext.h"
32#include "ImageBuffer.h"
33#include "ImageObserver.h"
34#include "IntRect.h"
35#include "MIMETypeRegistry.h"
36#include "Timer.h"
37#include <wtf/CurrentTime.h>
38#include <wtf/Vector.h>
39#include <wtf/text/WTFString.h>
40
41#if PLATFORM(IOS)
42#include <limits>
43#endif
44
45namespace WebCore {
46
47// FIXME: We should better integrate the iOS and non-iOS code in this class. Unlike other ports, the
48// iOS port caches the metadata for a frame without decoding the image.
49BitmapImage::BitmapImage(ImageObserver* observer)
50    : Image(observer)
51    , m_currentFrame(0)
52    , m_frames(0)
53    , m_repetitionCount(cAnimationNone)
54    , m_repetitionCountStatus(Unknown)
55    , m_repetitionsComplete(0)
56    , m_desiredFrameStartTime(0)
57    , m_decodedSize(0)
58    , m_decodedPropertiesSize(0)
59    , m_frameCount(0)
60#if PLATFORM(IOS)
61    // FIXME: We should expose a setting to enable/disable progressive loading remove the PLATFORM(IOS)-guard.
62    , m_progressiveLoadChunkTime(0)
63    , m_progressiveLoadChunkCount(0)
64#endif
65    , m_isSolidColor(false)
66    , m_checkedForSolidColor(false)
67    , m_animationFinished(false)
68    , m_allDataReceived(false)
69    , m_haveSize(false)
70    , m_sizeAvailable(false)
71    , m_hasUniformFrameSize(true)
72    , m_haveFrameCount(false)
73    , m_cachedImage(0)
74{
75}
76
77BitmapImage::~BitmapImage()
78{
79    invalidatePlatformData();
80    stopAnimation();
81}
82
83bool BitmapImage::hasSingleSecurityOrigin() const
84{
85    return true;
86}
87
88void BitmapImage::destroyDecodedData(bool destroyAll)
89{
90    unsigned frameBytesCleared = 0;
91    const size_t clearBeforeFrame = destroyAll ? m_frames.size() : m_currentFrame;
92
93    // Because we can advance frames without always needing to decode the actual
94    // bitmap data, |m_currentFrame| may be larger than m_frames.size();
95    // make sure not to walk off the end of the container in this case.
96    for (size_t i = 0; i <  std::min(clearBeforeFrame, m_frames.size()); ++i) {
97        // The underlying frame isn't actually changing (we're just trying to
98        // save the memory for the framebuffer data), so we don't need to clear
99        // the metadata.
100        unsigned frameBytes = m_frames[i].m_frameBytes;
101        if (m_frames[i].clear(false))
102            frameBytesCleared += frameBytes;
103    }
104
105    destroyMetadataAndNotify(frameBytesCleared);
106
107    m_source.clear(destroyAll, clearBeforeFrame, data(), m_allDataReceived);
108    return;
109}
110
111void BitmapImage::destroyDecodedDataIfNecessary(bool destroyAll)
112{
113    // Animated images >5MB are considered large enough that we'll only hang on
114    // to one frame at a time.
115#if PLATFORM(IOS)
116    static const unsigned cLargeAnimationCutoff = 2097152;
117
118     // If we have decoded frames but there is no encoded data, we shouldn't destroy
119     // the decoded image since we won't be able to reconstruct it later.
120     if (!data() && m_frames.size())
121         return;
122#else
123    static const unsigned cLargeAnimationCutoff = 5242880;
124#endif
125
126    // If we have decoded frames but there is no encoded data, we shouldn't destroy
127    // the decoded image since we won't be able to reconstruct it later.
128    if (!data() && m_frames.size())
129        return;
130
131    unsigned allFrameBytes = 0;
132    for (size_t i = 0; i < m_frames.size(); ++i)
133        allFrameBytes += m_frames[i].m_frameBytes;
134
135    if (allFrameBytes > cLargeAnimationCutoff)
136        destroyDecodedData(destroyAll);
137}
138
139void BitmapImage::destroyMetadataAndNotify(unsigned frameBytesCleared)
140{
141    m_isSolidColor = false;
142    m_checkedForSolidColor = false;
143    invalidatePlatformData();
144
145    ASSERT(m_decodedSize >= frameBytesCleared);
146    m_decodedSize -= frameBytesCleared;
147    if (frameBytesCleared > 0) {
148        frameBytesCleared += m_decodedPropertiesSize;
149        m_decodedPropertiesSize = 0;
150    }
151    if (frameBytesCleared && imageObserver())
152        imageObserver()->decodedSizeChanged(this, -safeCast<int>(frameBytesCleared));
153}
154
155#if PLATFORM(IOS)
156void BitmapImage::cacheFrame(size_t index, float scaleHint)
157#else
158void BitmapImage::cacheFrame(size_t index)
159#endif
160{
161    size_t numFrames = frameCount();
162    ASSERT(m_decodedSize == 0 || numFrames > 1);
163
164    if (m_frames.size() < numFrames)
165        m_frames.grow(numFrames);
166
167#if PLATFORM(IOS)
168    m_frames[index].m_frame = m_source.createFrameAtIndex(index, &scaleHint);
169    m_frames[index].m_subsamplingScale = scaleHint;
170#else
171    m_frames[index].m_frame = m_source.createFrameAtIndex(index);
172#endif
173    if (numFrames == 1 && m_frames[index].m_frame)
174        checkForSolidColor();
175
176    m_frames[index].m_orientation = m_source.orientationAtIndex(index);
177    m_frames[index].m_haveMetadata = true;
178    m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index);
179    if (repetitionCount(false) != cAnimationNone)
180        m_frames[index].m_duration = m_source.frameDurationAtIndex(index);
181    m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);
182    m_frames[index].m_frameBytes = m_source.frameBytesAtIndex(index);
183
184    const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size);
185    if (frameSize != m_size)
186        m_hasUniformFrameSize = false;
187    if (m_frames[index].m_frame) {
188        int deltaBytes = safeCast<int>(m_frames[index].m_frameBytes);
189        m_decodedSize += deltaBytes;
190        // The fully-decoded frame will subsume the partially decoded data used
191        // to determine image properties.
192        deltaBytes -= m_decodedPropertiesSize;
193        m_decodedPropertiesSize = 0;
194        if (imageObserver())
195            imageObserver()->decodedSizeChanged(this, deltaBytes);
196    }
197}
198
199#if PLATFORM(IOS)
200void BitmapImage::cacheFrameInfo(size_t index)
201{
202    size_t numFrames = frameCount();
203
204    if (m_frames.size() < numFrames)
205        m_frames.resize(numFrames);
206
207    ASSERT(!m_frames[index].m_haveInfo);
208
209    if (shouldAnimate())
210        m_frames[index].m_duration = m_source.frameDurationAtIndex(index);
211    m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);
212    m_frames[index].m_haveInfo = true;
213}
214#endif
215
216void BitmapImage::didDecodeProperties() const
217{
218    if (m_decodedSize)
219        return;
220    size_t updatedSize = m_source.bytesDecodedToDetermineProperties();
221    if (m_decodedPropertiesSize == updatedSize)
222        return;
223    int deltaBytes = updatedSize - m_decodedPropertiesSize;
224#if !ASSERT_DISABLED
225    bool overflow = updatedSize > m_decodedPropertiesSize && deltaBytes < 0;
226    bool underflow = updatedSize < m_decodedPropertiesSize && deltaBytes > 0;
227    ASSERT(!overflow && !underflow);
228#endif
229    m_decodedPropertiesSize = updatedSize;
230    if (imageObserver())
231        imageObserver()->decodedSizeChanged(this, deltaBytes);
232}
233
234void BitmapImage::updateSize(ImageOrientationDescription description) const
235{
236    if (!m_sizeAvailable || m_haveSize)
237        return;
238
239    m_size = m_source.size(description);
240    m_sizeRespectingOrientation = m_source.size(ImageOrientationDescription(RespectImageOrientation, description.imageOrientation()));
241    m_imageOrientation = static_cast<unsigned>(description.imageOrientation());
242    m_shouldRespectImageOrientation = static_cast<unsigned>(description.respectImageOrientation());
243#if PLATFORM(IOS)
244    m_originalSize = m_source.originalSize();
245    m_originalSizeRespectingOrientation = m_source.originalSize(RespectImageOrientation);
246#endif
247    m_haveSize = true;
248    didDecodeProperties();
249}
250
251FloatSize BitmapImage::size() const
252{
253    updateSize();
254    return m_size;
255}
256
257IntSize BitmapImage::sizeRespectingOrientation(ImageOrientationDescription description) const
258{
259    updateSize(description);
260    return m_sizeRespectingOrientation;
261}
262
263#if PLATFORM(IOS)
264FloatSize BitmapImage::originalSize() const
265{
266    updateSize();
267    return m_originalSize;
268}
269
270IntSize BitmapImage::originalSizeRespectingOrientation() const
271{
272    updateSize();
273    return m_originalSizeRespectingOrientation;
274}
275#endif
276
277IntSize BitmapImage::currentFrameSize() const
278{
279    if (!m_currentFrame || m_hasUniformFrameSize)
280        return IntSize(size());
281    IntSize frameSize = m_source.frameSizeAtIndex(m_currentFrame);
282    didDecodeProperties();
283    return frameSize;
284}
285
286bool BitmapImage::getHotSpot(IntPoint& hotSpot) const
287{
288    bool result = m_source.getHotSpot(hotSpot);
289    didDecodeProperties();
290    return result;
291}
292
293bool BitmapImage::dataChanged(bool allDataReceived)
294{
295    // Because we're modifying the current frame, clear its (now possibly
296    // inaccurate) metadata as well.
297#if !PLATFORM(IOS)
298    // Clear all partially-decoded frames. For most image formats, there is only
299    // one frame, but at least GIF and ICO can have more. With GIFs, the frames
300    // come in order and we ask to decode them in order, waiting to request a
301    // subsequent frame until the prior one is complete. Given that we clear
302    // incomplete frames here, this means there is at most one incomplete frame
303    // (even if we use destroyDecodedData() -- since it doesn't reset the
304    // metadata), and it is after all the complete frames.
305    //
306    // With ICOs, on the other hand, we may ask for arbitrary frames at
307    // different times (e.g. because we're displaying a higher-resolution image
308    // in the content area and using a lower-resolution one for the favicon),
309    // and the frames aren't even guaranteed to appear in the file in the same
310    // order as in the directory, so an arbitrary number of the frames might be
311    // incomplete (if we ask for frames for which we've not yet reached the
312    // start of the frame data), and any or none of them might be the particular
313    // frame affected by appending new data here. Thus we have to clear all the
314    // incomplete frames to be safe.
315    unsigned frameBytesCleared = 0;
316    for (size_t i = 0; i < m_frames.size(); ++i) {
317        // NOTE: Don't call frameIsCompleteAtIndex() here, that will try to
318        // decode any uncached (i.e. never-decoded or
319        // cleared-on-a-previous-pass) frames!
320        unsigned frameBytes = m_frames[i].m_frameBytes;
321        if (m_frames[i].m_haveMetadata && !m_frames[i].m_isComplete)
322            frameBytesCleared += (m_frames[i].clear(true) ? frameBytes : 0);
323    }
324    destroyMetadataAndNotify(frameBytesCleared);
325#else
326    int deltaBytes = 0;
327    if (!m_frames.isEmpty()) {
328        int bytes = m_frames[m_frames.size() - 1].m_frameBytes;
329        if (m_frames[m_frames.size() - 1].clear(true)) {
330            deltaBytes += bytes;
331            deltaBytes += m_decodedPropertiesSize;
332            m_decodedPropertiesSize = 0;
333        }
334    }
335    destroyMetadataAndNotify(deltaBytes);
336#endif
337
338    // Feed all the data we've seen so far to the image decoder.
339    m_allDataReceived = allDataReceived;
340#if PLATFORM(IOS)
341    // FIXME: We should expose a setting to enable/disable progressive loading and make this
342    // code conditional on it. Then we can remove the PLATFORM(IOS)-guard.
343    static const double chunkLoadIntervals[] = {0, 1, 3, 6, 15};
344    double interval = chunkLoadIntervals[std::min(m_progressiveLoadChunkCount, static_cast<uint16_t>(4))];
345
346    bool needsUpdate = false;
347    if (currentTime() - m_progressiveLoadChunkTime > interval) { // The first time through, the chunk time will be 0 and the image will get an update.
348        needsUpdate = true;
349        m_progressiveLoadChunkTime = currentTime();
350        ASSERT(m_progressiveLoadChunkCount <= std::numeric_limits<uint16_t>::max());
351        ++m_progressiveLoadChunkCount;
352    }
353    if (needsUpdate || allDataReceived)
354        m_source.setData(data(), allDataReceived);
355#else
356    m_source.setData(data(), allDataReceived);
357#endif
358
359    m_haveFrameCount = false;
360    m_hasUniformFrameSize = true;
361    return isSizeAvailable();
362}
363
364String BitmapImage::filenameExtension() const
365{
366    return m_source.filenameExtension();
367}
368
369size_t BitmapImage::frameCount()
370{
371    if (!m_haveFrameCount) {
372        m_frameCount = m_source.frameCount();
373        // If decoder is not initialized yet, m_source.frameCount() returns 0.
374        if (m_frameCount) {
375            didDecodeProperties();
376            m_haveFrameCount = true;
377        }
378    }
379    return m_frameCount;
380}
381
382bool BitmapImage::isSizeAvailable()
383{
384    if (m_sizeAvailable)
385        return true;
386
387    m_sizeAvailable = m_source.isSizeAvailable();
388    didDecodeProperties();
389
390    return m_sizeAvailable;
391}
392
393#if !PLATFORM(IOS)
394bool BitmapImage::ensureFrameIsCached(size_t index)
395{
396    if (index >= frameCount())
397        return false;
398
399    if (index >= m_frames.size() || !m_frames[index].m_frame)
400        cacheFrame(index);
401    return true;
402}
403#else
404bool BitmapImage::ensureFrameInfoIsCached(size_t index)
405{
406    if (index >= frameCount())
407        return false;
408
409    if (index >= m_frames.size() || !m_frames[index].m_haveInfo)
410        cacheFrameInfo(index);
411    return true;
412}
413#endif
414
415PassNativeImagePtr BitmapImage::frameAtIndex(size_t index)
416{
417#if PLATFORM(IOS)
418    return frameAtIndex(index, 1.0f);
419#else
420    if (!ensureFrameIsCached(index))
421        return nullptr;
422    return m_frames[index].m_frame;
423#endif
424}
425
426#if PLATFORM(IOS)
427PassNativeImagePtr BitmapImage::frameAtIndex(size_t index, float scaleHint)
428{
429    if (index >= frameCount())
430        return nullptr;
431
432    if (index >= m_frames.size() || !m_frames[index].m_frame)
433        cacheFrame(index, scaleHint);
434    else if (std::min(1.0f, scaleHint) > m_frames[index].m_subsamplingScale) {
435        // If the image is already cached, but at too small a size, re-decode a larger version.
436        int sizeChange = -m_frames[index].m_frameBytes;
437        ASSERT(static_cast<int>(m_decodedSize) + sizeChange >= 0);
438        m_frames[index].clear(true);
439        invalidatePlatformData();
440        m_decodedSize += sizeChange;
441        if (imageObserver())
442            imageObserver()->decodedSizeChanged(this, sizeChange);
443
444        cacheFrame(index, scaleHint);
445    }
446    return m_frames[index].m_frame;
447}
448#endif
449
450bool BitmapImage::frameIsCompleteAtIndex(size_t index)
451{
452#if PLATFORM(IOS)
453    // FIXME: cacheFrameInfo does not set m_isComplete. Should it?
454    if (!ensureFrameInfoIsCached(index))
455        return false;
456#else
457    if (!ensureFrameIsCached(index))
458        return false;
459#endif
460    return m_frames[index].m_isComplete;
461}
462
463float BitmapImage::frameDurationAtIndex(size_t index)
464{
465#if PLATFORM(IOS)
466    if (!ensureFrameInfoIsCached(index))
467        return 0;
468#else
469    if (!ensureFrameIsCached(index))
470        return 0;
471#endif
472    return m_frames[index].m_duration;
473}
474
475PassNativeImagePtr BitmapImage::nativeImageForCurrentFrame()
476{
477    return frameAtIndex(currentFrame());
478}
479
480bool BitmapImage::frameHasAlphaAtIndex(size_t index)
481{
482#if PLATFORM(IOS)
483    if (!ensureFrameInfoIsCached(index))
484        return true; // FIXME: Why would an invalid index return true here?
485#else
486    if (m_frames.size() <= index)
487        return true;
488#endif
489    if (m_frames[index].m_haveMetadata)
490        return m_frames[index].m_hasAlpha;
491
492    return m_source.frameHasAlphaAtIndex(index);
493}
494
495bool BitmapImage::currentFrameKnownToBeOpaque()
496{
497    return !frameHasAlphaAtIndex(currentFrame());
498}
499
500ImageOrientation BitmapImage::frameOrientationAtIndex(size_t index)
501{
502#if PLATFORM(IOS)
503    // FIXME: cacheFrameInfo does not set m_orientation. Should it?
504    if (!ensureFrameInfoIsCached(index))
505        return DefaultImageOrientation;
506#else
507    if (!ensureFrameIsCached(index))
508        return DefaultImageOrientation;
509#endif
510
511    if (m_frames[index].m_haveMetadata)
512        return m_frames[index].m_orientation;
513
514    return m_source.orientationAtIndex(index);
515}
516
517#if !ASSERT_DISABLED
518bool BitmapImage::notSolidColor()
519{
520    return size().width() != 1 || size().height() != 1 || frameCount() > 1;
521}
522#endif
523
524int BitmapImage::repetitionCount(bool imageKnownToBeComplete)
525{
526    if ((m_repetitionCountStatus == Unknown) || ((m_repetitionCountStatus == Uncertain) && imageKnownToBeComplete)) {
527        // Snag the repetition count.  If |imageKnownToBeComplete| is false, the
528        // repetition count may not be accurate yet for GIFs; in this case the
529        // decoder will default to cAnimationLoopOnce, and we'll try and read
530        // the count again once the whole image is decoded.
531        m_repetitionCount = m_source.repetitionCount();
532        didDecodeProperties();
533        m_repetitionCountStatus = (imageKnownToBeComplete || m_repetitionCount == cAnimationNone) ? Certain : Uncertain;
534    }
535    return m_repetitionCount;
536}
537
538bool BitmapImage::shouldAnimate()
539{
540    return (repetitionCount(false) != cAnimationNone && !m_animationFinished && imageObserver());
541}
542
543void BitmapImage::startAnimation(CatchUpAnimation catchUpIfNecessary)
544{
545    if (m_frameTimer || !shouldAnimate() || frameCount() <= 1)
546        return;
547
548    // If we aren't already animating, set now as the animation start time.
549    const double time = monotonicallyIncreasingTime();
550    if (!m_desiredFrameStartTime)
551        m_desiredFrameStartTime = time;
552
553    // Don't advance the animation to an incomplete frame.
554    size_t nextFrame = (m_currentFrame + 1) % frameCount();
555    if (!m_allDataReceived && !frameIsCompleteAtIndex(nextFrame))
556        return;
557
558    // Don't advance past the last frame if we haven't decoded the whole image
559    // yet and our repetition count is potentially unset.  The repetition count
560    // in a GIF can potentially come after all the rest of the image data, so
561    // wait on it.
562    if (!m_allDataReceived && repetitionCount(false) == cAnimationLoopOnce && m_currentFrame >= (frameCount() - 1))
563        return;
564
565    // Determine time for next frame to start.  By ignoring paint and timer lag
566    // in this calculation, we make the animation appear to run at its desired
567    // rate regardless of how fast it's being repainted.
568    const double currentDuration = frameDurationAtIndex(m_currentFrame);
569    m_desiredFrameStartTime += currentDuration;
570
571#if !PLATFORM(IOS)
572    // When an animated image is more than five minutes out of date, the
573    // user probably doesn't care about resyncing and we could burn a lot of
574    // time looping through frames below.  Just reset the timings.
575    const double cAnimationResyncCutoff = 5 * 60;
576    if ((time - m_desiredFrameStartTime) > cAnimationResyncCutoff)
577        m_desiredFrameStartTime = time + currentDuration;
578#else
579    // Maintaining frame-to-frame delays is more important than
580    // maintaining absolute animation timing, so reset the timings each frame.
581    m_desiredFrameStartTime = time + currentDuration;
582#endif
583
584    // The image may load more slowly than it's supposed to animate, so that by
585    // the time we reach the end of the first repetition, we're well behind.
586    // Clamp the desired frame start time in this case, so that we don't skip
587    // frames (or whole iterations) trying to "catch up".  This is a tradeoff:
588    // It guarantees users see the whole animation the second time through and
589    // don't miss any repetitions, and is closer to what other browsers do; on
590    // the other hand, it makes animations "less accurate" for pages that try to
591    // sync an image and some other resource (e.g. audio), especially if users
592    // switch tabs (and thus stop drawing the animation, which will pause it)
593    // during that initial loop, then switch back later.
594    if (nextFrame == 0 && m_repetitionsComplete == 0 && m_desiredFrameStartTime < time)
595        m_desiredFrameStartTime = time;
596
597    if (catchUpIfNecessary == DoNotCatchUp || time < m_desiredFrameStartTime) {
598        // Haven't yet reached time for next frame to start; delay until then.
599        m_frameTimer = std::make_unique<Timer<BitmapImage>>(this, &BitmapImage::advanceAnimation);
600        m_frameTimer->startOneShot(std::max(m_desiredFrameStartTime - time, 0.));
601    } else {
602        // We've already reached or passed the time for the next frame to start.
603        // See if we've also passed the time for frames after that to start, in
604        // case we need to skip some frames entirely.  Remember not to advance
605        // to an incomplete frame.
606        for (size_t frameAfterNext = (nextFrame + 1) % frameCount(); frameIsCompleteAtIndex(frameAfterNext); frameAfterNext = (nextFrame + 1) % frameCount()) {
607            // Should we skip the next frame?
608            double frameAfterNextStartTime = m_desiredFrameStartTime + frameDurationAtIndex(nextFrame);
609            if (time < frameAfterNextStartTime)
610                break;
611
612            // Yes; skip over it without notifying our observers.
613            if (!internalAdvanceAnimation(true))
614                return;
615            m_desiredFrameStartTime = frameAfterNextStartTime;
616            nextFrame = frameAfterNext;
617        }
618
619        // Draw the next frame immediately.  Note that m_desiredFrameStartTime
620        // may be in the past, meaning the next time through this function we'll
621        // kick off the next advancement sooner than this frame's duration would
622        // suggest.
623        if (internalAdvanceAnimation(false)) {
624            // The image region has been marked dirty, but once we return to our
625            // caller, draw() will clear it, and nothing will cause the
626            // animation to advance again.  We need to start the timer for the
627            // next frame running, or the animation can hang.  (Compare this
628            // with when advanceAnimation() is called, and the region is dirtied
629            // while draw() is not in the callstack, meaning draw() gets called
630            // to update the region and thus startAnimation() is reached again.)
631            // NOTE: For large images with slow or heavily-loaded systems,
632            // throwing away data as we go (see destroyDecodedData()) means we
633            // can spend so much time re-decoding data above that by the time we
634            // reach here we're behind again.  If we let startAnimation() run
635            // the catch-up code again, we can get long delays without painting
636            // as we race the timer, or even infinite recursion.  In this
637            // situation the best we can do is to simply change frames as fast
638            // as possible, so force startAnimation() to set a zero-delay timer
639            // and bail out if we're not caught up.
640            startAnimation(DoNotCatchUp);
641        }
642    }
643}
644
645void BitmapImage::stopAnimation()
646{
647    // This timer is used to animate all occurrences of this image.  Don't invalidate
648    // the timer unless all renderers have stopped drawing.
649    m_frameTimer = nullptr;
650}
651
652void BitmapImage::resetAnimation()
653{
654    stopAnimation();
655    m_currentFrame = 0;
656    m_repetitionsComplete = 0;
657    m_desiredFrameStartTime = 0;
658    m_animationFinished = false;
659
660    // For extremely large animations, when the animation is reset, we just throw everything away.
661    destroyDecodedDataIfNecessary(true);
662}
663
664void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& transform,
665    const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, BlendMode blendMode)
666{
667    if (tileRect.isEmpty())
668        return;
669
670    if (!ctxt->drawLuminanceMask()) {
671        Image::drawPattern(ctxt, tileRect, transform, phase, styleColorSpace, op, destRect, blendMode);
672        return;
673    }
674    if (!m_cachedImage) {
675        std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(expandedIntSize(tileRect.size()));
676        ASSERT(buffer.get());
677
678        ImageObserver* observer = imageObserver();
679        ASSERT(observer);
680
681        // Temporarily reset image observer, we don't want to receive any changeInRect() calls due to this relayout.
682        setImageObserver(0);
683
684        draw(buffer->context(), tileRect, tileRect, styleColorSpace, op, blendMode, ImageOrientationDescription());
685
686        setImageObserver(observer);
687        buffer->convertToLuminanceMask();
688
689        m_cachedImage = buffer->copyImage(DontCopyBackingStore, Unscaled);
690        m_cachedImage->setSpaceSize(spaceSize());
691
692        setImageObserver(observer);
693    }
694
695    ctxt->setDrawLuminanceMask(false);
696    m_cachedImage->drawPattern(ctxt, tileRect, transform, phase, styleColorSpace, op, destRect, blendMode);
697}
698
699
700void BitmapImage::advanceAnimation(Timer<BitmapImage>&)
701{
702    internalAdvanceAnimation(false);
703    // At this point the image region has been marked dirty, and if it's
704    // onscreen, we'll soon make a call to draw(), which will call
705    // startAnimation() again to keep the animation moving.
706}
707
708bool BitmapImage::internalAdvanceAnimation(bool skippingFrames)
709{
710    // Stop the animation.
711    stopAnimation();
712
713    ++m_currentFrame;
714    bool advancedAnimation = true;
715    bool destroyAll = false;
716    if (m_currentFrame >= frameCount()) {
717        ++m_repetitionsComplete;
718
719        // Get the repetition count again.  If we weren't able to get a
720        // repetition count before, we should have decoded the whole image by
721        // now, so it should now be available.
722        // Note that we don't need to special-case cAnimationLoopOnce here
723        // because it is 0 (see comments on its declaration in ImageSource.h).
724        if (repetitionCount(true) != cAnimationLoopInfinite && m_repetitionsComplete > m_repetitionCount) {
725            m_animationFinished = true;
726            m_desiredFrameStartTime = 0;
727            --m_currentFrame;
728            advancedAnimation = false;
729        } else {
730            m_currentFrame = 0;
731            destroyAll = true;
732        }
733    }
734    destroyDecodedDataIfNecessary(destroyAll);
735
736    // We need to draw this frame if we advanced to it while not skipping, or if
737    // while trying to skip frames we hit the last frame and thus had to stop.
738    if (skippingFrames != advancedAnimation)
739        imageObserver()->animationAdvanced(this);
740    return advancedAnimation;
741}
742
743bool BitmapImage::mayFillWithSolidColor()
744{
745    if (!m_checkedForSolidColor && frameCount() > 0) {
746        checkForSolidColor();
747        // WINCE PORT: checkForSolidColor() doesn't set m_checkedForSolidColor until
748        // it gets enough information to make final decision.
749#if !OS(WINCE)
750        ASSERT(m_checkedForSolidColor);
751#endif
752    }
753    return m_isSolidColor && !m_currentFrame;
754}
755
756Color BitmapImage::solidColor() const
757{
758    return m_solidColor;
759}
760
761bool BitmapImage::canAnimate()
762{
763    return shouldAnimate() && frameCount() > 1;
764}
765
766}
767