Bug 388547 - Initial support for x,y,dx,dy,rotate lists on SVG text and tspan elements. r=roc

This commit is contained in:
Robert Longson 2009-10-11 12:44:33 +01:00
Родитель 2c790fff6e
Коммит 1dbfbb3e36
13 изменённых файлов: 382 добавлений и 124 удалений

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

@ -41,7 +41,9 @@
#include "nsIDOMSVGTSpanElement.h" #include "nsIDOMSVGTSpanElement.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsSVGAnimatedLengthList.h" #include "nsSVGAnimatedLengthList.h"
#include "nsSVGAnimatedNumberList.h"
#include "nsSVGLengthList.h" #include "nsSVGLengthList.h"
#include "nsSVGNumberList.h"
#include "nsSVGSVGElement.h" #include "nsSVGSVGElement.h"
#include "nsSVGTextContentElement.h" #include "nsSVGTextContentElement.h"
#include "nsIFrame.h" #include "nsIFrame.h"
@ -91,6 +93,7 @@ protected:
nsCOMPtr<nsIDOMSVGAnimatedLengthList> mY; nsCOMPtr<nsIDOMSVGAnimatedLengthList> mY;
nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdX; nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdX;
nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdY; nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdY;
nsCOMPtr<nsIDOMSVGAnimatedNumberList> mRotate;
}; };
@ -178,6 +181,18 @@ nsSVGTSpanElement::Init()
NS_ENSURE_SUCCESS(rv,rv); NS_ENSURE_SUCCESS(rv,rv);
} }
// DOM property: nsIDOMSVGTextPositioningElement::rotate, #IMPLIED attrib: rotate
{
nsCOMPtr<nsIDOMSVGNumberList> numberList;
rv = NS_NewSVGNumberList(getter_AddRefs(numberList));
NS_ENSURE_SUCCESS(rv,rv);
rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mRotate),
numberList);
NS_ENSURE_SUCCESS(rv,rv);
rv = AddMappedSVGValue(nsGkAtoms::rotate, mRotate);
NS_ENSURE_SUCCESS(rv,rv);
}
return rv; return rv;
} }
@ -231,8 +246,9 @@ NS_IMETHODIMP nsSVGTSpanElement::GetDy(nsIDOMSVGAnimatedLengthList * *aDy)
/* readonly attribute nsIDOMSVGAnimatedNumberList rotate; */ /* readonly attribute nsIDOMSVGAnimatedNumberList rotate; */
NS_IMETHODIMP nsSVGTSpanElement::GetRotate(nsIDOMSVGAnimatedNumberList * *aRotate) NS_IMETHODIMP nsSVGTSpanElement::GetRotate(nsIDOMSVGAnimatedNumberList * *aRotate)
{ {
NS_NOTYETIMPLEMENTED("nsSVGTSpanElement::GetRotate"); *aRotate = mRotate;
return NS_ERROR_NOT_IMPLEMENTED; NS_IF_ADDREF(*aRotate);
return NS_OK;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------

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

@ -41,7 +41,9 @@
#include "nsIDOMSVGTextElement.h" #include "nsIDOMSVGTextElement.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsSVGAnimatedLengthList.h" #include "nsSVGAnimatedLengthList.h"
#include "nsSVGAnimatedNumberList.h"
#include "nsSVGLengthList.h" #include "nsSVGLengthList.h"
#include "nsSVGNumberList.h"
#include "nsSVGSVGElement.h" #include "nsSVGSVGElement.h"
#include "nsSVGTextContentElement.h" #include "nsSVGTextContentElement.h"
#include "nsIFrame.h" #include "nsIFrame.h"
@ -88,6 +90,7 @@ protected:
nsCOMPtr<nsIDOMSVGAnimatedLengthList> mY; nsCOMPtr<nsIDOMSVGAnimatedLengthList> mY;
nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdX; nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdX;
nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdY; nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdY;
nsCOMPtr<nsIDOMSVGAnimatedNumberList> mRotate;
}; };
@ -174,6 +177,18 @@ nsSVGTextElement::Init()
NS_ENSURE_SUCCESS(rv,rv); NS_ENSURE_SUCCESS(rv,rv);
} }
// DOM property: nsIDOMSVGTextPositioningElement::rotate, #IMPLIED attrib: rotate
{
nsCOMPtr<nsIDOMSVGNumberList> numberList;
rv = NS_NewSVGNumberList(getter_AddRefs(numberList));
NS_ENSURE_SUCCESS(rv,rv);
rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mRotate),
numberList);
NS_ENSURE_SUCCESS(rv,rv);
rv = AddMappedSVGValue(nsGkAtoms::rotate, mRotate);
NS_ENSURE_SUCCESS(rv,rv);
}
return rv; return rv;
} }
@ -227,8 +242,9 @@ NS_IMETHODIMP nsSVGTextElement::GetDy(nsIDOMSVGAnimatedLengthList * *aDy)
/* readonly attribute nsIDOMSVGAnimatedNumberList rotate; */ /* readonly attribute nsIDOMSVGAnimatedNumberList rotate; */
NS_IMETHODIMP nsSVGTextElement::GetRotate(nsIDOMSVGAnimatedNumberList * *aRotate) NS_IMETHODIMP nsSVGTextElement::GetRotate(nsIDOMSVGAnimatedNumberList * *aRotate)
{ {
NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetRotate"); *aRotate = mRotate;
return NS_ERROR_NOT_IMPLEMENTED; NS_IF_ADDREF(*aRotate);
return NS_OK;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------

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

@ -122,6 +122,7 @@ random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == text-font-weight-01.svg text-font-weigh
== switch-01.svg pass.svg == switch-01.svg pass.svg
== text-gradient-01.svg text-gradient-01-ref.svg == text-gradient-01.svg text-gradient-01-ref.svg
== text-in-link-01.svg text-in-link-01-ref.svg == text-in-link-01.svg text-in-link-01-ref.svg
== text-layout-01.svg text-layout-01-ref.svg
== text-scale-01.svg text-scale-01-ref.svg == text-scale-01.svg text-scale-01-ref.svg
== text-style-01a.svg text-style-01-ref.svg == text-style-01a.svg text-style-01-ref.svg
== text-style-01b.svg text-style-01-ref.svg == text-style-01b.svg text-style-01-ref.svg

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

@ -0,0 +1,42 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink"
font-family="monospace" font-size="20" xml:space="preserve">
<title>Reference to check that dx, dy works for text</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=388547 -->
<text x="30" y="30">TEST1</text>
<text x="30" y="60">T</text>
<text x="30" y="70"> E</text>
<text x="40" y="80"> ST2</text>
<text x="30" y="100">T</text>
<text x="30" y="110"> E</text>
<text x="40" y="120"> ST3</text>
<text x="30" y="160">T</text>
<text x="30" y="150"> EST4</text>
<text x="40" y="200">TEST5</text>
<text x="220" y="30">T</text>
<text x="240" y="30">E</text>
<text x="260" y="30">S</text>
<text x="280" y="30">T6</text>
<text x="220" y="70">T</text>
<text x="220" y="90">E</text>
<text x="220" y="110">S</text>
<text x="220" y="130">T</text>
<text x="220" y="150">7</text>
<text x="220" y="200">T ST8</text>
<g transform="translate(150,100)rotate(90) "><text>A</text></g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

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

@ -0,0 +1,36 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink"
font-family="monospace" font-size="20" xml:space="preserve">
<title>Testcase to check that dx, dy works for text</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=388547 -->
<defs>
<path id="h1" d="M 30,150 h 100"/>
<path id="h2" d="M 30,200 h 100"/>
<path id="h3" d="M 220,200 h 100"/>
</defs>
<text x="20" y="20" dx="10" dy="10">TEST1</text>
<text x="30" y="60" dx="0, 0, 10" dy="0, 10, 10">TEST2</text>
<text x="30" y="100">T<tspan dx="0, 10" dy="10, 10">EST</tspan>3</text>
<text><textPath xlink:href="#h1"><tspan dy="10, -10">TE</tspan>ST4</textPath></text>
<text><textPath xlink:href="#h2"><tspan dx="10">TE</tspan>ST5</textPath></text>
<text x="220, 240, 260, 280" y="30">TEST6</text>
<text x="220, 220, 220, 220, 220" y="70, 90, 110, 130, 150">TEST7</text>
<text><textPath xlink:href="#h3"><tspan dx="0,1000,-1000">TES</tspan>T8</textPath></text>
<text x="150" y="100" rotate="90">A</text>
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

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

@ -58,15 +58,12 @@ public:
NS_IMETHOD_(float) GetAdvance(PRBool aForceGlobalTransform)=0; NS_IMETHOD_(float) GetAdvance(PRBool aForceGlobalTransform)=0;
NS_IMETHOD_(void) SetGlyphPosition(float x, float y, PRBool aForceGlobalTransform)=0; NS_IMETHOD_(void) SetGlyphPosition(gfxPoint *aPosition, PRBool aForceGlobalTransform)=0;
NS_IMETHOD_(nsSVGTextPathFrame*) FindTextPathParent()=0; NS_IMETHOD_(nsSVGTextPathFrame*) FindTextPathParent()=0;
NS_IMETHOD_(PRBool) IsStartOfChunk()=0; // == is new absolutely positioned chunk. NS_IMETHOD_(PRBool) IsStartOfChunk()=0; // == is new absolutely positioned chunk.
NS_IMETHOD_(void) GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y)=0;
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetX()=0; NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetX()=0;
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetY()=0; NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetY()=0;
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetDx()=0;
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetDy()=0;
NS_IMETHOD_(PRUint16) GetTextAnchor()=0; NS_IMETHOD_(PRUint16) GetTextAnchor()=0;
NS_IMETHOD_(PRBool) IsAbsolutelyPositioned()=0; NS_IMETHOD_(PRBool) IsAbsolutelyPositioned()=0;
}; };

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

