Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(118)

Unified Diff: third_party/WebKit/Source/platform/graphics/BitmapImage.cpp

Issue 2262493003: Prevent synchronous layout while painting the last frame of a gif (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Refactor Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/BitmapImage.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
diff --git a/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp b/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
index ee7be35fabdebe16b7cf658e7770e2a03d23f6cb..c4fce9302a62270ee0ec3c0759d9f2f8da4d9ad9 100644
--- a/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
+++ b/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
@@ -520,9 +520,11 @@ void BitmapImage::startAnimation(CatchUpAnimation catchUpIfNecessary)
if (time < frameAfterNextStartTime)
break;
- // Yes; skip over it without notifying our observers.
- if (!internalAdvanceAnimation(true))
+ // Skip the next frame by advancing the animation forward one frame.
+ if (!internalAdvanceAnimation(SkipFramesToCatchUp)) {
+ DCHECK(m_animationFinished);
return;
+ }
m_desiredFrameStartTime = frameAfterNextStartTime;
nextFrame = frameAfterNext;
}
@@ -573,7 +575,7 @@ void BitmapImage::advanceTime(double deltaTimeInSeconds)
void BitmapImage::advanceAnimation(TimerBase*)
{
- internalAdvanceAnimation(false);
+ internalAdvanceAnimation();
// At this point the image region has been marked dirty, and if it's
// onscreen, we'll soon make a call to draw(), which will call
// startAnimation() again to keep the animation moving.
@@ -581,46 +583,62 @@ void BitmapImage::advanceAnimation(TimerBase*)
void BitmapImage::advanceAnimationWithoutCatchUp(TimerBase*)
{
- if (internalAdvanceAnimation(false))
+ if (internalAdvanceAnimation())
startAnimation(DoNotCatchUp);
}
-bool BitmapImage::internalAdvanceAnimation(bool skippingFrames)
+bool BitmapImage::internalAdvanceAnimation(AnimationAdvancement advancement)
{
// Stop the animation.
stopAnimation();
// See if anyone is still paying attention to this animation. If not, we don't
// advance and will remain suspended at the current frame until the animation is resumed.
- if (!skippingFrames && getImageObserver()->shouldPauseAnimation(this))
+ if (advancement != SkipFramesToCatchUp && getImageObserver()->shouldPauseAnimation(this))
return false;
- ++m_currentFrame;
- bool advancedAnimation = true;
- if (m_currentFrame >= frameCount()) {
- ++m_repetitionsComplete;
+ if (m_currentFrame + 1 < frameCount()) {
+ m_currentFrame++;
+ } else {
+ m_repetitionsComplete++;
- // Get the repetition count again. If we weren't able to get a
+ // Get the repetition count again. If we weren't able to get a
// repetition count before, we should have decoded the whole image by
// now, so it should now be available.
- // Note that we don't need to special-case cAnimationLoopOnce here
- // because it is 0 (see comments on its declaration in ImageAnimation.h).
+ // We don't need to special-case cAnimationLoopOnce here because it is
+ // 0 (see comments on its declaration in ImageAnimation.h).
if ((repetitionCount(true) != cAnimationLoopInfinite && m_repetitionsComplete > m_repetitionCount)
|| m_animationPolicy == ImageAnimationPolicyAnimateOnce) {
m_animationFinished = true;
m_desiredFrameStartTime = 0;
- --m_currentFrame;
- advancedAnimation = false;
- } else
- m_currentFrame = 0;
+
+ // We skipped to the last frame and cannot advance further. The
+ // observer will not receive animationAdvanced notifications while
+ // skipping but we still need to notify the observer to draw the
+ // last frame. Skipping frames occurs while painting so we do not
+ // synchronously notify the observer which could cause a layout.
+ if (advancement == SkipFramesToCatchUp) {
+ m_frameTimer = wrapUnique(new Timer<BitmapImage>(this, &BitmapImage::notifyObserversOfAnimationAdvance));
+ m_frameTimer->startOneShot(0, BLINK_FROM_HERE);
+ }
+
+ return false;
+ }
+
+ // Loop the animation back to the first frame.
+ m_currentFrame = 0;
}
- // We need to draw this frame if we advanced to it while not skipping, or if
- // while trying to skip frames we hit the last frame and thus had to stop.
- if (skippingFrames != advancedAnimation)
+ // We need to draw this frame if we advanced to it while not skipping.
+ if (advancement != SkipFramesToCatchUp)
getImageObserver()->animationAdvanced(this);
- return advancedAnimation;
+ return true;
+}
+
+void BitmapImage::notifyObserversOfAnimationAdvance(TimerBase*)
+{
+ getImageObserver()->animationAdvanced(this);
}
} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/BitmapImage.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698