1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsSVGEffects.h"
9 // Keep others in (case-insensitive) order:
10 #include "nsCSSFrameConstructor.h"
11 #include "nsISupportsImpl.h"
12 #include "nsSVGClipPathFrame.h"
13 #include "nsSVGPaintServerFrame.h"
14 #include "nsSVGPathGeometryElement.h"
15 #include "nsSVGFilterFrame.h"
16 #include "nsSVGMaskFrame.h"
17 #include "nsIReflowCallback.h"
18 #include "RestyleManager.h"
20 using namespace mozilla
;
21 using namespace mozilla::dom
;
23 // nsSVGRenderingObserver impl
24 NS_IMPL_ISUPPORTS(nsSVGRenderingObserver
, nsIMutationObserver
)
27 nsSVGRenderingObserver::StartListening()
29 Element
* target
= GetTarget();
31 target
->AddMutationObserver(this);
36 nsSVGRenderingObserver::StopListening()
38 Element
* target
= GetTarget();
41 target
->RemoveMutationObserver(this);
42 if (mInObserverList
) {
43 nsSVGEffects::RemoveRenderingObserver(target
, this);
44 mInObserverList
= false;
47 NS_ASSERTION(!mInObserverList
, "still in an observer list?");
53 * Note that in the current setup there are two separate observer lists.
55 * In nsSVGIDRenderingObserver's ctor, the new object adds itself to the
56 * mutation observer list maintained by the referenced element. In this way the
57 * nsSVGIDRenderingObserver is notified if there are any attribute or content
58 * tree changes to the element or any of its *descendants*.
60 * In nsSVGIDRenderingObserver::GetReferencedElement() the
61 * nsSVGIDRenderingObserver object also adds itself to an
62 * nsSVGRenderingObserverList object belonging to the referenced
65 * XXX: it would be nice to have a clear and concise executive summary of the
66 * benefits/necessity of maintaining a second observer list.
69 nsSVGIDRenderingObserver::nsSVGIDRenderingObserver(nsIURI
*aURI
,
72 : mElement(MOZ_THIS_IN_INITIALIZER_LIST()), mFrame(aFrame
),
73 mFramePresShell(aFrame
->PresContext()->PresShell())
75 // Start watching the target element
76 mElement
.Reset(aFrame
->GetContent(), aURI
, true, aReferenceImage
);
80 nsSVGIDRenderingObserver::~nsSVGIDRenderingObserver()
85 static nsSVGRenderingObserverList
*
86 GetObserverList(Element
*aElement
)
88 return static_cast<nsSVGRenderingObserverList
*>
89 (aElement
->GetProperty(nsGkAtoms::renderingobserverlist
));
93 nsSVGRenderingObserver::GetReferencedElement()
95 Element
* target
= GetTarget();
98 nsSVGRenderingObserverList
*observerList
= GetObserverList(target
);
99 bool inObserverList
= observerList
&& observerList
->Contains(this);
100 NS_ASSERTION(inObserverList
== mInObserverList
, "failed to track whether we're in our referenced element's observer list!");
102 NS_ASSERTION(!mInObserverList
, "In whose observer list are we, then?");
105 if (target
&& !mInObserverList
) {
106 nsSVGEffects::AddRenderingObserver(target
, this);
107 mInObserverList
= true;
113 nsSVGRenderingObserver::GetReferencedFrame()
115 Element
* referencedElement
= GetReferencedElement();
116 return referencedElement
? referencedElement
->GetPrimaryFrame() : nullptr;
120 nsSVGRenderingObserver::GetReferencedFrame(nsIAtom
* aFrameType
, bool* aOK
)
122 nsIFrame
* frame
= GetReferencedFrame();
124 if (frame
->GetType() == aFrameType
)
134 nsSVGIDRenderingObserver::DoUpdate()
136 if (mFramePresShell
->IsDestroying()) {
137 // mFrame is no longer valid. Bail out.
141 if (mElement
.get() && mInObserverList
) {
142 nsSVGEffects::RemoveRenderingObserver(mElement
.get(), this);
143 mInObserverList
= false;
145 if (mFrame
&& mFrame
->IsFrameOfType(nsIFrame::eSVG
)) {
146 // Changes should propagate out to things that might be observing
147 // the referencing frame or its ancestors.
148 nsSVGEffects::InvalidateRenderingObservers(mFrame
);
153 nsSVGRenderingObserver::InvalidateViaReferencedElement()
155 mInObserverList
= false;
160 nsSVGRenderingObserver::NotifyEvictedFromRenderingObserverList()
162 mInObserverList
= false; // We've been removed from rendering-obs. list.
163 StopListening(); // Remove ourselves from mutation-obs. list.
167 nsSVGRenderingObserver::AttributeChanged(nsIDocument
* aDocument
,
168 dom::Element
* aElement
,
169 int32_t aNameSpaceID
,
173 // An attribute belonging to the element that we are observing *or one of its
174 // descendants* has changed.
176 // In the case of observing a gradient element, say, we want to know if any
177 // of its 'stop' element children change, but we don't actually want to do
178 // anything for changes to SMIL element children, for example. Maybe it's not
179 // worth having logic to optimize for that, but in most cases it could be a
182 // XXXjwatt: do we really want to blindly break the link between our
183 // observers and ourselves for all attribute changes? For non-ID changes
184 // surely that is unnecessary.
190 nsSVGRenderingObserver::ContentAppended(nsIDocument
*aDocument
,
191 nsIContent
*aContainer
,
192 nsIContent
*aFirstNewContent
,
193 int32_t /* unused */)
199 nsSVGRenderingObserver::ContentInserted(nsIDocument
*aDocument
,
200 nsIContent
*aContainer
,
202 int32_t /* unused */)
208 nsSVGRenderingObserver::ContentRemoved(nsIDocument
*aDocument
,
209 nsIContent
*aContainer
,
211 int32_t aIndexInContainer
,
212 nsIContent
*aPreviousSibling
)
217 NS_IMPL_ISUPPORTS(nsSVGFilterProperty
, nsISupports
)
219 nsSVGFilterProperty::nsSVGFilterProperty(const nsTArray
<nsStyleFilter
> &aFilters
,
220 nsIFrame
*aFilteredFrame
) :
223 for (uint32_t i
= 0; i
< mFilters
.Length(); i
++) {
224 if (mFilters
[i
].GetType() != NS_STYLE_FILTER_URL
)
227 nsSVGFilterReference
*reference
=
228 new nsSVGFilterReference(mFilters
[i
].GetURL(), aFilteredFrame
);
229 NS_ADDREF(reference
);
230 mReferences
.AppendElement(reference
);
234 nsSVGFilterProperty::~nsSVGFilterProperty()
236 for (uint32_t i
= 0; i
< mReferences
.Length(); i
++) {
237 NS_RELEASE(mReferences
[i
]);
242 nsSVGFilterProperty::ReferencesValidResources()
244 for (uint32_t i
= 0; i
< mReferences
.Length(); i
++) {
245 if (!mReferences
[i
]->ReferencesValidResource())
252 nsSVGFilterProperty::IsInObserverLists() const
254 for (uint32_t i
= 0; i
< mReferences
.Length(); i
++) {
255 if (!mReferences
[i
]->IsInObserverList())
262 nsSVGFilterProperty::Invalidate()
264 for (uint32_t i
= 0; i
< mReferences
.Length(); i
++) {
265 mReferences
[i
]->Invalidate();
269 NS_IMPL_ISUPPORTS_INHERITED(nsSVGFilterReference
,
270 nsSVGIDRenderingObserver
,
271 nsISVGFilterReference
);
274 nsSVGFilterReference::GetFilterFrame()
276 return static_cast<nsSVGFilterFrame
*>
277 (GetReferencedFrame(nsGkAtoms::svgFilterFrame
, nullptr));
281 InvalidateAllContinuations(nsIFrame
* aFrame
)
283 for (nsIFrame
* f
= aFrame
; f
;
284 f
= nsLayoutUtils::GetNextContinuationOrIBSplitSibling(f
)) {
285 f
->InvalidateFrame();
290 nsSVGFilterReference::DoUpdate()
292 nsSVGIDRenderingObserver::DoUpdate();
296 // Repaint asynchronously in case the filter frame is being torn down
297 nsChangeHint changeHint
=
298 nsChangeHint(nsChangeHint_RepaintFrame
);
300 // Don't need to request UpdateOverflow if we're being reflowed.
301 if (!(mFrame
->GetStateBits() & NS_FRAME_IN_REFLOW
)) {
302 NS_UpdateHint(changeHint
, nsChangeHint_UpdateOverflow
);
304 mFramePresShell
->GetPresContext()->RestyleManager()->PostRestyleEvent(
305 mFrame
->GetContent()->AsElement(), nsRestyleHint(0), changeHint
);
309 nsSVGMarkerProperty::DoUpdate()
311 nsSVGIDRenderingObserver::DoUpdate();
315 NS_ASSERTION(mFrame
->IsFrameOfType(nsIFrame::eSVG
), "SVG frame expected");
317 // Repaint asynchronously in case the marker frame is being torn down
318 nsChangeHint changeHint
=
319 nsChangeHint(nsChangeHint_RepaintFrame
);
321 // Don't need to request ReflowFrame if we're being reflowed.
322 if (!(mFrame
->GetStateBits() & NS_FRAME_IN_REFLOW
)) {
323 // XXXjwatt: We need to unify SVG into standard reflow so we can just use
324 // nsChangeHint_NeedReflow | nsChangeHint_NeedDirtyReflow here.
325 nsSVGEffects::InvalidateRenderingObservers(mFrame
);
326 // XXXSDL KILL THIS!!!
327 nsSVGUtils::ScheduleReflowSVG(mFrame
);
329 mFramePresShell
->GetPresContext()->RestyleManager()->PostRestyleEvent(
330 mFrame
->GetContent()->AsElement(), nsRestyleHint(0), changeHint
);
334 nsSVGTextPathProperty::TargetIsValid()
336 Element
* target
= GetTarget();
337 return target
&& target
->IsSVG(nsGkAtoms::path
);
341 nsSVGTextPathProperty::DoUpdate()
343 nsSVGIDRenderingObserver::DoUpdate();
347 NS_ASSERTION(mFrame
->IsFrameOfType(nsIFrame::eSVG
) || mFrame
->IsSVGText(),
348 "SVG frame expected");
350 // Avoid getting into an infinite loop of reflows if the <textPath> is
351 // pointing to one of its ancestors. TargetIsValid returns true iff
352 // the target element is a <path> element, and we would not have this
353 // nsSVGTextPathProperty if this <textPath> were a descendant of the
356 // Note that we still have to post the restyle event when we
357 // change from being valid to invalid, so that mPositions on the
358 // SVGTextFrame gets updated, skipping the <textPath>, ensuring
359 // that nothing gets painted for that element.
360 bool nowValid
= TargetIsValid();
361 if (!mValid
&& !nowValid
) {
362 // Just return if we were previously invalid, and are still invalid.
367 // Repaint asynchronously in case the path frame is being torn down
368 nsChangeHint changeHint
=
369 nsChangeHint(nsChangeHint_RepaintFrame
| nsChangeHint_UpdateTextPath
);
370 mFramePresShell
->GetPresContext()->RestyleManager()->PostRestyleEvent(
371 mFrame
->GetContent()->AsElement(), nsRestyleHint(0), changeHint
);
375 nsSVGPaintingProperty::DoUpdate()
377 nsSVGIDRenderingObserver::DoUpdate();
381 if (mFrame
->GetStateBits() & NS_FRAME_SVG_LAYOUT
) {
382 nsSVGEffects::InvalidateRenderingObservers(mFrame
);
383 mFrame
->InvalidateFrameSubtree();
385 InvalidateAllContinuations(mFrame
);
389 static nsSVGRenderingObserver
*
390 CreateMarkerProperty(nsIURI
*aURI
, nsIFrame
*aFrame
, bool aReferenceImage
)
391 { return new nsSVGMarkerProperty(aURI
, aFrame
, aReferenceImage
); }
393 static nsSVGRenderingObserver
*
394 CreateTextPathProperty(nsIURI
*aURI
, nsIFrame
*aFrame
, bool aReferenceImage
)
395 { return new nsSVGTextPathProperty(aURI
, aFrame
, aReferenceImage
); }
397 static nsSVGRenderingObserver
*
398 CreatePaintingProperty(nsIURI
*aURI
, nsIFrame
*aFrame
, bool aReferenceImage
)
399 { return new nsSVGPaintingProperty(aURI
, aFrame
, aReferenceImage
); }
401 static nsSVGRenderingObserver
*
402 GetEffectProperty(nsIURI
*aURI
, nsIFrame
*aFrame
,
403 const FramePropertyDescriptor
*aProperty
,
404 nsSVGRenderingObserver
* (* aCreate
)(nsIURI
*, nsIFrame
*, bool))
409 FrameProperties props
= aFrame
->Properties();
410 nsSVGRenderingObserver
*prop
=
411 static_cast<nsSVGRenderingObserver
*>(props
.Get(aProperty
));
414 prop
= aCreate(aURI
, aFrame
, false);
418 props
.Set(aProperty
, static_cast<nsISupports
*>(prop
));
422 static nsSVGFilterProperty
*
423 GetOrCreateFilterProperty(nsIFrame
*aFrame
)
425 const nsStyleSVGReset
* style
= aFrame
->StyleSVGReset();
426 if (!style
->HasFilters())
429 FrameProperties props
= aFrame
->Properties();
430 nsSVGFilterProperty
*prop
=
431 static_cast<nsSVGFilterProperty
*>(props
.Get(nsSVGEffects::FilterProperty()));
434 prop
= new nsSVGFilterProperty(style
->mFilters
, aFrame
);
438 props
.Set(nsSVGEffects::FilterProperty(), static_cast<nsISupports
*>(prop
));
442 nsSVGMarkerProperty
*
443 nsSVGEffects::GetMarkerProperty(nsIURI
*aURI
, nsIFrame
*aFrame
,
444 const FramePropertyDescriptor
*aProp
)
446 NS_ABORT_IF_FALSE(aFrame
->GetType() == nsGkAtoms::svgPathGeometryFrame
&&
447 static_cast<nsSVGPathGeometryElement
*>(aFrame
->GetContent())->IsMarkable(),
449 return static_cast<nsSVGMarkerProperty
*>(
450 GetEffectProperty(aURI
, aFrame
, aProp
, CreateMarkerProperty
));
453 nsSVGTextPathProperty
*
454 nsSVGEffects::GetTextPathProperty(nsIURI
*aURI
, nsIFrame
*aFrame
,
455 const FramePropertyDescriptor
*aProp
)
457 return static_cast<nsSVGTextPathProperty
*>(
458 GetEffectProperty(aURI
, aFrame
, aProp
, CreateTextPathProperty
));
461 nsSVGPaintingProperty
*
462 nsSVGEffects::GetPaintingProperty(nsIURI
*aURI
, nsIFrame
*aFrame
,
463 const FramePropertyDescriptor
*aProp
)
465 return static_cast<nsSVGPaintingProperty
*>(
466 GetEffectProperty(aURI
, aFrame
, aProp
, CreatePaintingProperty
));
469 static nsSVGRenderingObserver
*
470 GetEffectPropertyForURI(nsIURI
*aURI
, nsIFrame
*aFrame
,
471 const FramePropertyDescriptor
*aProperty
,
472 nsSVGRenderingObserver
* (* aCreate
)(nsIURI
*, nsIFrame
*, bool))
477 FrameProperties props
= aFrame
->Properties();
478 nsSVGEffects::URIObserverHashtable
*hashtable
=
479 static_cast<nsSVGEffects::URIObserverHashtable
*>(props
.Get(aProperty
));
481 hashtable
= new nsSVGEffects::URIObserverHashtable();
482 props
.Set(aProperty
, hashtable
);
484 nsSVGRenderingObserver
* prop
=
485 static_cast<nsSVGRenderingObserver
*>(hashtable
->GetWeak(aURI
));
487 bool watchImage
= aProperty
== nsSVGEffects::BackgroundImageProperty();
488 prop
= aCreate(aURI
, aFrame
, watchImage
);
489 hashtable
->Put(aURI
, prop
);
494 nsSVGPaintingProperty
*
495 nsSVGEffects::GetPaintingPropertyForURI(nsIURI
*aURI
, nsIFrame
*aFrame
,
496 const FramePropertyDescriptor
*aProp
)
498 return static_cast<nsSVGPaintingProperty
*>(
499 GetEffectPropertyForURI(aURI
, aFrame
, aProp
, CreatePaintingProperty
));
502 nsSVGEffects::EffectProperties
503 nsSVGEffects::GetEffectProperties(nsIFrame
*aFrame
)
505 NS_ASSERTION(!aFrame
->GetPrevContinuation(), "aFrame should be first continuation");
507 EffectProperties result
;
508 const nsStyleSVGReset
*style
= aFrame
->StyleSVGReset();
509 result
.mFilter
= GetOrCreateFilterProperty(aFrame
);
511 GetPaintingProperty(style
->mClipPath
, aFrame
, ClipPathProperty());
513 GetPaintingProperty(style
->mMask
, aFrame
, MaskProperty());
517 nsSVGPaintServerFrame
*
518 nsSVGEffects::GetPaintServer(nsIFrame
*aTargetFrame
, const nsStyleSVGPaint
*aPaint
,
519 const FramePropertyDescriptor
*aType
)
521 if (aPaint
->mType
!= eStyleSVGPaintType_Server
)
524 nsIFrame
*frame
= aTargetFrame
->GetContent()->IsNodeOfType(nsINode::eTEXT
) ?
525 aTargetFrame
->GetParent() : aTargetFrame
;
526 nsSVGPaintingProperty
*property
=
527 nsSVGEffects::GetPaintingProperty(aPaint
->mPaint
.mPaintServer
, frame
, aType
);
530 nsIFrame
*result
= property
->GetReferencedFrame();
534 nsIAtom
*type
= result
->GetType();
535 if (type
!= nsGkAtoms::svgLinearGradientFrame
&&
536 type
!= nsGkAtoms::svgRadialGradientFrame
&&
537 type
!= nsGkAtoms::svgPatternFrame
)
540 return static_cast<nsSVGPaintServerFrame
*>(result
);
544 nsSVGEffects::EffectProperties::GetClipPathFrame(bool *aOK
)
548 nsSVGClipPathFrame
*frame
= static_cast<nsSVGClipPathFrame
*>
549 (mClipPath
->GetReferencedFrame(nsGkAtoms::svgClipPathFrame
, aOK
));
550 if (frame
&& aOK
&& *aOK
) {
551 *aOK
= frame
->IsValid();
557 nsSVGEffects::EffectProperties::GetMaskFrame(bool *aOK
)
561 return static_cast<nsSVGMaskFrame
*>
562 (mMask
->GetReferencedFrame(nsGkAtoms::svgMaskFrame
, aOK
));
566 nsSVGEffects::UpdateEffects(nsIFrame
*aFrame
)
568 NS_ASSERTION(aFrame
->GetContent()->IsElement(),
569 "aFrame's content should be an element");
571 FrameProperties props
= aFrame
->Properties();
572 props
.Delete(FilterProperty());
573 props
.Delete(MaskProperty());
574 props
.Delete(ClipPathProperty());
575 props
.Delete(MarkerBeginProperty());
576 props
.Delete(MarkerMiddleProperty());
577 props
.Delete(MarkerEndProperty());
578 props
.Delete(FillProperty());
579 props
.Delete(StrokeProperty());
580 props
.Delete(BackgroundImageProperty());
582 // Ensure that the filter is repainted correctly
583 // We can't do that in DoUpdate as the referenced frame may not be valid
584 GetOrCreateFilterProperty(aFrame
);
586 if (aFrame
->GetType() == nsGkAtoms::svgPathGeometryFrame
&&
587 static_cast<nsSVGPathGeometryElement
*>(aFrame
->GetContent())->IsMarkable()) {
588 // Set marker properties here to avoid reference loops
589 const nsStyleSVG
*style
= aFrame
->StyleSVG();
590 GetEffectProperty(style
->mMarkerStart
, aFrame
, MarkerBeginProperty(),
591 CreateMarkerProperty
);
592 GetEffectProperty(style
->mMarkerMid
, aFrame
, MarkerMiddleProperty(),
593 CreateMarkerProperty
);
594 GetEffectProperty(style
->mMarkerEnd
, aFrame
, MarkerEndProperty(),
595 CreateMarkerProperty
);
599 nsSVGFilterProperty
*
600 nsSVGEffects::GetFilterProperty(nsIFrame
*aFrame
)
602 NS_ASSERTION(!aFrame
->GetPrevContinuation(), "aFrame should be first continuation");
604 if (!aFrame
->StyleSVGReset()->HasFilters())
607 return static_cast<nsSVGFilterProperty
*>
608 (aFrame
->Properties().Get(FilterProperty()));
611 static PLDHashOperator
612 GatherEnumerator(nsPtrHashKey
<nsSVGRenderingObserver
>* aEntry
, void* aArg
)
614 nsTArray
<nsSVGRenderingObserver
*>* array
=
615 static_cast<nsTArray
<nsSVGRenderingObserver
*>*>(aArg
);
616 array
->AppendElement(aEntry
->GetKey());
618 return PL_DHASH_REMOVE
;
621 static PLDHashOperator
622 GatherEnumeratorForReflow(nsPtrHashKey
<nsSVGRenderingObserver
>* aEntry
, void* aArg
)
624 if (!aEntry
->GetKey()->ObservesReflow()) {
625 return PL_DHASH_NEXT
;
628 nsTArray
<nsSVGRenderingObserver
*>* array
=
629 static_cast<nsTArray
<nsSVGRenderingObserver
*>*>(aArg
);
630 array
->AppendElement(aEntry
->GetKey());
632 return PL_DHASH_REMOVE
;
636 nsSVGRenderingObserverList::InvalidateAll()
638 if (mObservers
.Count() == 0)
641 nsAutoTArray
<nsSVGRenderingObserver
*,10> observers
;
643 // The PL_DHASH_REMOVE in GatherEnumerator drops all our observers here:
644 mObservers
.EnumerateEntries(GatherEnumerator
, &observers
);
646 for (uint32_t i
= 0; i
< observers
.Length(); ++i
) {
647 observers
[i
]->InvalidateViaReferencedElement();
652 nsSVGRenderingObserverList::InvalidateAllForReflow()
654 if (mObservers
.Count() == 0)
657 nsAutoTArray
<nsSVGRenderingObserver
*,10> observers
;
659 // The PL_DHASH_REMOVE in GatherEnumerator drops all our observers here:
660 mObservers
.EnumerateEntries(GatherEnumeratorForReflow
, &observers
);
662 for (uint32_t i
= 0; i
< observers
.Length(); ++i
) {
663 observers
[i
]->InvalidateViaReferencedElement();
668 nsSVGRenderingObserverList::RemoveAll()
670 nsAutoTArray
<nsSVGRenderingObserver
*,10> observers
;
672 // The PL_DHASH_REMOVE in GatherEnumerator drops all our observers here:
673 mObservers
.EnumerateEntries(GatherEnumerator
, &observers
);
675 // Our list is now cleared. We need to notify the observers we've removed,
676 // so they can update their state & remove themselves as mutation-observers.
677 for (uint32_t i
= 0; i
< observers
.Length(); ++i
) {
678 observers
[i
]->NotifyEvictedFromRenderingObserverList();
683 nsSVGEffects::AddRenderingObserver(Element
*aElement
, nsSVGRenderingObserver
*aObserver
)
685 nsSVGRenderingObserverList
*observerList
= GetObserverList(aElement
);
687 observerList
= new nsSVGRenderingObserverList();
690 aElement
->SetProperty(nsGkAtoms::renderingobserverlist
, observerList
,
691 nsINode::DeleteProperty
<nsSVGRenderingObserverList
>);
693 aElement
->SetHasRenderingObservers(true);
694 observerList
->Add(aObserver
);
698 nsSVGEffects::RemoveRenderingObserver(Element
*aElement
, nsSVGRenderingObserver
*aObserver
)
700 nsSVGRenderingObserverList
*observerList
= GetObserverList(aElement
);
702 NS_ASSERTION(observerList
->Contains(aObserver
),
703 "removing observer from an element we're not observing?");
704 observerList
->Remove(aObserver
);
705 if (observerList
->IsEmpty()) {
706 aElement
->SetHasRenderingObservers(false);
712 nsSVGEffects::RemoveAllRenderingObservers(Element
*aElement
)
714 nsSVGRenderingObserverList
*observerList
= GetObserverList(aElement
);
716 observerList
->RemoveAll();
717 aElement
->SetHasRenderingObservers(false);
722 nsSVGEffects::InvalidateRenderingObservers(nsIFrame
*aFrame
)
724 NS_ASSERTION(!aFrame
->GetPrevContinuation(), "aFrame must be first continuation");
726 if (!aFrame
->GetContent()->IsElement())
729 nsSVGRenderingObserverList
*observerList
=
730 GetObserverList(aFrame
->GetContent()->AsElement());
732 observerList
->InvalidateAll();
736 // Check ancestor SVG containers. The root frame cannot be of type
737 // eSVGContainer so we don't have to check f for null here.
738 for (nsIFrame
*f
= aFrame
->GetParent();
739 f
->IsFrameOfType(nsIFrame::eSVGContainer
); f
= f
->GetParent()) {
740 if (f
->GetContent()->IsElement()) {
741 observerList
= GetObserverList(f
->GetContent()->AsElement());
743 observerList
->InvalidateAll();
751 nsSVGEffects::InvalidateDirectRenderingObservers(Element
*aElement
, uint32_t aFlags
/* = 0 */)
753 if (aElement
->HasRenderingObservers()) {
754 nsSVGRenderingObserverList
*observerList
= GetObserverList(aElement
);
756 if (aFlags
& INVALIDATE_REFLOW
) {
757 observerList
->InvalidateAllForReflow();
759 observerList
->InvalidateAll();
766 nsSVGEffects::InvalidateDirectRenderingObservers(nsIFrame
*aFrame
, uint32_t aFlags
/* = 0 */)
768 if (aFrame
->GetContent() && aFrame
->GetContent()->IsElement()) {
769 InvalidateDirectRenderingObservers(aFrame
->GetContent()->AsElement(), aFlags
);