@ -660,82 +660,193 @@ nsSVGGlyphFrame::GetCharacterData(nsAString & aCharacterData)
return !characterData.IsEmpty(); return !characterData.IsEmpty();
} }
static PRUint32
GetNumberOfLengthListItems(nsIDOMSVGLengthList *aList)
{
PRUint32 items = 0;
if (aList) {
aList->GetNumberOfItems(&items);
}
return items;
}
static PRUint32
GetNumberOfNumberListItems(nsIDOMSVGNumberList *aList)
{
PRUint32 items = 0;
if (aList) {
aList->GetNumberOfItems(&items);
}
return items;
}
static float
GetLengthListValue(nsIDOMSVGLengthList *aList, PRUint32 aIndex)
{
if (!aList) {
return 0.0f;
}
nsCOMPtr<nsIDOMSVGLength> length;
nsresult rv = aList->GetItem(aIndex, getter_AddRefs(length));
float value = 0.0f;
if (NS_SUCCEEDED(rv)) {
length->GetValue(&value);
}
return value;
}
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 PRBool
nsSVGGlyphFrame::GetCharacterPositions(nsTArray<CharacterPosition>* aCharacterPositions, nsSVGGlyphFrame::GetCharacterPositions(nsTArray<CharacterPosition>* aCharacterPositions,
float aMetricsScale) float aMetricsScale)
{ {
NS_ASSERTION(mTextRun->GetLength() > 0, "no text"); PRUint32 strLength = mTextRun->GetLength();
NS_ASSERTION(strLength > 0, "no text");
const gfxFloat radPerDeg = M_PI / 180.0;
nsCOMPtr<nsIDOMSVGLengthList> dxList = GetDx();
nsCOMPtr<nsIDOMSVGLengthList> dyList = GetDy();
nsCOMPtr<nsIDOMSVGNumberList> rotateList = GetRotate();
gfxPoint pos = mPosition;
nsSVGTextPathFrame *textPath = FindTextPathParent(); nsSVGTextPathFrame *textPath = FindTextPathParent();
/* we're an ordinary fragment - return */ if (textPath) {
/* XXX: we might want to use this for individual x/y/dx/dy adjustment */ nsRefPtr<gfxFlattenedPath> data = textPath->GetFlattenedPath();
if (!textPath)
// textPath frame, but invalid target
if (!data)
return PR_FALSE;
if (!aCharacterPositions->SetLength(strLength))
return PR_FALSE;
gfxFloat pathScale = textPath->GetPathScale();
CharacterPosition *cp = aCharacterPositions->Elements();
gfxFloat length = data->GetLength();
for (PRUint32 i = 0; i < strLength; i++) {
gfxFloat halfAdvance =
mTextRun->GetAdvanceWidth(i, 1, nsnull)*aMetricsScale / 2.0;
pos.x += GetLengthListValue(dxList, i) * pathScale;
pos.y += GetLengthListValue(dyList, i) * pathScale;
// check that we're within the path boundaries
cp[i].draw = (pos.x + halfAdvance >= 0.0 &&
pos.x + halfAdvance <= length);
if (cp[i].draw) {
// add y (normal)
// add rotation
// move point back along tangent
gfxPoint pt = data->FindPoint(gfxPoint(pos.x + halfAdvance, pos.y),
&(cp[i].angle));
cp[i].pos =
pt - gfxPoint(cos(cp[i].angle), sin(cp[i].angle)) * halfAdvance;
cp[i].angle += GetNumberListValue(rotateList, i) * radPerDeg;
}
pos.x += 2 * halfAdvance;
}
return PR_TRUE; return PR_TRUE;
}
nsRefPtr<gfxFlattenedPath> data = textPath->GetFlattenedPath(); nsCOMPtr<nsIDOMSVGLengthList> xList = GetX();
nsCOMPtr<nsIDOMSVGLengthList> yList = GetY();
/* textPath frame, but invalid target */ PRUint32 xListCount = GetNumberOfLengthListItems(xList);
if (!data) PRUint32 yListCount = GetNumberOfLengthListItems(yList);
return PR_FALSE;
gfxFloat length = data->GetLength(); if (xListCount <= 1 &&
PRUint32 strLength = mTextRun->GetLength(); yListCount <= 1 &&
GetNumberOfLengthListItems(yList) == 0 &&
GetNumberOfLengthListItems(dyList) == 0 &&
GetNumberOfNumberListItems(rotateList) == 0) {
// simple text without individual positioning
return PR_TRUE;
}
if (!aCharacterPositions->SetLength(strLength)) if (!aCharacterPositions->SetLength(strLength))
return PR_FALSE; return PR_FALSE;
CharacterPosition *cp = aCharacterPositions->Elements(); CharacterPosition *cp = aCharacterPositions->Elements();
for (PRUint32 k = 0; k < strLength; k++) PRUint16 anchor = GetTextAnchor();
cp[k].draw = PR_FALSE;
gfxFloat x = mPosition.x;
for (PRUint32 i = 0; i < strLength; i++) { for (PRUint32 i = 0; i < strLength; i++) {
gfxFloat halfAdvance = cp[i].draw = PR_TRUE;
mTextRun->GetAdvanceWidth(i, 1, nsnull)*aMetricsScale / 2.0;
/* have we run off the end of the path? */ gfxFloat advance = mTextRun->GetAdvanceWidth(i, 1, nsnull)*aMetricsScale;
if (x + halfAdvance > length) if (xListCount > 1 && i < xListCount) {
break; pos.x = GetLengthListValue(xList, i);
// apply text-anchor to character
/* check that we've advanced to the start of the path */ if (anchor == NS_STYLE_TEXT_ANCHOR_MIDDLE)
if (x + halfAdvance >= 0.0) { pos.x -= advance/2.0;
cp[i].draw = PR_TRUE; else if (anchor == NS_STYLE_TEXT_ANCHOR_END)
pos.x -= advance;
// add y (normal)
// add rotation
// move point back along tangent
gfxPoint pt = data->FindPoint(gfxPoint(x + halfAdvance, mPosition.y),
&(cp[i].angle));
cp[i].pos =
pt - gfxPoint(cos(cp[i].angle), sin(cp[i].angle)) * halfAdvance;
} }
x += 2 * halfAdvance; if (yListCount > 1 && i < yListCount) {
pos.y = GetLengthListValue(yList, i);
}
pos.x += GetLengthListValue(dxList, i);
pos.y += GetLengthListValue(dyList, i);
cp[i].pos = pos;
pos.x += advance;
cp[i].angle = GetNumberListValue(rotateList, i) * radPerDeg;
} }
return PR_TRUE; return PR_TRUE;
} }
float float
nsSVGGlyphFrame::GetSubStringAdvance(PRUint32 charnum, nsSVGGlyphFrame::GetSubStringAdvance(PRUint32 aCharnum,
PRUint32 fragmentChars) PRUint32 aFragmentChars,
float aMetricsScale)
{ {
if (fragmentChars == 0) if (aFragmentChars == 0)
return 0.0f; return 0.0f;
gfxFloat advance =
mTextRun->GetAdvanceWidth(aCharnum, aFragmentChars, nsnull) * aMetricsScale;
nsCOMPtr<nsIDOMSVGLengthList> dxlist = GetDx();
PRUint32 dxcount = GetNumberOfLengthListItems(dxlist);
if (dxcount) {
gfxFloat pathScale = 1.0;
nsSVGTextPathFrame *textPath = FindTextPathParent();
if (textPath)
pathScale = textPath->GetPathScale();
if (dxcount > aFragmentChars)
dxcount = aFragmentChars;
for (PRUint32 i = aCharnum; i < dxcount; i++) {
advance += GetLengthListValue(dxlist, i) * pathScale;
}
}
gfxFloat advance = mTextRun->GetAdvanceWidth(charnum, fragmentChars, nsnull);
return float(advance); return float(advance);
} }
gfxFloat gfxFloat
nsSVGGlyphFrame::GetBaselineOffset(PRBool aForceGlobalTransform) nsSVGGlyphFrame::GetBaselineOffset(float aMetricsScale)
{ {
float drawScale, metricsScale;
if (!EnsureTextRun(&drawScale, &metricsScale, aForceGlobalTransform))
return 0.0;
gfxTextRun::Metrics metrics = gfxTextRun::Metrics metrics =
mTextRun->MeasureText(0, mTextRun->GetLength(), mTextRun->MeasureText(0, mTextRun->GetLength(),
gfxFont::LOOSE_INK_EXTENTS, nsnull, nsnull); gfxFont::LOOSE_INK_EXTENTS, nsnull, nsnull);
@ -773,7 +884,7 @@ nsSVGGlyphFrame::GetBaselineOffset(PRBool aForceGlobalTransform)
NS_WARNING("We don't know about this type of dominant-baseline"); NS_WARNING("We don't know about this type of dominant-baseline");
return 0.0; return 0.0;
} }
return baselineAppUnits * metricsScale; return baselineAppUnits * aMetricsScale;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -914,9 +1025,40 @@ nsSVGGlyphFrame::GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
// nsISVGGlyphFragmentLeaf interface: // nsISVGGlyphFragmentLeaf interface:
NS_IMETHODIMP_(void) NS_IMETHODIMP_(void)
nsSVGGlyphFrame::SetGlyphPosition(float x, float y, PRBool aForceGlobalTransform) nsSVGGlyphFrame::SetGlyphPosition(gfxPoint *aPosition, PRBool aForceGlobalTransform)
{ {
mPosition.MoveTo(x, y - GetBaselineOffset(aForceGlobalTransform)); float drawScale, metricsScale;
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;
gfxFloat pathScale = 1.0;
nsSVGTextPathFrame *textPath = FindTextPathParent();
if (textPath)
pathScale = textPath->GetPathScale();
nsCOMPtr<nsIDOMSVGLengthList> dxList = GetDx();
nsCOMPtr<nsIDOMSVGLengthList> dyList = GetDy();
PRUint32 dxcount = GetNumberOfLengthListItems(dxList);
if (dxcount > strLength)
dxcount = strLength;
for (PRUint32 i = 0; i < dxcount; i++) {
aPosition->x += GetLengthListValue(dxList, i) * pathScale;
}
PRUint32 dycount = GetNumberOfLengthListItems(dyList);
if (dycount > strLength)
dycount = strLength;
for (PRUint32 i = 0; i < dycount; i++) {
aPosition->y += GetLengthListValue(dyList, i) * pathScale;
}
nsSVGUtils::UpdateGraphic(this); nsSVGUtils::UpdateGraphic(this);
} }
@ -1003,8 +1145,7 @@ nsSVGGlyphFrame::GetAdvance(PRBool aForceGlobalTransform)
if (!EnsureTextRun(&drawScale, &metricsScale, aForceGlobalTransform)) if (!EnsureTextRun(&drawScale, &metricsScale, aForceGlobalTransform))
return 0.0f; return 0.0f;
float advanceAppUnits = GetSubStringAdvance(0, mTextRun->GetLength()); return GetSubStringAdvance(0, mTextRun->GetLength(), metricsScale);
return advanceAppUnits * metricsScale;
} }
NS_IMETHODIMP_(nsSVGTextPathFrame*) NS_IMETHODIMP_(nsSVGTextPathFrame*)
@ -1033,11 +1174,6 @@ nsSVGGlyphFrame::IsStartOfChunk()
return PR_FALSE; return PR_FALSE;
} }
NS_IMETHODIMP_(void)
nsSVGGlyphFrame::GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y)
{
}
NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>) NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>)
nsSVGGlyphFrame::GetX() nsSVGGlyphFrame::GetX()
{ {
@ -1058,7 +1194,7 @@ nsSVGGlyphFrame::GetY()
return nsnull; return nsnull;
} }
NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>) already_AddRefed<nsIDOMSVGLengthList>
nsSVGGlyphFrame::GetDx() nsSVGGlyphFrame::GetDx()
{ {
nsSVGTextContainerFrame *containerFrame; nsSVGTextContainerFrame *containerFrame;
@ -1068,7 +1204,7 @@ nsSVGGlyphFrame::GetDx()
return nsnull; return nsnull;
} }
NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>) already_AddRefed<nsIDOMSVGLengthList>
nsSVGGlyphFrame::GetDy() nsSVGGlyphFrame::GetDy()
{ {
nsSVGTextContainerFrame *containerFrame; nsSVGTextContainerFrame *containerFrame;
@ -1078,6 +1214,16 @@ nsSVGGlyphFrame::GetDy()
return nsnull; return nsnull;
} }
already_AddRefed<nsIDOMSVGNumberList>
nsSVGGlyphFrame::GetRotate()
{
nsSVGTextContainerFrame *containerFrame;
containerFrame = static_cast<nsSVGTextContainerFrame *>(mParent);
if (containerFrame)
return containerFrame->GetRotate();
return nsnull;
}
NS_IMETHODIMP_(PRUint16) NS_IMETHODIMP_(PRUint16)
nsSVGGlyphFrame::GetTextAnchor() nsSVGGlyphFrame::GetTextAnchor()
{ {
@ -1142,8 +1288,7 @@ nsSVGGlyphFrame::GetSubStringLength(PRUint32 charnum, PRUint32 fragmentChars)
if (!EnsureTextRun(&drawScale, &metricsScale, PR_FALSE)) if (!EnsureTextRun(&drawScale, &metricsScale, PR_FALSE))
return 0.0f; return 0.0f;
float advanceAppUnits = GetSubStringAdvance(charnum, fragmentChars); return GetSubStringAdvance(charnum, fragmentChars, metricsScale);
return advanceAppUnits * metricsScale;
} }
PRInt32 PRInt32

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

