Bug 716140 - Calculate the difference between two imgStatusTrackers, notify for that difference, and apply it to the source. r=seth

This patch adds two semi-unrelated functions, currently unused:
 - SyncAndSyncNotifyDifference, which synchronizes the current
   imgStatusTracker to have the state of the argument imgStatusTracker, and
   notifies our observers about the new state;
 - CloneForRecording, which will let us create a new imgStatusTracker based on
   the current state for use with SyncAndSyncNotifyDifference.

--HG--
extra : rebase_source : 2b9072e38f9dabf4d2cbe0d7c129b44c81743591
This commit is contained in:
Joe Drew 2013-01-18 16:47:17 -05:00
parent 7eb23e8ba4
commit 5464a29b35
2 changed files with 62 additions and 4 deletions

View File

@ -13,6 +13,7 @@
#include "ImageLogging.h"
#include "RasterImage.h"
#include "nsIObserverService.h"
#include "RasterImage.h"
#include "mozilla/Util.h"
#include "mozilla/Assertions.h"
@ -291,15 +292,21 @@ imgStatusTracker::imgStatusTracker(Image* aImage)
mHadLastPart(false)
{}
// Private, used only by CloneForRecording.
imgStatusTracker::imgStatusTracker(const imgStatusTracker& aOther)
: mImage(aOther.mImage),
mTrackerObserver(new imgStatusTrackerNotifyingObserver(this)),
mState(aOther.mState),
mImageStatus(aOther.mImageStatus),
mIsMultipart(aOther.mIsMultipart),
mHadLastPart(aOther.mHadLastPart)
// Note: we explicitly don't copy mRequestRunnable, because it won't be
// nulled out when the mRequestRunnable's Run function eventually gets
// called.
// Note: we explicitly don't copy several fields:
// - mRequestRunnable, because it won't be nulled out when the
// mRequestRunnable's Run function eventually gets called.
// - mProperties, because we don't need it and it'd just point at the same
// object
// - mConsumers, because we don't need to talk to consumers
// - mInvalidRect, because the point of it is to be fired off and reset
{}
imgStatusTracker::~imgStatusTracker()
@ -480,6 +487,53 @@ imgStatusTracker::SyncNotifyState(imgRequestProxy* proxy, bool hasImage, uint32_
}
}
void
imgStatusTracker::SyncAndSyncNotifyDifference(imgStatusTracker* other)
{
uint32_t diffState = ~mState & other->mState;
bool unblockedOnload = mState & stateBlockingOnload && !(other->mState & stateBlockingOnload);
bool foundError = mImageStatus == imgIRequest::STATUS_ERROR;
// Now that we've calculated the difference in state, synchronize our state
// with the other tracker.
// First, actually synchronize our state.
mInvalidRect = mInvalidRect.Union(other->mInvalidRect);
mState |= other->mState;
mImageStatus = other->mImageStatus;
mIsMultipart = other->mIsMultipart;
mHadLastPart = other->mHadLastPart;
// Now that we've updated our state, notify all the consumers about the state
// that's changed.
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mConsumers);
while (iter.HasMore()) {
imgRequestProxy* proxy = iter.GetNext();
if (!proxy->NotificationsDeferred()) {
SyncNotifyState(proxy, mImage, diffState, mInvalidRect, other->mHadLastPart);
if (unblockedOnload) {
SendUnblockOnload(proxy);
}
}
}
// Reset the other rectangle for another go, if it's going to have one.
other->mInvalidRect.SetEmpty();
if (foundError) {
FireFailureNotification();
}
}
imgStatusTracker*
imgStatusTracker::CloneForRecording()
{
imgStatusTracker* clone = new imgStatusTracker(*this);
return clone;
}
void
imgStatusTracker::SyncNotify(imgRequestProxy* proxy)
{

View File

@ -58,7 +58,6 @@ public:
// imgRequestProxys in SyncNotify() and EmulateRequestFinished(), and must be
// alive as long as this instance is, because we hold a weak reference to it.
imgStatusTracker(mozilla::image::Image* aImage);
imgStatusTracker(const imgStatusTracker& aOther);
~imgStatusTracker();
// Image-setter, for imgStatusTrackers created by imgRequest::Init, which
@ -180,11 +179,14 @@ public:
inline imgDecoderObserver* GetDecoderObserver() { return mTrackerObserver.get(); }
imgStatusTracker* CloneForRecording();
private:
friend class imgStatusNotifyRunnable;
friend class imgRequestNotifyRunnable;
friend class imgStatusTrackerObserver;
friend class imgStatusTrackerNotifyingObserver;
imgStatusTracker(const imgStatusTracker& aOther);
void FireFailureNotification();
@ -192,6 +194,8 @@ private:
uint32_t state, nsIntRect& dirtyRect,
bool hadLastPart);
void SyncAndSyncNotifyDifference(imgStatusTracker* other);
nsCOMPtr<nsIRunnable> mRequestRunnable;
// The invalid area of the most recent frame we know about. (All previous