Bug 340859 - Implement pathLength attribute.

Patch by amenzie@us.ibm.com, r=tor, sr=roc.
This commit is contained in:
tor%cs.brown.edu 2006-07-11 15:52:15 +00:00
Родитель d158030827
Коммит b4a3da9a05
8 изменённых файлов: 87 добавлений и 40 удалений

Просмотреть файл

@ -46,6 +46,7 @@
#include "nsSVGPathElement.h"
#include "nsISVGValueUtils.h"
#include "nsSVGUtils.h"
#include "nsSVGAnimatedNumber.h"
NS_IMPL_NS_NEW_SVG_ELEMENT(Path)
@ -72,6 +73,20 @@ nsSVGPathElement::nsSVGPathElement(nsINodeInfo* aNodeInfo)
{
}
nsresult
nsSVGPathElement::Init()
{
nsresult rv = nsSVGPathElementBase::Init();
NS_ENSURE_SUCCESS(rv, rv);
{
rv = NS_NewSVGAnimatedNumber(getter_AddRefs(mPathLength), 0.0);
NS_ENSURE_SUCCESS(rv, rv);
rv = AddMappedSVGValue(nsSVGAtoms::pathLength, mPathLength);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
nsSVGPathElement::~nsSVGPathElement()
{
if (mSegments)
@ -90,7 +105,9 @@ NS_IMPL_DOM_CLONENODE_WITH_INIT(nsSVGPathElement)
NS_IMETHODIMP
nsSVGPathElement::GetPathLength(nsIDOMSVGAnimatedNumber * *aPathLength)
{
return NS_ERROR_NOT_IMPLEMENTED;
*aPathLength = mPathLength;
NS_IF_ADDREF(*aPathLength);
return NS_OK;
}
/* float getTotalLength (); */

Просмотреть файл

@ -94,6 +94,7 @@ protected:
nsINodeInfo *aNodeInfo);
nsSVGPathElement(nsINodeInfo *aNodeInfo);
virtual ~nsSVGPathElement();
nsresult Init();
public:
// interfaces:
@ -131,6 +132,7 @@ protected:
nsresult CreatePathSegList();
nsCOMPtr<nsIDOMSVGPathSegList> mSegments;
nsCOMPtr<nsIDOMSVGAnimatedNumber> mPathLength;
nsSVGPathList mPathData;
};

Просмотреть файл

@ -43,10 +43,11 @@
#include "nsIDOMSVGLengthList.h"
class nsISVGRendererGlyphMetrics;
class nsSVGTextPathFrame;
// {33397E2B-C1DC-49f0-9738-4891FE083C92}
// {bc02467f-f611-4c0f-8d95-e2923d66f775}
#define NS_ISVGGLYPHFRAGMENTLEAF_IID \
{ 0x33397e2b, 0xc1dc, 0x49f0, { 0x97, 0x38, 0x48, 0x91, 0xfe, 0x8, 0x3c, 0x92 } }
{ 0xbc02467f, 0xf611, 0x4c0f, { 0x8d, 0x95, 0xe2, 0x92, 0x3d, 0x66, 0xf7, 0x75 } }
class nsISVGGlyphFragmentLeaf : public nsISVGGlyphFragmentNode
{
@ -56,6 +57,7 @@ public:
NS_IMETHOD_(void) SetGlyphPosition(float x, float y)=0;
NS_IMETHOD GetGlyphMetrics(nsISVGRendererGlyphMetrics** metrics)=0;
NS_IMETHOD_(nsSVGTextPathFrame*) FindTextPathParent()=0;
NS_IMETHOD_(PRBool) IsStartOfChunk()=0; // == is new absolutely positioned chunk.
NS_IMETHOD_(void) GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y)=0;

Просмотреть файл

@ -412,24 +412,12 @@ nsSVGGlyphFrame::GetCharacterData(nsAString & aCharacterData)
return NS_OK;
}
/* void GetCharacterPosition (out nsSVGCharacterPosition aCP); */
/* void GetCharacterPosition (out nsSVGCharacterPosition aCP); */
NS_IMETHODIMP
nsSVGGlyphFrame::GetCharacterPosition(nsSVGCharacterPosition **aCharacterPosition)
{
*aCharacterPosition = nsnull;
nsSVGTextPathFrame *textPath = nsnull;
/* check if we're the child of a textPath */
for (nsIFrame *frame = GetParent();
frame != nsnull;
frame = frame->GetParent()) {
if (frame->GetType() == nsLayoutAtoms::svgTextPathFrame) {
textPath = NS_STATIC_CAST(nsSVGTextPathFrame*, frame);
break;
}
if (frame->GetType() == nsLayoutAtoms::svgTextFrame)
break;
}
nsSVGTextPathFrame *textPath = FindTextPathParent();
/* we're an ordinary fragment - return */
/* XXX: we might want to use this for individual x/y/dx/dy adjustment */
@ -479,7 +467,7 @@ nsSVGGlyphFrame::GetCharacterPosition(nsSVGCharacterPosition **aCharacterPositio
return NS_OK;
}
/* void GetGlyphPosition (out float aGlyphPositionX, out float aGlyphPositionY); */
/* void GetGlyphPosition (out float aGlyphPositionX, out float aGlyphPositionY); */
NS_IMETHODIMP
nsSVGGlyphFrame::GetGlyphPosition(float *aGlyphPositionX, float *aGlyphPositionY)
{
@ -692,6 +680,22 @@ nsSVGGlyphFrame::GetGlyphMetrics(nsISVGRendererGlyphMetrics** metrics)
return NS_OK;
}
NS_IMETHODIMP_(nsSVGTextPathFrame*)
nsSVGGlyphFrame::FindTextPathParent()
{
/* check if we're the child of a textPath */
for (nsIFrame *frame = GetParent();
frame != nsnull;
frame = frame->GetParent()) {
nsIAtom* type = frame->GetType();
if (type == nsLayoutAtoms::svgTextPathFrame) {
return NS_STATIC_CAST(nsSVGTextPathFrame*, frame);
} else if (type == nsLayoutAtoms::svgTextFrame)
return nsnull;
}
return nsnull;
}
NS_IMETHODIMP_(PRBool)
nsSVGGlyphFrame::IsStartOfChunk()
{

Просмотреть файл

@ -127,6 +127,7 @@ public:
// nsISVGGlyphFragmentLeaf interface:
NS_IMETHOD_(void) SetGlyphPosition(float x, float y);
NS_IMETHOD GetGlyphMetrics(nsISVGRendererGlyphMetrics** metrics);
NS_IMETHOD_(nsSVGTextPathFrame*) FindTextPathParent();
NS_IMETHOD_(PRBool) IsStartOfChunk(); // == is new absolutely positioned chunk.
NS_IMETHOD_(void) GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y);

Просмотреть файл

@ -41,6 +41,7 @@
#include "nsWeakReference.h"
#include "nsIDOMSVGLengthList.h"
#include "nsIDOMSVGLength.h"
#include "nsIDOMSVGAnimatedNumber.h"
#include "nsISVGGlyphFragmentNode.h"
#include "nsISVGGlyphFragmentLeaf.h"
#include "nsISVGRendererGlyphMetrics.h"
@ -515,31 +516,42 @@ GetSingleValue(nsISVGGlyphFragmentLeaf *fragment,
list->GetItem(0, getter_AddRefs(length));
length->GetValue(val);
/* check for % sizing of textpath */
PRUint16 type;
length->GetUnitType(&type);
if (type == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE) {
nsIFrame *glyph;
CallQueryInterface(fragment, &glyph);
nsSVGTextPathFrame *textPath = fragment->FindTextPathParent();
nsSVGTextPathFrame *textPath = nsnull;
/* check if we're the child of a textPath */
for (nsIFrame *frame = glyph; frame != nsnull; frame = frame->GetParent())
if (frame->GetType() == nsLayoutAtoms::svgTextPathFrame) {
textPath = NS_STATIC_CAST(nsSVGTextPathFrame*, frame);
break;
}
if (textPath) {
nsAutoPtr<nsSVGFlattenedPath> data(textPath->GetFlattenedPath());
if (!data)
return;
if (textPath) {
nsAutoPtr<nsSVGFlattenedPath> data(textPath->GetFlattenedPath());
if (!data)
return;
nsIFrame *pathFrame = textPath->GetPathFrame();
if (!pathFrame)
return;
/* check for % sizing of textpath */
PRUint16 type;
length->GetUnitType(&type);
if (type == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE) {
float percent;
length->GetValueInSpecifiedUnits(&percent);
*val = data->GetLength()*percent/100.0f;
} else if (pathFrame->GetContent()->HasAttr(kNameSpaceID_None,
nsGkAtoms::pathLength)) {
nsCOMPtr<nsIDOMSVGPathElement> pathElement =
do_QueryInterface(pathFrame->GetContent());
if (!pathElement)
return;
nsIDOMSVGAnimatedNumber* pathLength;
pathElement->GetPathLength(&pathLength);
if (!pathLength)
return;
float pl;
pathLength->GetAnimVal(&pl);
if (pl)
*val *= data->GetLength() / pl;
else
*val = 0;
}
}
}

Просмотреть файл

@ -169,8 +169,8 @@ nsSVGTextPathFrame::GetDy()
//----------------------------------------------------------------------
// nsSVGTextPathFrame methods:
nsSVGFlattenedPath *
nsSVGTextPathFrame::GetFlattenedPath() {
nsIFrame *
nsSVGTextPathFrame::GetPathFrame() {
nsIFrame *path = nsnull;
nsAutoString str;
@ -178,13 +178,21 @@ nsSVGTextPathFrame::GetFlattenedPath() {
nsCOMPtr<nsIURI> targetURI;
nsCOMPtr<nsIURI> base = mContent->GetBaseURI();
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI),
str, mContent->GetCurrentDoc(), base);
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), str,
mContent->GetCurrentDoc(), base);
nsSVGUtils::GetReferencedFrame(&path, targetURI, mContent,
GetPresContext()->PresShell());
if (!path || (path->GetType() != nsGkAtoms::svgPathGeometryFrame))
return nsnull;
return path;
}
nsSVGFlattenedPath *
nsSVGTextPathFrame::GetFlattenedPath() {
nsIFrame *path = GetPathFrame();
if (!path)
return nsnull;
if (!mSegments) {
nsCOMPtr<nsIDOMSVGAnimatedPathData> data =

Просмотреть файл

@ -84,6 +84,7 @@ public:
// nsSVGTextPathFrame methods:
nsSVGFlattenedPath *GetFlattenedPath();
nsIFrame *GetPathFrame();
// nsISupports interface:
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);