@ -145,15 +145,12 @@ public:
*/ */
NS_IMETHOD_(float) GetAdvance(PRBool aForceGlobalTransform); NS_IMETHOD_(float) GetAdvance(PRBool aForceGlobalTransform);
NS_IMETHOD_(void) SetGlyphPosition(float x, float y, PRBool aForceGlobalTransform); NS_IMETHOD_(void) SetGlyphPosition(gfxPoint *aPosition, PRBool aForceGlobalTransform);
NS_IMETHOD_(nsSVGTextPathFrame*) FindTextPathParent(); NS_IMETHOD_(nsSVGTextPathFrame*) FindTextPathParent();
NS_IMETHOD_(PRBool) IsStartOfChunk(); // == is new absolutely positioned chunk. NS_IMETHOD_(PRBool) IsStartOfChunk(); // == is new absolutely positioned chunk.
NS_IMETHOD_(void) GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y);
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetX(); NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetX();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetY(); NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetY();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetDx();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetDy();
NS_IMETHOD_(PRUint16) GetTextAnchor(); NS_IMETHOD_(PRUint16) GetTextAnchor();
NS_IMETHOD_(PRBool) IsAbsolutelyPositioned(); NS_IMETHOD_(PRBool) IsAbsolutelyPositioned();
@ -206,14 +203,19 @@ protected:
void SetupGlobalTransform(gfxContext *aContext); void SetupGlobalTransform(gfxContext *aContext);
nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars, nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
nscolor *foreground, nscolor *background); nscolor *foreground, nscolor *background);
float GetSubStringAdvance(PRUint32 charnum, PRUint32 fragmentChars); float GetSubStringAdvance(PRUint32 aCharnum, PRUint32 aFragmentChars,
gfxFloat GetBaselineOffset(PRBool aForceGlobalTransform); float aMetricsScale);
gfxFloat GetBaselineOffset(float aMetricsScale);
const nsTextFragment* GetFragment() const const nsTextFragment* GetFragment() const
{ {
return !(GetStateBits() & NS_STATE_SVG_PRINTING) ? return !(GetStateBits() & NS_STATE_SVG_PRINTING) ?
mContent->GetText() : nsLayoutUtils::GetTextFragmentForPrinting(this); mContent->GetText() : nsLayoutUtils::GetTextFragmentForPrinting(this);
} }
already_AddRefed<nsIDOMSVGLengthList> GetDx();
already_AddRefed<nsIDOMSVGLengthList> GetDy();
already_AddRefed<nsIDOMSVGNumberList> GetRotate();
// Used to support GetBBoxContribution by making GetConvasTM use this as the // Used to support GetBBoxContribution by making GetConvasTM use this as the
// parent transform instead of the real CanvasTM. // parent transform instead of the real CanvasTM.
nsCOMPtr<nsIDOMSVGMatrix> mOverrideCanvasTM; nsCOMPtr<nsIDOMSVGMatrix> mOverrideCanvasTM;

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

