Bug 333698 - Fix x and y positioning of nested tspans; r=longsonr; a=roc

This commit is contained in:
KUROSAWA, Takeshi 2010-09-18 12:46:48 +09:00
Родитель 799fb06cc7
Коммит 07c1e75fb0
8 изменённых файлов: 354 добавлений и 97 удалений

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

@ -65,6 +65,23 @@ public:
NS_IMETHOD_(PRBool) IsStartOfChunk()=0; // == is new absolutely positioned chunk.
NS_IMETHOD_(void) GetXY(mozilla::SVGUserUnitList *aX, mozilla::SVGUserUnitList *aY)=0;
NS_IMETHOD_(void) SetStartIndex(PRUint32 aStartIndex)=0;
/*
* Returns inherited x and y values instead of parent element's attribute
* values.
*/
NS_IMETHOD_(void) GetEffectiveXY(nsTArray<float> &aX, nsTArray<float> &aY)=0;
/*
* Returns inherited dx and dy values instead of parent element's attribute
* values.
*/
NS_IMETHOD_(void) GetEffectiveDxDy(nsTArray<float> &aDx,
nsTArray<float> &aDy)=0;
/*
* Returns inherited rotate values instead of parent element's attribute
* values.
*/
NS_IMETHOD_(void) GetEffectiveRotate(nsTArray<float> &aRotate)=0;
NS_IMETHOD_(PRUint16) GetTextAnchor()=0;
NS_IMETHOD_(PRBool) IsAbsolutelyPositioned()=0;
};

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

