bug 512260 - part 4 - call nsDocument::AddImage and RemoveImage on images stored in nsStyleContentData.r=dbaron,a=blocker
authorBobby Holley <bobbyholley@gmail.com>
Fri, 06 Aug 2010 13:27:01 -0400
changeset 50818 5e1f15ae17abff77e409fbf10dce636bff62b1ba
parent 50817 fad2fd7c2ad05e65fa08d74fd8fe317b4f2cae6c
child 50819 832a644e8dcac50c7db4c44ac86ba8201fac1a90
push idunknown
push userunknown
push dateunknown
reviewersdbaron, blocker
bugs512260
milestone2.0b5pre
bug 512260 - part 4 - call nsDocument::AddImage and RemoveImage on images stored in nsStyleContentData.r=dbaron,a=blocker
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -5843,16 +5843,24 @@ nsRuleNode::ComputeContentData(void* aSt
   }
 
   // marker-offset: length, auto, inherit
   SetCoord(contentData.mMarkerOffset, content->mMarkerOffset, parentContent->mMarkerOffset,
            SETCOORD_LH | SETCOORD_AUTO | SETCOORD_INITIAL_AUTO |
              SETCOORD_CALC_LENGTH_ONLY,
            aContext, mPresContext, canStoreInRuleTree);
 
+  // If we ended up with an image, track it.
+  for (PRUint32 i = 0; i < content->ContentCount(); ++i) {
+    if ((content->ContentAt(i).mType == eStyleContentType_Image) &&
+        content->ContentAt(i).mContent.mImage) {
+      content->ContentAt(i).TrackImage(aContext->PresContext());
+    }
+  }
+
   COMPUTE_END_RESET(Content, content)
 }
 
 const void*
 nsRuleNode::ComputeQuotesData(void* aStartStruct,
                               const nsRuleDataStruct& aData,
                               nsStyleContext* aContext,
                               nsRuleNode* aHighestNode,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2115,16 +2115,18 @@ nsChangeHint nsStyleVisibility::CalcDiff
 nsChangeHint nsStyleVisibility::MaxDifference()
 {
   return NS_STYLE_HINT_REFLOW;
 }
 #endif
 
 nsStyleContentData::~nsStyleContentData()
 {
+  NS_ABORT_IF_FALSE(!mImageTracked,
+                    "nsStyleContentData being destroyed while still tracking image!");
   if (mType == eStyleContentType_Image) {
     NS_IF_RELEASE(mContent.mImage);
   } else if (mType == eStyleContentType_Counter ||
              mType == eStyleContentType_Counters) {
     mContent.mCounters->Release();
   } else if (mContent.mString) {
     NS_Free(mContent.mString);
   }
@@ -2170,16 +2172,59 @@ PRBool nsStyleContentData::operator==(co
             eq);
   }
   if (mType == eStyleContentType_Counter ||
       mType == eStyleContentType_Counters)
     return *mContent.mCounters == *aOther.mContent.mCounters;
   return nsCRT::strcmp(mContent.mString, aOther.mContent.mString) == 0;
 }
 
+void
+nsStyleContentData::TrackImage(nsPresContext* aContext)
+{
+  // Sanity
+  NS_ABORT_IF_FALSE(!mImageTracked, "Already tracking image!");
+  NS_ABORT_IF_FALSE(mType == eStyleContentType_Image,
+                    "Tryingto do image tracking on non-image!");
+  NS_ABORT_IF_FALSE(mContent.mImage,
+                    "Can't track image when there isn't one!");
+
+  // Register the image with the document
+  nsIDocument* doc = aContext->Document();
+  if (doc)
+    doc->AddImage(mContent.mImage);
+
+  // Mark state
+#ifdef DEBUG
+  mImageTracked = true;
+#endif
+}
+
+void
+nsStyleContentData::UntrackImage(nsPresContext* aContext)
+{
+  // Sanity
+  NS_ABORT_IF_FALSE(mImageTracked, "Image not tracked!");
+  NS_ABORT_IF_FALSE(mType == eStyleContentType_Image,
+                    "Trying to do image tracking on non-image!");
+  NS_ABORT_IF_FALSE(mContent.mImage,
+                    "Can't untrack image when there isn't one!");
+
+  // Unregister the image with the document
+  nsIDocument* doc = aContext->Document();
+  if (doc)
+    doc->RemoveImage(mContent.mImage);
+
+  // Mark state
+#ifdef DEBUG
+  mImageTracked = false;
+#endif
+}
+
+
 //-----------------------
 // nsStyleContent
 //
 
 nsStyleContent::nsStyleContent(void)
   : mMarkerOffset(),
     mContents(nsnull),
     mIncrements(nsnull),
