Bug 375775 - filter crash with display:none. r+sr=roc
authortor@cs.brown.edu
Thu, 05 Apr 2007 06:23:21 -0700
changeset 366 44c5e1b29bf7574ca8235d4967c244511aeabab4
parent 365 1643d72c75c3a2b81aca6affa49e7e59139c26cc
child 367 bdd7973f1da341456579a62367b9087dbe691921
push idunknown
push userunknown
push dateunknown
bugs375775
milestone1.9a4pre
Bug 375775 - filter crash with display:none. r+sr=roc
layout/svg/base/src/nsSVGFilterFrame.cpp
layout/svg/base/src/nsSVGFilterFrame.h
layout/svg/base/src/nsSVGUtils.cpp
--- a/layout/svg/base/src/nsSVGFilterFrame.cpp
+++ b/layout/svg/base/src/nsSVGFilterFrame.cpp
@@ -52,41 +52,26 @@
 #include "gfxImageSurface.h"
 
 nsIFrame*
 NS_NewSVGFilterFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext)
 {
   return new (aPresShell) nsSVGFilterFrame(aContext);
 }
 
-nsSVGFilterFrame *
-NS_GetSVGFilterFrame(nsIURI *aURI, nsIContent *aContent)
+nsIContent *
+NS_GetSVGFilterElement(nsIURI *aURI, nsIContent *aContent)
 {
-  // Get the PresShell
-  nsIDocument *myDoc = aContent->GetCurrentDoc();
-  if (!myDoc) {
-    NS_WARNING("No document for this content!");
-    return nsnull;
-  }
-  nsIPresShell *presShell = myDoc->GetShellAt(0);
-  if (!presShell) {
-    NS_WARNING("no presshell");
-    return nsnull;
-  }
+  nsIContent* content = nsContentUtils::GetReferencedElement(aURI, aContent);
 
-  // Find the referenced frame
-  nsIFrame *filter;
-  if (!NS_SUCCEEDED(nsSVGUtils::GetReferencedFrame(&filter, aURI, aContent, presShell)))
-    return nsnull;
+  nsCOMPtr<nsIDOMSVGFilterElement> filter = do_QueryInterface(content);
+  if (filter)
+    return content;
 
-  nsIAtom* frameType = filter->GetType();
-  if (frameType != nsGkAtoms::svgFilterFrame)
-    return nsnull;
-
-  return NS_STATIC_CAST(nsSVGFilterFrame *, filter);
+  return nsnull;
 }
 
 NS_IMETHODIMP
 nsSVGFilterFrame::InitSVG()
 {
   nsresult rv = nsSVGFilterFrameBase::InitSVG();
   if (NS_FAILED(rv))
     return rv;
--- a/layout/svg/base/src/nsSVGFilterFrame.h
+++ b/layout/svg/base/src/nsSVGFilterFrame.h
@@ -65,12 +65,12 @@ public:
   virtual nsIAtom* GetType() const;
 
 private:
   // implementation helpers
   void FilterFailCleanup(nsSVGRenderState *aContext,
                          nsISVGChildFrame *aTarget);
 };
 
-nsSVGFilterFrame *
-NS_GetSVGFilterFrame(nsIURI *aURI, nsIContent *aContent);
+nsIContent *
+NS_GetSVGFilterElement(nsIURI *aURI, nsIContent *aContent);
 
 #endif