@ -657,31 +657,6 @@ nsSVGGlyphFrame::GetCharacterData(nsAString & aCharacterData)
return !characterData.IsEmpty();
}
static PRUint32
GetNumberOfNumberListItems(nsIDOMSVGNumberList *aList)
{
PRUint32 items = 0;
if (aList) {
aList->GetNumberOfItems(&items);
}
return items;
}
static float
GetNumberListValue(nsIDOMSVGNumberList *aList, PRUint32 aIndex)
{
if (!aList) {
return 0.0f;
}
nsCOMPtr<nsIDOMSVGNumber> number;
nsresult rv = aList->GetItem(aIndex, getter_AddRefs(number));
float value = 0.0f;
if (NS_SUCCEEDED(rv)) {
number->GetValue(&value);
}
return value;
}
PRBool
nsSVGGlyphFrame::GetCharacterPositions(nsTArray<CharacterPosition>* aCharacterPositions,
float aMetricsScale)
@ -691,15 +666,15 @@ nsSVGGlyphFrame::GetCharacterPositions(nsTArray<CharacterPosition>* aCharacterPo
const gfxFloat radPerDeg = M_PI / 180.0;
SVGUserUnitList dxList, dyList;
GetDxDy(&dxList, &dyList);
nsCOMPtr<nsIDOMSVGNumberList> rotateList = GetRotate();
PRBool rotateAllGlyphs = (GetNumberOfNumberListItems(rotateList) == 1);
gfxFloat overallGlyphRotation =
rotateAllGlyphs ? GetNumberListValue(rotateList, 0) * radPerDeg : 0.0;
nsTArray<float> xList, yList;
GetEffectiveXY(xList, yList);
nsTArray<float> dxList, dyList;
GetEffectiveDxDy(dxList, dyList);
nsTArray<float> rotateList;
GetEffectiveRotate(rotateList);
gfxPoint pos = mPosition;
gfxFloat angle = 0.0;
nsSVGTextPathFrame *textPath = FindTextPathParent();
@ -723,8 +698,15 @@ nsSVGGlyphFrame::GetCharacterPositions(nsTArray<CharacterPosition>* aCharacterPo
gfxFloat halfAdvance =
mTextRun->GetAdvanceWidth(i, 1, nsnull)*aMetricsScale / 2.0;
pos.x += i < dxList.Length() ? dxList[i] * pathScale : 0.0;
pos.y += i < dyList.Length() ? dyList[i] * pathScale : 0.0;
// use only x position for horizontal writing
if (i > 0 && i < xList.Length()) {
pos.x = xList[i];
}
pos.x += (i > 0 && i < dxList.Length()) ? dxList[i] * pathScale : 0.0;
pos.y += (i > 0 && i < dyList.Length()) ? dyList[i] * pathScale : 0.0;
if (i < rotateList.Length()) {
angle = rotateList[i] * radPerDeg;
}
// check that we're within the path boundaries
cp[i].draw = (pos.x + halfAdvance >= 0.0 &&
@ -739,25 +721,18 @@ nsSVGGlyphFrame::GetCharacterPositions(nsTArray<CharacterPosition>* aCharacterPo
&(cp[i].angle));
cp[i].pos =
pt - gfxPoint(cos(cp[i].angle), sin(cp[i].angle)) * halfAdvance;
cp[i].angle += rotateAllGlyphs ? overallGlyphRotation :
GetNumberListValue(rotateList, i) * radPerDeg;
cp[i].angle += angle;
}
pos.x += 2 * halfAdvance;
}
return PR_TRUE;
}
SVGUserUnitList xList, yList;
GetXY(&xList, &yList);
PRUint32 xListCount = xList.Length();
PRUint32 yListCount = yList.Length();
if (xListCount <= 1 &&
yListCount <= 1 &&
dxList.Length() == 0 &&
dyList.Length() == 0 &&
GetNumberOfNumberListItems(rotateList) == 0) {
if (xList.Length() <= 1 &&
yList.Length() <= 1 &&
dxList.Length() <= 1 &&
dyList.Length() <= 1 &&
rotateList.IsEmpty()) {
// simple text without individual positioning
return PR_TRUE;
}
@ -773,23 +748,26 @@ nsSVGGlyphFrame::GetCharacterPositions(nsTArray<CharacterPosition>* aCharacterPo
cp[i].draw = PR_TRUE;
gfxFloat advance = mTextRun->GetAdvanceWidth(i, 1, nsnull)*aMetricsScale;
if (xListCount > 1 && i < xListCount) {
if (xList.Length() > 1 && i < xList.Length()) {
pos.x = xList[i];
// apply text-anchor to character
if (anchor == NS_STYLE_TEXT_ANCHOR_MIDDLE)
pos.x -= advance/2.0;
else if (anchor == NS_STYLE_TEXT_ANCHOR_END)
pos.x -= advance;
}
if (yListCount > 1 && i < yListCount) {
if (yList.Length() > 1 && i < yList.Length()) {
pos.y = yList[i];
}
pos.x += i < dxList.Length() ? dxList[i] : 0.0;
pos.y += i < dyList.Length() ? dyList[i] : 0.0;
pos.x += (i > 0 && i < dxList.Length()) ? dxList[i] : 0.0;
pos.y += (i > 0 && i < dyList.Length()) ? dyList[i] : 0.0;
cp[i].pos = pos;
pos.x += advance;
cp[i].angle = rotateAllGlyphs ? overallGlyphRotation :
GetNumberListValue(rotateList, i) * radPerDeg;
if (i < rotateList.Length()) {
angle = rotateList[i] * radPerDeg;
}
cp[i].angle = angle;
}
return PR_TRUE;
}
@ -805,8 +783,8 @@ nsSVGGlyphFrame::GetSubStringAdvance(PRUint32 aCharnum,
gfxFloat advance =
mTextRun->GetAdvanceWidth(aCharnum, aFragmentChars, nsnull) * aMetricsScale;
SVGUserUnitList dxlist, notUsed;
GetDxDy(&dxlist, &notUsed);
nsTArray<float> dxlist, notUsed;
GetEffectiveDxDy(dxlist, notUsed);
PRUint32 dxcount = dxlist.Length();
if (dxcount) {
gfxFloat pathScale = 1.0;
@ -1008,32 +986,63 @@ nsSVGGlyphFrame::SetGlyphPosition(gfxPoint *aPosition, PRBool aForceGlobalTransf
{
float drawScale, metricsScale;
nsSVGTextPathFrame *textPath = FindTextPathParent();
// In a textPath, the 'y' attribute has no effect, so we reset 'y' here
// to use aPosition.y for dy only
if (textPath && textPath->GetFirstChild(nsnull) == this) {
aPosition->y = 0.0;
}
if (!EnsureTextRun(&drawScale, &metricsScale, aForceGlobalTransform))
return;
mPosition.MoveTo(aPosition->x, aPosition->y - GetBaselineOffset(metricsScale));
PRUint32 strLength = mTextRun->GetLength();
aPosition->x +=
mTextRun->GetAdvanceWidth(0, strLength, nsnull) * metricsScale;
nsTArray<float> xList, yList;
GetEffectiveXY(xList, yList);
PRUint32 xCount = NS_MIN(xList.Length(), strLength);
PRUint32 yCount = NS_MIN(yList.Length(), strLength);
// move aPosition to the last glyph position
gfxFloat x = aPosition->x;
if (xCount > 1) {
x = xList[xCount - 1];
x +=
mTextRun->GetAdvanceWidth(xCount - 1, 1, nsnull) * metricsScale;
// advance to the last glyph
if (strLength > xCount) {
x +=
mTextRun->GetAdvanceWidth(xCount, strLength - xCount, nsnull) *
metricsScale;
}
} else {
x += mTextRun->GetAdvanceWidth(0, strLength, nsnull) * metricsScale;
}
gfxFloat y = (textPath || yCount <= 1) ? aPosition->y : yList[yCount - 1];
aPosition->MoveTo(x, y - GetBaselineOffset(metricsScale));
gfxFloat pathScale = 1.0;
nsSVGTextPathFrame *textPath = FindTextPathParent();
if (textPath)
pathScale = textPath->GetPathScale();
SVGUserUnitList dxList, dyList;
GetDxDy(&dxList, &dyList);
nsTArray<float> dxList, dyList;
GetEffectiveDxDy(dxList, dyList);
PRUint32 dxcount = dxList.Length();
if (dxcount > strLength)
dxcount = strLength;
PRUint32 dxcount = NS_MIN(dxList.Length(), strLength);
if (dxcount > 0) {
mPosition.x += dxList[0] * pathScale;
}
for (PRUint32 i = 0; i < dxcount; i++) {
aPosition->x += dxList[i] * pathScale;
}
PRUint32 dycount = dyList.Length();
if (dycount > strLength)
dycount = strLength;
PRUint32 dycount = NS_MIN(dyList.Length(), strLength);
if (dycount > 0) {
mPosition.y += dyList[0]* pathScale;
}
for (PRUint32 i = 0; i < dycount; i++) {
aPosition->y += dyList[i] * pathScale;
}
@ -1157,19 +1166,51 @@ nsSVGGlyphFrame::IsStartOfChunk()
NS_IMETHODIMP_(void)
nsSVGGlyphFrame::GetXY(SVGUserUnitList *aX, SVGUserUnitList *aY)
{
nsSVGTextContainerFrame *containerFrame;
containerFrame = static_cast<nsSVGTextContainerFrame *>(mParent);
if (containerFrame)
containerFrame->GetXY(aX, aY);
static_cast<nsSVGTextContainerFrame *>(mParent)->GetXY(aX, aY);
}
NS_IMETHODIMP_(void)
nsSVGGlyphFrame::SetStartIndex(PRUint32 aStartIndex)
{
mStartIndex = aStartIndex;
}
NS_IMETHODIMP_(void)
nsSVGGlyphFrame::GetEffectiveXY(nsTArray<float> &aX, nsTArray<float> &aY)
{
nsTArray<float> x, y;
static_cast<nsSVGTextContainerFrame *>(mParent)->GetEffectiveXY(x, y);
PRInt32 strLength = GetNumberOfChars();
PRInt32 xCount = NS_MAX((PRInt32)(x.Length() - mStartIndex), 0);
xCount = NS_MIN(xCount, strLength);
aX.AppendElements(x.Elements() + mStartIndex, xCount);
PRInt32 yCount = NS_MAX((PRInt32)(y.Length() - mStartIndex), 0);
yCount = NS_MIN(yCount, strLength);
aY.AppendElements(y.Elements() + mStartIndex, yCount);
}
void
nsSVGGlyphFrame::GetDxDy(SVGUserUnitList *aDx, SVGUserUnitList *aDy)
{
nsSVGTextContainerFrame *containerFrame;
containerFrame = static_cast<nsSVGTextContainerFrame *>(mParent);
if (containerFrame)
containerFrame->GetDxDy(aDx, aDy);
static_cast<nsSVGTextContainerFrame *>(mParent)->GetDxDy(aDx, aDy);
}
void
nsSVGGlyphFrame::GetEffectiveDxDy(nsTArray<float> &aDx, nsTArray<float> &aDy)
{
nsTArray<float> dx, dy;
static_cast<nsSVGTextContainerFrame *>(mParent)->GetEffectiveDxDy(dx, dy);
PRInt32 strLength = GetNumberOfChars();
PRInt32 dxCount = NS_MAX((PRInt32)(dx.Length() - mStartIndex), 0);
dxCount = NS_MIN(dxCount, strLength);
aDx.AppendElements(dx.Elements() + mStartIndex, dxCount);
PRInt32 dyCount = NS_MAX((PRInt32)(dy.Length() - mStartIndex), 0);
dyCount = NS_MIN(dyCount, strLength);
aDy.AppendElements(dy.Elements() + mStartIndex, dyCount);
}
already_AddRefed<nsIDOMSVGNumberList>
@ -1182,6 +1223,23 @@ nsSVGGlyphFrame::GetRotate()
return nsnull;
}
void
nsSVGGlyphFrame::GetEffectiveRotate(nsTArray<float> &aRotate)
{
nsTArray<float> rotate;
static_cast<nsSVGTextContainerFrame *>(mParent)->GetEffectiveRotate(rotate);
PRInt32 strLength = GetNumberOfChars();
PRInt32 rotateCount = NS_MAX((PRInt32)(rotate.Length() - mStartIndex), 0);
rotateCount = NS_MIN(rotateCount, strLength);
if (rotateCount > 0) {
aRotate.AppendElements(rotate.Elements() + mStartIndex, rotateCount);
} else if (!rotate.IsEmpty()) {
// rotate is applied for extra characters too
aRotate.AppendElement(rotate[rotate.Length() - 1]);
}
}
NS_IMETHODIMP_(PRUint16)
nsSVGGlyphFrame::GetTextAnchor()
{
@ -1191,31 +1249,35 @@ nsSVGGlyphFrame::GetTextAnchor()
NS_IMETHODIMP_(PRBool)
nsSVGGlyphFrame::IsAbsolutelyPositioned()
{
nsIFrame *lastFrame = this;
PRBool hasTextPathAncestor = PR_FALSE;
for (nsIFrame *frame = GetParent();
frame != nsnull;
lastFrame = frame, frame = frame->GetParent()) {
frame = frame->GetParent()) {
/* need to be the first child if we are absolutely positioned */
if (!frame ||
frame->GetFirstChild(nsnull) != lastFrame)
if (!frame)
break;
// textPath is always absolutely positioned for our purposes
if (frame->GetType() == nsGkAtoms::svgTextPathFrame)
return PR_TRUE;
if (frame &&
(frame->GetContent()->HasAttr(kNameSpaceID_None, nsGkAtoms::x) ||
frame->GetContent()->HasAttr(kNameSpaceID_None, nsGkAtoms::y)))
// at the start of a 'text' element
// at the start of each 'textPath' element
if (frame->GetType() == nsGkAtoms::svgTextPathFrame) {
hasTextPathAncestor = PR_TRUE;
}
if ((frame->GetType() == nsGkAtoms::svgTextFrame ||
frame->GetType() == nsGkAtoms::svgTextPathFrame) &&
frame->GetFirstChild(nsnull) == this) {
return PR_TRUE;
}
if (frame->GetType() == nsGkAtoms::svgTextFrame)
break;
}
return PR_FALSE;
// for each character within a 'text', 'tspan', 'tref' and 'altGlyph' element
// which has an x or y attribute value assigned to it explicitly
nsTArray<float> x, y;
GetEffectiveXY(x, y);
// Note: the y of descendants of textPath has no effect in horizontal writing
return (!x.IsEmpty() || (!hasTextPathAncestor && !y.IsEmpty()));
}

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

@ -65,6 +65,7 @@ protected:
nsSVGGlyphFrame(nsStyleContext* aContext)
: nsSVGGlyphFrameBase(aContext),
mTextRun(nsnull),
mStartIndex(0),
mWhitespaceHandling(COMPRESS_WHITESPACE)
{}
~nsSVGGlyphFrame()
@ -150,6 +151,11 @@ public:
NS_IMETHOD_(PRBool) IsStartOfChunk(); // == is new absolutely positioned chunk.
NS_IMETHOD_(void) GetXY(mozilla::SVGUserUnitList *aX, mozilla::SVGUserUnitList *aY);
NS_IMETHOD_(void) SetStartIndex(PRUint32 aStartIndex);
NS_IMETHOD_(void) GetEffectiveXY(nsTArray<float> &aX, nsTArray<float> &aY);
NS_IMETHOD_(void) GetEffectiveDxDy(nsTArray<float> &aDx,
nsTArray<float> &aDy);
NS_IMETHOD_(void) GetEffectiveRotate(nsTArray<float> &aRotate);
NS_IMETHOD_(PRUint16) GetTextAnchor();
NS_IMETHOD_(PRBool) IsAbsolutelyPositioned();
@ -216,6 +222,8 @@ protected:
// Owning pointer, must call gfxTextRunWordCache::RemoveTextRun before deleting
gfxTextRun *mTextRun;
gfxPoint mPosition;
// The start index into the position and rotation data
PRUint32 mStartIndex;
PRUint8 mWhitespaceHandling;
};

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

@ -397,3 +397,136 @@ nsSVGTextContainerFrame::GetTextFrame()
}
return nsnull;
}
void
nsSVGTextContainerFrame::CopyPositionList(nsTArray<float> *parentList,
SVGUserUnitList *selfList,
nsTArray<float> &dstList,
PRUint32 aOffset)
{
dstList.Clear();
PRUint32 strLength = GetNumberOfChars();
PRUint32 parentCount = 0;
if (parentList && parentList->Length() > aOffset) {
parentCount = NS_MIN(parentList->Length() - aOffset, strLength);
}
PRUint32 selfCount = NS_MIN(selfList->Length(), strLength);
PRUint32 count = NS_MAX(parentCount, selfCount);
if (!dstList.SetLength(count))
return;
for (PRUint32 i = 0; i < selfCount; i++) {
dstList[i] = (*selfList)[i];
}
for (PRUint32 i = selfCount; i < parentCount; i++) {
dstList[i] = (*parentList)[aOffset + i];
}
}
void
nsSVGTextContainerFrame::CopyRotateList(nsTArray<float> *parentList,
nsCOMPtr<nsIDOMSVGNumberList> selfList,
nsTArray<float> &dstList,
PRUint32 aOffset)
{
dstList.Clear();
PRUint32 strLength = GetNumberOfChars();
PRUint32 parentCount = 0;
if (parentList && parentList->Length() > aOffset) {
parentCount = NS_MIN(parentList->Length() - aOffset, strLength);
}
PRUint32 selfCount = 0;
if (selfList) {
selfList->GetNumberOfItems(&selfCount);
}
selfCount = NS_MIN(selfCount, strLength);
PRUint32 count = NS_MAX(parentCount, selfCount);
if (count > 0) {
if (!dstList.SetLength(count))
return;
for (PRUint32 i = 0; i < selfCount; i++) {
dstList[i] = nsSVGUtils::GetNumberListValue(selfList, i);
}
for (PRUint32 i = selfCount; i < parentCount; i++) {
dstList[i] = (*parentList)[aOffset + i];
}
} else if (parentList && !parentList->IsEmpty()) {
// rotate is applied to extra characters too
dstList.AppendElement((*parentList)[parentList->Length() - 1]);
}
}
PRUint32
nsSVGTextContainerFrame::BuildPositionList(PRUint32 aOffset,
PRUint32 aDepth)
{
nsSVGTextContainerFrame *parent = do_QueryFrame(mParent);
nsTArray<float> *parentX = nsnull, *parentY = nsnull;
nsTArray<float> *parentDx = nsnull, *parentDy = nsnull;
nsTArray<float> *parentRotate = nsnull;
if (parent) {
parentX = &(parent->mX);
parentY = &(parent->mY);
parentDx = &(parent->mDx);
parentDy = &(parent->mDy);
parentRotate = &(parent->mRotate);
}
SVGUserUnitList x, y;
GetXY(&x, &y);
CopyPositionList(parentX, &x, mX, aOffset);
CopyPositionList(parentY, &y, mY, aOffset);
SVGUserUnitList dx, dy;
GetDxDy(&dx, &dy);
CopyPositionList(parentDx, &dx, mDx, aOffset);
CopyPositionList(parentDy, &dy, mDy, aOffset);
nsCOMPtr<nsIDOMSVGNumberList> rotate = GetRotate();
CopyRotateList(parentRotate, rotate, mRotate, aOffset);
PRUint32 startIndex = 0;
nsIFrame* kid = mFrames.FirstChild();
while (kid) {
nsSVGTextContainerFrame *text = do_QueryFrame(kid);
nsISVGGlyphFragmentLeaf *leaf = do_QueryFrame(kid);
if (text) {
startIndex += text->BuildPositionList(startIndex, aDepth + 1);
} else if (leaf) {
leaf->SetStartIndex(startIndex);
startIndex += leaf->GetNumberOfChars();
}
kid = kid->GetNextSibling();
}
return startIndex;
}
void
nsSVGTextContainerFrame::GetEffectiveXY(nsTArray<float> &aX,
nsTArray<float> &aY)
{
aX.AppendElements(mX);
aY.AppendElements(mY);
}
void
nsSVGTextContainerFrame::GetEffectiveDxDy(nsTArray<float> &aDx,
nsTArray<float> &aDy)
{
aDx.AppendElements(mDx);
aDy.AppendElements(mDy);
}
void
nsSVGTextContainerFrame::GetEffectiveRotate(nsTArray<float> &aRotate)
{
aRotate.AppendElements(mRotate);
}

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

@ -93,6 +93,9 @@ public:
* Get the character at the specified position
*/
virtual PRInt32 GetCharNumAtPosition(nsIDOMSVGPoint *point);
void GetEffectiveXY(nsTArray<float> &aX, nsTArray<float> &aY);
void GetEffectiveDxDy(nsTArray<float> &aDx, nsTArray<float> &aDy);
void GetEffectiveRotate(nsTArray<float> &aRotate);
protected:
/*
@ -111,6 +114,15 @@ protected:
* Set Whitespace handling
*/
void SetWhitespaceHandling();
void CopyPositionList(nsTArray<float> *parentList,
mozilla::SVGUserUnitList *selfList,
nsTArray<float> &dstList,
PRUint32 aOffset);
void CopyRotateList(nsTArray<float> *parentList,
nsCOMPtr<nsIDOMSVGNumberList> selfList,
nsTArray<float> &dstList,
PRUint32 aOffset);
PRUint32 BuildPositionList(PRUint32 aOffset, PRUint32 aDepth);
private:
/*
@ -126,6 +138,11 @@ private:
* if this is a text frame)
*/
nsSVGTextFrame * GetTextFrame();
nsTArray<float> mX;
nsTArray<float> mY;
nsTArray<float> mDx;
nsTArray<float> mDy;
nsTArray<float> mRotate;
};
#endif

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

@ -313,21 +313,20 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform)
return;
}
gfxPoint ctp(0.0, 0.0);
BuildPositionList(0, 0);
SVGUserUnitList xLengthList, yLengthList;
GetXY(&xLengthList, &yLengthList);
if (xLengthList.Length() > 0) ctp.x = xLengthList[0];
if (yLengthList.Length() > 0) ctp.y = yLengthList[0];
gfxPoint ctp(0.0, 0.0);
// loop over chunks
while (firstFragment) {
firstFragment->GetXY(&xLengthList, &yLengthList);
if (xLengthList.Length() > 0) ctp.x = xLengthList[0];
if (yLengthList.Length() > 0) ctp.y = yLengthList[0];
nsSVGTextPathFrame *textPath = firstFragment->FindTextPathParent();
nsTArray<float> effectiveXList, effectiveYList;
firstFragment->GetEffectiveXY(effectiveXList, effectiveYList);
if (!effectiveXList.IsEmpty()) ctp.x = effectiveXList[0];
if (!textPath && !effectiveYList.IsEmpty()) ctp.y = effectiveYList[0];
// check for startOffset on textPath
nsSVGTextPathFrame *textPath = firstFragment->FindTextPathParent();
if (textPath) {
if (!textPath->GetPathFrame()) {
// invalid text path, give up

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

@ -91,6 +91,7 @@
#include "nsSVGPathGeometryFrame.h"
#include "prdtoa.h"
#include "mozilla/dom/Element.h"
#include "nsIDOMSVGNumberList.h"
using namespace mozilla::dom;
@ -1516,6 +1517,20 @@ nsSVGUtils::NumberFromString(const nsAString& aString, float* aValue,
return PR_FALSE;
}
/* static */ float
nsSVGUtils::GetNumberListValue(nsIDOMSVGNumberList *aList, PRUint32 aIndex)
{
if (!aList) {
return 0.0f;
}
nsCOMPtr<nsIDOMSVGNumber> number;
nsresult rv = aList->GetItem(aIndex, getter_AddRefs(number));
float value = 0.0f;
if (NS_SUCCEEDED(rv)) {
number->GetValue(&value);
}
return value;
}
// ----------------------------------------------------------------------

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

@ -60,6 +60,7 @@ class nsIFrame;
struct nsStyleSVGPaint;
class nsIDOMSVGElement;
class nsIDOMSVGLength;
class nsIDOMSVGNumberList;
class nsIURI;
class nsSVGOuterSVGFrame;
class nsSVGPreserveAspectRatio;
@ -594,6 +595,11 @@ public:
NS_MIN(double(PR_INT32_MAX), aVal)));
}
/**
* Returns aIndex-th item of nsIDOMSVGNumberList
*/
static float GetNumberListValue(nsIDOMSVGNumberList *aList, PRUint32 aIndex);
private:
/* Computational (nil) surfaces */
static gfxASurface *gThebesComputationalSurface;