mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 666446, Part 9/10 - Implement methods in RasterImage in order to faciliate refresh driver-based animations. [r=dholbert,joe]
This commit is contained in:
parent
863ca35140
commit
63e27b0196
@ -55,6 +55,7 @@ Decoder::Decoder(RasterImage &aImage, imgIDecoderObserver* aObserver)
|
||||
, mInFrame(false)
|
||||
, mDecodeDone(false)
|
||||
, mDataError(false)
|
||||
, mIsAnimated(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -259,9 +260,14 @@ Decoder::PostFrameStop()
|
||||
// Flush any invalidations before we finish the frame
|
||||
FlushInvalidations();
|
||||
|
||||
// Fire notification
|
||||
if (mObserver)
|
||||
// Fire notifications
|
||||
if (mObserver) {
|
||||
mObserver->OnStopFrame(nsnull, mFrameCount - 1); // frame # is zero-indexed
|
||||
if (mFrameCount > 1 && !mIsAnimated) {
|
||||
mIsAnimated = true;
|
||||
mObserver->OnImageIsAnimated(nsnull);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -218,6 +218,7 @@ private:
|
||||
bool mInitialized;
|
||||
bool mSizeDecode;
|
||||
bool mInFrame;
|
||||
bool mIsAnimated;
|
||||
};
|
||||
|
||||
} // namespace imagelib
|
||||
|
@ -175,10 +175,10 @@ namespace mozilla {
|
||||
namespace imagelib {
|
||||
|
||||
#ifndef DEBUG
|
||||
NS_IMPL_ISUPPORTS4(RasterImage, imgIContainer, nsITimerCallback, nsIProperties,
|
||||
NS_IMPL_ISUPPORTS3(RasterImage, imgIContainer, nsIProperties,
|
||||
nsISupportsWeakReference)
|
||||
#else
|
||||
NS_IMPL_ISUPPORTS5(RasterImage, imgIContainer, nsITimerCallback, nsIProperties,
|
||||
NS_IMPL_ISUPPORTS4(RasterImage, imgIContainer, nsIProperties,
|
||||
imgIContainerDebug, nsISupportsWeakReference)
|
||||
#endif
|
||||
|
||||
@ -315,12 +315,167 @@ RasterImage::Init(imgIDecoderObserver *aObserver,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
RasterImage::AdvanceFrame(TimeStamp aTime, nsIntRect* aDirtyRect)
|
||||
{
|
||||
NS_ASSERTION(aTime <= TimeStamp::Now(),
|
||||
"Given time appears to be in the future");
|
||||
|
||||
imgFrame* nextFrame = nsnull;
|
||||
PRUint32 currentFrameIndex = mAnim->currentAnimationFrameIndex;
|
||||
PRUint32 nextFrameIndex = mAnim->currentAnimationFrameIndex + 1;
|
||||
PRUint32 timeout = 0;
|
||||
|
||||
// Figure out if we have the next full frame. This is more complicated than
|
||||
// just checking for mFrames.Length() because decoders append their frames
|
||||
// before they're filled in.
|
||||
NS_ABORT_IF_FALSE(mDecoder || nextFrameIndex <= mFrames.Length(),
|
||||
"How did we get 2 indices too far by incrementing?");
|
||||
|
||||
// If we don't have a decoder, we know we've got everything we're going to
|
||||
// get. If we do, we only display fully-downloaded frames; everything else
|
||||
// gets delayed.
|
||||
bool haveFullNextFrame = !mDecoder ||
|
||||
nextFrameIndex < mDecoder->GetCompleteFrameCount();
|
||||
|
||||
// If we're done decoding the next frame, go ahead and display it now and
|
||||
// reinit with the next frame's delay time.
|
||||
if (haveFullNextFrame) {
|
||||
if (mFrames.Length() == nextFrameIndex) {
|
||||
// End of Animation, unless we are looping forever
|
||||
|
||||
// If animation mode is "loop once", it's time to stop animating
|
||||
if (mAnimationMode == kLoopOnceAnimMode || mLoopCount == 0) {
|
||||
mAnimationFinished = PR_TRUE;
|
||||
EvaluateAnimation();
|
||||
}
|
||||
|
||||
// We may have used compositingFrame to build a frame, and then copied
|
||||
// it back into mFrames[..]. If so, delete composite to save memory
|
||||
if (mAnim->compositingFrame && mAnim->lastCompositedFrameIndex == -1) {
|
||||
mAnim->compositingFrame = nsnull;
|
||||
}
|
||||
|
||||
nextFrameIndex = 0;
|
||||
|
||||
if (mLoopCount > 0) {
|
||||
mLoopCount--;
|
||||
}
|
||||
|
||||
if (!mAnimating) {
|
||||
// break out early if we are actually done animating
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(nextFrame = mFrames[nextFrameIndex])) {
|
||||
// something wrong with the next frame, skip it
|
||||
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
||||
return false;
|
||||
}
|
||||
|
||||
timeout = nextFrame->GetTimeout();
|
||||
|
||||
} else {
|
||||
// Uh oh, the frame we want to show is currently being decoded (partial)
|
||||
// Wait until the next refresh driver tick and try again
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(timeout > 0)) {
|
||||
mAnimationFinished = PR_TRUE;
|
||||
EvaluateAnimation();
|
||||
}
|
||||
|
||||
imgFrame *frameToUse = nsnull;
|
||||
|
||||
if (nextFrameIndex == 0) {
|
||||
frameToUse = nextFrame;
|
||||
*aDirtyRect = mAnim->firstFrameRefreshArea;
|
||||
} else {
|
||||
imgFrame *curFrame = mFrames[currentFrameIndex];
|
||||
|
||||
if (!curFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Change frame
|
||||
if (NS_FAILED(DoComposite(aDirtyRect, curFrame,
|
||||
nextFrame, nextFrameIndex))) {
|
||||
// something went wrong, move on to next
|
||||
NS_WARNING("RasterImage::AdvanceFrame(): Compositing of frame failed");
|
||||
nextFrame->SetCompositingFailed(PR_TRUE);
|
||||
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
||||
mAnim->currentAnimationFrameTime = aTime;
|
||||
return false;
|
||||
}
|
||||
|
||||
nextFrame->SetCompositingFailed(PR_FALSE);
|
||||
}
|
||||
|
||||
// Set currentAnimationFrameIndex at the last possible moment
|
||||
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
||||
mAnim->currentAnimationFrameTime = aTime;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
/* [notxpcom] void requestRefresh ([const] in TimeStamp aTime); */
|
||||
// [notxpcom] void requestRefresh ([const] in TimeStamp aTime);
|
||||
NS_IMETHODIMP_(void)
|
||||
RasterImage::RequestRefresh(const mozilla::TimeStamp& aTime)
|
||||
{
|
||||
// TODO: Implement me as part of b666446
|
||||
if (!mAnimating || !ShouldAnimate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureAnimExists();
|
||||
|
||||
// only advance the frame if the current time is greater than or
|
||||
// equal to the current frame's end time.
|
||||
TimeStamp currentFrameEndTime = GetCurrentImgFrameEndTime();
|
||||
bool frameAdvanced = false;
|
||||
|
||||
// The dirtyRect variable will contain an accumulation of the sub-rectangles
|
||||
// that are dirty for each frame we advance in AdvanceFrame().
|
||||
nsIntRect dirtyRect;
|
||||
|
||||
while (currentFrameEndTime <= aTime) {
|
||||
TimeStamp oldFrameEndTime = currentFrameEndTime;
|
||||
nsIntRect frameDirtyRect;
|
||||
bool didAdvance = AdvanceFrame(aTime, &frameDirtyRect);
|
||||
frameAdvanced = frameAdvanced || didAdvance;
|
||||
currentFrameEndTime = GetCurrentImgFrameEndTime();
|
||||
|
||||
// Accumulate the dirty area.
|
||||
dirtyRect = dirtyRect.Union(frameDirtyRect);
|
||||
|
||||
// if we didn't advance a frame, and our frame end time didn't change,
|
||||
// then we need to break out of this loop & wait for the frame(s)
|
||||
// to finish downloading
|
||||
if (!frameAdvanced && (currentFrameEndTime == oldFrameEndTime)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (frameAdvanced) {
|
||||
nsCOMPtr<imgIContainerObserver> observer(do_QueryReferent(mObserver));
|
||||
|
||||
if (!observer) {
|
||||
NS_ERROR("Refreshing image after its imgRequest is gone");
|
||||
StopAnimation();
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify listeners that our frame has actually changed, but do this only
|
||||
// once for all frames that we've now passed (if AdvanceFrame() was called
|
||||
// more than once).
|
||||
#ifdef DEBUG
|
||||
mFramesNotified++;
|
||||
#endif
|
||||
|
||||
observer->FrameChanged(this, &dirtyRect);
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
@ -504,6 +659,27 @@ RasterImage::GetCurrentImgFrameIndex() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
TimeStamp
|
||||
RasterImage::GetCurrentImgFrameEndTime() const
|
||||
{
|
||||
imgFrame* currentFrame = mFrames[mAnim->currentAnimationFrameIndex];
|
||||
TimeStamp currentFrameTime = mAnim->currentAnimationFrameTime;
|
||||
PRInt64 timeout = currentFrame->GetTimeout();
|
||||
|
||||
if (timeout < 0) {
|
||||
// We need to return a sentinel value in this case, because our logic
|
||||
// doesn't work correctly if we have a negative timeout value. The reason
|
||||
// this positive infinity was chosen was because it works with the loop in
|
||||
// RequestRefresh() above.
|
||||
return TimeStamp() + TimeDuration::FromMilliseconds(UINT64_MAX_VAL);
|
||||
}
|
||||
|
||||
TimeDuration durationOfTimeout = TimeDuration::FromMilliseconds(timeout);
|
||||
TimeStamp currentFrameEndTime = currentFrameTime + durationOfTimeout;
|
||||
|
||||
return currentFrameEndTime;
|
||||
}
|
||||
|
||||
imgFrame*
|
||||
RasterImage::GetCurrentImgFrame()
|
||||
{
|
||||
@ -1186,25 +1362,18 @@ RasterImage::StartAnimation()
|
||||
|
||||
EnsureAnimExists();
|
||||
|
||||
NS_ABORT_IF_FALSE(mAnim && !mAnim->timer, "Anim must exist and not have a timer yet");
|
||||
|
||||
// Default timeout to 100: the timer notify code will do the right
|
||||
// thing, so just get that started.
|
||||
PRInt32 timeout = 100;
|
||||
imgFrame *currentFrame = GetCurrentImgFrame();
|
||||
imgFrame* currentFrame = GetCurrentImgFrame();
|
||||
if (currentFrame) {
|
||||
timeout = currentFrame->GetTimeout();
|
||||
if (timeout < 0) { // -1 means display this frame forever
|
||||
if (currentFrame->GetTimeout() < 0) { // -1 means display this frame forever
|
||||
mAnimationFinished = true;
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
// We need to set the time that this initial frame was first displayed, as
|
||||
// this is used in AdvanceFrame().
|
||||
mAnim->currentAnimationFrameTime = TimeStamp::Now();
|
||||
}
|
||||
|
||||
mAnim->timer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
NS_ENSURE_TRUE(mAnim->timer, NS_ERROR_OUT_OF_MEMORY);
|
||||
mAnim->timer->InitWithCallback(static_cast<nsITimerCallback*>(this),
|
||||
timeout, nsITimer::TYPE_REPEATING_SLACK);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1218,11 +1387,6 @@ RasterImage::StopAnimation()
|
||||
if (mError)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mAnim->timer) {
|
||||
mAnim->timer->Cancel();
|
||||
mAnim->timer = nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1478,127 +1642,6 @@ RasterImage::SetSourceSizeHint(PRUint32 sizeHint)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
/* void notify(in nsITimer timer); */
|
||||
NS_IMETHODIMP
|
||||
RasterImage::Notify(nsITimer *timer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
mFramesNotified++;
|
||||
#endif
|
||||
|
||||
// This should never happen since the timer is only set up in StartAnimation()
|
||||
// after mAnim is checked to exist.
|
||||
NS_ABORT_IF_FALSE(mAnim, "Need anim for Notify()");
|
||||
NS_ABORT_IF_FALSE(timer, "Need timer for Notify()");
|
||||
NS_ABORT_IF_FALSE(mAnim->timer == timer,
|
||||
"RasterImage::Notify() called with incorrect timer");
|
||||
|
||||
if (!mAnimating || !ShouldAnimate())
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<imgIContainerObserver> observer(do_QueryReferent(mObserver));
|
||||
if (!observer) {
|
||||
// the imgRequest that owns us is dead, we should die now too.
|
||||
NS_ABORT_IF_FALSE(mAnimationConsumers == 0,
|
||||
"If no observer, should have no consumers");
|
||||
if (mAnimating)
|
||||
StopAnimation();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mFrames.Length() == 0)
|
||||
return NS_OK;
|
||||
|
||||
imgFrame *nextFrame = nsnull;
|
||||
PRInt32 previousFrameIndex = mAnim->currentAnimationFrameIndex;
|
||||
PRUint32 nextFrameIndex = mAnim->currentAnimationFrameIndex + 1;
|
||||
PRInt32 timeout = 0;
|
||||
|
||||
// Figure out if we have the next full frame. This is more complicated than
|
||||
// just checking for mFrames.Length() because decoders append their frames
|
||||
// before they're filled in.
|
||||
NS_ABORT_IF_FALSE(mDecoder || nextFrameIndex <= mFrames.Length(),
|
||||
"How did we get 2 indicies too far by incrementing?");
|
||||
|
||||
// If we don't have a decoder, we know we've got everything we're going to get.
|
||||
// If we do, we only display fully-downloaded frames; everything else gets delayed.
|
||||
bool haveFullNextFrame = !mDecoder || nextFrameIndex < mDecoder->GetCompleteFrameCount();
|
||||
|
||||
// If we're done decoding the next frame, go ahead and display it now and
|
||||
// reinit the timer with the next frame's delay time.
|
||||
if (haveFullNextFrame) {
|
||||
if (mFrames.Length() == nextFrameIndex) {
|
||||
// End of Animation
|
||||
|
||||
// If animation mode is "loop once", it's time to stop animating
|
||||
if (mAnimationMode == kLoopOnceAnimMode || mLoopCount == 0) {
|
||||
mAnimationFinished = true;
|
||||
EvaluateAnimation();
|
||||
return NS_OK;
|
||||
} else {
|
||||
// We may have used compositingFrame to build a frame, and then copied
|
||||
// it back into mFrames[..]. If so, delete composite to save memory
|
||||
if (mAnim->compositingFrame && mAnim->lastCompositedFrameIndex == -1)
|
||||
mAnim->compositingFrame = nsnull;
|
||||
}
|
||||
|
||||
nextFrameIndex = 0;
|
||||
if (mLoopCount > 0)
|
||||
mLoopCount--;
|
||||
}
|
||||
|
||||
if (!(nextFrame = mFrames[nextFrameIndex])) {
|
||||
// something wrong with the next frame, skip it
|
||||
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
||||
mAnim->timer->SetDelay(100);
|
||||
return NS_OK;
|
||||
}
|
||||
timeout = nextFrame->GetTimeout();
|
||||
|
||||
} else {
|
||||
// Uh oh, the frame we want to show is currently being decoded (partial)
|
||||
// Wait a bit and try again
|
||||
mAnim->timer->SetDelay(100);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (timeout > 0)
|
||||
mAnim->timer->SetDelay(timeout);
|
||||
else {
|
||||
mAnimationFinished = true;
|
||||
EvaluateAnimation();
|
||||
}
|
||||
|
||||
nsIntRect dirtyRect;
|
||||
|
||||
if (nextFrameIndex == 0) {
|
||||
dirtyRect = mAnim->firstFrameRefreshArea;
|
||||
} else {
|
||||
imgFrame *prevFrame = mFrames[previousFrameIndex];
|
||||
if (!prevFrame)
|
||||
return NS_OK;
|
||||
|
||||
// Change frame and announce it
|
||||
if (NS_FAILED(DoComposite(&dirtyRect, prevFrame,
|
||||
nextFrame, nextFrameIndex))) {
|
||||
// something went wrong, move on to next
|
||||
NS_WARNING("RasterImage::Notify(): Composing Frame Failed\n");
|
||||
nextFrame->SetCompositingFailed(true);
|
||||
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
||||
return NS_OK;
|
||||
} else {
|
||||
nextFrame->SetCompositingFailed(false);
|
||||
}
|
||||
}
|
||||
// Set currentAnimationFrameIndex at the last possible moment
|
||||
mAnim->currentAnimationFrameIndex = nextFrameIndex;
|
||||
// Refreshes the screen
|
||||
observer->FrameChanged(this, &dirtyRect);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// DoComposite gets called when the timer for animation get fired and we have to
|
||||
// update the composited frame of the animation.
|
||||
|
@ -71,6 +71,7 @@
|
||||
#endif
|
||||
|
||||
class imgIDecoder;
|
||||
class imgIContainerObserver;
|
||||
class nsIInputStream;
|
||||
|
||||
#define NS_RASTERIMAGE_CID \
|
||||
@ -81,6 +82,12 @@ class nsIInputStream;
|
||||
{0xb1, 0x43, 0x33, 0x40, 0xc0, 0x01, 0x12, 0xf7} \
|
||||
}
|
||||
|
||||
/**
|
||||
* It would be nice if we had a macro for this in prtypes.h.
|
||||
* TODO: Place this macro in prtypes.h as PR_UINT64_MAX.
|
||||
*/
|
||||
#define UINT64_MAX_VAL PRUint64(-1)
|
||||
|
||||
/**
|
||||
* Handles static and animated image containers.
|
||||
*
|
||||
@ -88,15 +95,27 @@ class nsIInputStream;
|
||||
* @par A Quick Walk Through
|
||||
* The decoder initializes this class and calls AppendFrame() to add a frame.
|
||||
* Once RasterImage detects more than one frame, it starts the animation
|
||||
* with StartAnimation().
|
||||
* with StartAnimation(). Note that the invalidation events for RasterImage are
|
||||
* generated automatically using nsRefreshDriver.
|
||||
*
|
||||
* @par
|
||||
* StartAnimation() creates a timer. The timer calls Notify when the
|
||||
* specified frame delay time is up.
|
||||
* StartAnimation() initializes the animation helper object and sets the time
|
||||
* the first frame was displayed to the current clock time.
|
||||
*
|
||||
* @par
|
||||
* Notify() moves on to the next frame, sets up the new timer delay, destroys
|
||||
* the old frame, and forces a redraw via observer->FrameChanged().
|
||||
* When the refresh driver corresponding to the imgIContainer that this image is
|
||||
* a part of notifies the RasterImage that it's time to invalidate,
|
||||
* RequestRefresh() is called with a given TimeStamp to advance to. As long as
|
||||
* the timeout of the given frame (the frame's "delay") plus the time that frame
|
||||
* was first displayed is less than or equal to the TimeStamp given,
|
||||
* RequestRefresh() calls AdvanceFrame().
|
||||
*
|
||||
* @par
|
||||
* AdvanceFrame() is responsible for advancing a single frame of the animation.
|
||||
* It can return true, meaning that the frame advanced, or false, meaning that
|
||||
* the frame failed to advance (usually because the next frame hasn't been
|
||||
* decoded yet). It is also responsible for performing the final animation stop
|
||||
* procedure if the final frame of a non-looping animation is reached.
|
||||
*
|
||||
* @par
|
||||
* Each frame can have a different method of removing itself. These are
|
||||
@ -155,7 +174,6 @@ class imgDecodeWorker;
|
||||
class Decoder;
|
||||
|
||||
class RasterImage : public Image
|
||||
, public nsITimerCallback
|
||||
, public nsIProperties
|
||||
, public nsSupportsWeakReference
|
||||
#ifdef DEBUG
|
||||
@ -164,7 +182,6 @@ class RasterImage : public Image
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
NS_DECL_NSIPROPERTIES
|
||||
#ifdef DEBUG
|
||||
NS_DECL_IMGICONTAINERDEBUG
|
||||
@ -340,6 +357,10 @@ private:
|
||||
//! Area of the first frame that needs to be redrawn on subsequent loops.
|
||||
nsIntRect firstFrameRefreshArea;
|
||||
PRUint32 currentAnimationFrameIndex; // 0 to numFrames-1
|
||||
|
||||
// the time that the animation advanced to the current frame
|
||||
TimeStamp currentAnimationFrameTime;
|
||||
|
||||
//! Track the last composited frame for Optimizations (See DoComposite code)
|
||||
PRInt32 lastCompositedFrameIndex;
|
||||
/** For managing blending of frames
|
||||
@ -358,23 +379,33 @@ private:
|
||||
* when it's done with the current frame.
|
||||
*/
|
||||
nsAutoPtr<imgFrame> compositingPrevFrame;
|
||||
//! Timer to animate multiframed images
|
||||
nsCOMPtr<nsITimer> timer;
|
||||
|
||||
Anim() :
|
||||
firstFrameRefreshArea(),
|
||||
currentAnimationFrameIndex(0),
|
||||
lastCompositedFrameIndex(-1)
|
||||
{
|
||||
;
|
||||
}
|
||||
~Anim()
|
||||
{
|
||||
if (timer)
|
||||
timer->Cancel();
|
||||
}
|
||||
lastCompositedFrameIndex(-1) {}
|
||||
~Anim() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Advances the animation. Typically, this will advance a single frame, but it
|
||||
* may advance multiple frames. This may happen if we have infrequently
|
||||
* "ticking" refresh drivers (e.g. in background tabs), or extremely short-
|
||||
* lived animation frames.
|
||||
*
|
||||
* @param aTime the time that the animation should advance to. This will
|
||||
* typically be <= TimeStamp::Now().
|
||||
*
|
||||
* @param [out] aDirtyRect a pointer to an nsIntRect which encapsulates the
|
||||
* area to be repainted after the frame is advanced.
|
||||
*
|
||||
* @returns true, if the frame was successfully advanced, false if it was not
|
||||
* able to be advanced (e.g. the frame to which we want to advance is
|
||||
* still decoding). Note: If false is returned, then aDirtyRect will
|
||||
* remain unmodified.
|
||||
*/
|
||||
bool AdvanceFrame(mozilla::TimeStamp aTime, nsIntRect* aDirtyRect);
|
||||
|
||||
/**
|
||||
* Deletes and nulls out the frame in mFrames[framenum].
|
||||
*
|
||||
@ -391,6 +422,7 @@ private:
|
||||
imgFrame* GetCurrentImgFrame();
|
||||
imgFrame* GetCurrentDrawableImgFrame();
|
||||
PRUint32 GetCurrentImgFrameIndex() const;
|
||||
mozilla::TimeStamp GetCurrentImgFrameEndTime() const;
|
||||
|
||||
inline void EnsureAnimExists()
|
||||
{
|
||||
@ -409,9 +441,12 @@ private:
|
||||
// since we didn't kill the source data in the old world either, locking
|
||||
// is acceptable for the moment.
|
||||
LockImage();
|
||||
|
||||
// Notify our observers that we are starting animation.
|
||||
mStatusTracker->RecordImageIsAnimated();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Function for doing the frame compositing of animations
|
||||
*
|
||||
* @param aDirtyRect Area that the display will need to update
|
||||
@ -423,7 +458,7 @@ private:
|
||||
imgFrame* aPrevFrame,
|
||||
imgFrame* aNextFrame,
|
||||
PRInt32 aNextFrameIndex);
|
||||
|
||||
|
||||
/** Clears an area of <aFrame> with transparent black.
|
||||
*
|
||||
* @param aFrame Target Frame
|
||||
@ -431,7 +466,7 @@ private:
|
||||
* @note Does also clears the transparancy mask
|
||||
*/
|
||||
static void ClearFrame(imgFrame* aFrame);
|
||||
|
||||
|
||||
//! @overload
|
||||
static void ClearFrame(imgFrame* aFrame, nsIntRect &aRect);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user