Bug 666446, Part 1/10 - Add method to imgIContainer for notification of refresh driver events. [r=dholbert,joe][sr=mats]

This commit is contained in:
Scott Johnson 2011-11-09 13:39:15 -08:00
parent 70a91c0353
commit 6bc58fdc72
16 changed files with 133 additions and 12 deletions

View File

@ -372,6 +372,12 @@ nsImageLoadingContent::OnStopRequest(imgIRequest* aRequest, bool aLastPart)
return NS_OK;
}
NS_IMETHODIMP
nsImageLoadingContent::OnImageIsAnimated(imgIRequest *aRequest)
{
return NS_OK;
}
NS_IMETHODIMP
nsImageLoadingContent::OnDiscard(imgIRequest *aRequest)
{

View File

@ -106,6 +106,12 @@ nsStubImageDecoderObserver::OnDiscard(imgIRequest *aRequest)
return NS_OK;
}
NS_IMETHODIMP
nsStubImageDecoderObserver::OnImageIsAnimated(imgIRequest *aRequest)
{
return NS_OK;
}
NS_IMETHODIMP
nsStubImageDecoderObserver::FrameChanged(imgIContainer *aContainer,
const nsIntRect *aDirtyRect)

View File

@ -63,6 +63,11 @@ class ImageContainer;
}
class nsIFrame;
namespace mozilla {
class TimeStamp;
}
%}
[ptr] native gfxImageSurface(gfxImageSurface);
@ -77,6 +82,8 @@ native gfxGraphicsFilter(gfxPattern::GraphicsFilter);
[ptr] native nsIFrame(nsIFrame);
[ptr] native ImageContainer(mozilla::layers::ImageContainer);
[ptr] native LayerManager(mozilla::layers::LayerManager);
[ref] native TimeStamp(mozilla::TimeStamp);
/**
* imgIContainer is the interface that represents an image. It allows
@ -86,7 +93,7 @@ native gfxGraphicsFilter(gfxPattern::GraphicsFilter);
*
* Internally, imgIContainer also manages animation of images.
*/
[scriptable, uuid(239dfa70-2285-4d63-99cd-e9b7ff9555c7)]
[scriptable, uuid(8c82b89f-f90c-4a31-a544-6e1f759673d4)]
interface imgIContainer : nsISupports
{
/**
@ -278,6 +285,13 @@ 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

View File

@ -59,7 +59,7 @@ interface imgIContainer;
* filesystem. Decode notifications are fired as the image is decoded. If an
* image is decoded on load and not visibly discarded, decode notifications are
* nested logically inside load notifications as one might expect. However, with
* decode-on-draw, the set of decode notifications can come completely _after_
* decode-on-draw, the set of decode notifications can imgRcome completely _after_
* the load notifications, and can come multiple times if the image is
* discardable. Moreover, they can be interleaved in various ways. In general,
* any presumed ordering between load and decode notifications should not be
@ -77,7 +77,7 @@ interface imgIContainer;
* @version 0.1
* @see imagelib2
*/
[scriptable, uuid(9f6bfbee-9e04-43a0-b8f6-2159973efec8)]
[scriptable, uuid(2e5fa0c4-57f8-4d16-bda3-1daeba9caa34)]
interface imgIDecoderObserver : imgIContainerObserver
{
/**
@ -134,6 +134,12 @@ interface imgIDecoderObserver : imgIContainerObserver
*/
void onStopContainer(in imgIRequest aRequest, in imgIContainer aContainer);
/**
* Notification for when an image is known to be animated. This should be
* fired at the earliest possible time.
*/
void onImageIsAnimated(in imgIRequest aRequest);
/**
* In theory a decode notification, but currently a load notification.
*

View File

@ -315,6 +315,14 @@ RasterImage::Init(imgIDecoderObserver *aObserver,
return NS_OK;
}
//******************************************************************************
/* [notxpcom] void requestRefresh ([const] in TimeStamp aTime); */
NS_IMETHODIMP_(void)
RasterImage::RequestRefresh(const mozilla::TimeStamp& aTime)
{
// TODO: Implement me as part of b666446
}
//******************************************************************************
/* [noscript] imgIContainer extractFrame(PRUint32 aWhichFrame,
* [const] in nsIntRect aRegion,

View File

@ -188,6 +188,7 @@ 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);

View File

@ -172,7 +172,6 @@ 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");
@ -330,6 +329,14 @@ 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

View File

@ -42,6 +42,7 @@
#include "Image.h"
#include "nsIStreamListener.h"
#include "nsWeakReference.h"
#include "mozilla/TimeStamp.h"
class imgIDecoderObserver;
@ -81,6 +82,7 @@ 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);

View File

@ -796,6 +796,20 @@ NS_IMETHODIMP imgRequest::OnDiscard(imgIRequest *aRequest)
return NS_OK;
}
NS_IMETHODIMP imgRequest::OnImageIsAnimated(imgIRequest *aRequest)
{
NS_ABORT_IF_FALSE(mImage,
"OnImageIsAnimated callback before we've created our image");
mImage->GetStatusTracker().RecordImageIsAnimated();
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
while (iter.HasMore()) {
mImage->GetStatusTracker().SendImageIsAnimated(iter.GetNext());
}
return NS_OK;
}
/** nsIRequestObserver methods **/
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */

View File

@ -709,6 +709,16 @@ void imgRequestProxy::OnDiscard()
}
}
void imgRequestProxy::OnImageIsAnimated()
{
LOG_FUNC(gImgLog, "imgRequestProxy::OnImageIsAnimated");
if (mListener && !mCanceled) {
// Hold a ref to the listener while we call it, just in case.
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener);
mListener->OnImageIsAnimated(this);
}
}
void imgRequestProxy::OnStartRequest()
{
#ifdef PR_LOGGING

View File

@ -168,14 +168,15 @@ protected:
// notifications.
/* non-virtual imgIDecoderObserver methods */
void OnStartDecode ();
void OnStartContainer(imgIContainer *aContainer);
void OnStartFrame (PRUint32 aFrame);
void OnDataAvailable (bool aCurrentFrame, const nsIntRect * aRect);
void OnStopFrame (PRUint32 aFrame);
void OnStopContainer (imgIContainer *aContainer);
void OnStopDecode (nsresult status, const PRUnichar *statusArg);
void OnDiscard ();
void OnStartDecode ();
void OnStartContainer (imgIContainer *aContainer);
void OnStartFrame (PRUint32 aFrame);
void OnDataAvailable (bool aCurrentFrame, const nsIntRect * aRect);
void OnStopFrame (PRUint32 aFrame);
void OnStopContainer (imgIContainer *aContainer);
void OnStopDecode (nsresult status, const PRUnichar *statusArg);
void OnDiscard ();
void OnImageIsAnimated ();
/* non-virtual imgIContainerObserver methods */
void FrameChanged(imgIContainer *aContainer,

View File

@ -254,6 +254,14 @@ imgStatusTracker::SyncNotify(imgRequestProxy* proxy)
if (mState & stateFrameStopped)
proxy->OnStopFrame(frame);
}
// OnImageIsAnimated
bool isAnimated = false;
nsresult rv = mImage->GetAnimated(&isAnimated);
if (NS_SUCCEEDED(rv) && isAnimated) {
proxy->OnImageIsAnimated();
}
}
// See bug 505385 and imgRequest::OnStopDecode for more information on why we
@ -451,6 +459,24 @@ imgStatusTracker::RecordDiscard()
mImageStatus &= ~statusBitsToClear;
}
void
imgStatusTracker::SendImageIsAnimated(imgRequestProxy* aProxy)
{
if (!aProxy->NotificationsDeferred())
aProxy->OnImageIsAnimated();
}
void
imgStatusTracker::RecordImageIsAnimated()
{
NS_ABORT_IF_FALSE(mImage,
"RecordImageIsAnimated called before we have an Image");
// No bookkeeping necessary here - once decoding is complete, GetAnimated()
// will accurately return that this is an animated image. Until that time,
// the OnImageIsAnimated notification is the only indication an observer
// will have that an image has more than 1 frame.
}
void
imgStatusTracker::SendDiscard(imgRequestProxy* aProxy)
{

View File

@ -159,6 +159,8 @@ public:
void SendStopDecode(imgRequestProxy* aProxy, nsresult aStatus, const PRUnichar* statusArg);
void RecordDiscard();
void SendDiscard(imgRequestProxy* aProxy);
void RecordImageIsAnimated();
void SendImageIsAnimated(imgRequestProxy *aProxy);
/* non-virtual imgIContainerObserver methods */
void RecordFrameChanged(imgIContainer* aContainer,

View File

@ -1953,6 +1953,12 @@ nsImageFrame::IconLoad::OnStopDecode(imgIRequest *aRequest,
return NS_OK;
}
NS_IMETHODIMP
nsImageFrame::IconLoad::OnImageIsAnimated(imgIRequest *aRequest)
{
return NS_OK;
}
NS_IMETHODIMP
nsImageFrame::IconLoad::OnStopRequest(imgIRequest *aRequest,
bool aIsLastPart)

View File

@ -175,6 +175,12 @@ nsAlertsIconListener::OnDiscard(imgIRequest *aRequest)
return NS_OK;
}
NS_IMETHODIMP
nsAlertsIconListener::OnImageIsAnimated(imgIRequest *aRequest)
{
return NS_OK;
}
NS_IMETHODIMP
nsAlertsIconListener::OnStopFrame(imgIRequest* aRequest,
PRUint32 aFrame)

View File

@ -559,3 +559,9 @@ nsMenuItemIconX::OnDiscard(imgIRequest* aRequest)
{
return NS_OK;
}
NS_IMETHODIMP
nsMenuItemIconX::OnImageIsAnimated(imgIRequest* aRequest)
{
return NS_OK;
}