Bug 590252 - part 1 - Add framework to Decoder superclass to handle invalidations.r=joe,a=blocker
authorBobby Holley <bobbyholley@gmail.com>
Tue, 24 Aug 2010 16:40:45 -0400
changeset 51591 24ae66f16d4499cc171c5796e1e9d9304b76f179
parent 51590 b6e7aea76bc931e4c3f4bb9ef919a5e3435e90d2
child 51592 5875f7dbf9c66bb6e2574624d3a743acd7d52ac4
push idunknown
push userunknown
push dateunknown
reviewersjoe, blocker
bugs590252
milestone2.0b5pre
Bug 590252 - part 1 - Add framework to Decoder superclass to handle invalidations.r=joe,a=blocker
modules/libpr0n/src/Decoder.cpp
modules/libpr0n/src/Decoder.h
modules/libpr0n/src/RasterImage.cpp
--- a/modules/libpr0n/src/Decoder.cpp
+++ b/modules/libpr0n/src/Decoder.cpp
@@ -87,16 +87,36 @@ Decoder::Write(const char* aBuffer, PRUi
 
 nsresult
 Decoder::Finish()
 {
   // Implementation-specific finalization
   return FinishInternal();
 }
 
+void
+Decoder::FlushInvalidations()
+{
+  // If we've got an empty invalidation rect, we have nothing to do
+  if (mInvalidRect.IsEmpty())
+    return;
+
+  // Tell the image that it's been updated
+  mImage->FrameUpdated(mFrameCount - 1, mInvalidRect);
+
+  // Fire OnDataAvailable
+  if (mObserver) {
+    PRBool isCurrentFrame = mImage->GetCurrentFrameIndex() == (mFrameCount - 1);
+    mObserver->OnDataAvailable(nsnull, isCurrentFrame, &mInvalidRect);
+  }
+
+  // Clear the invalidation rectangle
+  mInvalidRect.Empty();
+}
+
 /*
  * Hook stubs. Override these as necessary in decoder implementations.
  */
 
 nsresult Decoder::InitInternal() {return NS_OK; }
 nsresult Decoder::WriteInternal(const char* aBuffer, PRUint32 aCount) {return NS_OK; }
 nsresult Decoder::FinishInternal() {return NS_OK; }
 
@@ -120,16 +140,21 @@ Decoder::PostSize(PRInt32 aWidth, PRInt3
 }
 
 void
 Decoder::PostFrameStart()
 {
   // We shouldn't already be mid-frame
   NS_ABORT_IF_FALSE(!mInFrame, "Starting new frame but not done with old one!");
 
+  // We should take care of any invalidation region when wrapping up the
+  // previous frame
+  NS_ABORT_IF_FALSE(mInvalidRect.IsEmpty(),
+                    "Start image frame with non-empty invalidation region!");
+
   // Update our state to reflect the new frame
   mFrameCount++;
   mInFrame = true;
 
   // Decoder implementations should only call this method if they successfully
   // appended the frame to the image. So mFrameCount should always match that
   // reported by the Image.
   NS_ABORT_IF_FALSE(mFrameCount == mImage->GetNumFrames(),
@@ -149,10 +174,23 @@ Decoder::PostFrameStop()
   // Update our state
   mInFrame = false;
 
   // Fire notification
   if (mObserver)
     mObserver->OnStopFrame(nsnull, mFrameCount - 1); // frame # is zero-indexed
 }
 
+void
+Decoder::PostInvalidation(nsIntRect& aRect)
+{
+  // We should be mid-frame
+  NS_ABORT_IF_FALSE(mInFrame, "Can't invalidate when not mid-frame!");
+
+  // Account for the new region
+  mInvalidRect.UnionRect(mInvalidRect, aRect);
+
+  // For now, just flush invalidations immediately. We'll stop doing this soon.
+  FlushInvalidations();
+}
+
 } // namespace imagelib
 } // namespace mozilla
--- a/modules/libpr0n/src/Decoder.h
+++ b/modules/libpr0n/src/Decoder.h
@@ -81,16 +81,21 @@ public:
 
   /**
    * Informs the decoder that all the data has been written.
    *
    * Notifications Sent: TODO
    */
   nsresult Finish();
 
+  /**
+   * Tells the decoder to flush any pending invalidations.
+   */
+  void FlushInvalidations();
+
   // We're not COM-y, so we don't get refcounts by default
   NS_INLINE_DECL_REFCOUNTING(Decoder)
 
   /*
    * State.
    */
 
   // If we're doing a "size decode", we more or less pass through the image
@@ -125,27 +130,32 @@ protected:
   // the image of its size and sends notifications.
   void PostSize(PRInt32 aWidth, PRInt32 aHeight);
 
   // Called by decoders when they begin/end a frame. Informs the image, sends
   // notifications, and does internal book-keeping.
   void PostFrameStart();
   void PostFrameStop();
 
+  // Called by the decoders when they have a region to invalidate. We may not
+  // actually pass these invalidations on right away.
+  void PostInvalidation(nsIntRect& aRect);
 
   /*
    * Member variables.
    *
    * XXX - Some of these become private later in the patch stack.
    */
   nsRefPtr<RasterImage> mImage;
   nsCOMPtr<imgIDecoderObserver> mObserver;
 
   PRUint32 mFrameCount; // Number of frames, including anything in-progress
 
+  nsIntRect mInvalidRect; // Tracks an invalidation region in the current frame.
+
   bool mInitialized;
   bool mSizeDecode;
   bool mInFrame;
 };
 
 } // namespace imagelib
 } // namespace mozilla
 
--- a/modules/libpr0n/src/RasterImage.cpp
+++ b/modules/libpr0n/src/RasterImage.cpp
@@ -925,26 +925,25 @@ RasterImage::EnsureCleanFrame(PRUint32 a
 
   return NS_OK;
 }
 
 
 nsresult
 RasterImage::FrameUpdated(PRUint32 aFrameNum, nsIntRect &aUpdatedRect)
 {
-  NS_ASSERTION(aFrameNum < mFrames.Length(), "Invalid frame index!");
-  if (aFrameNum >= mFrames.Length())
-    return NS_ERROR_INVALID_ARG;
+  NS_ABORT_IF_FALSE(aFrameNum < mFrames.Length(), "Invalid frame index!");
 
   imgFrame *frame = GetImgFrame(aFrameNum);
   NS_ABORT_IF_FALSE(frame, "Calling FrameUpdated on frame that doesn't exist!");
-  NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
   frame->ImageUpdated(aUpdatedRect);
 
+  // XXXbholley - this should turn into a void method as soon the decoders
+  // stop using it
   return NS_OK;
 }
 
 nsresult
 RasterImage::SetFrameDisposalMethod(PRUint32 aFrameNum,
                                     PRInt32 aDisposalMethod)
 {
   if (mError)