mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 01:48:05 +00:00
Bug 876499 - If a looping image is being asked to advance to a time that is more than one loop in the future, skip the intermediate frames and simply jump to the next multiple of the loop count. r=seth
When there is a long delay between calls to RequestRefresh(), for example because an animated image has been scrolled off the screen, the current animation frame time can be significantly behind the current time, requiring a huge number of composites to catch up. This patch makes us skip those intermediate composites, jumping to the closest multiple of the image's loop time. --HG-- extra : rebase_source : 3e9ef5bd3ad3f1e9d95def99e6bb546474a583c9
This commit is contained in:
parent
aeaafd9ad2
commit
43351f7d0c
@ -529,6 +529,39 @@ RasterImage::Init(const char* aMimeType,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
RasterImage::GetSingleLoopTime() const
|
||||||
|
{
|
||||||
|
if (!mAnim) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we aren't done decoding, we don't know the image's full play time.
|
||||||
|
if (!mHasBeenDecoded) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're not looping, a single loop time has no meaning
|
||||||
|
if (mLoopCount == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t looptime = 0;
|
||||||
|
for (uint32_t i = 0; i < mFrames.Length(); ++i) {
|
||||||
|
int32_t timeout = mFrames[i]->GetTimeout();
|
||||||
|
if (timeout > 0) {
|
||||||
|
looptime += static_cast<uint32_t>(timeout);
|
||||||
|
} else {
|
||||||
|
// If we have a frame that never times out, we're probably in an error
|
||||||
|
// case, but let's handle it more gracefully.
|
||||||
|
NS_WARNING("Negative frame timeout - how did this happen?");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return looptime;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RasterImage::AdvanceFrame(TimeStamp aTime, nsIntRect* aDirtyRect)
|
RasterImage::AdvanceFrame(TimeStamp aTime, nsIntRect* aDirtyRect)
|
||||||
{
|
{
|
||||||
@ -626,6 +659,19 @@ RasterImage::AdvanceFrame(TimeStamp aTime, nsIntRect* aDirtyRect)
|
|||||||
|
|
||||||
mAnim->currentAnimationFrameTime = GetCurrentImgFrameEndTime();
|
mAnim->currentAnimationFrameTime = GetCurrentImgFrameEndTime();
|
||||||
|
|
||||||
|
// If we can get closer to the current time by a multiple of the image's loop
|
||||||
|
// time, we should.
|
||||||
|
uint32_t loopTime = GetSingleLoopTime();
|
||||||
|
if (loopTime > 0) {
|
||||||
|
TimeDuration delay = aTime - mAnim->currentAnimationFrameTime;
|
||||||
|
if (delay.ToMilliseconds() > loopTime) {
|
||||||
|
// Explicitly use integer division to get the floor of the number of
|
||||||
|
// loops.
|
||||||
|
uint32_t loops = static_cast<uint32_t>(delay.ToMilliseconds()) / loopTime;
|
||||||
|
mAnim->currentAnimationFrameTime += TimeDuration::FromMilliseconds(loops * loopTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set currentAnimationFrameIndex at the last possible moment
|
// Set currentAnimationFrameIndex at the last possible moment
|
||||||
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
||||||
|
|
||||||
|
@ -610,6 +610,14 @@ private:
|
|||||||
*/
|
*/
|
||||||
bool AdvanceFrame(mozilla::TimeStamp aTime, nsIntRect* aDirtyRect);
|
bool AdvanceFrame(mozilla::TimeStamp aTime, nsIntRect* aDirtyRect);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the length of a single loop of this image, in milliseconds.
|
||||||
|
*
|
||||||
|
* If this image is not finished decoding, is not animated, or it is animated
|
||||||
|
* but does not loop, returns 0.
|
||||||
|
*/
|
||||||
|
uint32_t GetSingleLoopTime() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes and nulls out the frame in mFrames[framenum].
|
* Deletes and nulls out the frame in mFrames[framenum].
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user