diff --git a/layout/svg/nsSVGEffects.cpp b/layout/svg/nsSVGEffects.cpp index f1b50c9437e1..d80eb6f9f0bf 100644 --- a/layout/svg/nsSVGEffects.cpp +++ b/layout/svg/nsSVGEffects.cpp @@ -245,39 +245,37 @@ nsSVGFilterReference::GetFilterFrame() void nsSVGFilterReference::DoUpdate() { - nsSVGRenderingObserverProperty::DoUpdate(); + nsSVGIDRenderingObserver::DoUpdate(); - nsIFrame* frame = mFrameReference.Get(); - if (!frame) - return; - - // Repaint asynchronously in case the filter frame is being torn down - nsChangeHint changeHint = - nsChangeHint(nsChangeHint_RepaintFrame); - - // Don't need to request UpdateOverflow if we're being reflowed. - if (!(frame->GetStateBits() & NS_FRAME_IN_REFLOW)) { - NS_UpdateHint(changeHint, nsChangeHint_UpdateOverflow); + if (mFilterChainObserver) { + mFilterChainObserver->Invalidate(); } - frame->PresContext()->RestyleManager()->PostRestyleEvent( - frame->GetContent()->AsElement(), nsRestyleHint(0), changeHint); } NS_IMPL_ISUPPORTS(nsSVGFilterProperty, nsISupports) nsSVGFilterProperty::nsSVGFilterProperty(const nsTArray &aFilters, nsIFrame *aFilteredFrame) + : mFrameReference(aFilteredFrame) { + nsIContent* filteredElement = aFilteredFrame->GetContent(); for (uint32_t i = 0; i < aFilters.Length(); i++) { if (aFilters[i].GetType() != NS_STYLE_FILTER_URL) continue; nsRefPtr reference = - new nsSVGFilterReference(aFilters[i].GetURL(), aFilteredFrame); + new nsSVGFilterReference(aFilters[i].GetURL(), filteredElement, this); mReferences.AppendElement(reference); } } +nsSVGFilterProperty::~nsSVGFilterProperty() +{ + for (uint32_t i = 0; i < mReferences.Length(); i++) { + mReferences[i]->DetachFromChainObserver(); + } +} + bool nsSVGFilterProperty::ReferencesValidResources() { @@ -299,11 +297,28 @@ nsSVGFilterProperty::IsInObserverLists() const } void -nsSVGFilterProperty::Invalidate() +nsSVGFilterProperty::DoUpdate() { - for (uint32_t i = 0; i < mReferences.Length(); i++) { - mReferences[i]->Invalidate(); + nsIFrame* frame = mFrameReference.Get(); + if (!frame) + return; + + if (frame && frame->IsFrameOfType(nsIFrame::eSVG)) { + // Changes should propagate out to things that might be observing + // the referencing frame or its ancestors. + nsSVGEffects::InvalidateRenderingObservers(frame); } + + // Repaint asynchronously in case the filter frame is being torn down + nsChangeHint changeHint = + nsChangeHint(nsChangeHint_RepaintFrame); + + // Don't need to request UpdateOverflow if we're being reflowed. + if (!(frame->GetStateBits() & NS_FRAME_IN_REFLOW)) { + NS_UpdateHint(changeHint, nsChangeHint_UpdateOverflow); + } + frame->PresContext()->RestyleManager()->PostRestyleEvent( + frame->GetContent()->AsElement(), nsRestyleHint(0), changeHint); } void diff --git a/layout/svg/nsSVGEffects.h b/layout/svg/nsSVGEffects.h index 81e7b40be8f6..26ddde338351 100644 --- a/layout/svg/nsSVGEffects.h +++ b/layout/svg/nsSVGEffects.h @@ -29,6 +29,7 @@ class nsSVGClipPathFrame; class nsSVGPaintServerFrame; class nsSVGFilterFrame; class nsSVGMaskFrame; +class nsSVGFilterProperty; /* * This interface allows us to be notified when a piece of SVG content is @@ -197,13 +198,20 @@ protected: * The nsSVGFilterProperty class manages a list of nsSVGFilterReferences. */ class nsSVGFilterReference MOZ_FINAL : - public nsSVGRenderingObserverProperty, public nsISVGFilterReference { + public nsSVGIDRenderingObserver, public nsISVGFilterReference { public: - nsSVGFilterReference(nsIURI *aURI, nsIFrame *aFilteredFrame) - : nsSVGRenderingObserverProperty(aURI, aFilteredFrame, false) {} + nsSVGFilterReference(nsIURI* aURI, + nsIContent* aObservingContent, + nsSVGFilterProperty* aFilterChainObserver) + : nsSVGIDRenderingObserver(aURI, aObservingContent, false) + , mFilterChainObserver(aFilterChainObserver) + { + } bool ReferencesValidResource() { return GetFilterFrame(); } + void DetachFromChainObserver() { mFilterChainObserver = nullptr; } + /** * @return the filter frame, or null if there is no filter frame */ @@ -218,9 +226,11 @@ public: protected: virtual ~nsSVGFilterReference() {} -private: - // nsSVGRenderingObserverProperty + // nsSVGIDRenderingObserver virtual void DoUpdate() MOZ_OVERRIDE; + +private: + nsSVGFilterProperty* mFilterChainObserver; }; /** @@ -240,16 +250,19 @@ public: bool ReferencesValidResources(); bool IsInObserverLists() const; - void Invalidate(); + void Invalidate() { DoUpdate(); } // nsISupports NS_DECL_ISUPPORTS protected: - virtual ~nsSVGFilterProperty() {} + virtual ~nsSVGFilterProperty(); + + virtual void DoUpdate(); private: nsTArray> mReferences; + nsSVGFrameReferenceFromProperty mFrameReference; }; class nsSVGMarkerProperty : public nsSVGRenderingObserverProperty {