--- a/layout/svg/base/src/nsSVGUtils.cpp
+++ b/layout/svg/base/src/nsSVGUtils.cpp
@@ -78,20 +78,20 @@
 #include "gfxMatrix.h"
 #include "gfxRect.h"
 #include "gfxImageSurface.h"
 #include "gfxMatrix.h"
 #include "nsStubMutationObserver.h"
 
 class nsSVGFilterProperty : public nsStubMutationObserver {
 public:
-  nsSVGFilterProperty(nsSVGFilterFrame *aFilter, nsIFrame *aFrame);
+  nsSVGFilterProperty(nsIContent *aFilter, nsIFrame *aFilteredFrame);
 
   nsRect GetRect() { return mFilterRect; }
-  nsSVGFilterFrame *GetFilterFrame() { return mFilter; }
+  nsSVGFilterFrame *GetFilterFrame();
   void RemoveMutationObserver();
 
   // nsISupports
   NS_DECL_ISUPPORTS
 
   // nsIMutationObserver
   virtual void AttributeChanged(nsIDocument* aDocument, nsIContent* aContent,
                                 PRInt32 aNameSpaceID, nsIAtom* aAttribute,
@@ -103,54 +103,68 @@ public:
   virtual void ContentRemoved(nsIDocument* aDocument, nsIContent* aContainer,
                               nsIContent* aChild, PRInt32 aIndexInContainer);
   virtual void ParentChainChanged(nsIContent *aContent);
 
 private:
   void DoUpdate();
 
   nsWeakPtr mObservedFilter;
-  nsSVGFilterFrame *mFilter;
   nsIFrame *mFrame;  // frame being filtered
   nsRect mFilterRect;
 };
 
 NS_IMPL_ISUPPORTS1(nsSVGFilterProperty, nsIMutationObserver)
 
-nsSVGFilterProperty::nsSVGFilterProperty(nsSVGFilterFrame *aFilter,
-                                         nsIFrame *aFrame)
-  : mFilter(aFilter), mFrame(aFrame)
+nsSVGFilterProperty::nsSVGFilterProperty(nsIContent *aFilter,
+                                         nsIFrame *aFilteredFrame)
+  : mFrame(aFilteredFrame)
 {
-  mFilterRect = mFilter->GetInvalidationRegion(mFrame);
+  mObservedFilter = do_GetWeakReference(aFilter);
+
+  nsSVGFilterFrame *filter = GetFilterFrame();
+  if (filter)
+    mFilterRect = filter->GetInvalidationRegion(mFrame);
+
+  aFilter->AddMutationObserver(this);
+}
 
-  nsIFrame *filter = nsnull;
-  CallQueryInterface(mFilter, &filter);
+nsSVGFilterFrame *
+nsSVGFilterProperty::GetFilterFrame()
+{
+  nsCOMPtr<nsIContent> filter = do_QueryReferent(mObservedFilter);
+  if (filter) {
+    nsIFrame *frame =
+      NS_STATIC_CAST(nsGenericElement*, filter.get())->GetPrimaryFrame();
+    if (frame && frame->GetType() == nsGkAtoms::svgFilterFrame)
+      return NS_STATIC_CAST(nsSVGFilterFrame*, frame);
+  }
 
-  nsCOMPtr<nsIContent> filterContent = filter->GetContent();
-  mObservedFilter = do_GetWeakReference(filterContent);
-
-  filterContent->AddMutationObserver(this);
+  return nsnull;
 }
 
 void
 nsSVGFilterProperty::RemoveMutationObserver()
 {
   nsCOMPtr<nsIContent> filter = do_QueryReferent(mObservedFilter);
   if (filter)
     filter->RemoveMutationObserver(this);
 }
 
 void
 nsSVGFilterProperty::DoUpdate()
 {
   nsSVGOuterSVGFrame *outerSVGFrame = nsSVGUtils::GetOuterSVGFrame(mFrame);
   if (outerSVGFrame) {
     outerSVGFrame->InvalidateRect(mFilterRect);
-    mFilterRect = mFilter->GetInvalidationRegion(mFrame);
-    outerSVGFrame->InvalidateRect(mFilterRect);
+    nsSVGFilterFrame *filter = GetFilterFrame();
+    if (filter) {
+      mFilterRect = filter->GetInvalidationRegion(mFrame);
+      outerSVGFrame->InvalidateRect(mFilterRect);
+    }
   }
 }
 
 void
 nsSVGFilterProperty::AttributeChanged(nsIDocument *aDocument,
                                       nsIContent *aContent,
                                       PRInt32 aNameSpaceID,
                                       nsIAtom *aAttribute,
@@ -771,18 +785,18 @@ nsSVGUtils::RemoveObserver(nsISupports *
 // Effect helper functions
 
 static void
 AddEffectProperties(nsIFrame *aFrame)
 {
   const nsStyleSVGReset *style = aFrame->GetStyleSVGReset();
 
   if (style->mFilter && !(aFrame->GetStateBits() & NS_STATE_SVG_FILTERED)) {
-    nsSVGFilterFrame *filter = NS_GetSVGFilterFrame(style->mFilter,
-                                                    aFrame->GetContent());
+    nsIContent *filter = NS_GetSVGFilterElement(style->mFilter,
+                                                aFrame->GetContent());
     if (filter) {
       nsSVGFilterProperty *property = new nsSVGFilterProperty(filter, aFrame);
       if (!property) {
         NS_ERROR("Could not create filter property");
         return;
       }
       NS_ADDREF(property); // addref to allow QI - FilterPropertyDtor releases
       aFrame->SetProperty(nsGkAtoms::filter,
@@ -942,17 +956,19 @@ nsSVGUtils::PaintChildWithEffects(nsSVGR
     clip->ClipPaint(aContext, svgChildFrame, matrix);
   }
 
   /* Paint the child */
   if (state & NS_STATE_SVG_FILTERED) {
     nsSVGFilterProperty *property;
     property = NS_STATIC_CAST(nsSVGFilterProperty *,
                               aFrame->GetProperty(nsGkAtoms::filter));
-    property->GetFilterFrame()->FilterPaint(aContext, svgChildFrame);
+    nsSVGFilterFrame *filter = property->GetFilterFrame();
+    if (filter)
+      filter->FilterPaint(aContext, svgChildFrame);
   } else {
     svgChildFrame->PaintSVG(aContext, aDirtyRect);
   }
 
   if (state & NS_STATE_SVG_CLIPPED_TRIVIAL) {
     gfx->Restore();
   }