@@ -2195,16 +2240,31 @@ nsStyleContent::nsStyleContent(void)
 nsStyleContent::~nsStyleContent(void)
 {
   MOZ_COUNT_DTOR(nsStyleContent);
   DELETE_ARRAY_IF(mContents);
   DELETE_ARRAY_IF(mIncrements);
   DELETE_ARRAY_IF(mResets);
 }
 
+void 
+nsStyleContent::Destroy(nsPresContext* aContext)
+{
+  // Unregister any images we might have with the document.
+  for (PRUint32 i = 0; i < mContentCount; ++i) {
+    if ((mContents[i].mType == eStyleContentType_Image) &&
+        mContents[i].mContent.mImage) {
+      mContents[i].UntrackImage(aContext);
+    }
+  }
+
+  this->~nsStyleContent();
+  aContext->FreeToShell(sizeof(nsStyleContent), this);
+}
+
 nsStyleContent::nsStyleContent(const nsStyleContent& aSource)
    :mMarkerOffset(),
     mContents(nsnull),
     mIncrements(nsnull),
     mResets(nsnull),
     mContentCount(0),
     mIncrementCount(0),
     mResetCount(0)
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1481,29 +1481,43 @@ enum nsStyleContentType {
 
 struct nsStyleContentData {
   nsStyleContentType  mType;
   union {
     PRUnichar *mString;
     imgIRequest *mImage;
     nsCSSValue::Array* mCounters;
   } mContent;
+#ifdef DEBUG
+  bool mImageTracked;
+#endif
 
-  nsStyleContentData() : mType(nsStyleContentType(0)) { mContent.mString = nsnull; }
+  nsStyleContentData()
+    : mType(nsStyleContentType(0))
+#ifdef DEBUG
+    , mImageTracked(false)
+#endif
+  { mContent.mString = nsnull; }
+
   ~nsStyleContentData();
   nsStyleContentData& operator=(const nsStyleContentData& aOther);
   PRBool operator==(const nsStyleContentData& aOther) const;
 
   PRBool operator!=(const nsStyleContentData& aOther) const {
     return !(*this == aOther);
   }
 
+  void TrackImage(nsPresContext* aContext);
+  void UntrackImage(nsPresContext* aContext);
+
   void SetImage(imgIRequest* aRequest)
   {
-    NS_ASSERTION(mType == eStyleContentType_Image, "Wrong type!");
+    NS_ABORT_IF_FALSE(!mImageTracked,
+                      "Setting a new image without untracking the old one!");
+    NS_ABORT_IF_FALSE(mType == eStyleContentType_Image, "Wrong type!");
     NS_IF_ADDREF(mContent.mImage = aRequest);
   }
 private:
   nsStyleContentData(const nsStyleContentData&); // not to be implemented
 };
 
 struct nsStyleCounterData {
   nsString  mCounter;
@@ -1590,20 +1604,17 @@ protected:
 struct nsStyleContent {
   nsStyleContent(void);
   nsStyleContent(const nsStyleContent& aContent);
   ~nsStyleContent(void);
 
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
     return aContext->AllocateFromShell(sz);
   }
-  void Destroy(nsPresContext* aContext) {
-    this->~nsStyleContent();
-    aContext->FreeToShell(sizeof(nsStyleContent), this);
-  }
+  void Destroy(nsPresContext* aContext);
 
   nsChangeHint CalcDifference(const nsStyleContent& aOther) const;
 #ifdef DEBUG
   static nsChangeHint MaxDifference();
 #endif
   static PRBool ForceCompare() { return PR_FALSE; }
 
   PRUint32  ContentCount(void) const  { return mContentCount; } // [reset]