@ -40,6 +40,7 @@
#include "nsSVGOuterSVGFrame.h" #include "nsSVGOuterSVGFrame.h"
#include "nsIDOMSVGTextElement.h" #include "nsIDOMSVGTextElement.h"
#include "nsIDOMSVGAnimatedLengthList.h" #include "nsIDOMSVGAnimatedLengthList.h"
#include "nsIDOMSVGAnimatedNumberList.h"
#include "nsISVGGlyphFragmentLeaf.h" #include "nsISVGGlyphFragmentLeaf.h"
#include "nsDOMError.h" #include "nsDOMError.h"
@ -60,7 +61,7 @@ nsSVGTextContainerFrame::NotifyGlyphMetricsChange()
textFrame->NotifyGlyphMetricsChange(); textFrame->NotifyGlyphMetricsChange();
} }
NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>) already_AddRefed<nsIDOMSVGLengthList>
nsSVGTextContainerFrame::GetX() nsSVGTextContainerFrame::GetX()
{ {
nsCOMPtr<nsIDOMSVGTextPositioningElement> tpElement = nsCOMPtr<nsIDOMSVGTextPositioningElement> tpElement =
@ -69,9 +70,6 @@ nsSVGTextContainerFrame::GetX()
if (!tpElement) if (!tpElement)
return nsnull; return nsnull;
if (!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::x))
return nsnull;
nsCOMPtr<nsIDOMSVGAnimatedLengthList> animLengthList; nsCOMPtr<nsIDOMSVGAnimatedLengthList> animLengthList;
tpElement->GetX(getter_AddRefs(animLengthList)); tpElement->GetX(getter_AddRefs(animLengthList));
nsIDOMSVGLengthList *retval; nsIDOMSVGLengthList *retval;
@ -79,7 +77,7 @@ nsSVGTextContainerFrame::GetX()
return retval; return retval;
} }
NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>) already_AddRefed<nsIDOMSVGLengthList>
nsSVGTextContainerFrame::GetY() nsSVGTextContainerFrame::GetY()
{ {
nsCOMPtr<nsIDOMSVGTextPositioningElement> tpElement = nsCOMPtr<nsIDOMSVGTextPositioningElement> tpElement =
@ -88,9 +86,6 @@ nsSVGTextContainerFrame::GetY()
if (!tpElement) if (!tpElement)
return nsnull; return nsnull;
if (!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::y))
return nsnull;
nsCOMPtr<nsIDOMSVGAnimatedLengthList> animLengthList; nsCOMPtr<nsIDOMSVGAnimatedLengthList> animLengthList;
tpElement->GetY(getter_AddRefs(animLengthList)); tpElement->GetY(getter_AddRefs(animLengthList));
nsIDOMSVGLengthList *retval; nsIDOMSVGLengthList *retval;
@ -98,7 +93,7 @@ nsSVGTextContainerFrame::GetY()
return retval; return retval;
} }
NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>) already_AddRefed<nsIDOMSVGLengthList>
nsSVGTextContainerFrame::GetDx() nsSVGTextContainerFrame::GetDx()
{ {
nsCOMPtr<nsIDOMSVGTextPositioningElement> tpElement = nsCOMPtr<nsIDOMSVGTextPositioningElement> tpElement =
@ -114,7 +109,7 @@ nsSVGTextContainerFrame::GetDx()
return retval; return retval;
} }
NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>) already_AddRefed<nsIDOMSVGLengthList>
nsSVGTextContainerFrame::GetDy() nsSVGTextContainerFrame::GetDy()
{ {
nsCOMPtr<nsIDOMSVGTextPositioningElement> tpElement = nsCOMPtr<nsIDOMSVGTextPositioningElement> tpElement =
@ -130,6 +125,22 @@ nsSVGTextContainerFrame::GetDy()
return retval; return retval;
} }
already_AddRefed<nsIDOMSVGNumberList>
nsSVGTextContainerFrame::GetRotate()
{
nsCOMPtr<nsIDOMSVGTextPositioningElement> tpElement =
do_QueryInterface(mContent);
if (!tpElement)
return nsnull;
nsCOMPtr<nsIDOMSVGAnimatedNumberList> animNumberList;
tpElement->GetRotate(getter_AddRefs(animNumberList));
nsIDOMSVGNumberList *retval;
animNumberList->GetAnimVal(&retval);
return retval;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// nsIFrame methods // nsIFrame methods

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

@ -39,6 +39,7 @@
#include "nsSVGContainerFrame.h" #include "nsSVGContainerFrame.h"
#include "nsIDOMSVGLengthList.h" #include "nsIDOMSVGLengthList.h"
#include "nsIDOMSVGNumberList.h"
class nsISVGGlyphFragmentNode; class nsISVGGlyphFragmentNode;
class nsISVGGlyphFragmentLeaf; class nsISVGGlyphFragmentLeaf;
@ -52,10 +53,11 @@ public:
nsSVGDisplayContainerFrame(aContext) {} nsSVGDisplayContainerFrame(aContext) {}
void NotifyGlyphMetricsChange(); void NotifyGlyphMetricsChange();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetX(); virtual already_AddRefed<nsIDOMSVGLengthList> GetX();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetY(); virtual already_AddRefed<nsIDOMSVGLengthList> GetY();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetDx(); virtual already_AddRefed<nsIDOMSVGLengthList> GetDx();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetDy(); virtual already_AddRefed<nsIDOMSVGLengthList> GetDy();
virtual already_AddRefed<nsIDOMSVGNumberList> GetRotate();
public: public:
NS_DECL_QUERYFRAME_TARGET(nsSVGTextContainerFrame) NS_DECL_QUERYFRAME_TARGET(nsSVGTextContainerFrame)

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

@ -292,21 +292,19 @@ nsSVGTextFrame::NotifyGlyphMetricsChange()
} }
static void static void
GetSingleValue(nsIDOMSVGLengthList *list, float *val) GetSingleValue(nsIDOMSVGLengthList *list, gfxFloat *val)
{ {
if (!list) if (!list)
return; return;
PRUint32 count = 0; PRUint32 count = 0;
list->GetNumberOfItems(&count); list->GetNumberOfItems(&count);
#ifdef DEBUG
if (count > 1)
NS_WARNING("multiple lengths for x/y attributes on <text> elements not implemented yet!");
#endif
if (count) { if (count) {
nsCOMPtr<nsIDOMSVGLength> length; nsCOMPtr<nsIDOMSVGLength> length;
list->GetItem(0, getter_AddRefs(length)); list->GetItem(0, getter_AddRefs(length));
length->GetValue(val); float value;
length->GetValue(&value);
*val = value;
} }
} }
@ -330,26 +328,26 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform)
return; return;
} }
float x = 0, y = 0; gfxPoint ctp(0.0, 0.0);
{ {
nsCOMPtr<nsIDOMSVGLengthList> list = GetX(); nsCOMPtr<nsIDOMSVGLengthList> list = GetX();
GetSingleValue(list, &x); GetSingleValue(list, &ctp.x);
} }
{ {
nsCOMPtr<nsIDOMSVGLengthList> list = GetY(); nsCOMPtr<nsIDOMSVGLengthList> list = GetY();
GetSingleValue(list, &y); GetSingleValue(list, &ctp.y);
} }
// loop over chunks // loop over chunks
while (firstFragment) { while (firstFragment) {
{ {
nsCOMPtr<nsIDOMSVGLengthList> list = firstFragment->GetX(); nsCOMPtr<nsIDOMSVGLengthList> list = firstFragment->GetX();
GetSingleValue(list, &x); GetSingleValue(list, &ctp.x);
} }
{ {
nsCOMPtr<nsIDOMSVGLengthList> list = firstFragment->GetY(); nsCOMPtr<nsIDOMSVGLengthList> list = firstFragment->GetY();
GetSingleValue(list, &y); GetSingleValue(list, &ctp.y);
} }
// check for startOffset on textPath // check for startOffset on textPath
@ -359,7 +357,7 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform)
// invalid text path, give up // invalid text path, give up
return; return;
} }
x = textPath->GetStartOffset(); ctp.x = textPath->GetStartOffset();
} }
// determine x offset based on text_anchor: // determine x offset based on text_anchor:
@ -372,10 +370,7 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform)
fragment = firstFragment; fragment = firstFragment;
while (fragment) { while (fragment) {
float dx = 0.0f; chunkLength += fragment->GetAdvance(aForceGlobalTransform);
nsCOMPtr<nsIDOMSVGLengthList> list = fragment->GetDx();
GetSingleValue(list, &dx);
chunkLength += dx + fragment->GetAdvance(aForceGlobalTransform);
fragment = fragment->GetNextGlyphFragment(); fragment = fragment->GetNextGlyphFragment();
if (fragment && fragment->IsAbsolutelyPositioned()) if (fragment && fragment->IsAbsolutelyPositioned())
break; break;
@ -383,29 +378,16 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform)
} }
if (anchor == NS_STYLE_TEXT_ANCHOR_MIDDLE) if (anchor == NS_STYLE_TEXT_ANCHOR_MIDDLE)
x -= chunkLength/2.0f; ctp.x -= chunkLength/2.0f;
else if (anchor == NS_STYLE_TEXT_ANCHOR_END) else if (anchor == NS_STYLE_TEXT_ANCHOR_END)
x -= chunkLength; ctp.x -= chunkLength;
// set position of each fragment in this chunk: // set position of each fragment in this chunk:
fragment = firstFragment; fragment = firstFragment;
while (fragment) { while (fragment) {
float dx = 0.0f, dy = 0.0f; fragment->SetGlyphPosition(&ctp, aForceGlobalTransform);
{
nsCOMPtr<nsIDOMSVGLengthList> list = fragment->GetDx();
GetSingleValue(list, &dx);
}
{
nsCOMPtr<nsIDOMSVGLengthList> list = fragment->GetDy();
GetSingleValue(list, &dy);
}
fragment->SetGlyphPosition(x + dx, y + dy, aForceGlobalTransform);
x += dx + fragment->GetAdvance(aForceGlobalTransform);
y += dy;
fragment = fragment->GetNextGlyphFragment(); fragment = fragment->GetNextGlyphFragment();
if (fragment && fragment->IsAbsolutelyPositioned()) if (fragment && fragment->IsAbsolutelyPositioned())
break; break;

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

@ -84,30 +84,36 @@ nsSVGTextPathFrame::GetType() const
} }
NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>) already_AddRefed<nsIDOMSVGLengthList>
nsSVGTextPathFrame::GetX() nsSVGTextPathFrame::GetX()
{ {
return nsnull; return nsnull;
} }
NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>) already_AddRefed<nsIDOMSVGLengthList>
nsSVGTextPathFrame::GetY() nsSVGTextPathFrame::GetY()
{ {
return nsnull; return nsnull;
} }
NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>) already_AddRefed<nsIDOMSVGLengthList>
nsSVGTextPathFrame::GetDx() nsSVGTextPathFrame::GetDx()
{ {
return nsnull; return nsnull;
} }
NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>) already_AddRefed<nsIDOMSVGLengthList>
nsSVGTextPathFrame::GetDy() nsSVGTextPathFrame::GetDy()
{ {
return nsnull; return nsnull;
} }
already_AddRefed<nsIDOMSVGNumberList>
nsSVGTextPathFrame::GetRotate()
{
return nsnull;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// nsSVGTextPathFrame methods: // nsSVGTextPathFrame methods:

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

@ -39,6 +39,7 @@
#include "nsSVGTSpanFrame.h" #include "nsSVGTSpanFrame.h"
#include "nsSVGLengthList.h" #include "nsSVGLengthList.h"
#include "nsSVGNumberList.h"
typedef nsSVGTSpanFrame nsSVGTextPathFrameBase; typedef nsSVGTSpanFrame nsSVGTextPathFrameBase;
@ -84,10 +85,11 @@ public:
gfxFloat GetPathScale(); gfxFloat GetPathScale();
protected: protected:
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetX(); virtual already_AddRefed<nsIDOMSVGLengthList> GetX();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetY(); virtual already_AddRefed<nsIDOMSVGLengthList> GetY();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetDx(); virtual already_AddRefed<nsIDOMSVGLengthList> GetDx();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetDy(); virtual already_AddRefed<nsIDOMSVGLengthList> GetDy();
virtual already_AddRefed<nsIDOMSVGNumberList> GetRotate();
private: private:
already_AddRefed<gfxFlattenedPath> GetFlattenedPath(nsIFrame *path); already_AddRefed<gfxFlattenedPath> GetFlattenedPath(nsIFrame *path);