From 8bdd562d78e126e23009648e4daebc733cd4de33 Mon Sep 17 00:00:00 2001 From: "pavlov%netscape.com" Date: Thu, 25 Oct 2001 07:44:55 +0000 Subject: [PATCH] fixing bug 106623 r=bryner sr=hyatt git-svn-id: svn://10.0.0.236/trunk@106256 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/modules/libpr0n/src/imgContainer.cpp | 120 ++++++++----------- mozilla/modules/libpr0n/src/imgContainer.h | 31 ++++- 2 files changed, 81 insertions(+), 70 deletions(-) diff --git a/mozilla/modules/libpr0n/src/imgContainer.cpp b/mozilla/modules/libpr0n/src/imgContainer.cpp index 0b380d2ceac..b73f51b2056 100644 --- a/mozilla/modules/libpr0n/src/imgContainer.cpp +++ b/mozilla/modules/libpr0n/src/imgContainer.cpp @@ -36,18 +36,18 @@ NS_IMPL_ISUPPORTS3(imgContainer, imgIContainer, nsITimerCallback, imgIDecoderObs //****************************************************************************** imgContainer::imgContainer() : - mSize(0,0) + mSize(0,0), + mObserver(nsnull), + mCurrentDecodingFrameIndex(0), + mCurrentAnimationFrameIndex(0), + mCurrentFrameIsFinishedDecoding(PR_FALSE), + mDoneDecoding(PR_FALSE), + mAnimating(PR_FALSE), + mAnimationMode(0), + mLoopCount(-1) { NS_INIT_ISUPPORTS(); /* member initializers and constructor code */ - mCurrentDecodingFrameIndex = 0; - mCurrentAnimationFrameIndex = 0; - mCurrentFrameIsFinishedDecoding = PR_FALSE; - mDoneDecoding = PR_FALSE; - mAnimating = PR_FALSE; - mAnimationMode = 0; - mObserver = nsnull; - mLoopCount = -1; } //****************************************************************************** @@ -55,7 +55,7 @@ imgContainer::~imgContainer() { if (mTimer) mTimer->Cancel(); - + /* destructor code */ mFrames.Clear(); } @@ -105,13 +105,7 @@ NS_IMETHODIMP imgContainer::GetHeight(nscoord *aHeight) /* readonly attribute gfxIImageFrame currentFrame; */ NS_IMETHODIMP imgContainer::GetCurrentFrame(gfxIImageFrame * *aCurrentFrame) { - if (mCompositingFrame) { - *aCurrentFrame = mCompositingFrame; - NS_ADDREF(*aCurrentFrame); - return NS_OK; - } - - return this->GetFrameAt(mCurrentAnimationFrameIndex, aCurrentFrame); + return inlinedGetCurrentFrame(aCurrentFrame); } //****************************************************************************** @@ -125,16 +119,7 @@ NS_IMETHODIMP imgContainer::GetNumFrames(PRUint32 *aNumFrames) /* gfxIImageFrame getFrameAt (in unsigned long index); */ NS_IMETHODIMP imgContainer::GetFrameAt(PRUint32 index, gfxIImageFrame **_retval) { - nsISupports *sup = mFrames.ElementAt(index); // addrefs - if (!sup) - return NS_ERROR_FAILURE; - - nsresult rv; - rv = sup->QueryInterface(NS_GET_IID(gfxIImageFrame), (void**)_retval); // addrefs again - - NS_RELEASE(sup); - - return rv; + return inlinedGetFrameAt(index, _retval); } //****************************************************************************** @@ -145,10 +130,9 @@ NS_IMETHODIMP imgContainer::AppendFrame(gfxIImageFrame *item) // size is the same the frame size. Otherwise, we'll either need the composite frame // for animation compositing (GIF) or for filling in with a background color. // XXX IMPORTANT: this means that the frame should be initialized BEFORE appending to container - PRUint32 numFrames; - this->GetNumFrames(&numFrames); + PRUint32 numFrames = inlinedGetNumFrames(); - if(!mCompositingFrame) { + if (!mCompositingFrame) { nsRect frameRect; item->GetRect(frameRect); // We used to create a compositing frame if any frame was smaller than the logical @@ -174,14 +158,14 @@ NS_IMETHODIMP imgContainer::AppendFrame(gfxIImageFrame *item) } nsCOMPtr firstFrame; - this->GetFrameAt(0, getter_AddRefs(firstFrame)); - + inlinedGetFrameAt(0, getter_AddRefs(firstFrame)); + gfx_color backgroundColor, transColor; - if(NS_SUCCEEDED(firstFrame->GetTransparentColor(&transColor))) { + if (NS_SUCCEEDED(firstFrame->GetTransparentColor(&transColor))) { mCompositingFrame->SetTransparentColor(transColor); } - if(NS_SUCCEEDED(firstFrame->GetBackgroundColor(&backgroundColor))) { + if (NS_SUCCEEDED(firstFrame->GetBackgroundColor(&backgroundColor))) { mCompositingFrame->SetBackgroundColor(backgroundColor); FillWithColor(mCompositingFrame, backgroundColor); } @@ -199,16 +183,15 @@ NS_IMETHODIMP imgContainer::AppendFrame(gfxIImageFrame *item) if (!mTimer && (numFrames >= 1)) { PRInt32 timeout; nsCOMPtr currentFrame; - this->GetFrameAt(mCurrentDecodingFrameIndex, getter_AddRefs(currentFrame)); + inlinedGetFrameAt(mCurrentDecodingFrameIndex, getter_AddRefs(currentFrame)); currentFrame->GetTimeout(&timeout); if (timeout > 0) { // -1 means display this frame forever - - if(mAnimating) { + + if (mAnimating) { // Since we have more than one frame we need a timer mTimer = do_CreateInstance("@mozilla.org/timer;1"); - mTimer->Init( - NS_STATIC_CAST(nsITimerCallback*, this), - timeout, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK); + mTimer->Init(NS_STATIC_CAST(nsITimerCallback*, this), + timeout, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK); } } } @@ -235,7 +218,7 @@ NS_IMETHODIMP imgContainer::EndFrameDecode(PRUint32 aFrameNum, PRUint32 aTimeout mCurrentFrameIsFinishedDecoding = PR_TRUE; nsCOMPtr currentFrame; - this->GetFrameAt(aFrameNum-1, getter_AddRefs(currentFrame)); + inlinedGetFrameAt(aFrameNum-1, getter_AddRefs(currentFrame)); NS_ASSERTION(currentFrame, "Received an EndFrameDecode call with an invalid frame number"); if (!currentFrame) return NS_ERROR_UNEXPECTED; @@ -255,7 +238,7 @@ NS_IMETHODIMP imgContainer::DecodingComplete(void) mFrames.Count(&numFrames); if (numFrames == 1) { nsCOMPtr currentFrame; - GetFrameAt(0, getter_AddRefs(currentFrame)); + inlinedGetFrameAt(0, getter_AddRefs(currentFrame)); currentFrame->SetMutable(PR_FALSE); } return NS_OK; @@ -303,19 +286,18 @@ NS_IMETHODIMP imgContainer::StartAnimation() if (mTimer) return NS_OK; - PRUint32 numFrames; - this->GetNumFrames(&numFrames); + PRUint32 numFrames = inlinedGetNumFrames(); if (numFrames > 1) { PRInt32 timeout; nsCOMPtr currentFrame; - this->GetCurrentFrame(getter_AddRefs(currentFrame)); + inlinedGetCurrentFrame(getter_AddRefs(currentFrame)); if (currentFrame) { currentFrame->GetTimeout(&timeout); if (timeout > 0) { // -1 means display this frame forever mAnimating = PR_TRUE; - if(!mTimer) mTimer = do_CreateInstance("@mozilla.org/timer;1"); + if (!mTimer) mTimer = do_CreateInstance("@mozilla.org/timer;1"); mTimer->Init(NS_STATIC_CAST(nsITimerCallback*, this), timeout, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK); @@ -323,8 +305,8 @@ NS_IMETHODIMP imgContainer::StartAnimation() } else { // XXX hack.. the timer notify code will do the right thing, so just get that started mAnimating = PR_TRUE; - if(!mTimer) mTimer = do_CreateInstance("@mozilla.org/timer;1"); - + if (!mTimer) mTimer = do_CreateInstance("@mozilla.org/timer;1"); + mTimer->Init(NS_STATIC_CAST(nsITimerCallback*, this), 100, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK); } @@ -389,8 +371,7 @@ NS_IMETHODIMP_(void) imgContainer::Notify(nsITimer *timer) nsCOMPtr nextFrame; PRInt32 timeout = 100; - PRUint32 numFrames; - GetNumFrames(&numFrames); + PRUint32 numFrames = inlinedGetNumFrames(); if(!numFrames) return; @@ -399,14 +380,14 @@ NS_IMETHODIMP_(void) imgContainer::Notify(nsITimer *timer) PRUint32 previousAnimationFrameIndex = mCurrentAnimationFrameIndex; if (mCurrentFrameIsFinishedDecoding && !mDoneDecoding) { // If we have the next frame in the sequence set the timer callback from it - GetFrameAt(mCurrentAnimationFrameIndex+1, getter_AddRefs(nextFrame)); + inlinedGetFrameAt(mCurrentAnimationFrameIndex+1, getter_AddRefs(nextFrame)); if (nextFrame) { // Go to next frame in sequence nextFrame->GetTimeout(&timeout); mCurrentAnimationFrameIndex++; } else { // twiddle our thumbs - GetFrameAt(mCurrentAnimationFrameIndex, getter_AddRefs(nextFrame)); + inlinedGetFrameAt(mCurrentAnimationFrameIndex, getter_AddRefs(nextFrame)); if(!nextFrame) return; nextFrame->GetTimeout(&timeout); @@ -420,7 +401,7 @@ NS_IMETHODIMP_(void) imgContainer::Notify(nsITimer *timer) } // Go back to the beginning of the animation - GetFrameAt(0, getter_AddRefs(nextFrame)); + inlinedGetFrameAt(0, getter_AddRefs(nextFrame)); if(!nextFrame) return; mCurrentAnimationFrameIndex = 0; @@ -429,13 +410,13 @@ NS_IMETHODIMP_(void) imgContainer::Notify(nsITimer *timer) mLoopCount--; } else { mCurrentAnimationFrameIndex++; - GetFrameAt(mCurrentAnimationFrameIndex, getter_AddRefs(nextFrame)); + inlinedGetFrameAt(mCurrentAnimationFrameIndex, getter_AddRefs(nextFrame)); if(!nextFrame) return; nextFrame->GetTimeout(&timeout); } } else { - GetFrameAt(mCurrentAnimationFrameIndex, getter_AddRefs(nextFrame)); + inlinedGetFrameAt(mCurrentAnimationFrameIndex, getter_AddRefs(nextFrame)); if(!nextFrame) return; } @@ -472,8 +453,7 @@ void imgContainer::DoComposite(gfxIImageFrame** aFrameToUse, nsRect* aDirtyRect, *aFrameToUse = nsnull; - PRUint32 numFrames; - this->GetNumFrames(&numFrames); + PRUint32 numFrames = inlinedGetNumFrames(); PRInt32 nextFrameIndex = aNextFrame; PRInt32 prevFrameIndex = aPrevFrame; @@ -481,7 +461,7 @@ void imgContainer::DoComposite(gfxIImageFrame** aFrameToUse, nsRect* aDirtyRect, if(prevFrameIndex >= numFrames) prevFrameIndex = numFrames-1; nsCOMPtr prevFrame; - this->GetFrameAt(prevFrameIndex, getter_AddRefs(prevFrame)); + inlinedGetFrameAt(prevFrameIndex, getter_AddRefs(prevFrame)); PRInt32 prevFrameDisposalMethod; if(nextFrameIndex == 0) @@ -490,7 +470,7 @@ void imgContainer::DoComposite(gfxIImageFrame** aFrameToUse, nsRect* aDirtyRect, prevFrame->GetFrameDisposalMethod(&prevFrameDisposalMethod); nsCOMPtr nextFrame; - this->GetFrameAt(nextFrameIndex, getter_AddRefs(nextFrame)); + inlinedGetFrameAt(nextFrameIndex, getter_AddRefs(nextFrame)); PRInt32 x; PRInt32 y; @@ -507,19 +487,24 @@ void imgContainer::DoComposite(gfxIImageFrame** aFrameToUse, nsRect* aDirtyRect, switch (prevFrameDisposalMethod) { default: case 0: // DISPOSE_NOT_SPECIFIED - mCompositingFrame->QueryInterface(NS_GET_IID(gfxIImageFrame), (void**)aFrameToUse); // addrefs again + *aFrameToUse = mCompositingFrame; + NS_ADDREF(*aFrameToUse); nextFrame->DrawTo(mCompositingFrame, x, y, width, height); - break; + break; + case 1: // DISPOSE_KEEP Leave previous frame in the framebuffer - mCompositingFrame->QueryInterface(NS_GET_IID(gfxIImageFrame), (void**)aFrameToUse); // addrefs again + *aFrameToUse = mCompositingFrame; + NS_ADDREF(*aFrameToUse); nextFrame->DrawTo(mCompositingFrame, x, y, width, height); BuildCompositeMask(mCompositingFrame, nextFrame); - break; + break; + case 2: // DISPOSE_OVERWRITE_BGCOLOR Overwrite with background color - mCompositingFrame->QueryInterface(NS_GET_IID(gfxIImageFrame), (void**)aFrameToUse); // addrefs again - + *aFrameToUse = mCompositingFrame; + NS_ADDREF(*aFrameToUse); + // Not actually getting the background color here, and instead filling with // zeros fixes cases where the animation is transparent, but has a different // background color and so on Windows, we would correctly build the bit mask, but @@ -532,11 +517,12 @@ void imgContainer::DoComposite(gfxIImageFrame** aFrameToUse, nsRect* aDirtyRect, ZeroMask(mCompositingFrame); BuildCompositeMask(mCompositingFrame, nextFrame); - break; + break; + case 4: // DISPOSE_OVERWRITE_PREVIOUS Save-under //XXX Reblit previous composite into frame buffer // - break; + break; } (*aDirtyRect).x = 0; diff --git a/mozilla/modules/libpr0n/src/imgContainer.h b/mozilla/modules/libpr0n/src/imgContainer.h index 3103d76d951..b4235080dfd 100644 --- a/mozilla/modules/libpr0n/src/imgContainer.h +++ b/mozilla/modules/libpr0n/src/imgContainer.h @@ -66,9 +66,34 @@ public: virtual ~imgContainer(); private: + + inline PRUint32 inlinedGetNumFrames() { + PRUint32 nframes; + mFrames.Count(&nframes); + return nframes; + } + + inline nsresult inlinedGetFrameAt(PRUint32 index, gfxIImageFrame **_retval) { + *_retval = NS_STATIC_CAST(gfxIImageFrame*, mFrames.ElementAt(index)); + if (!*_retval) return NS_ERROR_FAILURE; + return NS_OK; + } + + inline nsresult inlinedGetCurrentFrame(gfxIImageFrame **_retval) { + if (mCompositingFrame) { + *_retval = mCompositingFrame; + NS_ADDREF(*_retval); + return NS_OK; + } + + return inlinedGetFrameAt(mCurrentAnimationFrameIndex, _retval); + } + /* additional members */ nsSupportsArray mFrames; nsSize mSize; + nsWeakPtr mObserver; + PRUint32 mCurrentDecodingFrameIndex; // 0 to numFrames-1 PRUint32 mCurrentAnimationFrameIndex; // 0 to numFrames-1 PRBool mCurrentFrameIsFinishedDecoding; @@ -76,12 +101,12 @@ private: PRBool mAnimating; PRUint16 mAnimationMode; PRInt32 mLoopCount; - - nsWeakPtr mObserver; + +private: // GIF specific bits nsCOMPtr mTimer; - + // GIF animations will use the mCompositingFrame to composite images // and just hand this back to the caller when it is time to draw the frame. nsCOMPtr mCompositingFrame;