Bug 505385 - Part 18: Reduce number of notifications - START_REQUEST/START_CONTAINER -> SIZE_AVAILABLE, remove START_DECODE and START_FRAME. Rename remaining ones for clarity. r=joe

This commit is contained in:
Josh Matthews 2012-10-12 12:11:23 -04:00
parent dd334e9c67
commit e5b76c73ef
25 changed files with 124 additions and 281 deletions

View File

@ -134,7 +134,7 @@ nsImageLoadingContent::Notify(imgIRequest* aRequest,
return OnImageIsAnimated(aRequest);
}
if (aType == imgINotificationObserver::STOP_REQUEST) {
if (aType == imgINotificationObserver::LOAD_COMPLETE) {
// We should definitely have a request here
NS_ABORT_IF_FALSE(aRequest, "no request?");
@ -144,17 +144,15 @@ nsImageLoadingContent::Notify(imgIRequest* aRequest,
NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE);
if (aType != imgINotificationObserver::FRAME_CHANGED) {
LOOP_OVER_OBSERVERS(Notify(aRequest, aType, aData));
}
LOOP_OVER_OBSERVERS(Notify(aRequest, aType, aData));
if (aType == imgINotificationObserver::START_CONTAINER) {
if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
// Have to check for state changes here, since we might have been in
// the LOADING state before.
UpdateImageState(true);
}
if (aType == imgINotificationObserver::STOP_REQUEST) {
if (aType == imgINotificationObserver::LOAD_COMPLETE) {
uint32_t reqStatus;
aRequest->GetImageStatus(&reqStatus);
nsresult status =

View File

@ -508,13 +508,13 @@ ImageDocument::ToggleImageSize()
NS_IMETHODIMP
ImageDocument::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData)
{
if (aType == imgINotificationObserver::START_CONTAINER) {
if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
nsCOMPtr<imgIContainer> image;
aRequest->GetImage(getter_AddRefs(image));
return OnStartContainer(aRequest, image);
}
if (aType == imgINotificationObserver::STOP_DECODE) {
if (aType == imgINotificationObserver::DECODE_COMPLETE) {
if (mImageContent) {
// Update the background-color of the image only after the
// image has been decoded to prevent flashes of just the
@ -533,7 +533,7 @@ ImageDocument::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aDa
}
}
if (aType == imgINotificationObserver::STOP_REQUEST) {
if (aType == imgINotificationObserver::LOAD_COMPLETE) {
uint32_t reqStatus;
aRequest->GetImageStatus(&reqStatus);
nsresult status =

View File

@ -5763,7 +5763,7 @@ nsSVGFEImageElement::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRec
{
nsresult rv = nsImageLoadingContent::Notify(aRequest, aType, aData);
if (aType == imgINotificationObserver::START_CONTAINER) {
if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
// Request a decode
nsCOMPtr<imgIContainer> container;
aRequest->GetImage(getter_AddRefs(container));
@ -5771,9 +5771,9 @@ nsSVGFEImageElement::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRec
container->StartDecoding();
}
if (aType == imgINotificationObserver::STOP_REQUEST ||
aType == imgINotificationObserver::FRAME_CHANGED ||
aType == imgINotificationObserver::START_CONTAINER) {
if (aType == imgINotificationObserver::LOAD_COMPLETE ||
aType == imgINotificationObserver::FRAME_UPDATE ||
aType == imgINotificationObserver::SIZE_AVAILABLE) {
Invalidate();
}

View File

@ -43,7 +43,7 @@ interface imgIContainer;
* @version 0.1
* @see imagelib2
*/
[scriptable, uuid(dad8093d-384b-4923-b83c-351c4e5f9dce)]
[scriptable, uuid(0089cf0c-210c-4b44-9ab0-8099b32bcf64)]
interface imgIDecoderObserver : imgIContainerObserver
{
/**
@ -74,13 +74,6 @@ interface imgIDecoderObserver : imgIContainerObserver
*/
void onStartContainer();
/**
* Decode notification.
*
* called when each frame is created.
*/
void onStartFrame();
/**
* Decode notification.
*

View File

@ -14,20 +14,16 @@ interface imgIRequest;
[ptr] native nsIntRect(nsIntRect);
[scriptable, builtinclass, uuid(9c606ef4-a8e9-45c0-9721-9d6171227ca5)]
[scriptable, builtinclass, uuid(90b3d21c-317d-4d96-93c0-12add64a26bf)]
interface imgINotificationObserver : nsISupports
{
const long START_REQUEST = 1;
const long START_CONTAINER = 2;
const long START_FRAME = 3;
const long DATA_AVAILABLE = 4;
const long STOP_FRAME = 5;
const long STOP_DECODE = 7;
const long DISCARD = 8;
const long IS_ANIMATED = 9;
const long FRAME_CHANGED = 10;
const long STOP_REQUEST = 11;
const long START_DECODE = 12;
const long SIZE_AVAILABLE = 1;
const long FRAME_UPDATE = 2;
const long FRAME_COMPLETE = 3;
const long LOAD_COMPLETE = 4;
const long DECODE_COMPLETE = 5;
const long DISCARD = 6;
const long IS_ANIMATED = 7;
[noscript] void notify(in imgIRequest aProxy, in long aType, [const] in nsIntRect aRect);
};

View File

@ -8,18 +8,14 @@
interface imgIRequest;
[scriptable, uuid(c5a58b5f-cd1f-4c47-a5ed-5013e0b53e95)]
[scriptable, uuid(10be55b3-2029-41a7-a975-538efed250ed)]
interface imgIScriptedNotificationObserver : nsISupports
{
void startRequest(in imgIRequest aRequest);
void startContainer(in imgIRequest aRequest);
void startFrame(in imgIRequest aRequest);
void startDecode(in imgIRequest aRequest);
void dataAvailable(in imgIRequest aRequest);
void stopFrame(in imgIRequest aRequest);
void stopDecode(in imgIRequest aRequest);
void stopRequest(in imgIRequest aRequest);
void sizeAvailable(in imgIRequest aRequest);
void frameUpdate(in imgIRequest aRequest);
void frameComplete(in imgIRequest aRequest);
void loadComplete(in imgIRequest aRequest);
void decodeComplete(in imgIRequest aRequest);
void discard(in imgIRequest aRequest);
void isAnimated(in imgIRequest aRequest);
void frameChanged(in imgIRequest aRequest);
};

View File

@ -220,10 +220,6 @@ Decoder::PostFrameStart()
// reported by the Image.
NS_ABORT_IF_FALSE(mFrameCount == mImage.GetNumFrames(),
"Decoder frame count doesn't match image's!");
// Fire notification
if (mObserver)
mObserver->OnStartFrame();
}
void

View File

@ -31,27 +31,19 @@ ScriptedNotificationObserver::Notify(imgIRequest* aRequest,
int32_t aType,
const nsIntRect* /*aUnused*/)
{
if (aType == imgINotificationObserver::START_REQUEST)
return mInner->StartRequest(aRequest);
if (aType == imgINotificationObserver::START_CONTAINER)
return mInner->StartContainer(aRequest);
if (aType == imgINotificationObserver::START_FRAME)
return mInner->StartFrame(aRequest);
if (aType == imgINotificationObserver::START_DECODE)
return mInner->StartDecode(aRequest);
if (aType == imgINotificationObserver::DATA_AVAILABLE)
return mInner->DataAvailable(aRequest);
if (aType == imgINotificationObserver::STOP_FRAME)
return mInner->StopFrame(aRequest);
if (aType == imgINotificationObserver::STOP_DECODE)
return mInner->StopDecode(aRequest);
if (aType == imgINotificationObserver::STOP_REQUEST)
return mInner->StopRequest(aRequest);
if (aType == imgINotificationObserver::SIZE_AVAILABLE)
return mInner->SizeAvailable(aRequest);
if (aType == imgINotificationObserver::FRAME_UPDATE)
return mInner->FrameUpdate(aRequest);
if (aType == imgINotificationObserver::FRAME_COMPLETE)
return mInner->FrameComplete(aRequest);
if (aType == imgINotificationObserver::DECODE_COMPLETE)
return mInner->DecodeComplete(aRequest);
if (aType == imgINotificationObserver::LOAD_COMPLETE)
return mInner->LoadComplete(aRequest);
if (aType == imgINotificationObserver::DISCARD)
return mInner->Discard(aRequest);
if (aType == imgINotificationObserver::IS_ANIMATED)
return mInner->IsAnimated(aRequest);
if (aType == imgINotificationObserver::FRAME_CHANGED)
return mInner->FrameChanged(aRequest);
return NS_OK;
}

View File

@ -612,30 +612,8 @@ NS_IMETHODIMP imgRequestProxy::GetHasTransferredData(bool* hasData)
return NS_OK;
}
void imgRequestProxy::FrameChanged(const nsIntRect *dirtyRect)
{
LOG_FUNC(gImgLog, "imgRequestProxy::FrameChanged");
if (mListener && !mCanceled) {
// Hold a ref to the listener while we call it, just in case.
nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
mListener->Notify(this, imgINotificationObserver::FRAME_CHANGED, dirtyRect);
}
}
/** imgIDecoderObserver methods **/
void imgRequestProxy::OnStartDecode()
{
LOG_FUNC(gImgLog, "imgRequestProxy::OnStartDecode");
if (mListener && !mCanceled) {
// Hold a ref to the listener while we call it, just in case.
nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
mListener->Notify(this, imgINotificationObserver::START_DECODE, nullptr);
}
}
void imgRequestProxy::OnStartContainer()
{
LOG_FUNC(gImgLog, "imgRequestProxy::OnStartContainer");
@ -643,30 +621,19 @@ void imgRequestProxy::OnStartContainer()
if (mListener && !mCanceled && !mSentStartContainer) {
// Hold a ref to the listener while we call it, just in case.
nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
mListener->Notify(this, imgINotificationObserver::START_CONTAINER, nullptr);
mListener->Notify(this, imgINotificationObserver::SIZE_AVAILABLE, nullptr);
mSentStartContainer = true;
}
}
void imgRequestProxy::OnStartFrame()
{
LOG_FUNC(gImgLog, "imgRequestProxy::OnStartFrame");
if (mListener && !mCanceled) {
// Hold a ref to the listener while we call it, just in case.
nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
mListener->Notify(this, imgINotificationObserver::START_FRAME, nullptr);
}
}
void imgRequestProxy::OnDataAvailable(const nsIntRect * rect)
void imgRequestProxy::OnFrameUpdate(const nsIntRect * rect)
{
LOG_FUNC(gImgLog, "imgRequestProxy::OnDataAvailable");
if (mListener && !mCanceled) {
// Hold a ref to the listener while we call it, just in case.
nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
mListener->Notify(this, imgINotificationObserver::DATA_AVAILABLE, rect);
mListener->Notify(this, imgINotificationObserver::FRAME_UPDATE, rect);
}
}
@ -677,7 +644,7 @@ void imgRequestProxy::OnStopFrame()
if (mListener && !mCanceled) {
// Hold a ref to the listener while we call it, just in case.
nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
mListener->Notify(this, imgINotificationObserver::STOP_FRAME, nullptr);
mListener->Notify(this, imgINotificationObserver::FRAME_COMPLETE, nullptr);
}
}
@ -688,7 +655,7 @@ void imgRequestProxy::OnStopDecode()
if (mListener && !mCanceled) {
// Hold a ref to the listener while we call it, just in case.
nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
mListener->Notify(this, imgINotificationObserver::STOP_DECODE, nullptr);
mListener->Notify(this, imgINotificationObserver::DECODE_COMPLETE, nullptr);
}
// Multipart needs reset for next OnStartContainer
@ -724,14 +691,6 @@ void imgRequestProxy::OnStartRequest()
GetName(name);
LOG_FUNC_WITH_PARAM(gImgLog, "imgRequestProxy::OnStartRequest", "name", name.get());
#endif
// Notify even if mCanceled, since OnStartRequest is guaranteed by the
// nsIStreamListener contract so it makes sense to do the same here.
if (mListener) {
// Hold a ref to the listener while we call it, just in case.
nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
mListener->Notify(this, imgINotificationObserver::START_REQUEST, nullptr);
}
}
void imgRequestProxy::OnStopRequest(bool lastPart)
@ -749,7 +708,7 @@ void imgRequestProxy::OnStopRequest(bool lastPart)
if (mListener) {
// Hold a ref to the listener while we call it, just in case.
nsCOMPtr<imgINotificationObserver> kungFuDeathGrip(mListener);
mListener->Notify(this, imgINotificationObserver::STOP_REQUEST, nullptr);
mListener->Notify(this, imgINotificationObserver::LOAD_COMPLETE, nullptr);
}
// If we're expecting more data from a multipart channel, re-add ourself

View File

@ -132,18 +132,13 @@ protected:
// notifications.
/* non-virtual imgIDecoderObserver methods */
void OnStartDecode ();
void OnStartContainer ();
void OnStartFrame ();
void OnDataAvailable (const nsIntRect * aRect);
void OnFrameUpdate (const nsIntRect * aRect);
void OnStopFrame ();
void OnStopDecode ();
void OnDiscard ();
void OnImageIsAnimated ();
/* non-virtual imgIContainerObserver methods */
void FrameChanged(const nsIntRect *aDirtyRect);
/* non-virtual sort-of-nsIRequestObserver methods */
void OnStartRequest();
void OnStopRequest(bool aLastPart);

View File

@ -46,20 +46,12 @@ NS_IMETHODIMP imgStatusTrackerObserver::FrameChanged(const nsIntRect *dirtyRect)
/** imgIDecoderObserver methods **/
/* void onStartDecode (); */
NS_IMETHODIMP imgStatusTrackerObserver::OnStartDecode()
{
LOG_SCOPE(gImgLog, "imgStatusTrackerObserver::OnStartDecode");
NS_ABORT_IF_FALSE(mTracker->GetImage(),
"OnStartDecode callback before we've created our image");
mTracker->RecordStartDecode();
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
while (iter.HasMore()) {
mTracker->SendStartDecode(iter.GetNext());
}
if (!mTracker->GetRequest()->GetMultipart()) {
MOZ_ASSERT(!mTracker->mBlockingOnload);
mTracker->mBlockingOnload = true;
@ -105,23 +97,6 @@ NS_IMETHODIMP imgStatusTrackerObserver::OnStartContainer()
return NS_OK;
}
/* void onStartFrame (); */
NS_IMETHODIMP imgStatusTrackerObserver::OnStartFrame()
{
LOG_SCOPE(gImgLog, "imgStatusTrackerObserver::OnStartFrame");
NS_ABORT_IF_FALSE(mTracker->GetImage(),
"OnStartFrame callback before we've created our image");
mTracker->RecordStartFrame();
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mTracker->mConsumers);
while (iter.HasMore()) {
mTracker->SendStartFrame(iter.GetNext());
}
return NS_OK;
}
/* [noscript] void onDataAvailable ([const] in nsIntRect rect); */
NS_IMETHODIMP imgStatusTrackerObserver::OnDataAvailable(const nsIntRect * rect)
{
@ -420,28 +395,22 @@ imgStatusTracker::SyncNotify(imgRequestProxy* proxy)
if (mState & stateHasSize)
proxy->OnStartContainer();
// OnStartDecode
if (mState & stateDecodeStarted)
proxy->OnStartDecode();
// BlockOnload
if (mState & stateBlockingOnload)
proxy->BlockOnload();
if (mImage) {
int16_t imageType = mImage->GetType();
// Send frame messages (OnStartFrame, OnDataAvailable, OnStopFrame)
// Send frame messages (OnDataAvailable, OnStopFrame)
if (imageType == imgIContainer::TYPE_VECTOR ||
static_cast<RasterImage*>(mImage)->GetNumFrames() > 0) {
proxy->OnStartFrame();
// OnDataAvailable
// XXX - Should only send partial rects here, but that needs to
// wait until we fix up the observer interface
nsIntRect r;
mImage->GetCurrentFrameRect(r);
proxy->OnDataAvailable(&r);
proxy->OnFrameUpdate(&r);
if (mState & stateFrameStopped)
proxy->OnStopFrame();
@ -527,25 +496,10 @@ void
imgStatusTracker::RecordDecoded()
{
NS_ABORT_IF_FALSE(mImage, "RecordDecoded called before we have an Image");
mState |= stateDecodeStarted | stateDecodeStopped | stateFrameStopped;
mState |= stateDecodeStopped | stateFrameStopped;
mImageStatus |= imgIRequest::STATUS_FRAME_COMPLETE | imgIRequest::STATUS_DECODE_COMPLETE;
}
/* non-virtual imgIDecoderObserver methods */
void
imgStatusTracker::RecordStartDecode()
{
NS_ABORT_IF_FALSE(mImage, "RecordStartDecode without an Image");
mState |= stateDecodeStarted;
}
void
imgStatusTracker::SendStartDecode(imgRequestProxy* aProxy)
{
if (!aProxy->NotificationsDeferred())
aProxy->OnStartDecode();
}
void
imgStatusTracker::RecordStartContainer(imgIContainer* aContainer)
{
@ -564,21 +518,6 @@ imgStatusTracker::SendStartContainer(imgRequestProxy* aProxy)
aProxy->OnStartContainer();
}
void
imgStatusTracker::RecordStartFrame()
{
NS_ABORT_IF_FALSE(mImage, "RecordStartFrame called before we have an Image");
// no bookkeeping necessary here - this is implied by imgIContainer's number
// of frames
}
void
imgStatusTracker::SendStartFrame(imgRequestProxy* aProxy)
{
if (!aProxy->NotificationsDeferred())
aProxy->OnStartFrame();
}
void
imgStatusTracker::RecordDataAvailable()
{
@ -593,7 +532,7 @@ imgStatusTracker::SendDataAvailable(imgRequestProxy* aProxy,
const nsIntRect* aRect)
{
if (!aProxy->NotificationsDeferred())
aProxy->OnDataAvailable(aRect);
aProxy->OnFrameUpdate(aRect);
}
@ -640,7 +579,7 @@ imgStatusTracker::RecordDiscard()
NS_ABORT_IF_FALSE(mImage,
"RecordDiscard called before we have an Image");
// Clear the state bits we no longer deserve.
uint32_t stateBitsToClear = stateDecodeStarted | stateDecodeStopped;
uint32_t stateBitsToClear = stateDecodeStopped;
mState &= ~stateBitsToClear;
// Clear the status bits we no longer deserve.
@ -689,7 +628,7 @@ imgStatusTracker::SendFrameChanged(imgRequestProxy* aProxy,
const nsIntRect* aDirtyRect)
{
if (!aProxy->NotificationsDeferred())
aProxy->FrameChanged(aDirtyRect);
aProxy->OnFrameUpdate(aDirtyRect);
}
/* non-virtual sort-of-nsIRequestObserver methods */
@ -702,7 +641,6 @@ imgStatusTracker::RecordStartRequest()
mImageStatus &= ~imgIRequest::STATUS_LOAD_COMPLETE;
mImageStatus &= ~imgIRequest::STATUS_FRAME_COMPLETE;
mState &= ~stateRequestStarted;
mState &= ~stateDecodeStarted;
mState &= ~stateDecodeStopped;
mState &= ~stateRequestStopped;
mState &= ~stateBlockingOnload;

View File

@ -32,7 +32,6 @@ class Image;
enum {
stateRequestStarted = PR_BIT(0),
stateHasSize = PR_BIT(1),
stateDecodeStarted = PR_BIT(2),
stateDecodeStopped = PR_BIT(3),
stateFrameStopped = PR_BIT(4),
stateRequestStopped = PR_BIT(5),
@ -149,12 +148,8 @@ public:
void RecordDecoded();
/* non-virtual imgIDecoderObserver methods */
void RecordStartDecode();
void SendStartDecode(imgRequestProxy* aProxy);
void RecordStartContainer(imgIContainer* aContainer);
void SendStartContainer(imgRequestProxy* aProxy);
void RecordStartFrame();
void SendStartFrame(imgRequestProxy* aProxy);
void RecordDataAvailable();
void SendDataAvailable(imgRequestProxy* aProxy, const nsIntRect* aRect);
void RecordStopFrame();

View File

@ -124,15 +124,11 @@ function getImagePref(pref)
// JS implementation of imgIScriptedNotificationObserver with stubs for all of its methods.
function ImageDecoderObserverStub()
{
this.startRequest = function startRequest(aRequest) {}
this.startDecode = function startDecode(aRequest) {}
this.startContainer = function startContainer(aRequest) {}
this.startFrame = function startFrame(aRequest) {}
this.stopFrame = function stopFrame(aRequest) {}
this.stopDecode = function stopDecode(aRequest) {}
this.stopRequest = function stopRequest(aRequest) {}
this.dataAvailable = function dataAvailable(aRequest) {}
this.sizeAvailable = function sizeAvailable(aRequest) {}
this.frameComplete = function frameComplete(aRequest) {}
this.decodeComplete = function decodeComplete(aRequest) {}
this.loadComplete = function loadComplete(aRequest) {}
this.frameUpdate = function frameUpdate(aRequest) {}
this.discard = function discard(aRequest) {}
this.isAnimated = function isAnimated(aRequest) {}
this.frameChanged = function frameChanged(aRequest) {}
}

View File

@ -91,7 +91,7 @@ function main() {
// Create, customize & attach decoder observer
observer = new ImageDecoderObserverStub();
observer.stopFrame = myOnStopFrame;
observer.frameComplete = myOnStopFrame;
gMyDecoderObserver =
Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
.createScriptedObserver(observer);

View File

@ -53,13 +53,10 @@ function checkClone(other_listener, aRequest)
// Ensure that all the callbacks were called on aRequest.
function checkAllCallbacks(listener, aRequest)
{
do_check_neq(listener.state & START_REQUEST, 0);
do_check_neq(listener.state & START_DECODE, 0);
do_check_neq(listener.state & START_CONTAINER, 0);
do_check_neq(listener.state & START_FRAME, 0);
do_check_neq(listener.state & STOP_FRAME, 0);
do_check_neq(listener.state & STOP_DECODE, 0);
do_check_neq(listener.state & STOP_REQUEST, 0);
do_check_neq(listener.state & SIZE_AVAILABLE, 0);
do_check_neq(listener.state & FRAME_COMPLETE, 0);
do_check_neq(listener.state & DECODE_COMPLETE, 0);
do_check_neq(listener.state & LOAD_COMPLETE, 0);
do_check_eq(listener.state, ALL_BITS);
do_test_finished();
@ -115,10 +112,10 @@ function firstLoadDone(oldlistener, aRequest)
function getChannelLoadImageStartCallback(streamlistener)
{
return function channelLoadStart(imglistener, aRequest) {
// We must not have received any status before we get this start callback.
// We must not have received all status before we get this start callback.
// If we have, we've broken people's expectations by delaying events from a
// channel we were given.
do_check_eq(streamlistener.requestStatus, 0);
do_check_eq(streamlistener.requestStatus & STOP_REQUEST, 0);
checkClone(imglistener, aRequest);
}

View File

@ -2,64 +2,47 @@
* Helper structures to track callbacks from image and channel loads.
*/
// One bit per callback that imageListener below implements. Stored in
// ImageListener.state.
// START_REQUEST and STOP_REQUEST are also reused by ChannelListener, and
// START_REQUEST and STOP_REQUEST are used by ChannelListener, and
// stored in ChannelListener.requestStatus.
const START_REQUEST = 0x01;
const START_DECODE = 0x02;
const START_CONTAINER = 0x04;
const START_FRAME = 0x08;
const STOP_FRAME = 0x10;
const STOP_DECODE = 0x20;
const STOP_REQUEST = 0x40;
const ALL_BITS = START_REQUEST | START_DECODE | START_CONTAINER | START_FRAME |
STOP_FRAME | STOP_DECODE | STOP_REQUEST;
const STOP_REQUEST = 0x02;
const DATA_AVAILABLE = 0x04;
// One bit per callback that imageListener below implements. Stored in
// ImageListener.state.
const SIZE_AVAILABLE = 0x01;
const FRAME_UPDATE = 0x02;
const FRAME_COMPLETE = 0x04;
const LOAD_COMPLETE = 0x08;
const DECODE_COMPLETE = 0x10;
const ALL_BITS = SIZE_AVAILABLE | FRAME_COMPLETE | DECODE_COMPLETE | LOAD_COMPLETE;
// An implementation of imgIDecoderObserver with the ability to call specified
// functions on onStartRequest and onStopRequest.
function ImageListener(start_callback, stop_callback)
{
this.startRequest = function onStartRequest(aRequest)
this.sizeAvailable = function onSizeAvailable(aRequest)
{
do_check_false(this.synchronous);
this.state |= START_REQUEST;
this.state |= SIZE_AVAILABLE;
if (this.start_callback)
this.start_callback(this, aRequest);
}
this.startDecode = function onStartDecode(aRequest)
this.frameComplete = function onFrameComplete(aRequest)
{
do_check_false(this.synchronous);
this.state |= START_DECODE;
this.state |= FRAME_COMPLETE;
}
this.startContainer = function onStartContainer(aRequest)
this.decodeComplete = function onDecodeComplete(aRequest)
{
do_check_false(this.synchronous);
this.state |= START_CONTAINER;
this.state |= DECODE_COMPLETE;
}
this.startFrame = function onStartFrame(aRequest)
{
do_check_false(this.synchronous);
this.state |= START_FRAME;
}
this.stopFrame = function onStopFrame(aRequest)
{
do_check_false(this.synchronous);
this.state |= STOP_FRAME;
}
this.stopDecode = function onStopDecode(aRequest)
{
do_check_false(this.synchronous);
this.state |= STOP_DECODE;
}
this.stopRequest = function onStopRequest(aRequest)
this.loadComplete = function onLoadcomplete(aRequest)
{
do_check_false(this.synchronous);
@ -67,12 +50,15 @@ function ImageListener(start_callback, stop_callback)
// reference loops!
aRequest.cancelAndForgetObserver(0);
this.state |= STOP_REQUEST;
this.state |= LOAD_COMPLETE;
if (this.stop_callback)
this.stop_callback(this, aRequest);
}
this.dataAvailable = function onDataAvailable(aRequest)
this.frameUpdate = function onFrameUpdate(aRequest)
{
}
this.isAnimated = function onIsAnimated()
{
}
@ -111,6 +97,8 @@ function ChannelListener()
{
if (this.outputListener)
this.outputListener.onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
this.requestStatus |= DATA_AVAILABLE;
}
this.onStopRequest = function onStopRequest(aRequest, aContext, aStatusCode)

View File

@ -1434,14 +1434,13 @@ nsBulletFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
NS_IMETHODIMP
nsBulletFrame::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
{
if (aType == imgINotificationObserver::START_CONTAINER) {
if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
nsCOMPtr<imgIContainer> image;
aRequest->GetImage(getter_AddRefs(image));
return OnStartContainer(aRequest, image);
}
if (aType == imgINotificationObserver::DATA_AVAILABLE ||
aType == imgINotificationObserver::FRAME_CHANGED) {
if (aType == imgINotificationObserver::FRAME_UPDATE) {
// The image has changed.
// Invalidate the entire content area. Maybe it's not optimal but it's simple and
// always correct, and I'll be a stunned mullet if it ever matters for performance

View File

@ -140,7 +140,8 @@ nsImageFrame::nsImageFrame(nsStyleContext* aContext) :
ImageFrameSuper(aContext),
mComputedSize(0, 0),
mIntrinsicRatio(0, 0),
mDisplayingIcon(false)
mDisplayingIcon(false),
mFirstFrameComplete(false)
{
// We assume our size is not constrained and we haven't gotten an
// initial reflow yet, so don't touch those flags.
@ -528,17 +529,21 @@ nsImageFrame::ShouldCreateImageFrameFor(Element* aElement,
nsresult
nsImageFrame::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData)
{
if (aType == imgINotificationObserver::START_CONTAINER) {
if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
nsCOMPtr<imgIContainer> image;
aRequest->GetImage(getter_AddRefs(image));
return OnStartContainer(aRequest, image);
}
if (aType == imgINotificationObserver::DATA_AVAILABLE) {
if (aType == imgINotificationObserver::FRAME_UPDATE) {
return OnDataAvailable(aRequest, aData);
}
if (aType == imgINotificationObserver::STOP_REQUEST) {
if (aType == imgINotificationObserver::FRAME_COMPLETE) {
mFirstFrameComplete = true;
}
if (aType == imgINotificationObserver::LOAD_COMPLETE) {
uint32_t imgStatus;
aRequest->GetImageStatus(&imgStatus);
nsresult status =
@ -546,12 +551,6 @@ nsImageFrame::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aDat
return OnStopRequest(aRequest, status);
}
if (aType == imgINotificationObserver::FRAME_CHANGED) {
nsCOMPtr<imgIContainer> image;
aRequest->GetImage(getter_AddRefs(image));
return FrameChanged(aRequest, image);
}
return NS_OK;
}
@ -596,6 +595,12 @@ nsresult
nsImageFrame::OnDataAvailable(imgIRequest *aRequest,
const nsIntRect *aRect)
{
if (mFirstFrameComplete) {
nsCOMPtr<imgIContainer> container;
aRequest->GetImage(getter_AddRefs(container));
return FrameChanged(aRequest, container);
}
// XXX do we need to make sure that the reflow from the
// OnStartContainer has been processed before we start calling
// invalidate?
@ -625,7 +630,7 @@ nsImageFrame::OnDataAvailable(imgIRequest *aRequest,
InvalidateFrameWithRect(invalid, nsDisplayItem::TYPE_IMAGE);
InvalidateFrameWithRect(invalid, nsDisplayItem::TYPE_ALT_FEEDBACK);
}
return NS_OK;
}
@ -1976,8 +1981,8 @@ void nsImageFrame::IconLoad::GetPrefs()
NS_IMETHODIMP
nsImageFrame::IconLoad::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
{
if (aType != imgINotificationObserver::STOP_REQUEST &&
aType != imgINotificationObserver::FRAME_CHANGED) {
if (aType != imgINotificationObserver::LOAD_COMPLETE &&
aType != imgINotificationObserver::FRAME_UPDATE) {
return NS_OK;
}

View File

@ -284,6 +284,7 @@ private:
nsSize mIntrinsicRatio;
bool mDisplayingIcon;
bool mFirstFrameComplete;
static nsIIOService* sIOService;

View File

@ -341,7 +341,7 @@ NS_INTERFACE_MAP_END
NS_IMETHODIMP
ImageLoader::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
{
if (aType == imgINotificationObserver::START_CONTAINER) {
if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
nsCOMPtr<imgIContainer> image;
aRequest->GetImage(getter_AddRefs(image));
return OnStartContainer(aRequest, image);
@ -351,11 +351,11 @@ ImageLoader::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData
return OnImageIsAnimated(aRequest);
}
if (aType == imgINotificationObserver::STOP_FRAME) {
if (aType == imgINotificationObserver::LOAD_COMPLETE) {
return OnStopFrame(aRequest);
}
if (aType == imgINotificationObserver::FRAME_CHANGED) {
if (aType == imgINotificationObserver::FRAME_UPDATE) {
return FrameChanged(aRequest);
}

View File

@ -563,18 +563,18 @@ nsSVGImageListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect
if (!mFrame)
return NS_ERROR_FAILURE;
if (aType == imgINotificationObserver::STOP_REQUEST) {
if (aType == imgINotificationObserver::LOAD_COMPLETE) {
nsSVGUtils::InvalidateAndScheduleReflowSVG(mFrame);
}
if (aType == imgINotificationObserver::FRAME_CHANGED) {
if (aType == imgINotificationObserver::FRAME_UPDATE) {
// No new dimensions, so we don't need to call
// nsSVGUtils::InvalidateAndScheduleBoundsUpdate.
nsSVGEffects::InvalidateRenderingObservers(mFrame);
nsSVGUtils::InvalidateBounds(mFrame);
}
if (aType == imgINotificationObserver::START_CONTAINER) {
if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
// Called once the resource's dimensions have been obtained.
aRequest->GetImage(getter_AddRefs(mFrame->mImageContainer));
nsSVGUtils::InvalidateAndScheduleReflowSVG(mFrame);

View File

@ -580,17 +580,17 @@ nsImageBoxFrame::GetFrameName(nsAString& aResult) const
nsresult
nsImageBoxFrame::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
{
if (aType == imgINotificationObserver::START_CONTAINER) {
if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
nsCOMPtr<imgIContainer> image;
aRequest->GetImage(getter_AddRefs(image));
return OnStartContainer(aRequest, image);
}
if (aType == imgINotificationObserver::STOP_DECODE) {
if (aType == imgINotificationObserver::DECODE_COMPLETE) {
return OnStopDecode(aRequest);
}
if (aType == imgINotificationObserver::STOP_REQUEST) {
if (aType == imgINotificationObserver::LOAD_COMPLETE) {
uint32_t imgStatus;
aRequest->GetImageStatus(&imgStatus);
nsresult status =
@ -602,7 +602,7 @@ nsImageBoxFrame::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* a
return OnImageIsAnimated(aRequest);
}
if (aType == imgINotificationObserver::FRAME_CHANGED) {
if (aType == imgINotificationObserver::FRAME_UPDATE) {
return FrameChanged(aRequest);
}

View File

@ -29,15 +29,14 @@ nsTreeImageListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRec
return mTreeFrame ? mTreeFrame->OnImageIsAnimated(aRequest) : NS_OK;
}
if (aType == imgINotificationObserver::START_CONTAINER) {
if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
// Ensure the animation (if any) is started. Note: There is no
// corresponding call to Decrement for this. This Increment will be
// 'cleaned up' by the Request when it is destroyed, but only then.
aRequest->IncrementAnimationConsumers();
}
if (aType == imgINotificationObserver::DATA_AVAILABLE ||
aType == imgINotificationObserver::FRAME_CHANGED) {
if (aType == imgINotificationObserver::FRAME_UPDATE) {
Invalidate();
}

View File

@ -92,11 +92,11 @@ nsAlertsIconListener::~nsAlertsIconListener()
NS_IMETHODIMP
nsAlertsIconListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
{
if (aType == imgINotificationObserver::STOP_REQUEST) {
if (aType == imgINotificationObserver::LOAD_COMPLETE) {
return OnStopRequest(aRequest);
}
if (aType == imgINotificationObserver::STOP_FRAME) {
if (aType == imgINotificationObserver::FRAME_COMPLETE) {
return OnStopFrame(aRequest);
}

View File

@ -324,11 +324,11 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI)
NS_IMETHODIMP
nsMenuItemIconX::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
{
if (aType == imgINotificationObserver::STOP_FRAME) {
if (aType == imgINotificationObserver::FRAME_COMPLETE) {
return OnStopFrame(aRequest);
}
if (aType == imgINotificationObserver::STOP_REQUEST) {
if (aType == imgINotificationObserver::LOAD_COMPLETE) {
if (mIconRequest && mIconRequest == aRequest) {
mIconRequest->Cancel(NS_BINDING_ABORTED);
mIconRequest = nullptr;