diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index dce50174c276..3e10429f21e0 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -111,8 +111,8 @@ NS_NewImageFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) nsImageFrame::nsImageFrame() : mLowSrcImageLoader(nsnull) #ifdef USE_IMG2 - , mIntrinsicSize(0, 0), - mGotInitialReflow(PR_FALSE) + , mGotInitialReflow(PR_FALSE) + , mIntrinsicSize(0, 0) #endif { // Size is constrained if we have a width and height. @@ -340,6 +340,19 @@ NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresConte { mInitialLoadCompleted = PR_TRUE; + if (aImage) + { + /* Get requested animation policy from the pres context: + * normal = 0 + * one frame = 1 + * one loop = 2 + */ + nsImageAnimation animateMode = eImageAnimation_Normal; //default value + nsresult rv = aPresContext->GetImageAnimationMode(&animateMode); + if (NS_SUCCEEDED(rv)) + aImage->SetAnimationMode(animateMode); + } + nscoord w, h; #ifdef DEBUG_pavlov NS_ENSURE_ARG_POINTER(aImage); @@ -1034,9 +1047,6 @@ nsImageFrame::Paint(nsIPresContext* aPresContext, nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); - // first get to see if lowsrc image is here - PRInt32 lowSrcLinesLoaded = -1; - PRInt32 imgSrcLinesLoaded = -1; #ifdef USE_IMG2 nsCOMPtr imgCon; @@ -1046,6 +1056,9 @@ nsImageFrame::Paint(nsIPresContext* aPresContext, mImageRequest->GetImage(getter_AddRefs(imgCon)); } #else + // first get to see if lowsrc image is here + PRInt32 lowSrcLinesLoaded = -1; + PRInt32 imgSrcLinesLoaded = -1; nsIImage * lowImage = nsnull; nsIImage * image = nsnull; #endif diff --git a/layout/html/base/src/nsImageFrame.cpp b/layout/html/base/src/nsImageFrame.cpp index dce50174c276..3e10429f21e0 100644 --- a/layout/html/base/src/nsImageFrame.cpp +++ b/layout/html/base/src/nsImageFrame.cpp @@ -111,8 +111,8 @@ NS_NewImageFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) nsImageFrame::nsImageFrame() : mLowSrcImageLoader(nsnull) #ifdef USE_IMG2 - , mIntrinsicSize(0, 0), - mGotInitialReflow(PR_FALSE) + , mGotInitialReflow(PR_FALSE) + , mIntrinsicSize(0, 0) #endif { // Size is constrained if we have a width and height. @@ -340,6 +340,19 @@ NS_IMETHODIMP nsImageFrame::OnStartContainer(imgIRequest *aRequest, nsIPresConte { mInitialLoadCompleted = PR_TRUE; + if (aImage) + { + /* Get requested animation policy from the pres context: + * normal = 0 + * one frame = 1 + * one loop = 2 + */ + nsImageAnimation animateMode = eImageAnimation_Normal; //default value + nsresult rv = aPresContext->GetImageAnimationMode(&animateMode); + if (NS_SUCCEEDED(rv)) + aImage->SetAnimationMode(animateMode); + } + nscoord w, h; #ifdef DEBUG_pavlov NS_ENSURE_ARG_POINTER(aImage); @@ -1034,9 +1047,6 @@ nsImageFrame::Paint(nsIPresContext* aPresContext, nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); - // first get to see if lowsrc image is here - PRInt32 lowSrcLinesLoaded = -1; - PRInt32 imgSrcLinesLoaded = -1; #ifdef USE_IMG2 nsCOMPtr imgCon; @@ -1046,6 +1056,9 @@ nsImageFrame::Paint(nsIPresContext* aPresContext, mImageRequest->GetImage(getter_AddRefs(imgCon)); } #else + // first get to see if lowsrc image is here + PRInt32 lowSrcLinesLoaded = -1; + PRInt32 imgSrcLinesLoaded = -1; nsIImage * lowImage = nsnull; nsIImage * image = nsnull; #endif diff --git a/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp b/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp index d29b222ab098..335756126adf 100644 --- a/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp +++ b/modules/libpr0n/decoders/gif/nsGIFDecoder2.cpp @@ -72,8 +72,6 @@ NS_IMETHODIMP nsGIFDecoder2::Init(imgIRequest *aRequest) mImageContainer = do_CreateInstance("@mozilla.org/image/container;1"); aRequest->SetImage(mImageContainer); - mImageContainer->StartAnimation(); - /* do gif init stuff */ /* Always decode to 24 bit pixdepth */ diff --git a/modules/libpr0n/public/imgIContainer.idl b/modules/libpr0n/public/imgIContainer.idl index cd76cb4eabdd..2fea94768574 100644 --- a/modules/libpr0n/public/imgIContainer.idl +++ b/modules/libpr0n/public/imgIContainer.idl @@ -75,6 +75,14 @@ interface imgIContainer : nsISupports readonly attribute unsigned long numFrames; + /** + * Animation mode. + * 0 = normal + * 1 = don't animate + * 2 = loop once + */ + attribute unsigned short animationMode; + gfxIImageFrame getFrameAt(in unsigned long index); /** diff --git a/modules/libpr0n/src/imgContainer.cpp b/modules/libpr0n/src/imgContainer.cpp index 6674737515da..c82527743e30 100644 --- a/modules/libpr0n/src/imgContainer.cpp +++ b/modules/libpr0n/src/imgContainer.cpp @@ -41,6 +41,7 @@ imgContainer::imgContainer() mCurrentFrameIsFinishedDecoding = PR_FALSE; mDoneDecoding = PR_FALSE; mAnimating = PR_FALSE; + mAnimationMode = 0; mObserver = nsnull; } @@ -213,21 +214,8 @@ NS_IMETHODIMP imgContainer::EndFrameDecode(PRUint32 aFrameNum, PRUint32 aTimeout if (!currentFrame) return NS_ERROR_UNEXPECTED; currentFrame->SetTimeout(aTimeout); - - if (!mTimer && mAnimating){ - PRUint32 numFrames; - this->GetNumFrames(&numFrames); - if (numFrames > 1) { - if (aTimeout > 0) { // -1 means display this frame forever - mAnimating = PR_TRUE; - mTimer = do_CreateInstance("@mozilla.org/timer;1"); - - mTimer->Init(NS_STATIC_CAST(nsITimerCallback*, this), - aTimeout, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK); - } - } - } + StartAnimation(); return NS_OK; } @@ -253,9 +241,28 @@ NS_IMETHODIMP imgContainer::Clear() } //****************************************************************************** +NS_IMETHODIMP imgContainer::GetAnimationMode(PRUint16 *aAnimationMode) +{ + if (!aAnimationMode) return NS_ERROR_NULL_POINTER; + *aAnimationMode = mAnimationMode; + return NS_OK; +} + +NS_IMETHODIMP imgContainer::SetAnimationMode(PRUint16 aAnimationMode) +{ + mAnimationMode = aAnimationMode; + return NS_OK; +} + /* void startAnimation () */ NS_IMETHODIMP imgContainer::StartAnimation() { + if (mAnimationMode == 1) // don't animate + { + mAnimating = PR_FALSE; + return NS_OK; + } + mAnimating = PR_TRUE; if (mTimer) @@ -363,6 +370,12 @@ NS_IMETHODIMP_(void) imgContainer::Notify(nsITimer *timer) } } else if (mDoneDecoding){ if ((numFrames-1) == mCurrentAnimationFrameIndex) { + // If animation mode is "loop once", it's time to stop animating + if (mAnimationMode == 2) { + this->StopAnimation(); + return; + } + // Go back to the beginning of the animation GetFrameAt(0, getter_AddRefs(nextFrame)); if(!nextFrame) return; @@ -404,7 +417,6 @@ NS_IMETHODIMP_(void) imgContainer::Notify(nsITimer *timer) observer->FrameChanged(this, nsnull, nextFrame, &dirtyRect); } - } //****************************************************************************** // DoComposite gets called when the timer for animation get fired and we have to diff --git a/modules/libpr0n/src/imgContainer.h b/modules/libpr0n/src/imgContainer.h index 626ec291ab02..86e0f2e413ea 100644 --- a/modules/libpr0n/src/imgContainer.h +++ b/modules/libpr0n/src/imgContainer.h @@ -74,6 +74,7 @@ private: PRBool mCurrentFrameIsFinishedDecoding; PRBool mDoneDecoding; PRBool mAnimating; + PRUint16 mAnimationMode; nsWeakPtr mObserver;