Bug 716140 - Make SVG images handle the new world order. r=dholbert
authorJoe Drew <joe@drew.ca>
Mon, 11 Feb 2013 19:34:20 -0500
changeset 125638 e47cbcb88803cd45add86dc3228f45a2e43a0032
parent 125637 3cf71e7e1efc2f7f5fabd870095ad74c5b955200
child 125639 e0683dc77a1b9e798c46b62904e8de8bc096949d
push id1444
push userryanvm@gmail.com
push dateThu, 21 Mar 2013 13:56:20 +0000
treeherderfx-team@a73a2b5c423b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs716140
milestone22.0a1
Bug 716140 - Make SVG images handle the new world order. r=dholbert
image/src/VectorImage.cpp
image/src/imgStatusTracker.cpp
image/src/imgStatusTracker.h
--- a/image/src/VectorImage.cpp
+++ b/image/src/VectorImage.cpp
@@ -374,17 +374,22 @@ VectorImage::OnImageDataComplete(nsIRequ
   // SVG document. This won't have any effect on our imgStatusTracker.
   nsresult finalStatus = OnStopRequest(aRequest, aContext, aStatus);
 
   // Give precedence to Necko failure codes.
   if (NS_FAILED(aStatus))
     finalStatus = aStatus;
 
   // Actually fire OnStopRequest.
-  GetStatusTracker().OnStopRequest(aLastPart, finalStatus);
+  if (mStatusTracker) {
+    nsRefPtr<imgStatusTracker> clone = mStatusTracker->CloneForRecording();
+    imgDecoderObserver* observer = clone->GetDecoderObserver();
+    observer->OnStopRequest(aLastPart, finalStatus);
+    mStatusTracker->SyncAndSyncNotifyDifference(clone);
+  }
   return finalStatus;
 }
 
 nsresult
 VectorImage::OnImageDataAvailable(nsIRequest* aRequest,
                                   nsISupports* aContext,
                                   nsIInputStream* aInStr,
                                   uint64_t aSourceOffset,
@@ -828,17 +833,20 @@ VectorImage::OnStartRequest(nsIRequest* 
     mError = true;
     return rv;
   }
 
   // Sending StartDecode will block page load until the document's ready.  (We
   // unblock it by sending StopDecode in OnSVGDocumentLoaded or
   // OnSVGDocumentError.)
   if (mStatusTracker) {
-    mStatusTracker->GetDecoderObserver()->OnStartDecode();
+    nsRefPtr<imgStatusTracker> clone = mStatusTracker->CloneForRecording();
+    imgDecoderObserver* observer = clone->GetDecoderObserver();
+    observer->OnStartDecode();
+    mStatusTracker->SyncAndSyncNotifyDifference(clone);
   }
 
   // Create a listener to wait until the SVG document is fully loaded, which
   // will signal that this image is ready to render. Certain error conditions
   // will prevent us from ever getting this notification, so we also create a
   // listener that waits for parsing to complete and cancels the
   // SVGLoadEventListener if needed. The listeners are automatically attached
   // to the document by their constructors.
@@ -907,40 +915,47 @@ VectorImage::OnSVGDocumentLoaded()
   mIsFullyLoaded = true;
   mHaveAnimations = mSVGDocumentWrapper->IsAnimated();
 
   // Start listening to our image for rendering updates.
   mRenderingObserver = new SVGRootRenderingObserver(mSVGDocumentWrapper, this);
 
   // Tell *our* observers that we're done loading.
   if (mStatusTracker) {
-    imgDecoderObserver* observer = mStatusTracker->GetDecoderObserver();
+    nsRefPtr<imgStatusTracker> clone = mStatusTracker->CloneForRecording();
+    imgDecoderObserver* observer = clone->GetDecoderObserver();
 
     observer->OnStartContainer(); // Signal that width/height are available.
     observer->FrameChanged(&nsIntRect::GetMaxSizedIntRect());
     observer->OnStopFrame();
     observer->OnStopDecode(NS_OK); // Unblock page load.
+
+    mStatusTracker->SyncAndSyncNotifyDifference(clone);
   }
 
   EvaluateAnimation();
 }
 
 void
 VectorImage::OnSVGDocumentError()
 {
   CancelAllListeners();
 
   // XXXdholbert Need to do something more for the parsing failed case -- right
   // now, this just makes us draw the "object" icon, rather than the (jagged)
   // "broken image" icon.  See bug 594505.
   mError = true;
 
   if (mStatusTracker) {
+    nsRefPtr<imgStatusTracker> clone = mStatusTracker->CloneForRecording();
+    imgDecoderObserver* observer = clone->GetDecoderObserver();
+
     // Unblock page load.
-    mStatusTracker->GetDecoderObserver()->OnStopDecode(NS_ERROR_FAILURE);
+    observer->OnStopDecode(NS_ERROR_FAILURE);
+    mStatusTracker->SyncAndSyncNotifyDifference(clone);
   }
 }
 
 //------------------------------------------------------------------------------
 // nsIStreamListener method
 
 //******************************************************************************
 /* void onDataAvailable(in nsIRequest request, in nsISupports ctxt,
@@ -960,16 +975,15 @@ VectorImage::OnDataAvailable(nsIRequest*
 
 // --------------------------
 // Invalidation helper method
 
 void
 VectorImage::InvalidateObserver()
 {
   if (mStatusTracker) {
-    imgDecoderObserver* observer = mStatusTracker->GetDecoderObserver();
-    observer->FrameChanged(&nsIntRect::GetMaxSizedIntRect());
-    observer->OnStopFrame();
+    mStatusTracker->FrameChanged(&nsIntRect::GetMaxSizedIntRect());
+    mStatusTracker->OnStopFrame();
   }
 }
 
 } // namespace image
 } // namespace mozilla
--- a/image/src/imgStatusTracker.cpp
+++ b/image/src/imgStatusTracker.cpp
@@ -951,16 +951,28 @@ imgStatusTracker::FrameChanged(const nsI
   /* notify the kids */
   nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mConsumers);
   while (iter.HasMore()) {
     SendFrameChanged(iter.GetNext(), aDirtyRect);
   }
 }
 
 void
+imgStatusTracker::OnStopFrame()
+{
+  RecordStopFrame();
+
+  /* notify the kids */
+  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mConsumers);
+  while (iter.HasMore()) {
+    SendStopFrame(iter.GetNext());
+  }
+}
+
+void
 imgStatusTracker::OnDataAvailable()
 {
   // Notify any imgRequestProxys that are observing us that we have an Image.
   nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mConsumers);
   while (iter.HasMore()) {
     iter.GetNext()->SetHasImage();
   }
 }
--- a/image/src/imgStatusTracker.h
+++ b/image/src/imgStatusTracker.h
@@ -163,16 +163,19 @@ public:
   void SendStopRequest(imgRequestProxy* aProxy, bool aLastPart, nsresult aStatus);
 
   void OnStartRequest();
   void OnDataAvailable();
   void OnStopRequest(bool aLastPart, nsresult aStatus);
   void OnDiscard();
   void FrameChanged(const nsIntRect* aDirtyRect);
   void OnUnlockedDraw();
+  // This is called only by VectorImage, and only to ensure tests work
+  // properly. Do not use it.
+  void OnStopFrame();
 
   /* non-virtual imgIOnloadBlocker methods */
   // NB: If UnblockOnload is sent, and then we are asked to replay the
   // notifications, we will not send a BlockOnload/UnblockOnload pair.  This
   // is different from all the other notifications.
   void RecordBlockOnload();
   void SendBlockOnload(imgRequestProxy* aProxy);
   void RecordUnblockOnload();