зеркало из https://github.com/mozilla/gecko-dev.git
Bug 333698 - Fix x and y positioning of nested tspans; r=longsonr; a=roc
This commit is contained in:
Родитель
799fb06cc7
Коммит
07c1e75fb0
|
@ -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, ¬Used);
|
||||
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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче