Bug 458010 - textPath should use nsReferencedElement instead of nsSVGUtils::GetReferencedFrame. r+sr=roc

This commit is contained in:
Robert Longson 2008-10-11 12:29:35 +01:00
parent 22caaa4ccc
commit 76faac31ae
8 changed files with 82 additions and 145 deletions

View File

@ -41,6 +41,7 @@
#include "nsSVGFilterFrame.h"
#include "nsSVGClipPathFrame.h"
#include "nsSVGMaskFrame.h"
#include "nsSVGTextPathFrame.h"
NS_IMPL_ISUPPORTS1(nsSVGRenderingObserver, nsIMutationObserver)
@ -248,6 +249,21 @@ nsSVGMarkerProperty::DoUpdate()
}
}
void
nsSVGTextPathProperty::DoUpdate()
{
nsSVGRenderingObserver::DoUpdate();
if (!mFrame)
return;
NS_ASSERTION(mFrame->IsFrameOfType(nsIFrame::eSVG), "SVG frame expected");
if (mFrame->GetType() == nsGkAtoms::svgTextPathFrame) {
nsSVGTextPathFrame* textPathFrame = static_cast<nsSVGTextPathFrame*>(mFrame);
textPathFrame->NotifyGlyphMetricsChange();
}
}
void
nsSVGPaintingProperty::DoUpdate()
{
@ -273,6 +289,10 @@ static nsSVGRenderingObserver *
CreateMarkerProperty(nsIURI *aURI, nsIFrame *aFrame)
{ return new nsSVGMarkerProperty(aURI, aFrame); }
static nsSVGRenderingObserver *
CreateTextPathProperty(nsIURI *aURI, nsIFrame *aFrame)
{ return new nsSVGTextPathProperty(aURI, aFrame); }
static nsSVGRenderingObserver *
CreatePaintingProperty(nsIURI *aURI, nsIFrame *aFrame)
{ return new nsSVGPaintingProperty(aURI, aFrame); }
@ -304,6 +324,13 @@ nsSVGEffects::GetMarkerProperty(nsIURI *aURI, nsIFrame *aFrame, nsIAtom *aProp)
GetEffectProperty(aURI, aFrame, aProp, CreateMarkerProperty));
}
nsSVGTextPathProperty *
nsSVGEffects::GetTextPathProperty(nsIURI *aURI, nsIFrame *aFrame, nsIAtom *aProp)
{
return static_cast<nsSVGTextPathProperty*>(
GetEffectProperty(aURI, aFrame, aProp, CreateTextPathProperty));
}
nsSVGPaintingProperty *
nsSVGEffects::GetPaintingProperty(nsIURI *aURI, nsIFrame *aFrame, nsIAtom *aProp)
{

View File

@ -159,6 +159,15 @@ protected:
virtual void DoUpdate();
};
class nsSVGTextPathProperty : public nsSVGRenderingObserver {
public:
nsSVGTextPathProperty(nsIURI *aURI, nsIFrame *aFrame)
: nsSVGRenderingObserver(aURI, aFrame) {}
protected:
virtual void DoUpdate();
};
class nsSVGPaintingProperty : public nsSVGRenderingObserver {
public:
nsSVGPaintingProperty(nsIURI *aURI, nsIFrame *aFrame)
@ -278,6 +287,11 @@ public:
*/
static nsSVGMarkerProperty *
GetMarkerProperty(nsIURI *aURI, nsIFrame *aFrame, nsIAtom *aProp);
/**
* Get an nsSVGTextPathProperty for the frame, creating a fresh one if necessary
*/
static nsSVGTextPathProperty *
GetTextPathProperty(nsIURI *aURI, nsIFrame *aFrame, nsIAtom *aProp);
/**
* Get an nsSVGPaintingProperty for the frame, creating a fresh one if necessary
*/

View File

@ -53,16 +53,11 @@
//----------------------------------------------------------------------
// Implementation
nsSVGGradientFrame::nsSVGGradientFrame(nsStyleContext* aContext,
nsIDOMSVGURIReference *aRef) :
nsSVGGradientFrame::nsSVGGradientFrame(nsStyleContext* aContext) :
nsSVGGradientFrameBase(aContext),
mLoopFlag(PR_FALSE),
mNoHRefURI(PR_FALSE)
{
if (aRef) {
// Get the href
aRef->GetHref(getter_AddRefs(mHref));
}
}
//----------------------------------------------------------------------
@ -303,8 +298,8 @@ nsSVGGradientFrame::GetReferencedGradient()
if (!property) {
// Fetch our gradient element's xlink:href attribute
nsAutoString href;
mHref->GetAnimVal(href);
nsSVGGradientElement *grad = static_cast<nsSVGGradientElement *>(mContent);
const nsString &href = grad->mStringAttributes[nsSVGGradientElement::HREF].GetAnimValue();
if (href.IsEmpty()) {
mNoHRefURI = PR_TRUE;
return nsnull; // no URL
@ -620,10 +615,7 @@ NS_NewSVGLinearGradientFrame(nsIPresShell* aPresShell,
return nsnull;
}
nsCOMPtr<nsIDOMSVGURIReference> aRef = do_QueryInterface(aContent);
NS_ASSERTION(aRef, "NS_NewSVGLinearGradientFrame -- Content doesn't support nsIDOMSVGURIReference");
return new (aPresShell) nsSVGLinearGradientFrame(aContext, aRef);
return new (aPresShell) nsSVGLinearGradientFrame(aContext);
}
nsIFrame*
@ -637,8 +629,5 @@ NS_NewSVGRadialGradientFrame(nsIPresShell* aPresShell,
return nsnull;
}
nsCOMPtr<nsIDOMSVGURIReference> aRef = do_QueryInterface(aContent);
NS_ASSERTION(aRef, "NS_NewSVGRadialGradientFrame -- Content doesn't support nsIDOMSVGURIReference");
return new (aPresShell) nsSVGRadialGradientFrame(aContext, aRef);
return new (aPresShell) nsSVGRadialGradientFrame(aContext);
}

View File

@ -57,8 +57,7 @@ typedef nsSVGPaintServerFrame nsSVGGradientFrameBase;
class nsSVGGradientFrame : public nsSVGGradientFrameBase
{
protected:
nsSVGGradientFrame(nsStyleContext* aContext,
nsIDOMSVGURIReference *aRef);
nsSVGGradientFrame(nsStyleContext* aContext);
public:
// nsSVGPaintServerFrame methods:
@ -136,10 +135,6 @@ protected:
nsRefPtr<nsSVGElement> mSourceContent;
private:
// href of the other gradient we reference (if any)
// XXX this should go away, we can watch our content directly
nsCOMPtr<nsIDOMSVGAnimatedString> mHref;
// Flag to mark this frame as "in use" during recursive calls along our
// gradient's reference chain so we can detect reference loops. See:
// http://www.w3.org/TR/SVG11/pservers.html#LinearGradientElementHrefAttribute
@ -162,9 +157,8 @@ class nsSVGLinearGradientFrame : public nsSVGLinearGradientFrameBase
nsIContent* aContent,
nsStyleContext* aContext);
protected:
nsSVGLinearGradientFrame(nsStyleContext* aContext,
nsIDOMSVGURIReference *aRef) :
nsSVGLinearGradientFrameBase(aContext, aRef) {}
nsSVGLinearGradientFrame(nsStyleContext* aContext) :
nsSVGLinearGradientFrameBase(aContext) {}
public:
// nsIFrame interface:
@ -199,9 +193,8 @@ class nsSVGRadialGradientFrame : public nsSVGRadialGradientFrameBase
nsIContent* aContent,
nsStyleContext* aContext);
protected:
nsSVGRadialGradientFrame(nsStyleContext* aContext,
nsIDOMSVGURIReference *aRef) :
nsSVGRadialGradientFrameBase(aContext, aRef) {}
nsSVGRadialGradientFrame(nsStyleContext* aContext) :
nsSVGRadialGradientFrameBase(aContext) {}
public:
// nsIFrame interface:

View File

@ -66,16 +66,11 @@ static void printRect(char *msg, nsIDOMSVGRect *aRect);
//----------------------------------------------------------------------
// Implementation
nsSVGPatternFrame::nsSVGPatternFrame(nsStyleContext* aContext,
nsIDOMSVGURIReference *aRef) :
nsSVGPatternFrame::nsSVGPatternFrame(nsStyleContext* aContext) :
nsSVGPatternFrameBase(aContext),
mLoopFlag(PR_FALSE), mPaintLoopFlag(PR_FALSE),
mNoHRefURI(PR_FALSE)
{
if (aRef) {
// Get the hRef
aRef->GetHref(getter_AddRefs(mHref));
}
}
//----------------------------------------------------------------------
@ -437,8 +432,8 @@ nsSVGPatternFrame::GetReferencedPattern()
if (!property) {
// Fetch our pattern element's xlink:href attribute
nsAutoString href;
mHref->GetAnimVal(href);
nsSVGPatternElement *pattern = static_cast<nsSVGPatternElement *>(mContent);
const nsString &href = pattern->mStringAttributes[nsSVGPatternElement::HREF].GetAnimValue();
if (href.IsEmpty()) {
mNoHRefURI = PR_TRUE;
return nsnull; // no URL
@ -761,14 +756,7 @@ nsIFrame* NS_NewSVGPatternFrame(nsIPresShell* aPresShell,
return nsnull;
}
nsCOMPtr<nsIDOMSVGURIReference> ref = do_QueryInterface(aContent);
NS_ASSERTION(ref,
"NS_NewSVGPatternFrame -- Content doesn't support nsIDOMSVGURIReference");
#ifdef DEBUG_scooter
printf("NS_NewSVGPatternFrame\n");
#endif
return new (aPresShell) nsSVGPatternFrame(aContext, ref);
return new (aPresShell) nsSVGPatternFrame(aContext);
}
#ifdef DEBUG_scooter

View File

@ -64,7 +64,7 @@ public:
nsIContent* aContent,
nsStyleContext* aContext);
nsSVGPatternFrame(nsStyleContext* aContext) : nsSVGPatternFrameBase(aContext) {}
nsSVGPatternFrame(nsStyleContext* aContext);
nsresult PaintPattern(gfxASurface **surface,
gfxMatrix *patternMatrix,
@ -103,9 +103,6 @@ public:
#endif // DEBUG
protected:
nsSVGPatternFrame(nsStyleContext* aContext,
nsIDOMSVGURIReference *aRef);
// Internal methods for handling referenced patterns
nsSVGPatternFrame* GetReferencedPattern();
// Helper to look at our pattern and then along its reference chain (if any)
@ -150,7 +147,6 @@ private:
nsCOMPtr<nsIDOMSVGMatrix> mCTM;
protected:
nsCOMPtr<nsIDOMSVGAnimatedString> mHref;
// This flag is used to detect loops in xlink:href processing
PRPackedBool mLoopFlag;
// This flag is used to detect loops when painting this pattern

View File

@ -35,46 +35,14 @@
* ***** END LICENSE BLOCK ***** */
#include "nsSVGTextPathFrame.h"
#include "nsSVGTextFrame.h"
#include "nsIDOMSVGTextPathElement.h"
#include "nsIDOMSVGAnimatedLength.h"
#include "nsSVGLength.h"
#include "nsSVGLength2.h"
#include "nsIDOMSVGURIReference.h"
#include "nsSVGUtils.h"
#include "nsSVGEffects.h"
#include "nsContentUtils.h"
#include "nsIDOMSVGAnimatedPathData.h"
#include "nsSVGPathElement.h"
#include "nsSVGTextPathElement.h"
NS_IMPL_ISUPPORTS1(nsSVGPathListener, nsIMutationObserver)
nsSVGPathListener::nsSVGPathListener(nsIContent *aPathElement,
nsSVGTextPathFrame *aTextPathFrame) :
mTextPathFrame(aTextPathFrame)
{
mObservedPath = do_GetWeakReference(aPathElement);
aPathElement->AddMutationObserver(this);
}
nsSVGPathListener::~nsSVGPathListener()
{
nsCOMPtr<nsIContent> path = do_QueryReferent(mObservedPath);
if (path)
path->RemoveMutationObserver(this);
}
void
nsSVGPathListener::AttributeChanged(nsIDocument *aDocument,
nsIContent *aContent,
PRInt32 aNameSpaceID,
nsIAtom *aAttribute,
PRInt32 aModType,
PRUint32 aStateMask)
{
mTextPathFrame->NotifyGlyphMetricsChange();
}
//----------------------------------------------------------------------
// Implementation
@ -97,24 +65,6 @@ NS_NewSVGTextPathFrame(nsIPresShell* aPresShell, nsIContent* aContent,
return new (aPresShell) nsSVGTextPathFrame(aContext);
}
NS_IMETHODIMP
nsSVGTextPathFrame::Init(nsIContent* aContent,
nsIFrame* aParent,
nsIFrame* aPrevInFlow)
{
nsSVGTextPathFrameBase::Init(aContent, aParent, aPrevInFlow);
{
nsCOMPtr<nsIDOMSVGURIReference> aRef = do_QueryInterface(mContent);
if (aRef)
aRef->GetHref(getter_AddRefs(mHref));
if (!mHref)
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsIAtom *
nsSVGTextPathFrame::GetType() const
{
@ -152,21 +102,32 @@ nsSVGTextPathFrame::GetDy()
nsIFrame *
nsSVGTextPathFrame::GetPathFrame()
{
nsIFrame *path = nsnull;
nsSVGTextPathProperty *property =
static_cast<nsSVGTextPathProperty*>(GetProperty(nsGkAtoms::href));
nsAutoString str;
mHref->GetAnimVal(str);
if (!property) {
nsSVGTextPathElement *tp = static_cast<nsSVGTextPathElement*>(mContent);
const nsString &href = tp->mStringAttributes[nsSVGTextPathElement::HREF].GetAnimValue();
if (href.IsEmpty()) {
return nsnull; // no URL
}
nsCOMPtr<nsIURI> targetURI;
nsCOMPtr<nsIURI> base = mContent->GetBaseURI();
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), str,
mContent->GetCurrentDoc(), base);
nsCOMPtr<nsIURI> targetURI;
nsCOMPtr<nsIURI> base = mContent->GetBaseURI();
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), href,
mContent->GetCurrentDoc(), base);
nsSVGUtils::GetReferencedFrame(&path, targetURI, mContent,
PresContext()->PresShell());
if (!path || (path->GetType() != nsGkAtoms::svgPathGeometryFrame))
property = nsSVGEffects::GetTextPathProperty(
targetURI, this, nsGkAtoms::href);
if (!property)
return nsnull;
}
nsIFrame *result = property->GetReferencedFrame();
if (!result || result->GetType() != nsGkAtoms::svgPathGeometryFrame)
return nsnull;
return path;
return result;
}
already_AddRefed<gfxFlattenedPath>
@ -183,10 +144,6 @@ nsSVGTextPathFrame::GetFlattenedPath(nsIFrame *path)
nsSVGPathGeometryElement *element = static_cast<nsSVGPathGeometryElement*>
(path->GetContent());
if (!mPathListener) {
mPathListener = new nsSVGPathListener(path->GetContent(), this);
}
nsCOMPtr<nsIDOMSVGMatrix> localTM = element->GetLocalTransformMatrix();
return element->GetFlattenedPath(localTM);
@ -240,7 +197,8 @@ nsSVGTextPathFrame::AttributeChanged(PRInt32 aNameSpaceID,
NotifyGlyphMetricsChange();
} else if (aNameSpaceID == kNameSpaceID_XLink &&
aAttribute == nsGkAtoms::href) {
mPathListener = nsnull;
// Blow away our reference, if any
DeleteProperty(nsGkAtoms::href);
NotifyGlyphMetricsChange();
}

View File

@ -40,29 +40,9 @@
#include "nsSVGTSpanFrame.h"
#include "nsIDOMSVGAnimatedString.h"
#include "nsSVGLengthList.h"
#include "nsIDOMSVGLength.h"
#include "gfxPath.h"
#include "nsStubMutationObserver.h"
class nsSVGTextPathFrame;
class nsSVGPathListener : public nsStubMutationObserver {
public:
nsSVGPathListener(nsIContent *aPathElement,
nsSVGTextPathFrame *aTextPathFrame);
~nsSVGPathListener();
// nsISupports
NS_DECL_ISUPPORTS
// nsIMutationObserver
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
private:
nsWeakPtr mObservedPath;
nsSVGTextPathFrame *mTextPathFrame;
};
typedef nsSVGTSpanFrame nsSVGTextPathFrameBase;
class nsSVGTextPathFrame : public nsSVGTextPathFrameBase
@ -75,9 +55,6 @@ protected:
public:
// nsIFrame:
NS_IMETHOD Init(nsIContent* aContent,
nsIFrame* aParent,
nsIFrame* aPrevInFlow);
NS_IMETHOD AttributeChanged(PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType);
@ -110,11 +87,6 @@ protected:
private:
already_AddRefed<gfxFlattenedPath> GetFlattenedPath(nsIFrame *path);
nsCOMPtr<nsIDOMSVGAnimatedString> mHref;
nsRefPtr<nsSVGPathListener> mPathListener;
friend class nsSVGPathListener;
};
#endif