mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 10:00:54 +00:00
Bug 276431 patch 12c: Make nsSVGRenderingObserver into a generic interface, and rename the existing impl to nsSVGIDRenderingObserver. r=roc a=blocking
This commit is contained in:
parent
def5d6741d
commit
15c9ddb76a
@ -48,24 +48,52 @@
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
// nsSVGRenderingObserver impl
|
||||
NS_IMPL_ISUPPORTS1(nsSVGRenderingObserver, nsIMutationObserver)
|
||||
|
||||
void
|
||||
nsSVGRenderingObserver::StartListening()
|
||||
{
|
||||
Element* target = GetTarget();
|
||||
if (target) {
|
||||
target->AddMutationObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGRenderingObserver::StopListening()
|
||||
{
|
||||
Element* target = GetTarget();
|
||||
|
||||
if (target) {
|
||||
target->RemoveMutationObserver(this);
|
||||
if (mInObserverList) {
|
||||
nsSVGEffects::RemoveRenderingObserver(target, this);
|
||||
mInObserverList = PR_FALSE;
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(!mInObserverList, "still in an observer list?");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* nsSVGRenderingObserver is notified if there are any attribute or content
|
||||
* In nsSVGIDRenderingObserver's ctor, the new object adds itself to the
|
||||
* mutation observer list maintained by the referenced element. In this way the
|
||||
* nsSVGIDRenderingObserver is notified if there are any attribute or content
|
||||
* tree changes to the element or any of its *descendants*.
|
||||
*
|
||||
* In nsSVGRenderingObserver::GetReferencedElement() the nsSVGRenderingObserver
|
||||
* object also adds itself to an nsSVGRenderingObserverList object belonging
|
||||
* to the referenced element.
|
||||
* In nsSVGIDRenderingObserver::GetReferencedElement() the
|
||||
* nsSVGIDRenderingObserver object also adds itself to an
|
||||
* nsSVGRenderingObserverList object belonging 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.
|
||||
*/
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsSVGRenderingObserver, nsIMutationObserver)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable "warning C4355: 'this' : used in base member initializer list".
|
||||
// We can ignore that warning because we know that mElement's constructor
|
||||
@ -73,12 +101,11 @@ NS_IMPL_ISUPPORTS1(nsSVGRenderingObserver, nsIMutationObserver)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4355)
|
||||
#endif
|
||||
nsSVGRenderingObserver::nsSVGRenderingObserver(nsIURI *aURI,
|
||||
nsIFrame *aFrame,
|
||||
PRBool aReferenceImage)
|
||||
nsSVGIDRenderingObserver::nsSVGIDRenderingObserver(nsIURI *aURI,
|
||||
nsIFrame *aFrame,
|
||||
PRBool aReferenceImage)
|
||||
: mElement(this), mFrame(aFrame),
|
||||
mFramePresShell(aFrame->PresContext()->PresShell()),
|
||||
mInObserverList(PR_FALSE)
|
||||
mFramePresShell(aFrame->PresContext()->PresShell())
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
@ -88,32 +115,11 @@ nsSVGRenderingObserver::nsSVGRenderingObserver(nsIURI *aURI,
|
||||
StartListening();
|
||||
}
|
||||
|
||||
nsSVGRenderingObserver::~nsSVGRenderingObserver()
|
||||
nsSVGIDRenderingObserver::~nsSVGIDRenderingObserver()
|
||||
{
|
||||
StopListening();
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGRenderingObserver::StartListening()
|
||||
{
|
||||
if (mElement.get()) {
|
||||
mElement.get()->AddMutationObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGRenderingObserver::StopListening()
|
||||
{
|
||||
if (mElement.get()) {
|
||||
mElement.get()->RemoveMutationObserver(this);
|
||||
if (mInObserverList) {
|
||||
nsSVGEffects::RemoveRenderingObserver(mElement.get(), this);
|
||||
mInObserverList = PR_FALSE;
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(!mInObserverList, "still in an observer list?");
|
||||
}
|
||||
|
||||
static nsSVGRenderingObserverList *
|
||||
GetObserverList(Element *aElement)
|
||||
{
|
||||
@ -124,20 +130,21 @@ GetObserverList(Element *aElement)
|
||||
Element*
|
||||
nsSVGRenderingObserver::GetReferencedElement()
|
||||
{
|
||||
Element* target = GetTarget();
|
||||
#ifdef DEBUG
|
||||
if (mElement.get()) {
|
||||
nsSVGRenderingObserverList *observerList = GetObserverList(mElement.get());
|
||||
if (target) {
|
||||
nsSVGRenderingObserverList *observerList = GetObserverList(target);
|
||||
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);
|
||||
if (target && !mInObserverList) {
|
||||
nsSVGEffects::AddRenderingObserver(target, this);
|
||||
mInObserverList = PR_TRUE;
|
||||
}
|
||||
return mElement.get();
|
||||
return target;
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
@ -160,7 +167,7 @@ nsSVGRenderingObserver::GetReferencedFrame(nsIAtom* aFrameType, PRBool* aOK)
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGRenderingObserver::DoUpdate()
|
||||
nsSVGIDRenderingObserver::DoUpdate()
|
||||
{
|
||||
if (mFramePresShell->IsDestroying()) {
|
||||
// mFrame is no longer valid. Bail out.
|
||||
@ -237,7 +244,7 @@ nsSVGRenderingObserver::ContentRemoved(nsIDocument *aDocument,
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(nsSVGFilterProperty,
|
||||
nsSVGRenderingObserver,
|
||||
nsSVGIDRenderingObserver,
|
||||
nsISVGFilterProperty)
|
||||
|
||||
nsSVGFilterFrame *
|
||||
@ -258,7 +265,7 @@ InvalidateAllContinuations(nsIFrame* aFrame)
|
||||
void
|
||||
nsSVGFilterProperty::DoUpdate()
|
||||
{
|
||||
nsSVGRenderingObserver::DoUpdate();
|
||||
nsSVGIDRenderingObserver::DoUpdate();
|
||||
if (!mFrame)
|
||||
return;
|
||||
|
||||
@ -276,7 +283,7 @@ nsSVGFilterProperty::DoUpdate()
|
||||
void
|
||||
nsSVGMarkerProperty::DoUpdate()
|
||||
{
|
||||
nsSVGRenderingObserver::DoUpdate();
|
||||
nsSVGIDRenderingObserver::DoUpdate();
|
||||
if (!mFrame)
|
||||
return;
|
||||
|
||||
@ -293,7 +300,7 @@ nsSVGMarkerProperty::DoUpdate()
|
||||
void
|
||||
nsSVGTextPathProperty::DoUpdate()
|
||||
{
|
||||
nsSVGRenderingObserver::DoUpdate();
|
||||
nsSVGIDRenderingObserver::DoUpdate();
|
||||
if (!mFrame)
|
||||
return;
|
||||
|
||||
@ -308,7 +315,7 @@ nsSVGTextPathProperty::DoUpdate()
|
||||
void
|
||||
nsSVGPaintingProperty::DoUpdate()
|
||||
{
|
||||
nsSVGRenderingObserver::DoUpdate();
|
||||
nsSVGIDRenderingObserver::DoUpdate();
|
||||
if (!mFrame)
|
||||
return;
|
||||
|
||||
|
@ -51,21 +51,24 @@ class nsSVGFilterFrame;
|
||||
class nsSVGMaskFrame;
|
||||
|
||||
/*
|
||||
* SVG elements reference supporting resources by element ID. We need to
|
||||
* track when those resources change and when the DOM changes in ways
|
||||
* that affect which element is referenced by a given ID (e.g., when
|
||||
* element IDs change). The code here is responsible for that.
|
||||
*
|
||||
* When a frame references a supporting resource, we create a property
|
||||
* object derived from nsSVGRenderingObserver to manage the relationship. The
|
||||
* property object is attached to the referencing frame.
|
||||
* This interface allows us to be notified when a piece of SVG content is
|
||||
* re-rendered.
|
||||
*
|
||||
* Concrete implementations of this interface need to implement
|
||||
* "GetTarget()" to specify the piece of SVG content that they'd like to
|
||||
* monitor, and they need to implement "DoUpdate" to specify how we'll react
|
||||
* when that content gets re-rendered. They also need to implement a
|
||||
* constructor and destructor, which should call StartListening and
|
||||
* StopListening, respectively.
|
||||
*/
|
||||
class nsSVGRenderingObserver : public nsStubMutationObserver {
|
||||
public:
|
||||
typedef mozilla::dom::Element Element;
|
||||
nsSVGRenderingObserver(nsIURI* aURI, nsIFrame *aFrame,
|
||||
PRBool aReferenceImage);
|
||||
virtual ~nsSVGRenderingObserver();
|
||||
nsSVGRenderingObserver()
|
||||
: mInObserverList(PR_FALSE)
|
||||
{}
|
||||
virtual ~nsSVGRenderingObserver()
|
||||
{}
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -77,24 +80,59 @@ public:
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||
|
||||
void InvalidateViaReferencedElement();
|
||||
|
||||
Element* GetReferencedElement();
|
||||
nsIFrame* GetReferencedFrame();
|
||||
|
||||
/**
|
||||
* @param aOK this is only for the convenience of callers. We set *aOK to false
|
||||
* if this function returns null.
|
||||
*/
|
||||
nsIFrame* GetReferencedFrame(nsIAtom* aFrameType, PRBool* aOK);
|
||||
|
||||
Element* GetReferencedElement();
|
||||
|
||||
protected:
|
||||
// This is called when the referenced resource changes.
|
||||
virtual void DoUpdate();
|
||||
// Non-virtual protected methods
|
||||
void StartListening();
|
||||
void StopListening();
|
||||
|
||||
// Virtual protected methods
|
||||
virtual void DoUpdate() = 0; // called when the referenced resource changes.
|
||||
|
||||
// This is an internally-used version of GetReferencedElement that doesn't
|
||||
// forcibly add us as an observer. (whereas GetReferencedElement does)
|
||||
virtual Element* GetTarget() = 0;
|
||||
|
||||
// Whether we're in our referenced element's observer list at this time.
|
||||
PRPackedBool mInObserverList;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* SVG elements reference supporting resources by element ID. We need to
|
||||
* track when those resources change and when the DOM changes in ways
|
||||
* that affect which element is referenced by a given ID (e.g., when
|
||||
* element IDs change). The code here is responsible for that.
|
||||
*
|
||||
* When a frame references a supporting resource, we create a property
|
||||
* object derived from nsSVGIDRenderingObserver to manage the relationship. The
|
||||
* property object is attached to the referencing frame.
|
||||
*/
|
||||
class nsSVGIDRenderingObserver : public nsSVGRenderingObserver {
|
||||
public:
|
||||
typedef mozilla::dom::Element Element;
|
||||
nsSVGIDRenderingObserver(nsIURI* aURI, nsIFrame *aFrame,
|
||||
PRBool aReferenceImage);
|
||||
virtual ~nsSVGIDRenderingObserver();
|
||||
|
||||
protected:
|
||||
Element* GetTarget() { return mElement.get(); }
|
||||
|
||||
// This is called when the referenced resource changes.
|
||||
virtual void DoUpdate();
|
||||
|
||||
class SourceReference : public nsReferencedElement {
|
||||
public:
|
||||
SourceReference(nsSVGRenderingObserver* aContainer) : mContainer(aContainer) {}
|
||||
SourceReference(nsSVGIDRenderingObserver* aContainer) : mContainer(aContainer) {}
|
||||
protected:
|
||||
virtual void ElementChanged(Element* aFrom, Element* aTo) {
|
||||
mContainer->StopListening();
|
||||
@ -108,7 +146,7 @@ protected:
|
||||
*/
|
||||
virtual PRBool IsPersistent() { return PR_TRUE; }
|
||||
private:
|
||||
nsSVGRenderingObserver* mContainer;
|
||||
nsSVGIDRenderingObserver* mContainer;
|
||||
};
|
||||
|
||||
SourceReference mElement;
|
||||
@ -120,16 +158,14 @@ 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;
|
||||
// Whether we're in our referenced element's observer list at this time.
|
||||
PRPackedBool mInObserverList;
|
||||
};
|
||||
|
||||
class nsSVGFilterProperty :
|
||||
public nsSVGRenderingObserver, public nsISVGFilterProperty {
|
||||
public nsSVGIDRenderingObserver, public nsISVGFilterProperty {
|
||||
public:
|
||||
nsSVGFilterProperty(nsIURI *aURI, nsIFrame *aFilteredFrame,
|
||||
PRBool aReferenceImage)
|
||||
: nsSVGRenderingObserver(aURI, aFilteredFrame, aReferenceImage) {}
|
||||
: nsSVGIDRenderingObserver(aURI, aFilteredFrame, aReferenceImage) {}
|
||||
|
||||
/**
|
||||
* @return the filter frame, or null if there is no filter frame
|
||||
@ -147,28 +183,28 @@ private:
|
||||
virtual void DoUpdate();
|
||||
};
|
||||
|
||||
class nsSVGMarkerProperty : public nsSVGRenderingObserver {
|
||||
class nsSVGMarkerProperty : public nsSVGIDRenderingObserver {
|
||||
public:
|
||||
nsSVGMarkerProperty(nsIURI *aURI, nsIFrame *aFrame, PRBool aReferenceImage)
|
||||
: nsSVGRenderingObserver(aURI, aFrame, aReferenceImage) {}
|
||||
: nsSVGIDRenderingObserver(aURI, aFrame, aReferenceImage) {}
|
||||
|
||||
protected:
|
||||
virtual void DoUpdate();
|
||||
};
|
||||
|
||||
class nsSVGTextPathProperty : public nsSVGRenderingObserver {
|
||||
class nsSVGTextPathProperty : public nsSVGIDRenderingObserver {
|
||||
public:
|
||||
nsSVGTextPathProperty(nsIURI *aURI, nsIFrame *aFrame, PRBool aReferenceImage)
|
||||
: nsSVGRenderingObserver(aURI, aFrame, aReferenceImage) {}
|
||||
: nsSVGIDRenderingObserver(aURI, aFrame, aReferenceImage) {}
|
||||
|
||||
protected:
|
||||
virtual void DoUpdate();
|
||||
};
|
||||
|
||||
class nsSVGPaintingProperty : public nsSVGRenderingObserver {
|
||||
class nsSVGPaintingProperty : public nsSVGIDRenderingObserver {
|
||||
public:
|
||||
nsSVGPaintingProperty(nsIURI *aURI, nsIFrame *aFrame, PRBool aReferenceImage)
|
||||
: nsSVGRenderingObserver(aURI, aFrame, aReferenceImage) {}
|
||||
: nsSVGIDRenderingObserver(aURI, aFrame, aReferenceImage) {}
|
||||
|
||||
protected:
|
||||
virtual void DoUpdate();
|
||||
|
Loading…
Reference in New Issue
Block a user