Back out bug 666446 due to Talos regression.
|
@ -42,7 +42,6 @@ interface nsIChannel;
|
|||
interface nsIStreamListener;
|
||||
interface nsIURI;
|
||||
interface nsIDocument;
|
||||
interface nsIFrame;
|
||||
|
||||
/**
|
||||
* This interface represents a content node that loads images. The interface
|
||||
|
@ -66,7 +65,7 @@ interface nsIFrame;
|
|||
* sufficient, when combined with the imageBlockingStatus information.)
|
||||
*/
|
||||
|
||||
[scriptable, uuid(f7debb84-2854-4731-a57b-1bd752ad71f8)]
|
||||
[scriptable, uuid(95c74255-df9a-4060-b5a0-0d111fcafe08)]
|
||||
interface nsIImageLoadingContent : imgIDecoderObserver
|
||||
{
|
||||
/**
|
||||
|
@ -129,18 +128,6 @@ interface nsIImageLoadingContent : imgIDecoderObserver
|
|||
*/
|
||||
imgIRequest getRequest(in long aRequestType);
|
||||
|
||||
/**
|
||||
* Used to notify the image loading content node that a frame has been
|
||||
* created.
|
||||
*/
|
||||
[notxpcom] void frameCreated(in nsIFrame aFrame);
|
||||
|
||||
/**
|
||||
* Used to notify the image loading content node that a frame has been
|
||||
* destroyed.
|
||||
*/
|
||||
[notxpcom] void frameDestroyed(in nsIFrame aFrame);
|
||||
|
||||
/**
|
||||
* Used to find out what type of request one is dealing with (eg
|
||||
* which request got passed through to the imgIDecoderObserver
|
||||
|
|
|
@ -3225,7 +3225,6 @@ nsDocument::DeleteShell()
|
|||
if (IsEventHandlingEnabled()) {
|
||||
RevokeAnimationFrameNotifications();
|
||||
}
|
||||
|
||||
mPresShell = nsnull;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,6 @@
|
|||
#include "nsIDOMNode.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
|
@ -116,9 +115,7 @@ nsImageLoadingContent::nsImageLoadingContent()
|
|||
mNewRequestsWillNeedAnimationReset(false),
|
||||
mPendingRequestNeedsResetAnimation(false),
|
||||
mCurrentRequestNeedsResetAnimation(false),
|
||||
mStateChangerDepth(0),
|
||||
mCurrentRequestRegistered(false),
|
||||
mPendingRequestRegistered(false)
|
||||
mStateChangerDepth(0)
|
||||
{
|
||||
if (!nsContentUtils::GetImgLoader()) {
|
||||
mLoadingEnabled = false;
|
||||
|
@ -200,15 +197,6 @@ nsImageLoadingContent::OnStartDecode(imgIRequest* aRequest)
|
|||
}
|
||||
}
|
||||
|
||||
bool* requestFlag = GetRegisteredFlagForRequest(aRequest);
|
||||
if (requestFlag) {
|
||||
nsLayoutUtils::RegisterImageRequest(GetFramePresContext(), aRequest,
|
||||
requestFlag);
|
||||
} else {
|
||||
NS_ERROR("Starting to decode an image other than our current/pending "
|
||||
"request?");
|
||||
}
|
||||
|
||||
LOOP_OVER_OBSERVERS(OnStartDecode(aRequest));
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -341,13 +329,6 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
|
|||
nsIPresShell* shell = doc ? doc->GetShell() : nsnull;
|
||||
if (shell) {
|
||||
|
||||
// Make sure that our image requests are deregistered from the refresh
|
||||
// driver if they aren't animated. Note that this must be mCurrentRequest,
|
||||
// or we would have aborted up above.
|
||||
nsLayoutUtils::DeregisterImageRequestIfNotAnimated(GetFramePresContext(),
|
||||
mCurrentRequest,
|
||||
&mCurrentRequestRegistered);
|
||||
|
||||
// We need to figure out whether to kick off decoding
|
||||
bool doRequestDecode = false;
|
||||
|
||||
|
@ -520,44 +501,6 @@ nsImageLoadingContent::GetRequest(PRInt32 aRequestType,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
nsImageLoadingContent::FrameCreated(nsIFrame* aFrame)
|
||||
{
|
||||
NS_ASSERTION(aFrame, "aFrame is null");
|
||||
|
||||
// We need to make sure that our image request is registered.
|
||||
nsPresContext* presContext = aFrame->PresContext();
|
||||
|
||||
if (mCurrentRequest) {
|
||||
nsLayoutUtils::RegisterImageRequest(presContext, mCurrentRequest,
|
||||
&mCurrentRequestRegistered);
|
||||
nsLayoutUtils::DeregisterImageRequestIfNotAnimated(presContext,
|
||||
mCurrentRequest,
|
||||
&mCurrentRequestRegistered);
|
||||
} else if (mPendingRequest) {
|
||||
// We don't need to do the same check for animation, because this will be
|
||||
// done when decoding is finished.
|
||||
nsLayoutUtils::RegisterImageRequest(presContext, mPendingRequest,
|
||||
&mPendingRequestRegistered);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
nsImageLoadingContent::FrameDestroyed(nsIFrame* aFrame)
|
||||
{
|
||||
NS_ASSERTION(aFrame, "aFrame is null");
|
||||
|
||||
// We need to make sure that our image request is deregistered.
|
||||
if (mCurrentRequest) {
|
||||
nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(),
|
||||
mCurrentRequest,
|
||||
&mCurrentRequestRegistered);
|
||||
} else if (mPendingRequest) {
|
||||
nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(),
|
||||
mPendingRequest,
|
||||
&mPendingRequestRegistered);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageLoadingContent::GetRequestType(imgIRequest* aRequest,
|
||||
|
@ -924,23 +867,6 @@ nsImageLoadingContent::GetOurDocument()
|
|||
return thisContent->OwnerDoc();
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsImageLoadingContent::GetOurPrimaryFrame()
|
||||
{
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
|
||||
return thisContent->GetPrimaryFrame();
|
||||
}
|
||||
|
||||
nsPresContext* nsImageLoadingContent::GetFramePresContext()
|
||||
{
|
||||
nsIFrame* frame = GetOurPrimaryFrame();
|
||||
if (!frame) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return frame->PresContext();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImageLoadingContent::StringToURI(const nsAString& aSpec,
|
||||
nsIDocument* aDocument,
|
||||
|
@ -1060,16 +986,6 @@ nsImageLoadingContent::ClearCurrentRequest(nsresult aReason)
|
|||
NS_ABORT_IF_FALSE(!mCurrentURI,
|
||||
"Shouldn't have both mCurrentRequest and mCurrentURI!");
|
||||
|
||||
// Deregister this image from the refresh driver so it no longer receives
|
||||
// notifications.
|
||||
nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(), mCurrentRequest,
|
||||
&mCurrentRequestRegistered);
|
||||
|
||||
// Deregister this image from the refresh driver so it no longer receives
|
||||
// notifications.
|
||||
nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(), mCurrentRequest,
|
||||
&mCurrentRequestRegistered);
|
||||
|
||||
// Clean up the request.
|
||||
UntrackImage(mCurrentRequest);
|
||||
mCurrentRequest->CancelAndForgetObserver(aReason);
|
||||
|
@ -1093,29 +1009,12 @@ nsImageLoadingContent::ClearPendingRequest(nsresult aReason)
|
|||
nsCxPusher pusher;
|
||||
pusher.PushNull();
|
||||
|
||||
// Deregister this image from the refresh driver so it no longer receives
|
||||
// notifications.
|
||||
nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(), mPendingRequest,
|
||||
&mPendingRequestRegistered);
|
||||
|
||||
UntrackImage(mPendingRequest);
|
||||
mPendingRequest->CancelAndForgetObserver(aReason);
|
||||
mPendingRequest = nsnull;
|
||||
mPendingRequestNeedsResetAnimation = false;
|
||||
}
|
||||
|
||||
bool*
|
||||
nsImageLoadingContent::GetRegisteredFlagForRequest(imgIRequest* aRequest)
|
||||
{
|
||||
if (aRequest == mCurrentRequest) {
|
||||
return &mCurrentRequestRegistered;
|
||||
} else if (aRequest == mPendingRequest) {
|
||||
return &mPendingRequestRegistered;
|
||||
} else {
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsImageLoadingContent::HaveSize(imgIRequest *aImage)
|
||||
{
|
||||
|
|
|
@ -146,24 +146,6 @@ protected:
|
|||
*/
|
||||
nsIDocument* GetOurDocument();
|
||||
|
||||
/**
|
||||
* Helper function to get the frame associated with this content. Not named
|
||||
* GetPrimaryFrame to prevent ambiguous method names in subclasses.
|
||||
*
|
||||
* @return The frame which we belong to, or nsnull if it doesn't exist.
|
||||
*/
|
||||
nsIFrame* GetOurPrimaryFrame();
|
||||
|
||||
/**
|
||||
* Helper function to get the PresContext associated with this content's
|
||||
* frame. Not named GetPresContext to prevent ambiguous method names in
|
||||
* subclasses.
|
||||
*
|
||||
* @return The nsPresContext associated with our frame, or nsnull if either
|
||||
* the frame doesn't exist, or the frame's prescontext doesn't exist.
|
||||
*/
|
||||
nsPresContext* GetFramePresContext();
|
||||
|
||||
/**
|
||||
* CancelImageRequests is called by subclasses when they want to
|
||||
* cancel all image requests (for example when the subclass is
|
||||
|
@ -320,16 +302,6 @@ protected:
|
|||
void ClearCurrentRequest(nsresult aReason);
|
||||
void ClearPendingRequest(nsresult aReason);
|
||||
|
||||
/**
|
||||
* Retrieve a pointer to the 'registered with the refresh driver' flag for
|
||||
* which a particular image request corresponds.
|
||||
*
|
||||
* @returns A pointer to the boolean flag for a given image request, or
|
||||
* |nsnull| if the request is not either |mPendingRequest| or
|
||||
* |mCurrentRequest|.
|
||||
*/
|
||||
bool* GetRegisteredFlagForRequest(imgIRequest* aRequest);
|
||||
|
||||
/**
|
||||
* Static helper method to tell us if we have the size of a request. The
|
||||
* image may be null.
|
||||
|
@ -410,11 +382,6 @@ private:
|
|||
|
||||
/* The number of nested AutoStateChangers currently tracking our state. */
|
||||
PRUint8 mStateChangerDepth;
|
||||
|
||||
// Flags to indicate whether each of the current and pending requests are
|
||||
// registered with the refresh driver.
|
||||
bool mCurrentRequestRegistered;
|
||||
bool mPendingRequestRegistered;
|
||||
};
|
||||
|
||||
#endif // nsImageLoadingContent_h__
|
||||
|
|
|
@ -56,10 +56,6 @@ interface imgIDecoderObserver;
|
|||
#include "limits.h"
|
||||
|
||||
class nsIFrame;
|
||||
|
||||
namespace mozilla {
|
||||
class TimeStamp;
|
||||
}
|
||||
%}
|
||||
|
||||
[ptr] native gfxImageSurface(gfxImageSurface);
|
||||
|
@ -72,7 +68,6 @@ native gfxGraphicsFilter(gfxPattern::GraphicsFilter);
|
|||
[ref] native nsIntRect(nsIntRect);
|
||||
[ref] native nsIntSize(nsIntSize);
|
||||
[ptr] native nsIFrame(nsIFrame);
|
||||
[ref] native TimeStamp(mozilla::TimeStamp);
|
||||
|
||||
/**
|
||||
* imgIContainer is the interface that represents an image. It allows
|
||||
|
@ -266,13 +261,6 @@ interface imgIContainer : nsISupports
|
|||
*/
|
||||
void unlockImage();
|
||||
|
||||
/**
|
||||
* Indicates that this imgIContainer has been triggered to update
|
||||
* its internal animation state. Likely this should only be called
|
||||
* from within nsImageFrame or objects of similar type.
|
||||
*/
|
||||
[notxpcom] void requestRefresh([const] in TimeStamp aTime);
|
||||
|
||||
/**
|
||||
* Animation mode Constants
|
||||
* 0 = normal
|
||||
|
|
|
@ -173,10 +173,10 @@ namespace mozilla {
|
|||
namespace imagelib {
|
||||
|
||||
#ifndef DEBUG
|
||||
NS_IMPL_ISUPPORTS3(RasterImage, imgIContainer, nsIProperties,
|
||||
NS_IMPL_ISUPPORTS4(RasterImage, imgIContainer, nsITimerCallback, nsIProperties,
|
||||
nsISupportsWeakReference)
|
||||
#else
|
||||
NS_IMPL_ISUPPORTS4(RasterImage, imgIContainer, nsIProperties,
|
||||
NS_IMPL_ISUPPORTS5(RasterImage, imgIContainer, nsITimerCallback, nsIProperties,
|
||||
imgIContainerDebug, nsISupportsWeakReference)
|
||||
#endif
|
||||
|
||||
|
@ -313,169 +313,6 @@ 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);
|
||||
NS_IMETHODIMP_(void)
|
||||
RasterImage::RequestRefresh(const mozilla::TimeStamp& aTime)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
/* [noscript] imgIContainer extractFrame(PRUint32 aWhichFrame,
|
||||
* [const] in nsIntRect aRegion,
|
||||
|
@ -657,27 +494,6 @@ 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()
|
||||
{
|
||||
|
@ -1322,18 +1138,25 @@ 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();
|
||||
if (currentFrame) {
|
||||
if (currentFrame->GetTimeout() < 0) { // -1 means display this frame forever
|
||||
timeout = currentFrame->GetTimeout();
|
||||
if (timeout < 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;
|
||||
}
|
||||
|
||||
|
@ -1347,6 +1170,11 @@ RasterImage::StopAnimation()
|
|||
if (mError)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mAnim->timer) {
|
||||
mAnim->timer->Cancel();
|
||||
mAnim->timer = nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1602,6 +1430,127 @@ 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,7 +71,6 @@
|
|||
#endif
|
||||
|
||||
class imgIDecoder;
|
||||
class imgIContainerObserver;
|
||||
class nsIInputStream;
|
||||
|
||||
#define NS_RASTERIMAGE_CID \
|
||||
|
@ -82,12 +81,6 @@ 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.
|
||||
*
|
||||
|
@ -95,27 +88,15 @@ 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(). Note that the invalidation events for RasterImage are
|
||||
* generated automatically using nsRefreshDriver.
|
||||
* with StartAnimation().
|
||||
*
|
||||
* @par
|
||||
* StartAnimation() initializes the animation helper object and sets the time
|
||||
* the first frame was displayed to the current clock time.
|
||||
* StartAnimation() creates a timer. The timer calls Notify when the
|
||||
* specified frame delay time is up.
|
||||
*
|
||||
* @par
|
||||
* 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.
|
||||
* Notify() moves on to the next frame, sets up the new timer delay, destroys
|
||||
* the old frame, and forces a redraw via observer->FrameChanged().
|
||||
*
|
||||
* @par
|
||||
* Each frame can have a different method of removing itself. These are
|
||||
|
@ -170,6 +151,7 @@ class imgDecodeWorker;
|
|||
class Decoder;
|
||||
|
||||
class RasterImage : public Image
|
||||
, public nsITimerCallback
|
||||
, public nsIProperties
|
||||
, public nsSupportsWeakReference
|
||||
#ifdef DEBUG
|
||||
|
@ -178,6 +160,7 @@ class RasterImage : public Image
|
|||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
NS_DECL_NSIPROPERTIES
|
||||
#ifdef DEBUG
|
||||
NS_DECL_IMGICONTAINERDEBUG
|
||||
|
@ -200,7 +183,6 @@ public:
|
|||
NS_SCRIPTABLE NS_IMETHOD LockImage(void);
|
||||
NS_SCRIPTABLE NS_IMETHOD UnlockImage(void);
|
||||
NS_SCRIPTABLE NS_IMETHOD ResetAnimation(void);
|
||||
NS_IMETHOD_(void) RequestRefresh(const mozilla::TimeStamp& aTime);
|
||||
// END NS_DECL_IMGICONTAINER
|
||||
|
||||
RasterImage(imgStatusTracker* aStatusTracker = nsnull);
|
||||
|
@ -352,10 +334,6 @@ 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
|
||||
|
@ -374,33 +352,23 @@ 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() {}
|
||||
lastCompositedFrameIndex(-1)
|
||||
{
|
||||
;
|
||||
}
|
||||
~Anim()
|
||||
{
|
||||
if (timer)
|
||||
timer->Cancel();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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].
|
||||
*
|
||||
|
@ -417,7 +385,6 @@ private:
|
|||
imgFrame* GetCurrentImgFrame();
|
||||
imgFrame* GetCurrentDrawableImgFrame();
|
||||
PRUint32 GetCurrentImgFrameIndex() const;
|
||||
mozilla::TimeStamp GetCurrentImgFrameEndTime() const;
|
||||
|
||||
inline void EnsureAnimExists()
|
||||
{
|
||||
|
|
|
@ -172,6 +172,7 @@ SVGDrawingCallback::operator()(gfxContext* aContext,
|
|||
gfxContextMatrixAutoSaveRestore contextMatrixRestorer(aContext);
|
||||
aContext->Multiply(gfxMatrix(aTransform).Invert());
|
||||
|
||||
|
||||
nsPresContext* presContext = presShell->GetPresContext();
|
||||
NS_ABORT_IF_FALSE(presContext, "pres shell w/out pres context");
|
||||
|
||||
|
@ -329,14 +330,6 @@ VectorImage::GetWidth(PRInt32* aWidth)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
/* [notxpcom] void requestRefresh ([const] in TimeStamp aTime); */
|
||||
NS_IMETHODIMP_(void)
|
||||
VectorImage::RequestRefresh(const mozilla::TimeStamp& aTime)
|
||||
{
|
||||
// TODO: Implement for b666446.
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
/* readonly attribute PRInt32 height; */
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include "Image.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
class imgIDecoderObserver;
|
||||
|
||||
|
@ -77,7 +76,6 @@ public:
|
|||
NS_SCRIPTABLE NS_IMETHOD LockImage(void);
|
||||
NS_SCRIPTABLE NS_IMETHOD UnlockImage(void);
|
||||
NS_SCRIPTABLE NS_IMETHOD ResetAnimation(void);
|
||||
NS_IMETHOD_(void) RequestRefresh(const mozilla::TimeStamp& aTime);
|
||||
// END NS_DECL_IMGICONTAINER
|
||||
|
||||
VectorImage(imgStatusTracker* aStatusTracker = nsnull);
|
||||
|
|
|
@ -93,27 +93,8 @@ _TEST_FILES = imgutils.js \
|
|||
# test_bug478398.html disabled - See bug 579139
|
||||
|
||||
_CHROME_FILES = imgutils.js \
|
||||
animationPolling.js \
|
||||
lime-anim-100x100.svg \
|
||||
animation.svg \
|
||||
test_animSVGImage.html \
|
||||
test_animation.html \
|
||||
animated-gif-finalframe.gif \
|
||||
animated-gif.gif \
|
||||
animated-gif2.gif \
|
||||
purple.gif \
|
||||
test_svg_animatedGIF.html \
|
||||
test_bullet_animation.html \
|
||||
test_background_image_anim.html \
|
||||
filter.svg \
|
||||
filter-final.svg \
|
||||
test_svg_filter_animation.html \
|
||||
test_xultree_animation.xhtml \
|
||||
test_changeOfSource.html \
|
||||
test_changeOfSource2.html \
|
||||
test_undisplayed_iframe.html \
|
||||
iframe.html \
|
||||
ref-iframe.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
Двоичные данные
image/test/mochitest/animated-gif-finalframe.gif
До Ширина: | Высота: | Размер: 72 B |
Двоичные данные
image/test/mochitest/animated-gif.gif
До Ширина: | Высота: | Размер: 146 B |
Двоичные данные
image/test/mochitest/animated-gif2.gif
До Ширина: | Высота: | Размер: 165 B |
|
@ -1,5 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<image id="anim" xlink:href="animated-gif.gif" width="40" height="40"/>
|
||||
</svg>
|
||||
|
До Ширина: | Высота: | Размер: 170 B |
|
@ -1,395 +0,0 @@
|
|||
var currentTest;
|
||||
var gIsImageLoaded = false;
|
||||
var gIsRefImageLoaded = false;
|
||||
|
||||
function pollForSuccess ()
|
||||
{
|
||||
if (!currentTest.isTestFinished) {
|
||||
if (!currentTest.reusingReferenceImage || (currentTest.reusingReferenceImage
|
||||
&& gRefImageLoaded)) {
|
||||
currentTest.checkImage();
|
||||
}
|
||||
|
||||
setTimeout(pollForSuccess, currentTest.pollFreq);
|
||||
}
|
||||
};
|
||||
|
||||
function imageLoadCallback()
|
||||
{
|
||||
gIsImageLoaded = true;
|
||||
}
|
||||
|
||||
function referencePoller()
|
||||
{
|
||||
currentTest.takeReferenceSnapshot();
|
||||
}
|
||||
|
||||
function reuseImageCallback()
|
||||
{
|
||||
gIsRefImageLoaded = true;
|
||||
}
|
||||
|
||||
function failTest ()
|
||||
{
|
||||
if (currentTest.isTestFinished || currentTest.closeFunc) {
|
||||
return;
|
||||
}
|
||||
|
||||
ok(false, "timing out after " + currentTest.timeout + "ms. "
|
||||
+ "Animated image still doesn't look correct, " + "after call #"
|
||||
+ currentTest.onStopFrameCounter + " to onStopFrame");
|
||||
currentTest.wereFailures = true;
|
||||
|
||||
currentTest.enableDisplay(document.getElementById(currentTest.debugElementId));
|
||||
|
||||
currentTest.cleanUpAndFinish();
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new AnimationTest object.
|
||||
*
|
||||
* @param pollFreq The amount of time (in ms) to wait between consecutive
|
||||
* snapshots if the reference image and the test image don't match.
|
||||
* @param timeout The total amount of time (in ms) to wait before declaring the
|
||||
* test as failed.
|
||||
* @param referenceElementId The id attribute of the reference image element, or
|
||||
* the source of the image to change to, once the reference snapshot has
|
||||
* been successfully taken. This latter option could be used if you don't
|
||||
* want the image to become invisible at any time during the test.
|
||||
* @param imageElementId The id attribute of the test image element.
|
||||
* @param debugElementId The id attribute of the div where links should be
|
||||
* appended if the test fails.
|
||||
* @param cleanId The id attribute of the div or element to use as the 'clean'
|
||||
* test. This element is only enabled when we are testing to verify that
|
||||
* the reference image has been loaded. It can be undefined.
|
||||
* @param srcAttr The location of the source of the image, for preloading. This
|
||||
* is usually not required, but it useful for preloading reference
|
||||
* images.
|
||||
* @param xulTest A boolean value indicating whether or not this is a XUL test
|
||||
* (uses hidden=true/false rather than display: none to hide/show
|
||||
* elements).
|
||||
* @param closeFunc A function that should be called when this test is finished.
|
||||
* If null, then cleanUpAndFinish() will be called. This can be used to
|
||||
* chain tests together, so they are all finished exactly once.
|
||||
* @returns {AnimationTest}
|
||||
*/
|
||||
function AnimationTest(pollFreq, timeout, referenceElementId, imageElementId,
|
||||
debugElementId, cleanId, srcAttr, xulTest, closeFunc)
|
||||
{
|
||||
// We want to test the cold loading behavior, so clear cache in case an
|
||||
// earlier test got our image in there already.
|
||||
clearImageCache();
|
||||
|
||||
this.wereFailures = false;
|
||||
this.pollFreq = pollFreq;
|
||||
this.timeout = timeout;
|
||||
this.imageElementId = imageElementId;
|
||||
this.referenceElementId = referenceElementId;
|
||||
|
||||
if (!document.getElementById(referenceElementId)) {
|
||||
// In this case, we're assuming the user passed in a string that
|
||||
// indicates the source of the image they want to change to,
|
||||
// after the reference image has been taken.
|
||||
this.reusingImageAsReference = true;
|
||||
}
|
||||
|
||||
this.srcAttr = srcAttr;
|
||||
this.debugElementId = debugElementId;
|
||||
this.referenceSnapshot = ""; // value will be set in takeReferenceSnapshot()
|
||||
this.onStopFrameCounter = 0;
|
||||
this.isTestFinished = false;
|
||||
this.numRefsTaken = 0;
|
||||
this.blankWaitTime = 0;
|
||||
|
||||
this.cleanId = cleanId ? cleanId : '';
|
||||
this.xulTest = xulTest ? xulTest : '';
|
||||
this.closeFunc = closeFunc ? closeFunc : '';
|
||||
|
||||
if (this.srcAttr) {
|
||||
this.myImage = new Image();
|
||||
this.myImage.onload = imageLoadCallback;
|
||||
this.myImage.src = this.srcAttr;
|
||||
} else {
|
||||
gIsImageLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
AnimationTest.prototype.outputDebugInfo = function(message, id, dataUri)
|
||||
{
|
||||
var debugElement = document.getElementById(this.debugElementId);
|
||||
var newDataUriElement = document.createElement("a");
|
||||
newDataUriElement.setAttribute("id", id);
|
||||
newDataUriElement.setAttribute("href", dataUri);
|
||||
newDataUriElement.appendChild(document.createTextNode(message));
|
||||
debugElement.appendChild(newDataUriElement);
|
||||
var brElement = document.createElement("br");
|
||||
debugElement.appendChild(brElement);
|
||||
};
|
||||
|
||||
AnimationTest.prototype.isFinished = function()
|
||||
{
|
||||
return this.isTestFinished;
|
||||
};
|
||||
|
||||
AnimationTest.prototype.takeCleanSnapshot = function()
|
||||
{
|
||||
var cleanElement;
|
||||
if (this.cleanId) {
|
||||
cleanElement = document.getElementById(this.cleanId);
|
||||
}
|
||||
|
||||
// Enable clean page comparison element
|
||||
if (cleanElement) {
|
||||
this.enableDisplay(cleanElement);
|
||||
}
|
||||
|
||||
// Take a snapshot of the initial (clean) page
|
||||
this.cleanSnapshot = snapshotWindow(window, false);
|
||||
|
||||
// Disable the clean page comparison element
|
||||
if (cleanElement) {
|
||||
this.disableDisplay(cleanElement);
|
||||
}
|
||||
|
||||
var dataString1 = "Clean Snapshot";
|
||||
this.outputDebugInfo(dataString1, 'cleanSnap',
|
||||
this.cleanSnapshot.toDataURL());
|
||||
};
|
||||
|
||||
AnimationTest.prototype.takeBlankSnapshot = function()
|
||||
{
|
||||
// Take a snapshot of the initial (essentially blank) page
|
||||
this.blankSnapshot = snapshotWindow(window, false);
|
||||
|
||||
var dataString1 = "Initial Blank Snapshot";
|
||||
this.outputDebugInfo(dataString1, 'blank1Snap',
|
||||
this.blankSnapshot.toDataURL());
|
||||
};
|
||||
|
||||
/**
|
||||
* Begin the AnimationTest. This will utilize the information provided in the
|
||||
* constructor to invoke a mochitest on animated images. It will automatically
|
||||
* fail if allowed to run past the timeout.
|
||||
*/
|
||||
AnimationTest.prototype.beginTest = function ()
|
||||
{
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
currentTest = this;
|
||||
|
||||
this.takeReferenceSnapshot();
|
||||
|
||||
// In case something goes wrong, fail earlier than mochitest timeout,
|
||||
// and with more information.
|
||||
setTimeout(failTest, this.timeout);
|
||||
|
||||
if (!this.reusingImageAsReference) {
|
||||
this.disableDisplay(document.getElementById(this.imageElementId));
|
||||
}
|
||||
|
||||
this.setupPolledImage();
|
||||
setTimeout(pollForSuccess, 10);
|
||||
};
|
||||
|
||||
AnimationTest.prototype.setupPolledImage = function ()
|
||||
{
|
||||
// Make sure the image is visible
|
||||
if (!this.reusingImageAsReference) {
|
||||
this.enableDisplay(document.getElementById(this.imageElementId));
|
||||
var currentSnapshot = snapshotWindow(window, false);
|
||||
var result = compareSnapshots(currentSnapshot, this.referenceSnapshot, true);
|
||||
|
||||
var dataString = "Snapshot #" + this.onStopFrameCounter;
|
||||
this.outputDebugInfo(dataString, 'snap' + this.onStopFrameCounter,
|
||||
currentSnapshot.toDataURL());
|
||||
|
||||
if (result[0]) {
|
||||
// SUCCESS!
|
||||
ok(true, "Animated image looks correct, " + "at call #"
|
||||
+ this.onStopFrameCounter + " to onStopFrame");
|
||||
|
||||
this.cleanUpAndFinish();
|
||||
}
|
||||
} else {
|
||||
if (!gIsRefImageLoaded) {
|
||||
this.myImage = new Image();
|
||||
this.myImage.onload = reuseImageCallback;
|
||||
document.getElementById(this.imageElementId).setAttribute('src',
|
||||
this.referenceElementId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AnimationTest.prototype.checkImage = function ()
|
||||
{
|
||||
if (this.isTestFinished) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.onStopFrameCounter++;
|
||||
|
||||
// We need this for some tests, because we need to force the
|
||||
// test image to be visible.
|
||||
if (!this.reusingImageAsReference) {
|
||||
this.enableDisplay(document.getElementById(this.imageElementId));
|
||||
}
|
||||
|
||||
var currentSnapshot = snapshotWindow(window, false);
|
||||
var result = compareSnapshots(currentSnapshot, this.referenceSnapshot, true);
|
||||
|
||||
var dataString = "Snapshot #" + this.onStopFrameCounter;
|
||||
this.outputDebugInfo(dataString, 'snap' + this.onStopFrameCounter,
|
||||
currentSnapshot.toDataURL());
|
||||
|
||||
if (result[0]) {
|
||||
// SUCCESS!
|
||||
ok(true, "Animated image looks correct, " + "at call #"
|
||||
+ this.onStopFrameCounter + " to onStopFrame");
|
||||
|
||||
this.cleanUpAndFinish();
|
||||
}
|
||||
};
|
||||
|
||||
AnimationTest.prototype.takeReferenceSnapshot = function ()
|
||||
{
|
||||
this.numRefsTaken++;
|
||||
|
||||
// Test to make sure the reference image doesn't match a clean snapshot
|
||||
if (!this.cleanSnapshot) {
|
||||
this.takeCleanSnapshot();
|
||||
}
|
||||
|
||||
// Used later to verify that the reference div disappeared
|
||||
if (!this.blankSnapshot) {
|
||||
this.takeBlankSnapshot();
|
||||
}
|
||||
|
||||
if (this.reusingImageAsReference) {
|
||||
// Show reference div, & take a snapshot
|
||||
var referenceDiv = document.getElementById(this.imageElementId);
|
||||
this.enableDisplay(referenceDiv);
|
||||
|
||||
this.referenceSnapshot = snapshotWindow(window, false);
|
||||
var snapResult = compareSnapshots(this.cleanSnapshot, this.referenceSnapshot,
|
||||
false);
|
||||
if (!snapResult[0]) {
|
||||
if (this.blankWaitTime > 2000) {
|
||||
// if it took longer than two seconds to load the image, we probably
|
||||
// have a problem.
|
||||
this.wereFailures = true;
|
||||
ok(snapResult[0],
|
||||
"Reference snapshot shouldn't match clean (non-image) snapshot");
|
||||
} else {
|
||||
this.blankWaitTime += 20;
|
||||
// let's wait a bit and see if it clears up
|
||||
setTimeout(referencePoller, 20);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ok(snapResult[0],
|
||||
"Reference snapshot shouldn't match clean (non-image) snapshot");
|
||||
|
||||
var dataString = "Reference Snapshot #" + this.numRefsTaken;
|
||||
this.outputDebugInfo(dataString, 'refSnapId',
|
||||
this.referenceSnapshot.toDataURL());
|
||||
} else {
|
||||
// Make sure the animation section is hidden
|
||||
this.disableDisplay(document.getElementById(this.imageElementId));
|
||||
|
||||
// Show reference div, & take a snapshot
|
||||
var referenceDiv = document.getElementById(this.referenceElementId);
|
||||
this.enableDisplay(referenceDiv);
|
||||
|
||||
this.referenceSnapshot = snapshotWindow(window, false);
|
||||
var snapResult = compareSnapshots(this.cleanSnapshot, this.referenceSnapshot, false);
|
||||
if (!snapResult[0]) {
|
||||
if (this.blankWaitTime > 2000) {
|
||||
// if it took longer than two seconds to load the image, we probably
|
||||
// have a problem.
|
||||
this.wereFailures = true;
|
||||
ok(snapResult[0],
|
||||
"Reference snapshot shouldn't match clean (non-image) snapshot");
|
||||
} else {
|
||||
this.blankWaitTime += 20;
|
||||
// let's wait a bit and see if it clears up
|
||||
setTimeout(referencePoller, 20);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ok(snapResult[0],
|
||||
"Reference snapshot shouldn't match clean (non-image) snapshot");
|
||||
|
||||
var dataString = "Reference Snapshot #" + this.numRefsTaken;
|
||||
this.outputDebugInfo(dataString, 'refSnapId',
|
||||
this.referenceSnapshot.toDataURL());
|
||||
|
||||
// Re-hide reference div, and take another snapshot to be sure it's gone
|
||||
this.disableDisplay(referenceDiv);
|
||||
this.testBlankCameBack();
|
||||
}
|
||||
};
|
||||
|
||||
AnimationTest.prototype.enableDisplay = function(element)
|
||||
{
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.xulTest) {
|
||||
element.style.display = '';
|
||||
} else {
|
||||
element.setAttribute('hidden', 'false');
|
||||
}
|
||||
};
|
||||
|
||||
AnimationTest.prototype.disableDisplay = function(element)
|
||||
{
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.xulTest) {
|
||||
element.style.display = 'none';
|
||||
} else {
|
||||
element.setAttribute('hidden', 'true');
|
||||
}
|
||||
};
|
||||
|
||||
AnimationTest.prototype.testBlankCameBack = function()
|
||||
{
|
||||
var blankSnapshot2 = snapshotWindow(window, false);
|
||||
var result = compareSnapshots(this.blankSnapshot, blankSnapshot2, true);
|
||||
ok(result[0], "Reference image should disappear when it becomes display:none");
|
||||
|
||||
if (!result[0]) {
|
||||
this.wereFailures = true;
|
||||
var dataString = "Second Blank Snapshot";
|
||||
this.outputDebugInfo(dataString, 'blank2SnapId', result[2]);
|
||||
}
|
||||
};
|
||||
|
||||
AnimationTest.prototype.cleanUpAndFinish = function ()
|
||||
{
|
||||
// On the off chance that failTest and checkImage are triggered
|
||||
// back-to-back, use a flag to prevent multiple calls to SimpleTest.finish.
|
||||
if (this.isTestFinished) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isTestFinished = true;
|
||||
|
||||
// Call our closing function, if one exists
|
||||
if (this.closeFunc) {
|
||||
this.closeFunc();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.wereFailures) {
|
||||
document.getElementById(this.debugElementId).style.display = 'block';
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
document.getElementById(this.debugElementId).style.display = "";
|
||||
};
|
|
@ -1,9 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<filter id="filter1" x="0%" y="0%" width="100%" height="100%">
|
||||
<feImage xlink:href="animated-gif-finalframe.gif"/>
|
||||
</filter>
|
||||
<g>
|
||||
<rect x="0" y="0" width="100%" height="100%" filter="url(#filter1)"/>
|
||||
</g>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 299 B |
|
@ -1,9 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
|
||||
<filter id="filter1" x="0%" y="0%" width="100%" height="100%">
|
||||
<feImage xlink:href="animated-gif.gif"/>
|
||||
</filter>
|
||||
<g>
|
||||
<rect x="0" y="0" width="100%" height="100%" filter="url(#filter1)"/>
|
||||
</g>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 288 B |
|
@ -1,5 +0,0 @@
|
|||
<html>
|
||||
<body bgcolor="gray">
|
||||
<img src="animated-gif.gif">
|
||||
</body>
|
||||
</html>
|
Двоичные данные
image/test/mochitest/purple.gif
До Ширина: | Высота: | Размер: 86 B |
|
@ -1,6 +0,0 @@
|
|||
<html>
|
||||
<body bgcolor="gray">
|
||||
<div id="referenceImage"
|
||||
style="height: 40px; width: 40px; background: #2aff00"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,46 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - General Animated GIF Test</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content">
|
||||
<div id="referenceDiv" style="height: 40px; width: 40px;
|
||||
display: none; background: #2aff00"></div>
|
||||
<div id="animatedImage">
|
||||
<img id="animatedGif" src="animated-gif.gif" style="display: none;">
|
||||
<div id="text-descr"></div>
|
||||
</div>
|
||||
<div id="debug" style="display:none">
|
||||
</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
function main()
|
||||
{
|
||||
var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
|
||||
'animatedGif', 'debug');
|
||||
animTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,44 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - Animated Background Images</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<div id="referenceDiv" style="height: 140px; width: 140px;
|
||||
display: none; background: #2aff00"></div>
|
||||
<div id="bgImage" style="height: 140px; width: 140px; background-image: url(animated-gif.gif); display: none;">
|
||||
</div>
|
||||
</div>
|
||||
<div id="debug" style="display:none"></div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 666446 nsImageLoader/RasterImage**/
|
||||
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
function main() {
|
||||
var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
|
||||
'bgImage', 'debug');
|
||||
animTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,57 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - Animated Bullets</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content">
|
||||
<div id="cleanDiv" style="display: none;">
|
||||
<ul>
|
||||
<li>Test 1</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="referenceDiv" style="display: none;">
|
||||
<ul>
|
||||
<li style="list-style-image: url(animated-gif-finalframe.gif);">Test 1</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="animatedImage" style="display: none;">
|
||||
<ul>
|
||||
<li style="list-style-image: url(animated-gif.gif);">Test 1</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="text-descr"></div>
|
||||
<div id="debug" style="display:none">
|
||||
</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
function main()
|
||||
{
|
||||
var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
|
||||
'animatedImage', 'debug', 'cleanDiv',
|
||||
'animated-gif-finalframe.gif');
|
||||
animTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,63 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - Change of Source (1st Version)</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content">
|
||||
<div id="referenceDiv" style="height: 40px; width: 40px;
|
||||
display: none; background: #2aff00;">
|
||||
</div>
|
||||
<div id="animatedImage">
|
||||
<img id='animatedGif' src="animated-gif.gif" style="display: none;">
|
||||
</div>
|
||||
<div id="text-descr"></div>
|
||||
<div id="debug" style="display:none">
|
||||
</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
var gAnimTest;
|
||||
var gIntervalId;
|
||||
|
||||
function initSecondTest() {
|
||||
document.getElementById('debug').style.display = 'none';
|
||||
document.getElementById('referenceDiv').style.background = "#9600ff";
|
||||
document.getElementById('animatedGif').setAttribute('src',
|
||||
'animated-gif2.gif');
|
||||
document.getElementById('animatedGif').style.display = 'none';
|
||||
var secondTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
|
||||
'animatedGif', 'debug', '', '', false);
|
||||
secondTest.beginTest();
|
||||
}
|
||||
|
||||
function main()
|
||||
{
|
||||
gAnimTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
|
||||
'animatedGif', 'debug', '', '', false,
|
||||
initSecondTest);
|
||||
gAnimTest.beginTest();
|
||||
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,48 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 691792 - Change of Source (2nd Version)</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=691792">
|
||||
Mozilla Bug 691792: Change of src attribute for animated gifs no longer works as expected
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content">
|
||||
<div id="animatedImage">
|
||||
<img id='animatedGif' src="purple.gif" style="display: none;">
|
||||
</div>
|
||||
<div id="text-descr"></div>
|
||||
<div id="debug" style="display:none">
|
||||
</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
var gAnimTest;
|
||||
var gIntervalId;
|
||||
|
||||
function main()
|
||||
{
|
||||
gAnimTest = new AnimationTest(20, FAILURE_TIMEOUT, 'animated-gif2.gif',
|
||||
'animatedGif', 'debug', '', 'animated-gif2.gif',
|
||||
false);
|
||||
gAnimTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,52 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - Animated Raster Images inside of SVG Frames</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
|
||||
<!-- Make sure embed element is snapped to an exact pixel. -->
|
||||
<div class="bug-header" style="height: 100px;">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<div id="referenceDiv" style="height: 40px; width: 40px;
|
||||
display: none; background: #2aff00"></div>
|
||||
<!--
|
||||
We use <embed> here instead of <img> because the <img> tag utilizes
|
||||
the VectorImage class for SVG, whereas in this test, we are testing
|
||||
RasterImage.
|
||||
-->
|
||||
<embed id="embeddedSVG" src="animation.svg" type="image/svg+xml" style="display: none;"/>
|
||||
</div>
|
||||
<div id="debug" style="display:none"></div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 666446 nsSVGImageFrame/RasterImage**/
|
||||
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
function main() {
|
||||
var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
|
||||
'embeddedSVG', 'debug', '', 'src');
|
||||
animTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,42 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - Animated Images within SVG Filters</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<embed id="referenceImage" src="filter-final.svg" type="image/svg+xml" style="display: none;"/>
|
||||
<embed id="embeddedSVGFilt" src="filter.svg" type="image/svg+xml" style="display: none;"/>
|
||||
</div>
|
||||
<div id="debug" style="display:none"></div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 666446 nsSVGFEImageElement/RasterImage**/
|
||||
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
function main() {
|
||||
var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceImage',
|
||||
'embeddedSVGFilt', 'debug', '', 'src');
|
||||
animTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,48 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - Test for Animated Gif within IFRAME</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content">
|
||||
<div id="referenceDiv" style="display:none;">
|
||||
<iframe id="referenceIFrame" src="ref-iframe.html" width="50%" height="100">
|
||||
Browser does not support iframes.
|
||||
</iframe>
|
||||
</div>
|
||||
<div id="animatedImage">
|
||||
<iframe id="imageIFrame" src="iframe.html" width="50%" height="100" style="display: none;">
|
||||
Browser does not support iframes.
|
||||
</iframe>
|
||||
</div>
|
||||
<div id="debug" style="display: none"></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
const FAILURE_TIMEOUT = 120000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
function main()
|
||||
{
|
||||
var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceDiv',
|
||||
'imageIFrame', 'debug');
|
||||
animTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -1,67 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xml:lang="en" lang="en">
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=666446
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 666446 - Animated Images within SVG Filters</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<script type="application/javascript" src="imgutils.js"></script>
|
||||
<script type="application/javascript" src="animationPolling.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666446">
|
||||
Mozilla Bug 666446: lots of animated gifs swamp us with paint events
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<xul:caption label="Bug 666446 - XULTree Test" />
|
||||
<xul:separator />
|
||||
<br />
|
||||
<xul:window id="main" title="Bug 666446: XUL Tree Testing" width="100" height="100">
|
||||
<xul:tree flex="1">
|
||||
<xul:treecols>
|
||||
<xul:treecol id="icon" label="Icon" flex="1" />
|
||||
</xul:treecols>
|
||||
|
||||
<xul:treechildren>
|
||||
<xul:treeitem id="referenceItem" hidden="true">
|
||||
<xul:treerow>
|
||||
<xul:treecell src="animated-gif-finalframe.gif" width="40" height="40" />
|
||||
</xul:treerow>
|
||||
</xul:treeitem>
|
||||
<xul:treeitem id="imageItem" hidden="true">
|
||||
<xul:treerow>
|
||||
<xul:treecell src="animated-gif.gif" width="40" height="40" />
|
||||
</xul:treerow>
|
||||
</xul:treeitem>
|
||||
</xul:treechildren>
|
||||
</xul:tree>
|
||||
</xul:window>
|
||||
</div>
|
||||
<div id="debug" style="display:none"></div>
|
||||
<pre id="test">
|
||||
<script type="text/javascript;version=1.8">
|
||||
|
||||
/** Test for Bug 666446 nsSVGFEImageElement/RasterImage**/
|
||||
|
||||
const FAILURE_TIMEOUT = 5000; // Fail early after 120 seconds (2 minutes)
|
||||
|
||||
function main() {
|
||||
var animTest = new AnimationTest(20, FAILURE_TIMEOUT, 'referenceItem',
|
||||
'imageItem', 'debug', '',
|
||||
'animated-gif-finalframe.gif', true);
|
||||
animTest.beginTest();
|
||||
}
|
||||
|
||||
window.onload = main;
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -57,7 +57,6 @@
|
|||
|
||||
#include "nsStyleContext.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
|
||||
// Paint forcing
|
||||
#include "prenv.h"
|
||||
|
@ -68,14 +67,17 @@ nsImageLoader::nsImageLoader(nsIFrame *aFrame, PRUint32 aActions,
|
|||
nsImageLoader *aNextLoader)
|
||||
: mFrame(aFrame),
|
||||
mActions(aActions),
|
||||
mNextLoader(aNextLoader),
|
||||
mRequestRegistered(false)
|
||||
mNextLoader(aNextLoader)
|
||||
{
|
||||
}
|
||||
|
||||
nsImageLoader::~nsImageLoader()
|
||||
{
|
||||
Destroy();
|
||||
mFrame = nsnull;
|
||||
|
||||
if (mRequest) {
|
||||
mRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsImageLoader>
|
||||
|
@ -103,15 +105,12 @@ nsImageLoader::Destroy()
|
|||
todestroy->Destroy();
|
||||
}
|
||||
|
||||
if (mRequest && mFrame) {
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
mFrame = nsnull;
|
||||
|
||||
nsLayoutUtils::DeregisterImageRequest(presContext, mRequest,
|
||||
&mRequestRegistered);
|
||||
if (mRequest) {
|
||||
mRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
mFrame = nsnull;
|
||||
mRequest = nsnull;
|
||||
}
|
||||
|
||||
|
@ -128,31 +127,17 @@ nsImageLoader::Load(imgIRequest *aImage)
|
|||
if (!aImage)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Deregister mRequest from the refresh driver, since it is no longer
|
||||
// going to be managed by this nsImageLoader.
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
|
||||
nsLayoutUtils::DeregisterImageRequest(presContext, mRequest,
|
||||
&mRequestRegistered);
|
||||
|
||||
// Make sure to clone into a temporary, then set mRequest, since
|
||||
// cloning may notify and we don't want to trigger paints from this
|
||||
// code.
|
||||
nsCOMPtr<imgIRequest> newRequest;
|
||||
nsresult rv = aImage->Clone(this, getter_AddRefs(newRequest));
|
||||
mRequest.swap(newRequest);
|
||||
|
||||
// Re-register mRequest with the refresh driver, but immediately deregister
|
||||
// if it isn't animated.
|
||||
nsLayoutUtils::RegisterImageRequest(presContext, mRequest,
|
||||
&mRequestRegistered);
|
||||
|
||||
nsLayoutUtils::DeregisterImageRequestIfNotAnimated(presContext, mRequest,
|
||||
&mRequestRegistered);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP nsImageLoader::OnStartContainer(imgIRequest *aRequest,
|
||||
imgIContainer *aImage)
|
||||
{
|
||||
|
@ -284,35 +269,3 @@ nsImageLoader::DoRedraw(const nsRect* aDamageRect)
|
|||
mFrame->Invalidate(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageLoader::OnStartDecode(imgIRequest *aRequest)
|
||||
{
|
||||
// Register our image request with the refresh driver.
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
if (!presContext) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mRequest == aRequest) {
|
||||
nsLayoutUtils::RegisterImageRequest(presContext, mRequest,
|
||||
&mRequestRegistered);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageLoader::OnStopDecode(imgIRequest *aRequest, nsresult status,
|
||||
const PRUnichar *statusArg)
|
||||
{
|
||||
if (mRequest == aRequest) {
|
||||
// Deregister the imgIRequest with the refresh driver if the
|
||||
// image is not animated.
|
||||
nsLayoutUtils::DeregisterImageRequestIfNotAnimated(mFrame->PresContext(),
|
||||
mRequest,
|
||||
&mRequestRegistered);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -82,10 +82,6 @@ public:
|
|||
|
||||
// imgIDecoderObserver (override nsStubImageDecoderObserver)
|
||||
NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
|
||||
NS_IMETHOD OnStartDecode(imgIRequest *aRequest);
|
||||
NS_IMETHOD OnStopDecode(imgIRequest *aRequest,
|
||||
nsresult status,
|
||||
const PRUnichar *statusArg);
|
||||
NS_IMETHOD OnStopFrame(imgIRequest *aRequest, PRUint32 aFrame);
|
||||
NS_IMETHOD OnStopRequest(imgIRequest *aRequest, bool aLastPart);
|
||||
// Do not override OnDataAvailable since background images are not
|
||||
|
@ -113,8 +109,4 @@ private:
|
|||
nsCOMPtr<imgIRequest> mRequest;
|
||||
PRUint32 mActions;
|
||||
nsRefPtr<nsImageLoader> mNextLoader;
|
||||
|
||||
// This is a boolean flag indicating whether or not the current image request
|
||||
// has been registered with the refresh driver.
|
||||
bool mRequestRegistered;
|
||||
};
|
||||
|
|
|
@ -4327,102 +4327,6 @@ nsLayoutUtils::Shutdown()
|
|||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsLayoutUtils::RegisterImageRequest(nsPresContext* aPresContext,
|
||||
imgIRequest* aRequest,
|
||||
bool* aRequestRegistered)
|
||||
{
|
||||
if (!aPresContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRequestRegistered && *aRequestRegistered) {
|
||||
// Our request is already registered with the refresh driver, so
|
||||
// no need to register it again.
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRequest) {
|
||||
nsCOMPtr<imgIContainer> image;
|
||||
aRequest->GetImage(getter_AddRefs(image));
|
||||
if (image) {
|
||||
if (!aPresContext->RefreshDriver()->AddImageRequest(aRequest)) {
|
||||
NS_WARNING("Unable to add image request");
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRequestRegistered) {
|
||||
*aRequestRegistered = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsLayoutUtils::DeregisterImageRequest(nsPresContext* aPresContext,
|
||||
imgIRequest* aRequest,
|
||||
bool* aRequestRegistered)
|
||||
{
|
||||
if (!aPresContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Deregister our imgIRequest with the refresh driver to
|
||||
// complete tear-down, but only if it has been registered
|
||||
if (aRequestRegistered && !*aRequestRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRequest) {
|
||||
nsCOMPtr<imgIContainer> image;
|
||||
aRequest->GetImage(getter_AddRefs(image));
|
||||
if (image) {
|
||||
aPresContext->RefreshDriver()->RemoveImageRequest(aRequest);
|
||||
|
||||
if (aRequestRegistered) {
|
||||
*aRequestRegistered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsLayoutUtils::DeregisterImageRequestIfNotAnimated(nsPresContext* aPresContext,
|
||||
imgIRequest* aRequest,
|
||||
bool* aRequestRegistered)
|
||||
{
|
||||
if (!aPresContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRequestRegistered && !*aRequestRegistered) {
|
||||
// Image request isn't registered with the refresh driver - no need
|
||||
// to try and deregister it.
|
||||
return;
|
||||
}
|
||||
|
||||
// Deregister the imgIRequest with the refresh driver if the
|
||||
// image is not animated
|
||||
nsCOMPtr<imgIContainer> imageContainer;
|
||||
if (aRequest) {
|
||||
aRequest->GetImage(getter_AddRefs(imageContainer));
|
||||
bool animated;
|
||||
|
||||
if (!imageContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = imageContainer->GetAnimated(&animated);
|
||||
if (NS_SUCCEEDED(rv) && !animated) {
|
||||
nsLayoutUtils::DeregisterImageRequest(aPresContext, aRequest,
|
||||
aRequestRegistered);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsSetAttrRunnable::nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName,
|
||||
const nsAString& aValue)
|
||||
: mContent(aContent),
|
||||
|
|
|
@ -1454,63 +1454,6 @@ public:
|
|||
|
||||
static void Shutdown();
|
||||
|
||||
/**
|
||||
* Register an imgIRequest object with a refresh driver.
|
||||
*
|
||||
* @param aPresContext The nsPresContext whose refresh driver we want to
|
||||
* register with.
|
||||
* @param aRequest A pointer to the imgIRequest object which the client wants
|
||||
* to register with the refresh driver.
|
||||
* @param aRequestRegistered A pointer to a boolean value which indicates
|
||||
* whether the given image request is registered. If
|
||||
* *aRequestRegistered is true, then this request will not be
|
||||
* registered again. If the request is registered by this function,
|
||||
* then *aRequestRegistered will be set to true upon the completion of
|
||||
* this function.
|
||||
*
|
||||
*/
|
||||
static void RegisterImageRequest(nsPresContext* aPresContext,
|
||||
imgIRequest* aRequest,
|
||||
bool* aRequestRegistered);
|
||||
/**
|
||||
* Deregister an imgIRequest object from a refresh driver.
|
||||
*
|
||||
* @param aPresContext The nsPresContext whose refresh driver we want to
|
||||
* deregister from.
|
||||
* @param aRequest A pointer to the imgIRequest object with which the client
|
||||
* previously registered and now wants to deregister from the refresh
|
||||
* driver.
|
||||
* @param aRequestRegistered A pointer to a boolean value which indicates
|
||||
* whether the given image request is registered. If
|
||||
* *aRequestRegistered is false, then this request will not be
|
||||
* deregistered. If the request is deregistered by this function,
|
||||
* then *aRequestRegistered will be set to false upon the completion of
|
||||
* this function.
|
||||
*/
|
||||
static void DeregisterImageRequest(nsPresContext* aPresContext,
|
||||
imgIRequest* aRequest,
|
||||
bool* aRequestRegistered);
|
||||
/**
|
||||
* Deregister an imgIRequest object from a refresh driver, if the
|
||||
* imgIRequest object represents a static (i.e. not animated) image.
|
||||
*
|
||||
* @param aPresContext The nsPresContext whose refresh driver we want to
|
||||
* deregister from.
|
||||
* @param aRequest A pointer to the imgIRequest object with which the client
|
||||
* previously registered and now wants to deregister from the refresh
|
||||
* driver.
|
||||
* @param aRequestRegistered A pointer to a boolean value which indicates
|
||||
* whether the given image request is registered. If
|
||||
* *aRequestRegistered is false, then this request will not be
|
||||
* deregistered. If the request is deregistered by this function,
|
||||
* then *aRequestRegistered will be set to false upon the completion of
|
||||
* this function.
|
||||
*/
|
||||
|
||||
static void DeregisterImageRequestIfNotAnimated(nsPresContext* aPresContext,
|
||||
imgIRequest* aRequest,
|
||||
bool* aRequestRegistered);
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* Assert that there are no duplicate continuations of the same frame
|
||||
|
|
|
@ -114,7 +114,6 @@ nsRefreshDriver::nsRefreshDriver(nsPresContext *aPresContext)
|
|||
mTimerIsPrecise(false),
|
||||
mLastTimerInterval(0)
|
||||
{
|
||||
mRequests.Init();
|
||||
}
|
||||
|
||||
nsRefreshDriver::~nsRefreshDriver()
|
||||
|
@ -186,29 +185,6 @@ nsRefreshDriver::RemoveRefreshObserver(nsARefreshObserver *aObserver,
|
|||
return array.RemoveElement(aObserver);
|
||||
}
|
||||
|
||||
bool
|
||||
nsRefreshDriver::AddImageRequest(imgIRequest* aRequest)
|
||||
{
|
||||
if (!mRequests.PutEntry(aRequest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureTimerStarted(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsRefreshDriver::RemoveImageRequest(imgIRequest* aRequest)
|
||||
{
|
||||
mRequests.RemoveEntry(aRequest);
|
||||
}
|
||||
|
||||
void nsRefreshDriver::ClearAllImageRequests()
|
||||
{
|
||||
mRequests.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
nsRefreshDriver::EnsureTimerStarted(bool aAdjustingTimer)
|
||||
{
|
||||
|
@ -262,7 +238,6 @@ nsRefreshDriver::ObserverCount() const
|
|||
for (PRUint32 i = 0; i < ArrayLength(mObservers); ++i) {
|
||||
sum += mObservers[i].Length();
|
||||
}
|
||||
|
||||
// Even while throttled, we need to process layout and style changes. Style
|
||||
// changes can trigger transitions which fire events when they complete, and
|
||||
// layout changes can affect media queries on child documents, triggering
|
||||
|
@ -274,12 +249,6 @@ nsRefreshDriver::ObserverCount() const
|
|||
return sum;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
nsRefreshDriver::ImageRequestCount() const
|
||||
{
|
||||
return mRequests.Count();
|
||||
}
|
||||
|
||||
void
|
||||
nsRefreshDriver::UpdateMostRecentRefresh()
|
||||
{
|
||||
|
@ -334,7 +303,7 @@ nsRefreshDriver::Notify(nsITimer *aTimer)
|
|||
UpdateMostRecentRefresh();
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
|
||||
if (!presShell || (ObserverCount() == 0 && ImageRequestCount() == 0)) {
|
||||
if (!presShell || ObserverCount() == 0) {
|
||||
// Things are being destroyed, or we no longer have any observers.
|
||||
// We don't want to stop the timer when observers are initially
|
||||
// removed, because sometimes observers can be added and removed
|
||||
|
@ -363,7 +332,6 @@ nsRefreshDriver::Notify(nsITimer *aTimer)
|
|||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
// Don't just loop while we have things in mBeforePaintTargets,
|
||||
// the whole point is that event handlers should readd the
|
||||
|
@ -436,17 +404,6 @@ nsRefreshDriver::Notify(nsITimer *aTimer)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform notification to imgIRequests subscribed to listen
|
||||
* for refresh events.
|
||||
*/
|
||||
|
||||
ImageRequestParameters parms = {mMostRecentRefresh};
|
||||
if (mRequests.Count()) {
|
||||
mRequests.EnumerateEntries(nsRefreshDriver::ImageRequestEnumerator, &parms);
|
||||
EnsureTimerStarted(false);
|
||||
}
|
||||
|
||||
if (mThrottled ||
|
||||
(mTimerIsPrecise !=
|
||||
(GetRefreshTimerType() == nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP))) {
|
||||
|
@ -467,24 +424,6 @@ nsRefreshDriver::Notify(nsITimer *aTimer)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsRefreshDriver::ImageRequestEnumerator(nsISupportsHashKey* aEntry,
|
||||
void* aUserArg)
|
||||
{
|
||||
ImageRequestParameters* parms =
|
||||
static_cast<ImageRequestParameters*> (aUserArg);
|
||||
mozilla::TimeStamp mostRecentRefresh = parms->ts;
|
||||
imgIRequest* req = static_cast<imgIRequest*>(aEntry->GetKey());
|
||||
NS_ABORT_IF_FALSE(req, "Unable to retrieve the image request");
|
||||
nsCOMPtr<imgIContainer> image;
|
||||
req->GetImage(getter_AddRefs(image));
|
||||
if (image) {
|
||||
image->RequestRefresh(mostRecentRefresh);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsRefreshDriver::Freeze()
|
||||
{
|
||||
|
@ -498,7 +437,7 @@ nsRefreshDriver::Thaw()
|
|||
{
|
||||
NS_ASSERTION(mFrozen, "Thaw called on an unfrozen refresh driver");
|
||||
mFrozen = false;
|
||||
if (ObserverCount() || ImageRequestCount()) {
|
||||
if (ObserverCount()) {
|
||||
// FIXME: This isn't quite right, since our EnsureTimerStarted call
|
||||
// updates our mMostRecentRefresh, but the DoRefresh call won't run
|
||||
// and notify our observers until we get back to the event loop.
|
||||
|
|
|
@ -50,13 +50,10 @@
|
|||
#include "nsTObserverArray.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
class nsPresContext;
|
||||
class nsIPresShell;
|
||||
class nsIDocument;
|
||||
class imgIRequest;
|
||||
|
||||
/**
|
||||
* An abstract base class to be implemented by callers wanting to be
|
||||
|
@ -131,24 +128,6 @@ public:
|
|||
bool RemoveRefreshObserver(nsARefreshObserver *aObserver,
|
||||
mozFlushType aFlushType);
|
||||
|
||||
/**
|
||||
* Add/Remove imgIRequest versions of observers.
|
||||
*
|
||||
* These are used for hooking into the refresh driver for
|
||||
* controlling animated images.
|
||||
*
|
||||
* @note The refresh driver owns a reference to these listeners.
|
||||
*
|
||||
* @note Technically, imgIRequest objects are not nsARefreshObservers, but
|
||||
* for controlling animated image repaint events, we subscribe the
|
||||
* imgIRequests to the nsRefreshDriver for notification of paint events.
|
||||
*
|
||||
* @returns whether the operation succeeded, or void in the case of removal.
|
||||
*/
|
||||
bool AddImageRequest(imgIRequest* aRequest);
|
||||
void RemoveImageRequest(imgIRequest* aRequest);
|
||||
void ClearAllImageRequests();
|
||||
|
||||
/**
|
||||
* Add / remove presshells that we should flush style and layout on
|
||||
*/
|
||||
|
@ -239,15 +218,10 @@ public:
|
|||
|
||||
private:
|
||||
typedef nsTObserverArray<nsARefreshObserver*> ObserverArray;
|
||||
typedef nsTHashtable<nsISupportsHashKey> RequestTable;
|
||||
|
||||
void EnsureTimerStarted(bool aAdjustingTimer);
|
||||
void StopTimer();
|
||||
|
||||
PRUint32 ObserverCount() const;
|
||||
PRUint32 ImageRequestCount() const;
|
||||
static PLDHashOperator ImageRequestEnumerator(nsISupportsHashKey* aEntry,
|
||||
void* aUserArg);
|
||||
void UpdateMostRecentRefresh();
|
||||
ObserverArray& ArrayFor(mozFlushType aFlushType);
|
||||
// Trigger a refresh immediately, if haven't been disconnected or frozen.
|
||||
|
@ -278,8 +252,6 @@ private:
|
|||
|
||||
// separate arrays for each flush type we support
|
||||
ObserverArray mObservers[3];
|
||||
RequestTable mRequests;
|
||||
|
||||
nsAutoTArray<nsIPresShell*, 16> mStyleFlushObservers;
|
||||
nsAutoTArray<nsIPresShell*, 16> mLayoutFlushObservers;
|
||||
// nsTArray on purpose, because we want to be able to swap.
|
||||
|
@ -290,11 +262,6 @@ private:
|
|||
// This is the last interval we used for our timer. May be 0 if we
|
||||
// haven't computed a timer interval yet.
|
||||
mutable PRInt32 mLastTimerInterval;
|
||||
|
||||
// Helper struct for processing image requests
|
||||
struct ImageRequestParameters {
|
||||
mozilla::TimeStamp ts;
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* !defined(nsRefreshDriver_h_) */
|
||||
|
|
|
@ -78,7 +78,6 @@ public:
|
|||
NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
|
||||
NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, bool aCurrentFrame,
|
||||
const nsIntRect *aRect);
|
||||
NS_IMETHOD OnStartDecode(imgIRequest *aRequest);
|
||||
NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult status,
|
||||
const PRUnichar *statusArg);
|
||||
// imgIContainerObserver (override nsStubImageDecoderObserver)
|
||||
|
@ -102,10 +101,6 @@ nsBulletFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
{
|
||||
// Stop image loading first
|
||||
if (mImageRequest) {
|
||||
// Deregister our image request from the refresh driver
|
||||
nsLayoutUtils::DeregisterImageRequest(PresContext(),
|
||||
mImageRequest,
|
||||
&mRequestRegistered);
|
||||
mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||
mImageRequest = nsnull;
|
||||
}
|
||||
|
@ -175,8 +170,6 @@ nsBulletFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
|||
if (same) {
|
||||
needNewRequest = false;
|
||||
} else {
|
||||
nsLayoutUtils::DeregisterImageRequest(PresContext(), mImageRequest,
|
||||
&mRequestRegistered);
|
||||
mImageRequest->Cancel(NS_ERROR_FAILURE);
|
||||
mImageRequest = nsnull;
|
||||
}
|
||||
|
@ -185,15 +178,10 @@ nsBulletFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
|||
|
||||
if (needNewRequest) {
|
||||
newRequest->Clone(mListener, getter_AddRefs(mImageRequest));
|
||||
nsLayoutUtils::RegisterImageRequest(PresContext(), mImageRequest,
|
||||
&mRequestRegistered);
|
||||
}
|
||||
} else {
|
||||
// No image request on the new style context
|
||||
if (mImageRequest) {
|
||||
nsLayoutUtils::DeregisterImageRequest(PresContext(), mImageRequest,
|
||||
&mRequestRegistered);
|
||||
|
||||
mImageRequest->Cancel(NS_ERROR_FAILURE);
|
||||
mImageRequest = nsnull;
|
||||
}
|
||||
|
@ -1533,17 +1521,6 @@ NS_IMETHODIMP nsBulletFrame::OnDataAvailable(imgIRequest *aRequest,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsBulletFrame::OnStartDecode(imgIRequest* aRequest)
|
||||
{
|
||||
// Register the image request with the refresh driver.
|
||||
if (aRequest == mImageRequest) {
|
||||
nsLayoutUtils::RegisterImageRequest(PresContext(), mImageRequest,
|
||||
&mRequestRegistered);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsBulletFrame::OnStopDecode(imgIRequest *aRequest,
|
||||
nsresult aStatus,
|
||||
const PRUnichar *aStatusArg)
|
||||
|
@ -1560,14 +1537,6 @@ NS_IMETHODIMP nsBulletFrame::OnStopDecode(imgIRequest *aRequest,
|
|||
}
|
||||
#endif
|
||||
|
||||
// Deregister the imgIRequest with the refresh driver if the
|
||||
// image is not animated.
|
||||
if (aRequest == mImageRequest) {
|
||||
nsLayoutUtils::DeregisterImageRequestIfNotAnimated(PresContext(),
|
||||
mImageRequest,
|
||||
&mRequestRegistered);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1665,25 +1634,17 @@ NS_IMETHODIMP nsBulletListener::OnDataAvailable(imgIRequest *aRequest,
|
|||
const nsIntRect *aRect)
|
||||
{
|
||||
if (!mFrame)
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return mFrame->OnDataAvailable(aRequest, aCurrentFrame, aRect);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsBulletListener::OnStartDecode(imgIRequest *aRequest)
|
||||
{
|
||||
if (!mFrame)
|
||||
return NS_OK;
|
||||
|
||||
return mFrame->OnStartDecode(aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsBulletListener::OnStopDecode(imgIRequest *aRequest,
|
||||
nsresult status,
|
||||
const PRUnichar *statusArg)
|
||||
{
|
||||
if (!mFrame)
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return mFrame->OnStopDecode(aRequest, status, statusArg);
|
||||
}
|
||||
|
@ -1692,7 +1653,7 @@ NS_IMETHODIMP nsBulletListener::FrameChanged(imgIContainer *aContainer,
|
|||
const nsIntRect *aDirtyRect)
|
||||
{
|
||||
if (!mFrame)
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return mFrame->FrameChanged(aContainer, aDirtyRect);
|
||||
}
|
||||
|
|
|
@ -84,7 +84,6 @@ public:
|
|||
NS_IMETHOD OnDataAvailable(imgIRequest *aRequest,
|
||||
bool aCurrentFrame,
|
||||
const nsIntRect *aRect);
|
||||
NS_IMETHOD OnStartDecode(imgIRequest *aRequest);
|
||||
NS_IMETHOD OnStopDecode(imgIRequest *aRequest,
|
||||
nsresult aStatus,
|
||||
const PRUnichar *aStatusArg);
|
||||
|
@ -122,12 +121,6 @@ protected:
|
|||
nsSize mComputedSize;
|
||||
PRInt32 mOrdinal;
|
||||
bool mTextIsRTL;
|
||||
|
||||
private:
|
||||
|
||||
// This is a boolean flag indicating whether or not the current image request
|
||||
// has been registered with the refresh driver.
|
||||
bool mRequestRegistered;
|
||||
};
|
||||
|
||||
#endif /* nsBulletFrame_h___ */
|
||||
|
|
|
@ -579,10 +579,6 @@ protected:
|
|||
/**
|
||||
* Implements Destroy(). Do not call this directly except from within a
|
||||
* DestroyFrom() implementation.
|
||||
*
|
||||
* @note This will always be called, so it is not necessary to override
|
||||
* Destroy() in subclasses of nsFrame, just DestroyFrom().
|
||||
*
|
||||
* @param aDestructRoot is the root of the subtree being destroyed
|
||||
*/
|
||||
virtual void DestroyFrom(nsIFrame* aDestructRoot) = 0;
|
||||
|
|
|
@ -231,10 +231,6 @@ nsImageFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
nsCxPusher pusher;
|
||||
pusher.PushNull();
|
||||
|
||||
// Notify our image loading content that we are going away so it can
|
||||
// deregister with our refresh driver.
|
||||
imageLoader->FrameDestroyed(this);
|
||||
|
||||
imageLoader->RemoveObserver(mListener);
|
||||
}
|
||||
|
||||
|
@ -280,10 +276,6 @@ nsImageFrame::Init(nsIContent* aContent,
|
|||
if (!gIconLoad)
|
||||
LoadIcons(aPresContext);
|
||||
|
||||
// We have a PresContext now, so we need to notify the image content node
|
||||
// that it can register images.
|
||||
imageLoader->FrameCreated(this);
|
||||
|
||||
// Give image loads associated with an image frame a small priority boost!
|
||||
nsCOMPtr<imgIRequest> currentRequest;
|
||||
imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
||||
|
|
|
@ -103,7 +103,6 @@ public:
|
|||
NS_IMETHOD Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIFrame* aPrevInFlow);
|
||||
virtual void DestroyFrom(nsIFrame* aDestructRoot);
|
||||
|
||||
/**
|
||||
* Get the "type" of the frame
|
||||
|
@ -180,10 +179,6 @@ nsSVGImageFrame::Init(nsIContent* aContent,
|
|||
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
|
||||
NS_ENSURE_TRUE(imageLoader, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// We should have a PresContext now, so let's notify our image loader that
|
||||
// we need to register any image animations with the refresh driver.
|
||||
imageLoader->FrameCreated(this);
|
||||
|
||||
// Push a null JSContext on the stack so that code that runs within
|
||||
// the below code doesn't think it's being called by JS. See bug
|
||||
// 604262.
|
||||
|
@ -195,19 +190,6 @@ nsSVGImageFrame::Init(nsIContent* aContent,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsSVGImageFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
||||
{
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader =
|
||||
do_QueryInterface(nsFrame::mContent);
|
||||
|
||||
if (imageLoader) {
|
||||
imageLoader->FrameDestroyed(this);
|
||||
}
|
||||
|
||||
nsFrame::DestroyFrom(aDestructRoot);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsIFrame methods:
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
#include "nsFrame.h"
|
||||
#include "nsSVGEffects.h"
|
||||
#include "nsImageLoadingContent.h"
|
||||
|
||||
class nsSVGLeafFrame : public nsFrame
|
||||
{
|
||||
|
@ -48,12 +47,6 @@ protected:
|
|||
public:
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
|
||||
NS_IMETHOD Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIFrame* asPrevInFlow);
|
||||
|
||||
virtual void DestroyFrom(nsIFrame* aDestructRoot);
|
||||
|
||||
virtual bool IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eSVG));
|
||||
|
@ -77,33 +70,6 @@ NS_NewSVGLeafFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
|||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsSVGLeafFrame)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGLeafFrame::Init(nsIContent* aContent, nsIFrame* aParent, nsIFrame* asPrevInFlow)
|
||||
{
|
||||
nsFrame::Init(aContent, aParent, asPrevInFlow);
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader =
|
||||
do_QueryInterface(nsFrame::mContent);
|
||||
|
||||
if (imageLoader) {
|
||||
imageLoader->FrameCreated(this);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsSVGLeafFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
||||
{
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader =
|
||||
do_QueryInterface(nsFrame::mContent);
|
||||
|
||||
if (imageLoader) {
|
||||
imageLoader->FrameDestroyed(this);
|
||||
}
|
||||
|
||||
nsFrame::DestroyFrom(aDestructRoot);
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsSVGLeafFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
||||
{
|
||||
|
|
|
@ -72,7 +72,6 @@
|
|||
#include "nsIDOMDocument.h"
|
||||
#include "nsTransform2D.h"
|
||||
#include "nsITheme.h"
|
||||
#include "nsIImageLoadingContent.h"
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIURI.h"
|
||||
|
@ -174,7 +173,6 @@ nsImageBoxFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
|||
nsImageBoxFrame::nsImageBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext):
|
||||
nsLeafBoxFrame(aShell, aContext),
|
||||
mIntrinsicSize(0,0),
|
||||
mRequestRegistered(false),
|
||||
mLoadFlags(nsIRequest::LOAD_NORMAL),
|
||||
mUseSrcAttr(false),
|
||||
mSuppressStyleCheck(false)
|
||||
|
@ -197,16 +195,9 @@ nsImageBoxFrame::MarkIntrinsicWidthsDirty()
|
|||
void
|
||||
nsImageBoxFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
||||
{
|
||||
if (mImageRequest) {
|
||||
nsPresContext* presContext = PresContext();
|
||||
NS_ASSERTION(presContext, "No PresContext");
|
||||
nsLayoutUtils::DeregisterImageRequest(presContext,
|
||||
mImageRequest,
|
||||
&mRequestRegistered);
|
||||
|
||||
// Release image loader first so that it's refcnt can go to zero
|
||||
if (mImageRequest)
|
||||
mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
if (mListener)
|
||||
reinterpret_cast<nsImageBoxListener*>(mListener.get())->SetFrame(nsnull); // set the frame to null so we don't send messages to a dead object.
|
||||
|
@ -241,12 +232,7 @@ nsImageBoxFrame::Init(nsIContent* aContent,
|
|||
void
|
||||
nsImageBoxFrame::UpdateImage()
|
||||
{
|
||||
nsPresContext* presContext = PresContext();
|
||||
NS_ASSERTION(presContext, "No PresContext");
|
||||
|
||||
if (mImageRequest) {
|
||||
nsLayoutUtils::DeregisterImageRequest(presContext, mImageRequest,
|
||||
&mRequestRegistered);
|
||||
mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||
mImageRequest = nsnull;
|
||||
}
|
||||
|
@ -273,12 +259,6 @@ nsImageBoxFrame::UpdateImage()
|
|||
nsContentUtils::LoadImage(uri, doc, mContent->NodePrincipal(),
|
||||
doc->GetDocumentURI(), mListener, mLoadFlags,
|
||||
getter_AddRefs(mImageRequest));
|
||||
|
||||
// Register our imgIRequest with the refresh driver
|
||||
nsLayoutUtils::RegisterImageRequest(presContext,
|
||||
mImageRequest,
|
||||
&mRequestRegistered);
|
||||
|
||||
}
|
||||
} else {
|
||||
// Only get the list-style-image if we aren't being drawn
|
||||
|
@ -603,31 +583,10 @@ NS_IMETHODIMP nsImageBoxFrame::OnStopContainer(imgIRequest *request,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageBoxFrame::OnStartDecode(imgIRequest* aRequest)
|
||||
{
|
||||
nsPresContext* presContext = PresContext();
|
||||
NS_ASSERTION(presContext, "No PresContext");
|
||||
|
||||
nsLayoutUtils::RegisterImageRequest(presContext,
|
||||
mImageRequest,
|
||||
&mRequestRegistered);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageBoxFrame::OnStopDecode(imgIRequest *request,
|
||||
nsresult aStatus,
|
||||
const PRUnichar *statusArg)
|
||||
{
|
||||
// If the imgIRequest does not represent an animated image, then we should
|
||||
// deregister it from our refresh driver.
|
||||
nsPresContext* presContext = PresContext();
|
||||
NS_ASSERTION(presContext, "No PresContext");
|
||||
|
||||
nsLayoutUtils::DeregisterImageRequestIfNotAnimated(presContext,
|
||||
mImageRequest,
|
||||
&mRequestRegistered);
|
||||
|
||||
if (NS_SUCCEEDED(aStatus))
|
||||
// Fire an onload DOM event.
|
||||
FireImageDOMEvent(mContent, NS_LOAD);
|
||||
|
@ -665,7 +624,7 @@ NS_IMETHODIMP nsImageBoxListener::OnStartContainer(imgIRequest *request,
|
|||
imgIContainer *image)
|
||||
{
|
||||
if (!mFrame)
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return mFrame->OnStartContainer(request, image);
|
||||
}
|
||||
|
@ -674,26 +633,17 @@ NS_IMETHODIMP nsImageBoxListener::OnStopContainer(imgIRequest *request,
|
|||
imgIContainer *image)
|
||||
{
|
||||
if (!mFrame)
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return mFrame->OnStopContainer(request, image);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageBoxListener::OnStartDecode(imgIRequest *aRequest)
|
||||
{
|
||||
if (!mFrame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return mFrame->OnStartDecode(aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageBoxListener::OnStopDecode(imgIRequest *request,
|
||||
nsresult status,
|
||||
const PRUnichar *statusArg)
|
||||
{
|
||||
if (!mFrame)
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return mFrame->OnStopDecode(request, status, statusArg);
|
||||
}
|
||||
|
|
|
@ -56,7 +56,6 @@ public:
|
|||
// imgIDecoderObserver (override nsStubImageDecoderObserver)
|
||||
NS_IMETHOD OnStartContainer(imgIRequest *request, imgIContainer *image);
|
||||
NS_IMETHOD OnStopContainer(imgIRequest *request, imgIContainer *image);
|
||||
NS_IMETHOD OnStartDecode(imgIRequest *aRequest);
|
||||
NS_IMETHOD OnStopDecode(imgIRequest *request, nsresult status,
|
||||
const PRUnichar *statusArg);
|
||||
// imgIContainerObserver (override nsStubImageDecoderObserver)
|
||||
|
@ -120,7 +119,6 @@ public:
|
|||
|
||||
NS_IMETHOD OnStartContainer(imgIRequest *request, imgIContainer *image);
|
||||
NS_IMETHOD OnStopContainer(imgIRequest *request, imgIContainer *image);
|
||||
NS_IMETHOD OnStartDecode(imgIRequest *aRequest);
|
||||
NS_IMETHOD OnStopDecode(imgIRequest *request,
|
||||
nsresult status,
|
||||
const PRUnichar *statusArg);
|
||||
|
@ -144,10 +142,6 @@ private:
|
|||
nsSize mIntrinsicSize;
|
||||
nsSize mImageSize;
|
||||
|
||||
// Boolean variable to determine if the current image request has been
|
||||
// registered with the refresh driver.
|
||||
bool mRequestRegistered;
|
||||
|
||||
nsCOMPtr<imgIRequest> mImageRequest;
|
||||
nsCOMPtr<imgIDecoderObserver> mListener;
|
||||
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dave Hyatt <hyatt@mozilla.org> (Original Author)
|
||||
* Jan Varga <varga@ku.sk>
|
||||
* Scott Johnson <sjohnson@mozilla.com>, Mozilla Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsITreeImageListener_h__
|
||||
#define nsITreeImageListener_h__
|
||||
|
||||
// The interface for our image listener.
|
||||
// {90586540-2D50-403e-8DCE-981CAA778444}
|
||||
#define NS_ITREEIMAGELISTENER_IID \
|
||||
{ 0x90586540, 0x2d50, 0x403e, { 0x8d, 0xce, 0x98, 0x1c, 0xaa, 0x77, 0x84, 0x44 } }
|
||||
|
||||
class nsITreeImageListener : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITREEIMAGELISTENER_IID)
|
||||
|
||||
NS_IMETHOD AddCell(PRInt32 aIndex, nsITreeColumn* aCol) = 0;
|
||||
|
||||
/**
|
||||
* Clear the internal frame pointer to prevent dereferencing an object
|
||||
* that no longer exists.
|
||||
*/
|
||||
NS_IMETHOD ClearFrame() = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsITreeImageListener, NS_ITREEIMAGELISTENER_IID)
|
||||
|
||||
#endif
|
|
@ -54,7 +54,6 @@
|
|||
|
||||
#include "nsTreeBodyFrame.h"
|
||||
#include "nsTreeSelection.h"
|
||||
#include "nsTreeImageListener.h"
|
||||
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsCSSAnonBoxes.h"
|
||||
|
@ -115,14 +114,6 @@ static PLDHashOperator
|
|||
CancelImageRequest(const nsAString& aKey,
|
||||
nsTreeImageCacheEntry aEntry, void* aData)
|
||||
{
|
||||
|
||||
// If our imgIRequest object was registered with the refresh driver,
|
||||
// then we need to deregister it.
|
||||
nsTreeBodyFrame* frame = static_cast<nsTreeBodyFrame*>(aData);
|
||||
|
||||
nsLayoutUtils::DeregisterImageRequest(frame->PresContext(), aEntry.request,
|
||||
nsnull);
|
||||
|
||||
aEntry.request->CancelAndForgetObserver(NS_BINDING_ABORTED);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
@ -173,8 +164,7 @@ nsTreeBodyFrame::nsTreeBodyFrame(nsIPresShell* aPresShell, nsStyleContext* aCont
|
|||
// Destructor
|
||||
nsTreeBodyFrame::~nsTreeBodyFrame()
|
||||
{
|
||||
mImageCache.EnumerateRead(CancelImageRequest, this);
|
||||
DetachImageListeners();
|
||||
mImageCache.EnumerateRead(CancelImageRequest, nsnull);
|
||||
delete mSlots;
|
||||
}
|
||||
|
||||
|
@ -207,11 +197,8 @@ nsTreeBodyFrame::Init(nsIContent* aContent,
|
|||
mIndentation = GetIndentation();
|
||||
mRowHeight = GetRowHeight();
|
||||
|
||||
NS_ENSURE_TRUE(mCreatedListeners.Init(), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
NS_ENSURE_TRUE(mImageCache.Init(16), NS_ERROR_OUT_OF_MEMORY);
|
||||
EnsureBoxObject();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -2167,14 +2154,10 @@ nsTreeBodyFrame::GetImage(PRInt32 aRowIndex, nsTreeColumn* aCol, bool aUseContex
|
|||
if (!*aResult) {
|
||||
// Create a new nsTreeImageListener object and pass it our row and column
|
||||
// information.
|
||||
nsTreeImageListener* listener = new nsTreeImageListener(this);
|
||||
nsTreeImageListener* listener = new nsTreeImageListener(mTreeBoxObject);
|
||||
if (!listener)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
if (!mCreatedListeners.PutEntry(listener)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
listener->AddCell(aRowIndex, aCol);
|
||||
nsCOMPtr<imgIDecoderObserver> imgDecoderObserver = listener;
|
||||
|
||||
|
@ -4253,7 +4236,7 @@ nsresult
|
|||
nsTreeBodyFrame::ClearStyleAndImageCaches()
|
||||
{
|
||||
mStyleCache.Clear();
|
||||
mImageCache.EnumerateRead(CancelImageRequest, this);
|
||||
mImageCache.EnumerateRead(CancelImageRequest, nsnull);
|
||||
mImageCache.Clear();
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -4485,20 +4468,6 @@ nsTreeBodyFrame::PostScrollEvent()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeBodyFrame::DetachImageListeners()
|
||||
{
|
||||
mCreatedListeners.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeBodyFrame::RemoveTreeImageListener(nsTreeImageListener* aListener)
|
||||
{
|
||||
if (aListener) {
|
||||
mCreatedListeners.RemoveEntry(aListener);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
void
|
||||
nsTreeBodyFrame::FireRowCountChangedEvent(PRInt32 aIndex, PRInt32 aCount)
|
||||
|
@ -4672,19 +4641,3 @@ nsTreeBodyFrame::FullScrollbarsUpdate(bool aNeedsFullInvalidation)
|
|||
nsContentUtils::AddScriptRunner(new nsOverflowChecker(this));
|
||||
return weakFrame.IsAlive();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTreeBodyFrame::OnStartDecode(imgIRequest* aRequest)
|
||||
{
|
||||
nsLayoutUtils::RegisterImageRequest(PresContext(), aRequest, nsnull);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTreeBodyFrame::OnStopDecode(imgIRequest* aRequest, nsresult aStatus,
|
||||
const PRUnichar* aStatusArg)
|
||||
{
|
||||
nsLayoutUtils::DeregisterImageRequestIfNotAnimated(PresContext(), aRequest,
|
||||
nsnull);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "nsTArray.h"
|
||||
#include "nsTreeStyleCache.h"
|
||||
#include "nsTreeColumns.h"
|
||||
#include "nsTreeImageListener.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "imgIRequest.h"
|
||||
|
@ -61,10 +62,8 @@
|
|||
#include "nsScrollbarFrame.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
#include "nsITreeImageListener.h"
|
||||
|
||||
class nsOverflowChecker;
|
||||
class nsTreeImageListener;
|
||||
|
||||
// An entry in the tree's image cache
|
||||
struct nsTreeImageCacheEntry
|
||||
|
@ -92,13 +91,6 @@ public:
|
|||
NS_DECL_QUERYFRAME
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
|
||||
// Callback handler methods for refresh driver based animations.
|
||||
// Calls to these functions are forwarded from nsTreeImageListener. These
|
||||
// mirror how nsImageFrame works.
|
||||
nsresult OnStartDecode(imgIRequest* aRequest);
|
||||
nsresult OnStopDecode(imgIRequest* aRequest, nsresult aStatus,
|
||||
const PRUnichar* aStatusArg);
|
||||
|
||||
// non-virtual signatures like nsITreeBodyFrame
|
||||
nsresult GetColumns(nsITreeColumns **aColumns);
|
||||
nsresult GetView(nsITreeView **aView);
|
||||
|
@ -443,15 +435,6 @@ public:
|
|||
return col;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an nsITreeImageListener from being tracked by this frame. Only tree
|
||||
* image listeners that are created by this frame are tracked.
|
||||
*
|
||||
* @param aListener A pointer to an nsTreeImageListener to no longer
|
||||
* track.
|
||||
*/
|
||||
void RemoveTreeImageListener(nsTreeImageListener* aListener);
|
||||
|
||||
protected:
|
||||
|
||||
// Create a new timer. This method is used to delay various actions like
|
||||
|
@ -482,12 +465,6 @@ protected:
|
|||
void PostScrollEvent();
|
||||
void FireScrollEvent();
|
||||
|
||||
/**
|
||||
* Clear the pointer to this frame for all nsTreeImageListeners that were
|
||||
* created by this frame.
|
||||
*/
|
||||
void DetachImageListeners();
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
/**
|
||||
* Fires 'treeRowCountChanged' event asynchronously. The event supports
|
||||
|
@ -625,11 +602,6 @@ protected: // Data Members
|
|||
bool mHorizontalOverflow;
|
||||
|
||||
bool mReflowCallbackPosted;
|
||||
|
||||
// Hash table to keep track of which listeners we created and thus
|
||||
// have pointers to us.
|
||||
nsTHashtable<nsPtrHashKey<nsTreeImageListener> > mCreatedListeners;
|
||||
|
||||
}; // class nsTreeBodyFrame
|
||||
|
||||
#endif
|
||||
|
|
|
@ -44,8 +44,8 @@
|
|||
|
||||
NS_IMPL_ISUPPORTS3(nsTreeImageListener, imgIDecoderObserver, imgIContainerObserver, nsITreeImageListener)
|
||||
|
||||
nsTreeImageListener::nsTreeImageListener(nsTreeBodyFrame* aTreeFrame)
|
||||
: mTreeFrame(aTreeFrame),
|
||||
nsTreeImageListener::nsTreeImageListener(nsITreeBoxObject* aTree)
|
||||
: mTree(aTree),
|
||||
mInvalidationSuppressed(true),
|
||||
mInvalidationArea(nsnull)
|
||||
{
|
||||
|
@ -56,29 +56,6 @@ nsTreeImageListener::~nsTreeImageListener()
|
|||
delete mInvalidationArea;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTreeImageListener::OnStartDecode(imgIRequest *aRequest)
|
||||
{
|
||||
if (!mTreeFrame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// grab the frame we want to use
|
||||
return mTreeFrame->OnStartDecode(aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTreeImageListener::OnStopDecode(imgIRequest *aRequest,
|
||||
nsresult aStatus,
|
||||
const PRUnichar *aStatusArg)
|
||||
{
|
||||
if (!mTreeFrame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return mTreeFrame->OnStopDecode(aRequest, aStatus, aStatusArg);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTreeImageListener::OnStartContainer(imgIRequest *aRequest,
|
||||
imgIContainer *aImage)
|
||||
{
|
||||
|
@ -136,16 +113,10 @@ void
|
|||
nsTreeImageListener::Invalidate()
|
||||
{
|
||||
if (!mInvalidationSuppressed) {
|
||||
for (InvalidationArea* currArea = mInvalidationArea; currArea;
|
||||
currArea = currArea->GetNext()) {
|
||||
for (InvalidationArea* currArea = mInvalidationArea; currArea; currArea = currArea->GetNext()) {
|
||||
// Loop from min to max, invalidating each cell that was listening for this image.
|
||||
for (PRInt32 i = currArea->GetMin(); i <= currArea->GetMax(); ++i) {
|
||||
if (mTreeFrame) {
|
||||
nsITreeBoxObject* tree = mTreeFrame->GetTreeBoxObject();
|
||||
if (tree) {
|
||||
tree->InvalidateCell(i, currArea->GetCol());
|
||||
}
|
||||
}
|
||||
mTree->InvalidateCell(i, currArea->GetCol());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -169,10 +140,3 @@ nsTreeImageListener::InvalidationArea::AddRow(PRInt32 aIndex)
|
|||
else if (aIndex > mMax)
|
||||
mMax = aIndex;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTreeImageListener::ClearFrame()
|
||||
{
|
||||
mTreeFrame = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -44,21 +44,33 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsITreeColumns.h"
|
||||
#include "nsStubImageDecoderObserver.h"
|
||||
#include "nsTreeBodyFrame.h"
|
||||
#include "nsITreeImageListener.h"
|
||||
|
||||
class nsITreeBoxObject;
|
||||
|
||||
// The interface for our image listener.
|
||||
// {90586540-2D50-403e-8DCE-981CAA778444}
|
||||
#define NS_ITREEIMAGELISTENER_IID \
|
||||
{ 0x90586540, 0x2d50, 0x403e, { 0x8d, 0xce, 0x98, 0x1c, 0xaa, 0x77, 0x84, 0x44 } }
|
||||
|
||||
class nsITreeImageListener : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITREEIMAGELISTENER_IID)
|
||||
|
||||
NS_IMETHOD AddCell(PRInt32 aIndex, nsITreeColumn* aCol) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsITreeImageListener, NS_ITREEIMAGELISTENER_IID)
|
||||
|
||||
// This class handles image load observation.
|
||||
class nsTreeImageListener : public nsStubImageDecoderObserver, public nsITreeImageListener
|
||||
{
|
||||
public:
|
||||
nsTreeImageListener(nsTreeBodyFrame *aTreeFrame);
|
||||
nsTreeImageListener(nsITreeBoxObject* aTree);
|
||||
~nsTreeImageListener();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
// imgIDecoderObserver (override nsStubImageDecoderObserver)
|
||||
NS_IMETHOD OnStartDecode(imgIRequest *aRequest);
|
||||
NS_IMETHOD OnStopDecode(imgIRequest *aRequest,
|
||||
nsresult aStatus, const PRUnichar *aStatusArg);
|
||||
NS_IMETHOD OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage);
|
||||
NS_IMETHOD OnDataAvailable(imgIRequest *aRequest, bool aCurrentFrame,
|
||||
const nsIntRect *aRect);
|
||||
|
@ -67,7 +79,6 @@ public:
|
|||
const nsIntRect *aDirtyRect);
|
||||
|
||||
NS_IMETHOD AddCell(PRInt32 aIndex, nsITreeColumn* aCol);
|
||||
NS_IMETHOD ClearFrame();
|
||||
|
||||
friend class nsTreeBodyFrame;
|
||||
|
||||
|
@ -76,7 +87,7 @@ protected:
|
|||
void Invalidate();
|
||||
|
||||
private:
|
||||
nsTreeBodyFrame* mTreeFrame;
|
||||
nsITreeBoxObject* mTree;
|
||||
|
||||
// A guard that prevents us from recursive painting.
|
||||
bool mInvalidationSuppressed;
|
||||
|
|