mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 572689 - Make nsSVGRenderingObservers observe elements instead of frames. r=roc
This commit is contained in:
parent
fae48f3bbd
commit
eaba422dce
@ -320,7 +320,8 @@ public:
|
||||
mFlagsOrSlots(NODE_DOESNT_HAVE_SLOTS),
|
||||
mNextSibling(nsnull),
|
||||
mPreviousSibling(nsnull),
|
||||
mFirstChild(nsnull)
|
||||
mFirstChild(nsnull),
|
||||
mNodeHasRenderingObservers(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1147,6 +1148,10 @@ public:
|
||||
NS_NOTREACHED("How did we get here?");
|
||||
}
|
||||
|
||||
bool HasRenderingObservers() { return mNodeHasRenderingObservers; }
|
||||
void SetHasRenderingObservers(bool aValue)
|
||||
{ mNodeHasRenderingObservers = aValue; }
|
||||
|
||||
// Optimized way to get classinfo. May return null.
|
||||
virtual nsXPCClassInfo* GetClassInfo() = 0;
|
||||
protected:
|
||||
@ -1279,6 +1284,9 @@ protected:
|
||||
nsIContent* mNextSibling;
|
||||
nsIContent* mPreviousSibling;
|
||||
nsIContent* mFirstChild;
|
||||
|
||||
// More flags
|
||||
bool mNodeHasRenderingObservers : 1;
|
||||
};
|
||||
|
||||
|
||||
|
@ -794,6 +794,7 @@ GK_ATOM(refresh, "refresh")
|
||||
GK_ATOM(rel, "rel")
|
||||
GK_ATOM(rem, "rem")
|
||||
GK_ATOM(removeelement, "removeelement")
|
||||
GK_ATOM(renderingobserverlist, "renderingobserverlist")
|
||||
GK_ATOM(repeat, "repeat")
|
||||
GK_ATOM(replace, "replace")
|
||||
GK_ATOM(reset, "reset")
|
||||
|
@ -350,7 +350,7 @@ nsFrame::Init(nsIContent* aContent,
|
||||
mState |= state & (NS_FRAME_SELECTED_CONTENT |
|
||||
NS_FRAME_INDEPENDENT_SELECTION |
|
||||
NS_FRAME_IS_SPECIAL |
|
||||
NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS);
|
||||
NS_FRAME_MAY_BE_TRANSFORMED);
|
||||
}
|
||||
if (mParent) {
|
||||
nsFrameState state = mParent->GetStateBits();
|
||||
@ -362,7 +362,7 @@ nsFrame::Init(nsIContent* aContent,
|
||||
if (GetStyleDisplay()->HasTransform()) {
|
||||
// The frame gets reconstructed if we toggle the -moz-transform
|
||||
// property, so we can set this bit here and then ignore it.
|
||||
mState |= NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS;
|
||||
mState |= NS_FRAME_MAY_BE_TRANSFORMED;
|
||||
}
|
||||
|
||||
DidSetStyleContext(nsnull);
|
||||
@ -721,7 +721,7 @@ nsIFrame::GetPaddingRect() const
|
||||
PRBool
|
||||
nsIFrame::IsTransformed() const
|
||||
{
|
||||
return (mState & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS) &&
|
||||
return (mState & NS_FRAME_MAY_BE_TRANSFORMED) &&
|
||||
GetStyleDisplay()->HasTransform();
|
||||
}
|
||||
|
||||
@ -1259,7 +1259,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||
/* If we're being transformed, we need to invert the matrix transform so that we don't
|
||||
* grab points in the wrong coordinate system!
|
||||
*/
|
||||
if ((mState & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS) &&
|
||||
if ((mState & NS_FRAME_MAY_BE_TRANSFORMED) &&
|
||||
disp->HasTransform()) {
|
||||
dirtyRect = nsDisplayTransform::UntransformRect(dirtyRect, this, nsPoint(0, 0));
|
||||
inTransform = PR_TRUE;
|
||||
@ -1382,7 +1382,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||
/* If we're going to apply a transformation, wrap everything in an
|
||||
* nsDisplayTransform.
|
||||
*/
|
||||
if ((mState & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS) &&
|
||||
if ((mState & NS_FRAME_MAY_BE_TRANSFORMED) &&
|
||||
disp->HasTransform()) {
|
||||
rv = resultList.AppendNewToTop(
|
||||
new (aBuilder) nsDisplayTransform(aBuilder, this, &resultList));
|
||||
@ -1494,9 +1494,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
// Child is composited if it's transformed, partially transparent, or has
|
||||
// SVG effects.
|
||||
PRBool isComposited = disp->mOpacity != 1.0f ||
|
||||
((aChild->mState & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS) &&
|
||||
aChild->GetStyleDisplay()->HasTransform())
|
||||
PRBool isComposited = disp->mOpacity != 1.0f || aChild->IsTransformed()
|
||||
#ifdef MOZ_SVG
|
||||
|| nsSVGIntegrationUtils::UsingEffectsForFrame(aChild)
|
||||
#endif
|
||||
@ -3878,8 +3876,7 @@ nsIFrame::InvalidateInternalAfterResize(const nsRect& aDamageRect, nscoord aX,
|
||||
// Don't need to invalidate any more Thebes layers
|
||||
aFlags |= INVALIDATE_NO_THEBES_LAYERS;
|
||||
}
|
||||
if ((mState & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS) &&
|
||||
GetStyleDisplay()->HasTransform()) {
|
||||
if (IsTransformed()) {
|
||||
nsRect newDamageRect;
|
||||
newDamageRect.UnionRect(nsDisplayTransform::TransformRect
|
||||
(aDamageRect, this, nsPoint(-aX, -aY)), aDamageRect);
|
||||
@ -4171,8 +4168,7 @@ nsIFrame::GetOverflowRectRelativeToParent() const
|
||||
nsRect
|
||||
nsIFrame::GetOverflowRectRelativeToSelf() const
|
||||
{
|
||||
if ((mState & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS) &&
|
||||
GetStyleDisplay()->HasTransform()) {
|
||||
if (IsTransformed()) {
|
||||
nsRect* preTransformBBox = static_cast<nsRect*>
|
||||
(Properties().Get(PreTransformBBoxProperty()));
|
||||
if (preTransformBBox)
|
||||
@ -5870,9 +5866,7 @@ nsIFrame::FinishAndStoreOverflow(nsRect* aOverflowArea, nsSize aNewSize)
|
||||
&hasOutlineOrEffects);
|
||||
|
||||
/* If we're transformed, transform the overflow rect by the current transformation. */
|
||||
PRBool hasTransform =
|
||||
(mState & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS) &&
|
||||
GetStyleDisplay()->HasTransform();
|
||||
PRBool hasTransform = IsTransformed();
|
||||
if (hasTransform) {
|
||||
Properties().
|
||||
Set(nsIFrame::PreTransformBBoxProperty(), new nsRect(*aOverflowArea));
|
||||
|
@ -235,10 +235,7 @@ typedef PRUint64 nsFrameState;
|
||||
// to its coordinate system (e.g. CSS transform, SVG foreignObject).
|
||||
// This is used primarily in GetTransformMatrix to optimize for the
|
||||
// common case.
|
||||
// ALSO, if this bit is set, the frame's first-continuation may
|
||||
// have an associated nsSVGRenderingObserverList.
|
||||
#define NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS \
|
||||
NS_FRAME_STATE_BIT(16)
|
||||
#define NS_FRAME_MAY_BE_TRANSFORMED NS_FRAME_STATE_BIT(16)
|
||||
|
||||
#ifdef IBMBIDI
|
||||
// If this bit is set, the frame itself is a bidi continuation,
|
||||
|
@ -46,18 +46,19 @@
|
||||
#include "nsFrameManager.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
/**
|
||||
* Note that in the current setup there are two separate observer lists.
|
||||
*
|
||||
* In nsSVGRenderingObserver's ctor, the new object adds itself to the mutation
|
||||
* observer list maintained by the referenced *element*. In this way the
|
||||
* observer list maintained by the referenced element. In this way the
|
||||
* nsSVGRenderingObserver is notified if there are any attribute or content
|
||||
* tree changes to the element or any of its *descendants*.
|
||||
*
|
||||
* In nsSVGRenderingObserver::GetReferencedFrame() the nsSVGRenderingObserver
|
||||
* In nsSVGRenderingObserver::GetReferencedElement() the nsSVGRenderingObserver
|
||||
* object also adds itself to an nsSVGRenderingObserverList object belonging
|
||||
* to the nsIFrame corresponding to the referenced element.
|
||||
* to the referenced element.
|
||||
*
|
||||
* XXX: it would be nice to have a clear and concise executive summary of the
|
||||
* benefits/necessity of maintaining a second observer list.
|
||||
@ -76,57 +77,73 @@ nsSVGRenderingObserver::nsSVGRenderingObserver(nsIURI *aURI,
|
||||
nsIFrame *aFrame)
|
||||
: mElement(this), mFrame(aFrame),
|
||||
mFramePresShell(aFrame->PresContext()->PresShell()),
|
||||
mReferencedFrame(nsnull),
|
||||
mReferencedFramePresShell(nsnull)
|
||||
mInObserverList(PR_FALSE)
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
{
|
||||
// Start watching the target element
|
||||
mElement.Reset(aFrame->GetContent(), aURI);
|
||||
StartListening();
|
||||
}
|
||||
|
||||
nsSVGRenderingObserver::~nsSVGRenderingObserver()
|
||||
{
|
||||
StopListening();
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGRenderingObserver::StartListening()
|
||||
{
|
||||
if (mElement.get()) {
|
||||
mElement.get()->AddMutationObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
nsSVGRenderingObserver::~nsSVGRenderingObserver()
|
||||
void
|
||||
nsSVGRenderingObserver::StopListening()
|
||||
{
|
||||
if (mElement.get()) {
|
||||
mElement.get()->RemoveMutationObserver(this);
|
||||
if (mInObserverList) {
|
||||
nsSVGEffects::RemoveRenderingObserver(mElement.get(), this);
|
||||
mInObserverList = PR_FALSE;
|
||||
}
|
||||
}
|
||||
if (mReferencedFrame && !mReferencedFramePresShell->IsDestroying()) {
|
||||
nsSVGEffects::RemoveRenderingObserver(mReferencedFrame, this);
|
||||
NS_ASSERTION(!mInObserverList, "still in an observer list?");
|
||||
}
|
||||
|
||||
static nsSVGRenderingObserverList *
|
||||
GetObserverList(Element *aElement)
|
||||
{
|
||||
return static_cast<nsSVGRenderingObserverList*>
|
||||
(aElement->GetProperty(nsGkAtoms::renderingobserverlist));
|
||||
}
|
||||
|
||||
Element*
|
||||
nsSVGRenderingObserver::GetReferencedElement()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (mElement.get()) {
|
||||
nsSVGRenderingObserverList *observerList = GetObserverList(mElement.get());
|
||||
PRBool inObserverList = observerList && observerList->Contains(this);
|
||||
NS_ASSERTION(inObserverList == mInObserverList, "failed to track whether we're in our referenced element's observer list!");
|
||||
} else {
|
||||
NS_ASSERTION(!mInObserverList, "In whose observer list are we, then?");
|
||||
}
|
||||
#endif
|
||||
if (mElement.get() && !mInObserverList) {
|
||||
nsSVGEffects::AddRenderingObserver(mElement.get(), this);
|
||||
mInObserverList = PR_TRUE;
|
||||
}
|
||||
return mElement.get();
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsSVGRenderingObserver::GetReferencedFrame()
|
||||
{
|
||||
if (mReferencedFrame && !mReferencedFramePresShell->IsDestroying()) {
|
||||
// Don't test this assertion if it's not a good time to call
|
||||
// GetPrimaryFrame
|
||||
if (!mReferencedFramePresShell->FrameManager()->IsDestroyingFrames()) {
|
||||
NS_ASSERTION(mElement.get() &&
|
||||
static_cast<nsGenericElement*>(mElement.get())->GetPrimaryFrame() == mReferencedFrame,
|
||||
"Cached frame is incorrect!");
|
||||
}
|
||||
return mReferencedFrame;
|
||||
}
|
||||
|
||||
if (mElement.get()) {
|
||||
nsIDocument* doc = mElement.get()->GetCurrentDoc();
|
||||
nsIPresShell* shell = doc ? doc->GetShell() : nsnull;
|
||||
if (shell && !shell->FrameManager()->IsDestroyingFrames()) {
|
||||
nsIFrame* frame = mElement.get()->GetPrimaryFrame();
|
||||
if (frame) {
|
||||
mReferencedFrame = frame;
|
||||
mReferencedFramePresShell = shell;
|
||||
nsSVGEffects::AddRenderingObserver(mReferencedFrame, this);
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
Element* referencedElement = GetReferencedElement();
|
||||
return referencedElement ? referencedElement->GetPrimaryFrame() : nsnull;
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
@ -149,10 +166,9 @@ nsSVGRenderingObserver::DoUpdate()
|
||||
mFrame = nsnull;
|
||||
return;
|
||||
}
|
||||
if (mReferencedFrame) {
|
||||
nsSVGEffects::RemoveRenderingObserver(mReferencedFrame, this);
|
||||
mReferencedFrame = nsnull;
|
||||
mReferencedFramePresShell = nsnull;
|
||||
if (mElement.get() && mInObserverList) {
|
||||
nsSVGEffects::RemoveRenderingObserver(mElement.get(), this);
|
||||
mInObserverList = PR_FALSE;
|
||||
}
|
||||
if (mFrame && mFrame->IsFrameOfType(nsIFrame::eSVG)) {
|
||||
// Changes should propagate out to things that might be observing
|
||||
@ -162,12 +178,9 @@ nsSVGRenderingObserver::DoUpdate()
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGRenderingObserver::InvalidateViaReferencedFrame()
|
||||
nsSVGRenderingObserver::InvalidateViaReferencedElement()
|
||||
{
|
||||
// Clear mReferencedFrame since the referenced frame has already
|
||||
// dropped its reference back to us
|
||||
mReferencedFrame = nsnull;
|
||||
mReferencedFramePresShell = nsnull;
|
||||
mInObserverList = PR_FALSE;
|
||||
DoUpdate();
|
||||
}
|
||||
|
||||
@ -511,56 +524,42 @@ nsSVGRenderingObserverList::InvalidateAll()
|
||||
mObservers.EnumerateEntries(GatherEnumerator, &observers);
|
||||
|
||||
for (PRUint32 i = 0; i < observers.Length(); ++i) {
|
||||
observers[i]->InvalidateViaReferencedFrame();
|
||||
observers[i]->InvalidateViaReferencedElement();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DestroyObservers(void* aPropertyValue)
|
||||
DestroyObservers(void *aObject, nsIAtom *aPropertyName,
|
||||
void *aPropertyValue, void *aData)
|
||||
{
|
||||
delete static_cast<nsSVGRenderingObserverList*>(aPropertyValue);
|
||||
}
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(ObserversProperty, DestroyObservers)
|
||||
|
||||
static nsSVGRenderingObserverList *
|
||||
GetObserverList(nsIFrame *aFrame)
|
||||
{
|
||||
if (!(aFrame->GetStateBits() & NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS))
|
||||
return nsnull;
|
||||
return static_cast<nsSVGRenderingObserverList*>
|
||||
(aFrame->Properties().Get(ObserversProperty()));
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGEffects::AddRenderingObserver(nsIFrame *aFrame, nsSVGRenderingObserver *aObserver)
|
||||
nsSVGEffects::AddRenderingObserver(Element *aElement, nsSVGRenderingObserver *aObserver)
|
||||
{
|
||||
NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame must be first continuation");
|
||||
|
||||
nsSVGRenderingObserverList *observerList = GetObserverList(aFrame);
|
||||
nsSVGRenderingObserverList *observerList = GetObserverList(aElement);
|
||||
if (!observerList) {
|
||||
observerList = new nsSVGRenderingObserverList();
|
||||
if (!observerList)
|
||||
return;
|
||||
for (nsIFrame* f = aFrame; f; f = f->GetNextContinuation()) {
|
||||
f->AddStateBits(NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS);
|
||||
}
|
||||
aFrame->Properties().Set(ObserversProperty(), observerList);
|
||||
aElement->SetProperty(nsGkAtoms::renderingobserverlist, observerList, DestroyObservers);
|
||||
}
|
||||
aElement->SetHasRenderingObservers(true);
|
||||
observerList->Add(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGEffects::RemoveRenderingObserver(nsIFrame *aFrame, nsSVGRenderingObserver *aObserver)
|
||||
nsSVGEffects::RemoveRenderingObserver(Element *aElement, nsSVGRenderingObserver *aObserver)
|
||||
{
|
||||
NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame must be first continuation");
|
||||
|
||||
nsSVGRenderingObserverList *observerList = GetObserverList(aFrame);
|
||||
nsSVGRenderingObserverList *observerList = GetObserverList(aElement);
|
||||
if (observerList) {
|
||||
NS_ASSERTION(observerList->Contains(aObserver),
|
||||
"removing observer from an element we're not observing?");
|
||||
observerList->Remove(aObserver);
|
||||
// Don't remove the property even if the observer list is empty.
|
||||
// This might not be a good time to modify the frame property
|
||||
// hashtables.
|
||||
if (observerList->IsEmpty()) {
|
||||
aElement->SetHasRenderingObservers(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -569,7 +568,11 @@ nsSVGEffects::InvalidateRenderingObservers(nsIFrame *aFrame)
|
||||
{
|
||||
NS_ASSERTION(!aFrame->GetPrevContinuation(), "aFrame must be first continuation");
|
||||
|
||||
nsSVGRenderingObserverList *observerList = GetObserverList(aFrame);
|
||||
if (!aFrame->GetContent()->IsElement())
|
||||
return;
|
||||
|
||||
nsSVGRenderingObserverList *observerList =
|
||||
GetObserverList(aFrame->GetContent()->AsElement());
|
||||
if (observerList) {
|
||||
observerList->InvalidateAll();
|
||||
return;
|
||||
@ -579,10 +582,23 @@ nsSVGEffects::InvalidateRenderingObservers(nsIFrame *aFrame)
|
||||
// eSVGContainer so we don't have to check f for null here.
|
||||
for (nsIFrame *f = aFrame->GetParent();
|
||||
f->IsFrameOfType(nsIFrame::eSVGContainer); f = f->GetParent()) {
|
||||
observerList = GetObserverList(f);
|
||||
if (f->GetContent()->IsElement()) {
|
||||
observerList = GetObserverList(f->GetContent()->AsElement());
|
||||
if (observerList) {
|
||||
observerList->InvalidateAll();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGEffects::InvalidateDirectRenderingObservers(Element *aElement)
|
||||
{
|
||||
if (aElement->HasRenderingObservers()) {
|
||||
nsSVGRenderingObserverList *observerList = GetObserverList(aElement);
|
||||
if (observerList) {
|
||||
observerList->InvalidateAll();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -590,8 +606,7 @@ nsSVGEffects::InvalidateRenderingObservers(nsIFrame *aFrame)
|
||||
void
|
||||
nsSVGEffects::InvalidateDirectRenderingObservers(nsIFrame *aFrame)
|
||||
{
|
||||
nsSVGRenderingObserverList *observerList = GetObserverList(aFrame);
|
||||
if (observerList) {
|
||||
observerList->InvalidateAll();
|
||||
if (aFrame->GetContent() && aFrame->GetContent()->IsElement()) {
|
||||
InvalidateDirectRenderingObservers(aFrame->GetContent()->AsElement());
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ class nsSVGMaskFrame;
|
||||
*/
|
||||
class nsSVGRenderingObserver : public nsStubMutationObserver {
|
||||
public:
|
||||
typedef mozilla::dom::Element Element;
|
||||
nsSVGRenderingObserver(nsIURI* aURI, nsIFrame *aFrame);
|
||||
virtual ~nsSVGRenderingObserver();
|
||||
|
||||
@ -74,8 +75,9 @@ public:
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||
|
||||
void InvalidateViaReferencedFrame();
|
||||
void InvalidateViaReferencedElement();
|
||||
|
||||
Element* GetReferencedElement();
|
||||
nsIFrame* GetReferencedFrame();
|
||||
/**
|
||||
* @param aOK this is only for the convenience of callers. We set *aOK to false
|
||||
@ -86,19 +88,17 @@ public:
|
||||
protected:
|
||||
// This is called when the referenced resource changes.
|
||||
virtual void DoUpdate();
|
||||
void StartListening();
|
||||
void StopListening();
|
||||
|
||||
class SourceReference : public nsReferencedElement {
|
||||
public:
|
||||
SourceReference(nsSVGRenderingObserver* aContainer) : mContainer(aContainer) {}
|
||||
protected:
|
||||
virtual void ElementChanged(Element* aFrom, Element* aTo) {
|
||||
if (aFrom) {
|
||||
aFrom->RemoveMutationObserver(mContainer);
|
||||
}
|
||||
mContainer->StopListening();
|
||||
nsReferencedElement::ElementChanged(aFrom, aTo);
|
||||
if (aTo) {
|
||||
aTo->AddMutationObserver(mContainer);
|
||||
}
|
||||
mContainer->StartListening();
|
||||
mContainer->DoUpdate();
|
||||
}
|
||||
/**
|
||||
@ -119,8 +119,8 @@ protected:
|
||||
// we test the presshell to see if it's destroying itself. If it is,
|
||||
// then the frame pointer is not valid and we know the frame has gone away.
|
||||
nsIPresShell *mFramePresShell;
|
||||
nsIFrame *mReferencedFrame;
|
||||
nsIPresShell *mReferencedFramePresShell;
|
||||
// Whether we're in our referenced element's observer list at this time.
|
||||
PRPackedBool mInObserverList;
|
||||
};
|
||||
|
||||
class nsSVGFilterProperty :
|
||||
@ -177,11 +177,11 @@ protected:
|
||||
* nsSVGRenderingObservers can be added or removed. They are not strongly
|
||||
* referenced so an observer must be removed before it dies.
|
||||
* When InvalidateAll is called, all outstanding references get
|
||||
* InvalidateViaReferencedFrame()
|
||||
* InvalidateViaReferencedElement()
|
||||
* called on them and the list is cleared. The intent is that
|
||||
* the observer will force repainting of whatever part of the document
|
||||
* is needed, and then at paint time the observer will do a clean lookup
|
||||
* of the referenced frame and [re-]add itself to the frame's observer list.
|
||||
* of the referenced element and [re-]add itself to the element's observer list.
|
||||
*
|
||||
* InvalidateAll must be called before this object is destroyed, i.e.
|
||||
* before the referenced frame is destroyed. This should normally happen
|
||||
@ -204,6 +204,12 @@ public:
|
||||
{ mObservers.PutEntry(aObserver); }
|
||||
void Remove(nsSVGRenderingObserver* aObserver)
|
||||
{ mObservers.RemoveEntry(aObserver); }
|
||||
#ifdef DEBUG
|
||||
PRBool Contains(nsSVGRenderingObserver* aObserver)
|
||||
{ return (mObservers.GetEntry(aObserver) != nsnull); }
|
||||
#endif
|
||||
PRBool IsEmpty()
|
||||
{ return mObservers.Count() == 0; }
|
||||
|
||||
/**
|
||||
* Drop all our observers, and notify them that we have changed and dropped
|
||||
@ -217,6 +223,7 @@ private:
|
||||
|
||||
class nsSVGEffects {
|
||||
public:
|
||||
typedef mozilla::dom::Element Element;
|
||||
typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
|
||||
typedef nsInterfaceHashtable<nsURIHashKey, nsIMutationObserver>
|
||||
URIObserverHashtable;
|
||||
@ -299,31 +306,32 @@ public:
|
||||
/**
|
||||
* @param aFrame must be a first-continuation.
|
||||
*/
|
||||
static void AddRenderingObserver(nsIFrame *aFrame, nsSVGRenderingObserver *aObserver);
|
||||
static void AddRenderingObserver(Element *aElement, nsSVGRenderingObserver *aObserver);
|
||||
/**
|
||||
* @param aFrame must be a first-continuation.
|
||||
*/
|
||||
static void RemoveRenderingObserver(nsIFrame *aFrame, nsSVGRenderingObserver *aObserver);
|
||||
static void RemoveRenderingObserver(Element *aElement, nsSVGRenderingObserver *aObserver);
|
||||
/**
|
||||
* This can be called on any first-continuation frame. We invalidate aFrame's
|
||||
* observers, if any, or else walk up to the nearest observable SVG parent
|
||||
* This can be called on any frame. We invalidate the observers of aFrame's
|
||||
* element, if any, or else walk up to the nearest observable SVG parent
|
||||
* frame with observers and invalidate them instead.
|
||||
*
|
||||
* Note that this method is very different to e.g.
|
||||
* nsNodeUtils::AttributeChanged which walks up the content node tree (not
|
||||
* the frame tree) all the way to the root node (not stopping if it
|
||||
* encounters a non-container SVG node) invalidating all mutation observers
|
||||
* (not just nsSVGRenderingObservers) on all nodes along the way (not just
|
||||
* the first node it finds with observers). In other words, by doing all the
|
||||
* nsNodeUtils::AttributeChanged which walks up the content node tree all the
|
||||
* way to the root node (not stopping if it encounters a non-container SVG
|
||||
* node) invalidating all mutation observers (not just
|
||||
* nsSVGRenderingObservers) on all nodes along the way (not just the first
|
||||
* node it finds with observers). In other words, by doing all the
|
||||
* things in parentheses in the preceding sentence, this method uses
|
||||
* knowledge about our implementation and what can be affected by SVG effects
|
||||
* to make invalidation relatively lightweight when an SVG effect changes.
|
||||
*/
|
||||
static void InvalidateRenderingObservers(nsIFrame *aFrame);
|
||||
/**
|
||||
* This can be called on any frame. Only direct observers of this frame, if
|
||||
* any, are invalidated.
|
||||
* This can be called on any element or frame. Only direct observers of this
|
||||
* (frame's) element, if any, are invalidated.
|
||||
*/
|
||||
static void InvalidateDirectRenderingObservers(Element *aElement);
|
||||
static void InvalidateDirectRenderingObservers(nsIFrame *aFrame);
|
||||
|
||||
/**
|
||||
|
@ -70,8 +70,7 @@ nsSVGForeignObjectFrame::nsSVGForeignObjectFrame(nsStyleContext* aContext)
|
||||
: nsSVGForeignObjectFrameBase(aContext),
|
||||
mInReflow(PR_FALSE)
|
||||
{
|
||||
AddStateBits(NS_FRAME_REFLOW_ROOT |
|
||||
NS_FRAME_MAY_BE_TRANSFORMED_OR_HAVE_RENDERING_OBSERVERS);
|
||||
AddStateBits(NS_FRAME_REFLOW_ROOT | NS_FRAME_MAY_BE_TRANSFORMED);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user