From 1dbfbb3e36cb0930285e1740a824d01c6868aefe Mon Sep 17 00:00:00 2001 From: Robert Longson Date: Sun, 11 Oct 2009 12:44:33 +0100 Subject: [PATCH] Bug 388547 - Initial support for x,y,dx,dy,rotate lists on SVG text and tspan elements. r=roc --- content/svg/content/src/nsSVGTSpanElement.cpp | 20 +- content/svg/content/src/nsSVGTextElement.cpp | 20 +- layout/reftests/svg/reftest.list | 1 + layout/reftests/svg/text-layout-01-ref.svg | 42 +++ layout/reftests/svg/text-layout-01.svg | 36 +++ layout/svg/base/src/nsISVGGlyphFragmentLeaf.h | 5 +- layout/svg/base/src/nsSVGGlyphFrame.cpp | 257 ++++++++++++++---- layout/svg/base/src/nsSVGGlyphFrame.h | 14 +- .../svg/base/src/nsSVGTextContainerFrame.cpp | 31 ++- layout/svg/base/src/nsSVGTextContainerFrame.h | 10 +- layout/svg/base/src/nsSVGTextFrame.cpp | 46 +--- layout/svg/base/src/nsSVGTextPathFrame.cpp | 14 +- layout/svg/base/src/nsSVGTextPathFrame.h | 10 +- 13 files changed, 382 insertions(+), 124 deletions(-) create mode 100644 layout/reftests/svg/text-layout-01-ref.svg create mode 100644 layout/reftests/svg/text-layout-01.svg diff --git a/content/svg/content/src/nsSVGTSpanElement.cpp b/content/svg/content/src/nsSVGTSpanElement.cpp index 274786360c69..7d9d4b7b7382 100644 --- a/content/svg/content/src/nsSVGTSpanElement.cpp +++ b/content/svg/content/src/nsSVGTSpanElement.cpp @@ -41,7 +41,9 @@ #include "nsIDOMSVGTSpanElement.h" #include "nsCOMPtr.h" #include "nsSVGAnimatedLengthList.h" +#include "nsSVGAnimatedNumberList.h" #include "nsSVGLengthList.h" +#include "nsSVGNumberList.h" #include "nsSVGSVGElement.h" #include "nsSVGTextContentElement.h" #include "nsIFrame.h" @@ -91,6 +93,7 @@ protected: nsCOMPtr mY; nsCOMPtr mdX; nsCOMPtr mdY; + nsCOMPtr mRotate; }; @@ -178,6 +181,18 @@ nsSVGTSpanElement::Init() NS_ENSURE_SUCCESS(rv,rv); } + // DOM property: nsIDOMSVGTextPositioningElement::rotate, #IMPLIED attrib: rotate + { + nsCOMPtr 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; } @@ -231,8 +246,9 @@ NS_IMETHODIMP nsSVGTSpanElement::GetDy(nsIDOMSVGAnimatedLengthList * *aDy) /* readonly attribute nsIDOMSVGAnimatedNumberList rotate; */ NS_IMETHODIMP nsSVGTSpanElement::GetRotate(nsIDOMSVGAnimatedNumberList * *aRotate) { - NS_NOTYETIMPLEMENTED("nsSVGTSpanElement::GetRotate"); - return NS_ERROR_NOT_IMPLEMENTED; + *aRotate = mRotate; + NS_IF_ADDREF(*aRotate); + return NS_OK; } //---------------------------------------------------------------------- diff --git a/content/svg/content/src/nsSVGTextElement.cpp b/content/svg/content/src/nsSVGTextElement.cpp index 8d3824b5a719..3b07ed56c197 100644 --- a/content/svg/content/src/nsSVGTextElement.cpp +++ b/content/svg/content/src/nsSVGTextElement.cpp @@ -41,7 +41,9 @@ #include "nsIDOMSVGTextElement.h" #include "nsCOMPtr.h" #include "nsSVGAnimatedLengthList.h" +#include "nsSVGAnimatedNumberList.h" #include "nsSVGLengthList.h" +#include "nsSVGNumberList.h" #include "nsSVGSVGElement.h" #include "nsSVGTextContentElement.h" #include "nsIFrame.h" @@ -88,6 +90,7 @@ protected: nsCOMPtr mY; nsCOMPtr mdX; nsCOMPtr mdY; + nsCOMPtr mRotate; }; @@ -174,6 +177,18 @@ nsSVGTextElement::Init() NS_ENSURE_SUCCESS(rv,rv); } + // DOM property: nsIDOMSVGTextPositioningElement::rotate, #IMPLIED attrib: rotate + { + nsCOMPtr 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; } @@ -227,8 +242,9 @@ NS_IMETHODIMP nsSVGTextElement::GetDy(nsIDOMSVGAnimatedLengthList * *aDy) /* readonly attribute nsIDOMSVGAnimatedNumberList rotate; */ NS_IMETHODIMP nsSVGTextElement::GetRotate(nsIDOMSVGAnimatedNumberList * *aRotate) { - NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetRotate"); - return NS_ERROR_NOT_IMPLEMENTED; + *aRotate = mRotate; + NS_IF_ADDREF(*aRotate); + return NS_OK; } //---------------------------------------------------------------------- diff --git a/layout/reftests/svg/reftest.list b/layout/reftests/svg/reftest.list index e5f1c63362fb..6acdc04f946f 100644 --- a/layout/reftests/svg/reftest.list +++ b/layout/reftests/svg/reftest.list @@ -122,6 +122,7 @@ random-if(MOZ_WIDGET_TOOLKIT=="gtk2") == text-font-weight-01.svg text-font-weigh == switch-01.svg pass.svg == text-gradient-01.svg text-gradient-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-style-01a.svg text-style-01-ref.svg == text-style-01b.svg text-style-01-ref.svg diff --git a/layout/reftests/svg/text-layout-01-ref.svg b/layout/reftests/svg/text-layout-01-ref.svg new file mode 100644 index 000000000000..ba48c83dd327 --- /dev/null +++ b/layout/reftests/svg/text-layout-01-ref.svg @@ -0,0 +1,42 @@ + + + + Reference to check that dx, dy works for text + + + + TEST1 + + T + E + ST2 + + T + E + ST3 + + T + EST4 + + TEST5 + + T + E + S + T6 + + T + E + S + T + 7 + + T ST8 + + A + diff --git a/layout/reftests/svg/text-layout-01.svg b/layout/reftests/svg/text-layout-01.svg new file mode 100644 index 000000000000..6e87c17a901a --- /dev/null +++ b/layout/reftests/svg/text-layout-01.svg @@ -0,0 +1,36 @@ + + + + Testcase to check that dx, dy works for text + + + + + + + + + + TEST1 + + TEST2 + + TEST3 + + TEST4 + + TEST5 + + TEST6 + + TEST7 + + TEST8 + + A + diff --git a/layout/svg/base/src/nsISVGGlyphFragmentLeaf.h b/layout/svg/base/src/nsISVGGlyphFragmentLeaf.h index 39037cb5e3d7..3392b7eb870a 100644 --- a/layout/svg/base/src/nsISVGGlyphFragmentLeaf.h +++ b/layout/svg/base/src/nsISVGGlyphFragmentLeaf.h @@ -58,15 +58,12 @@ public: 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_(PRBool) IsStartOfChunk()=0; // == is new absolutely positioned chunk. - NS_IMETHOD_(void) GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y)=0; NS_IMETHOD_(already_AddRefed) GetX()=0; NS_IMETHOD_(already_AddRefed) GetY()=0; - NS_IMETHOD_(already_AddRefed) GetDx()=0; - NS_IMETHOD_(already_AddRefed) GetDy()=0; NS_IMETHOD_(PRUint16) GetTextAnchor()=0; NS_IMETHOD_(PRBool) IsAbsolutelyPositioned()=0; }; diff --git a/layout/svg/base/src/nsSVGGlyphFrame.cpp b/layout/svg/base/src/nsSVGGlyphFrame.cpp index 561ef7a9a678..e5edb452f58a 100644 --- a/layout/svg/base/src/nsSVGGlyphFrame.cpp +++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp @@ -660,82 +660,193 @@ nsSVGGlyphFrame::GetCharacterData(nsAString & aCharacterData) 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 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 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* aCharacterPositions, 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 dxList = GetDx(); + nsCOMPtr dyList = GetDy(); + nsCOMPtr rotateList = GetRotate(); + + gfxPoint pos = mPosition; nsSVGTextPathFrame *textPath = FindTextPathParent(); - /* we're an ordinary fragment - return */ - /* XXX: we might want to use this for individual x/y/dx/dy adjustment */ - if (!textPath) + if (textPath) { + nsRefPtr data = textPath->GetFlattenedPath(); + + // 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; + } - nsRefPtr data = textPath->GetFlattenedPath(); + nsCOMPtr xList = GetX(); + nsCOMPtr yList = GetY(); - /* textPath frame, but invalid target */ - if (!data) - return PR_FALSE; + PRUint32 xListCount = GetNumberOfLengthListItems(xList); + PRUint32 yListCount = GetNumberOfLengthListItems(yList); - gfxFloat length = data->GetLength(); - PRUint32 strLength = mTextRun->GetLength(); + if (xListCount <= 1 && + yListCount <= 1 && + GetNumberOfLengthListItems(yList) == 0 && + GetNumberOfLengthListItems(dyList) == 0 && + GetNumberOfNumberListItems(rotateList) == 0) { + // simple text without individual positioning + return PR_TRUE; + } if (!aCharacterPositions->SetLength(strLength)) return PR_FALSE; CharacterPosition *cp = aCharacterPositions->Elements(); - for (PRUint32 k = 0; k < strLength; k++) - cp[k].draw = PR_FALSE; + PRUint16 anchor = GetTextAnchor(); - gfxFloat x = mPosition.x; for (PRUint32 i = 0; i < strLength; i++) { - gfxFloat halfAdvance = - mTextRun->GetAdvanceWidth(i, 1, nsnull)*aMetricsScale / 2.0; + cp[i].draw = PR_TRUE; - /* have we run off the end of the path? */ - if (x + halfAdvance > length) - break; - - /* check that we've advanced to the start of the path */ - if (x + halfAdvance >= 0.0) { - cp[i].draw = PR_TRUE; - - // 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; + gfxFloat advance = mTextRun->GetAdvanceWidth(i, 1, nsnull)*aMetricsScale; + if (xListCount > 1 && i < xListCount) { + pos.x = GetLengthListValue(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; } - 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; } float -nsSVGGlyphFrame::GetSubStringAdvance(PRUint32 charnum, - PRUint32 fragmentChars) +nsSVGGlyphFrame::GetSubStringAdvance(PRUint32 aCharnum, + PRUint32 aFragmentChars, + float aMetricsScale) { - if (fragmentChars == 0) + if (aFragmentChars == 0) return 0.0f; + + gfxFloat advance = + mTextRun->GetAdvanceWidth(aCharnum, aFragmentChars, nsnull) * aMetricsScale; + + nsCOMPtr 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); } gfxFloat -nsSVGGlyphFrame::GetBaselineOffset(PRBool aForceGlobalTransform) +nsSVGGlyphFrame::GetBaselineOffset(float aMetricsScale) { - float drawScale, metricsScale; - - if (!EnsureTextRun(&drawScale, &metricsScale, aForceGlobalTransform)) - return 0.0; - gfxTextRun::Metrics metrics = mTextRun->MeasureText(0, mTextRun->GetLength(), 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"); return 0.0; } - return baselineAppUnits * metricsScale; + return baselineAppUnits * aMetricsScale; } //---------------------------------------------------------------------- @@ -914,9 +1025,40 @@ nsSVGGlyphFrame::GetHighlight(PRUint32 *charnum, PRUint32 *nchars, // nsISVGGlyphFragmentLeaf interface: 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 dxList = GetDx(); + nsCOMPtr 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); } @@ -1003,8 +1145,7 @@ nsSVGGlyphFrame::GetAdvance(PRBool aForceGlobalTransform) if (!EnsureTextRun(&drawScale, &metricsScale, aForceGlobalTransform)) return 0.0f; - float advanceAppUnits = GetSubStringAdvance(0, mTextRun->GetLength()); - return advanceAppUnits * metricsScale; + return GetSubStringAdvance(0, mTextRun->GetLength(), metricsScale); } NS_IMETHODIMP_(nsSVGTextPathFrame*) @@ -1033,11 +1174,6 @@ nsSVGGlyphFrame::IsStartOfChunk() return PR_FALSE; } -NS_IMETHODIMP_(void) -nsSVGGlyphFrame::GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y) -{ -} - NS_IMETHODIMP_(already_AddRefed) nsSVGGlyphFrame::GetX() { @@ -1058,7 +1194,7 @@ nsSVGGlyphFrame::GetY() return nsnull; } -NS_IMETHODIMP_(already_AddRefed) +already_AddRefed nsSVGGlyphFrame::GetDx() { nsSVGTextContainerFrame *containerFrame; @@ -1068,7 +1204,7 @@ nsSVGGlyphFrame::GetDx() return nsnull; } -NS_IMETHODIMP_(already_AddRefed) +already_AddRefed nsSVGGlyphFrame::GetDy() { nsSVGTextContainerFrame *containerFrame; @@ -1078,6 +1214,16 @@ nsSVGGlyphFrame::GetDy() return nsnull; } +already_AddRefed +nsSVGGlyphFrame::GetRotate() +{ + nsSVGTextContainerFrame *containerFrame; + containerFrame = static_cast(mParent); + if (containerFrame) + return containerFrame->GetRotate(); + return nsnull; +} + NS_IMETHODIMP_(PRUint16) nsSVGGlyphFrame::GetTextAnchor() { @@ -1142,8 +1288,7 @@ nsSVGGlyphFrame::GetSubStringLength(PRUint32 charnum, PRUint32 fragmentChars) if (!EnsureTextRun(&drawScale, &metricsScale, PR_FALSE)) return 0.0f; - float advanceAppUnits = GetSubStringAdvance(charnum, fragmentChars); - return advanceAppUnits * metricsScale; + return GetSubStringAdvance(charnum, fragmentChars, metricsScale); } PRInt32 diff --git a/layout/svg/base/src/nsSVGGlyphFrame.h b/layout/svg/base/src/nsSVGGlyphFrame.h index 27d37e7874bb..5161361accfd 100644 --- a/layout/svg/base/src/nsSVGGlyphFrame.h +++ b/layout/svg/base/src/nsSVGGlyphFrame.h @@ -145,15 +145,12 @@ public: */ 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_(PRBool) IsStartOfChunk(); // == is new absolutely positioned chunk. - NS_IMETHOD_(void) GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y); NS_IMETHOD_(already_AddRefed) GetX(); NS_IMETHOD_(already_AddRefed) GetY(); - NS_IMETHOD_(already_AddRefed) GetDx(); - NS_IMETHOD_(already_AddRefed) GetDy(); NS_IMETHOD_(PRUint16) GetTextAnchor(); NS_IMETHOD_(PRBool) IsAbsolutelyPositioned(); @@ -206,14 +203,19 @@ protected: void SetupGlobalTransform(gfxContext *aContext); nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars, nscolor *foreground, nscolor *background); - float GetSubStringAdvance(PRUint32 charnum, PRUint32 fragmentChars); - gfxFloat GetBaselineOffset(PRBool aForceGlobalTransform); + float GetSubStringAdvance(PRUint32 aCharnum, PRUint32 aFragmentChars, + float aMetricsScale); + gfxFloat GetBaselineOffset(float aMetricsScale); const nsTextFragment* GetFragment() const { return !(GetStateBits() & NS_STATE_SVG_PRINTING) ? mContent->GetText() : nsLayoutUtils::GetTextFragmentForPrinting(this); } + already_AddRefed GetDx(); + already_AddRefed GetDy(); + already_AddRefed GetRotate(); + // Used to support GetBBoxContribution by making GetConvasTM use this as the // parent transform instead of the real CanvasTM. nsCOMPtr mOverrideCanvasTM; diff --git a/layout/svg/base/src/nsSVGTextContainerFrame.cpp b/layout/svg/base/src/nsSVGTextContainerFrame.cpp index 4fe9ded989ba..337285445a32 100644 --- a/layout/svg/base/src/nsSVGTextContainerFrame.cpp +++ b/layout/svg/base/src/nsSVGTextContainerFrame.cpp @@ -40,6 +40,7 @@ #include "nsSVGOuterSVGFrame.h" #include "nsIDOMSVGTextElement.h" #include "nsIDOMSVGAnimatedLengthList.h" +#include "nsIDOMSVGAnimatedNumberList.h" #include "nsISVGGlyphFragmentLeaf.h" #include "nsDOMError.h" @@ -60,7 +61,7 @@ nsSVGTextContainerFrame::NotifyGlyphMetricsChange() textFrame->NotifyGlyphMetricsChange(); } -NS_IMETHODIMP_(already_AddRefed) +already_AddRefed nsSVGTextContainerFrame::GetX() { nsCOMPtr tpElement = @@ -69,9 +70,6 @@ nsSVGTextContainerFrame::GetX() if (!tpElement) return nsnull; - if (!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::x)) - return nsnull; - nsCOMPtr animLengthList; tpElement->GetX(getter_AddRefs(animLengthList)); nsIDOMSVGLengthList *retval; @@ -79,7 +77,7 @@ nsSVGTextContainerFrame::GetX() return retval; } -NS_IMETHODIMP_(already_AddRefed) +already_AddRefed nsSVGTextContainerFrame::GetY() { nsCOMPtr tpElement = @@ -88,9 +86,6 @@ nsSVGTextContainerFrame::GetY() if (!tpElement) return nsnull; - if (!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::y)) - return nsnull; - nsCOMPtr animLengthList; tpElement->GetY(getter_AddRefs(animLengthList)); nsIDOMSVGLengthList *retval; @@ -98,7 +93,7 @@ nsSVGTextContainerFrame::GetY() return retval; } -NS_IMETHODIMP_(already_AddRefed) +already_AddRefed nsSVGTextContainerFrame::GetDx() { nsCOMPtr tpElement = @@ -114,7 +109,7 @@ nsSVGTextContainerFrame::GetDx() return retval; } -NS_IMETHODIMP_(already_AddRefed) +already_AddRefed nsSVGTextContainerFrame::GetDy() { nsCOMPtr tpElement = @@ -130,6 +125,22 @@ nsSVGTextContainerFrame::GetDy() return retval; } +already_AddRefed +nsSVGTextContainerFrame::GetRotate() +{ + nsCOMPtr tpElement = + do_QueryInterface(mContent); + + if (!tpElement) + return nsnull; + + nsCOMPtr animNumberList; + tpElement->GetRotate(getter_AddRefs(animNumberList)); + nsIDOMSVGNumberList *retval; + animNumberList->GetAnimVal(&retval); + return retval; +} + //---------------------------------------------------------------------- // nsIFrame methods diff --git a/layout/svg/base/src/nsSVGTextContainerFrame.h b/layout/svg/base/src/nsSVGTextContainerFrame.h index 738c217c8a35..dcb7b214ee64 100644 --- a/layout/svg/base/src/nsSVGTextContainerFrame.h +++ b/layout/svg/base/src/nsSVGTextContainerFrame.h @@ -39,6 +39,7 @@ #include "nsSVGContainerFrame.h" #include "nsIDOMSVGLengthList.h" +#include "nsIDOMSVGNumberList.h" class nsISVGGlyphFragmentNode; class nsISVGGlyphFragmentLeaf; @@ -52,10 +53,11 @@ public: nsSVGDisplayContainerFrame(aContext) {} void NotifyGlyphMetricsChange(); - NS_IMETHOD_(already_AddRefed) GetX(); - NS_IMETHOD_(already_AddRefed) GetY(); - NS_IMETHOD_(already_AddRefed) GetDx(); - NS_IMETHOD_(already_AddRefed) GetDy(); + virtual already_AddRefed GetX(); + virtual already_AddRefed GetY(); + virtual already_AddRefed GetDx(); + virtual already_AddRefed GetDy(); + virtual already_AddRefed GetRotate(); public: NS_DECL_QUERYFRAME_TARGET(nsSVGTextContainerFrame) diff --git a/layout/svg/base/src/nsSVGTextFrame.cpp b/layout/svg/base/src/nsSVGTextFrame.cpp index 03b838aefe59..a649fa4830fb 100644 --- a/layout/svg/base/src/nsSVGTextFrame.cpp +++ b/layout/svg/base/src/nsSVGTextFrame.cpp @@ -292,21 +292,19 @@ nsSVGTextFrame::NotifyGlyphMetricsChange() } static void -GetSingleValue(nsIDOMSVGLengthList *list, float *val) +GetSingleValue(nsIDOMSVGLengthList *list, gfxFloat *val) { if (!list) return; PRUint32 count = 0; list->GetNumberOfItems(&count); -#ifdef DEBUG - if (count > 1) - NS_WARNING("multiple lengths for x/y attributes on elements not implemented yet!"); -#endif if (count) { nsCOMPtr 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; } - float x = 0, y = 0; + gfxPoint ctp(0.0, 0.0); { nsCOMPtr list = GetX(); - GetSingleValue(list, &x); + GetSingleValue(list, &ctp.x); } { nsCOMPtr list = GetY(); - GetSingleValue(list, &y); + GetSingleValue(list, &ctp.y); } // loop over chunks while (firstFragment) { { nsCOMPtr list = firstFragment->GetX(); - GetSingleValue(list, &x); + GetSingleValue(list, &ctp.x); } { nsCOMPtr list = firstFragment->GetY(); - GetSingleValue(list, &y); + GetSingleValue(list, &ctp.y); } // check for startOffset on textPath @@ -359,7 +357,7 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform) // invalid text path, give up return; } - x = textPath->GetStartOffset(); + ctp.x = textPath->GetStartOffset(); } // determine x offset based on text_anchor: @@ -372,10 +370,7 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform) fragment = firstFragment; while (fragment) { - float dx = 0.0f; - nsCOMPtr list = fragment->GetDx(); - GetSingleValue(list, &dx); - chunkLength += dx + fragment->GetAdvance(aForceGlobalTransform); + chunkLength += fragment->GetAdvance(aForceGlobalTransform); fragment = fragment->GetNextGlyphFragment(); if (fragment && fragment->IsAbsolutelyPositioned()) break; @@ -383,29 +378,16 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform) } if (anchor == NS_STYLE_TEXT_ANCHOR_MIDDLE) - x -= chunkLength/2.0f; + ctp.x -= chunkLength/2.0f; else if (anchor == NS_STYLE_TEXT_ANCHOR_END) - x -= chunkLength; + ctp.x -= chunkLength; // set position of each fragment in this chunk: fragment = firstFragment; while (fragment) { - float dx = 0.0f, dy = 0.0f; - { - nsCOMPtr list = fragment->GetDx(); - GetSingleValue(list, &dx); - } - { - nsCOMPtr list = fragment->GetDy(); - GetSingleValue(list, &dy); - } - - fragment->SetGlyphPosition(x + dx, y + dy, aForceGlobalTransform); - - x += dx + fragment->GetAdvance(aForceGlobalTransform); - y += dy; + fragment->SetGlyphPosition(&ctp, aForceGlobalTransform); fragment = fragment->GetNextGlyphFragment(); if (fragment && fragment->IsAbsolutelyPositioned()) break; diff --git a/layout/svg/base/src/nsSVGTextPathFrame.cpp b/layout/svg/base/src/nsSVGTextPathFrame.cpp index 6c261b2c7117..664f5d419557 100644 --- a/layout/svg/base/src/nsSVGTextPathFrame.cpp +++ b/layout/svg/base/src/nsSVGTextPathFrame.cpp @@ -84,30 +84,36 @@ nsSVGTextPathFrame::GetType() const } -NS_IMETHODIMP_(already_AddRefed) +already_AddRefed nsSVGTextPathFrame::GetX() { return nsnull; } -NS_IMETHODIMP_(already_AddRefed) +already_AddRefed nsSVGTextPathFrame::GetY() { return nsnull; } -NS_IMETHODIMP_(already_AddRefed) +already_AddRefed nsSVGTextPathFrame::GetDx() { return nsnull; } -NS_IMETHODIMP_(already_AddRefed) +already_AddRefed nsSVGTextPathFrame::GetDy() { return nsnull; } +already_AddRefed +nsSVGTextPathFrame::GetRotate() +{ + return nsnull; +} + //---------------------------------------------------------------------- // nsSVGTextPathFrame methods: diff --git a/layout/svg/base/src/nsSVGTextPathFrame.h b/layout/svg/base/src/nsSVGTextPathFrame.h index 0e3c4164040f..4310c9286bb6 100644 --- a/layout/svg/base/src/nsSVGTextPathFrame.h +++ b/layout/svg/base/src/nsSVGTextPathFrame.h @@ -39,6 +39,7 @@ #include "nsSVGTSpanFrame.h" #include "nsSVGLengthList.h" +#include "nsSVGNumberList.h" typedef nsSVGTSpanFrame nsSVGTextPathFrameBase; @@ -84,10 +85,11 @@ public: gfxFloat GetPathScale(); protected: - NS_IMETHOD_(already_AddRefed) GetX(); - NS_IMETHOD_(already_AddRefed) GetY(); - NS_IMETHOD_(already_AddRefed) GetDx(); - NS_IMETHOD_(already_AddRefed) GetDy(); + virtual already_AddRefed GetX(); + virtual already_AddRefed GetY(); + virtual already_AddRefed GetDx(); + virtual already_AddRefed GetDy(); + virtual already_AddRefed GetRotate(); private: already_AddRefed GetFlattenedPath(nsIFrame *path);