Bug 339039 - Text spans return incorrect number of characters with getNumberOfChars(). r=tor,sr=roc

This commit is contained in:
longsonr%gmail.com 2006-06-12 15:50:31 +00:00
Родитель 6a60ce6050
Коммит dedc74de85
11 изменённых файлов: 399 добавлений и 388 удалений

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

@ -44,8 +44,9 @@
class nsISVGRendererGlyphMetrics;
// {33397E2B-C1DC-49f0-9738-4891FE083C92}
#define NS_ISVGGLYPHFRAGMENTLEAF_IID \
{ 0x7e8500f1, 0xb3a5, 0x4e8a, { 0x90, 0x78, 0x03, 0x34, 0xc7, 0xcb, 0x30, 0x16 } }
{ 0x33397e2b, 0xc1dc, 0x49f0, { 0x97, 0x38, 0x48, 0x91, 0xfe, 0x8, 0x3c, 0x92 } }
class nsISVGGlyphFragmentLeaf : public nsISVGGlyphFragmentNode
{
@ -54,13 +55,9 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISVGGLYPHFRAGMENTLEAF_IID)
NS_IMETHOD_(void) SetGlyphPosition(float x, float y)=0;
NS_IMETHOD_(float) GetGlyphPositionX()=0;
NS_IMETHOD_(float) GetGlyphPositionY()=0;
NS_IMETHOD GetGlyphMetrics(nsISVGRendererGlyphMetrics** metrics)=0;
NS_IMETHOD_(PRBool) IsStartOfChunk()=0; // == is new absolutely positioned chunk.
NS_IMETHOD_(void) GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y)=0;
NS_IMETHOD_(PRUint32) GetNumberOfChars()=0;
NS_IMETHOD_(PRUint32) GetCharNumberOffset()=0;
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetX()=0;
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetY()=0;

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

@ -44,9 +44,9 @@
class nsISVGGlyphFragmentLeaf;
// {5A3A3929-9F98-4756-8C85-9689EB05983B}
// {AEEE492E-AF86-4c6a-AF14-88E224DD10E5}
#define NS_ISVGGLYPHFRAGMENTNODE_IID \
{ 0x5a3a3929, 0x9f98, 0x4756, { 0x8c, 0x85, 0x96, 0x89, 0xeb, 0x05, 0x98, 0x3b } }
{ 0xaeee492e, 0xaf86, 0x4c6a, { 0xaf, 0x14, 0x88, 0xe2, 0x24, 0xdd, 0x10, 0xe5 } }
class nsISVGGlyphFragmentNode : public nsISupports
{
@ -54,6 +54,10 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISVGGLYPHFRAGMENTNODE_IID)
NS_IMETHOD_(PRUint32) GetNumberOfChars()=0;
NS_IMETHOD_(float) GetComputedTextLength()=0;
NS_IMETHOD_(float) GetSubStringLength(PRUint32 charnum, PRUint32 fragmentChars)=0;
NS_IMETHOD_(PRInt32) GetCharNumAtPosition(nsIDOMSVGPoint *point)=0;
NS_IMETHOD_(nsISVGGlyphFragmentLeaf *) GetFirstGlyphFragment()=0;
NS_IMETHOD_(nsISVGGlyphFragmentLeaf *) GetNextGlyphFragment()=0;
NS_IMETHOD_(PRUint32) BuildGlyphFragmentTree(PRUint32 charNum, PRBool lastBranch)=0;

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

@ -83,7 +83,6 @@ NS_NewSVGGlyphFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsIFrame* pa
nsSVGGlyphFrame::nsSVGGlyphFrame(nsStyleContext* aContext)
: nsSVGGlyphFrameBase(aContext),
mCharOffset(0),
mFragmentTreeDirty(PR_FALSE)
{
}
@ -145,7 +144,7 @@ nsSVGGlyphFrame::CharacterDataChanged(nsPresContext* aPresContext,
nsIContent* aChild,
PRBool aAppend)
{
return UpdateGraphic();
return UpdateGraphic();
}
nsresult
@ -458,7 +457,7 @@ FindPoint(nsSVGPathData *data,
}
}
/* readonly attribute nsSVGCharacterPostion characterPosition; */
/* void GetCharacterPosition (out nsSVGCharacterPosition aCP); */
NS_IMETHODIMP
nsSVGGlyphFrame::GetCharacterPosition(nsSVGCharacterPosition **aCharacterPosition)
{
@ -466,11 +465,16 @@ nsSVGGlyphFrame::GetCharacterPosition(nsSVGCharacterPosition **aCharacterPositio
nsISVGPathFlatten *textPath = nsnull;
/* check if we're the child of a textPath */
for (nsIFrame *frame = this; frame != nsnull; frame = frame->GetParent())
for (nsIFrame *frame = GetParent();
frame != nsnull;
frame = frame->GetParent()) {
if (frame->GetType() == nsLayoutAtoms::svgTextPathFrame) {
frame->QueryInterface(NS_GET_IID(nsISVGPathFlatten), (void **)&textPath);
CallQueryInterface(frame, &textPath);
break;
}
if (frame->GetType() == nsLayoutAtoms::svgTextFrame)
break;
}
/* we're an ordinary fragment - return */
/* XXX: we might want to use this for individual x/y/dx/dy adjustment */
@ -520,6 +524,15 @@ nsSVGGlyphFrame::GetCharacterPosition(nsSVGCharacterPosition **aCharacterPositio
return NS_OK;
}
/* void GetGlyphPosition (out float aGlyphPositionX, out float aGlyphPositionY); */
NS_IMETHODIMP
nsSVGGlyphFrame::GetGlyphPosition(float *aGlyphPositionX, float *aGlyphPositionY)
{
*aGlyphPositionX = mX;
*aGlyphPositionY = mY;
return NS_OK;
}
/* readonly attribute unsigned short textRendering; */
NS_IMETHODIMP
nsSVGGlyphFrame::GetTextRendering(PRUint16 *aTextRendering)
@ -716,19 +729,6 @@ nsSVGGlyphFrame::SetGlyphPosition(float x, float y)
UpdateGeometry(PR_TRUE, PR_FALSE);
}
NS_IMETHODIMP_(float)
nsSVGGlyphFrame::GetGlyphPositionX()
{
return mX;
}
NS_IMETHODIMP_(float)
nsSVGGlyphFrame::GetGlyphPositionY()
{
return mY;
}
NS_IMETHODIMP
nsSVGGlyphFrame::GetGlyphMetrics(nsISVGRendererGlyphMetrics** metrics)
{
@ -752,18 +752,6 @@ nsSVGGlyphFrame::GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y)
{
}
NS_IMETHODIMP_(PRUint32)
nsSVGGlyphFrame::GetNumberOfChars()
{
return mCharacterData.Length();
}
NS_IMETHODIMP_(PRUint32)
nsSVGGlyphFrame::GetCharNumberOffset()
{
return mCharOffset;
}
NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>)
nsSVGGlyphFrame::GetX()
{
@ -819,7 +807,7 @@ nsSVGGlyphFrame::IsAbsolutelyPositioned()
{
nsIFrame *lastFrame = this;
for (nsIFrame *frame = this->GetParent();
for (nsIFrame *frame = GetParent();
frame != nsnull;
lastFrame = frame, frame = frame->GetParent()) {
@ -848,6 +836,42 @@ nsSVGGlyphFrame::IsAbsolutelyPositioned()
//----------------------------------------------------------------------
// nsISVGGlyphFragmentNode interface:
NS_IMETHODIMP_(PRUint32)
nsSVGGlyphFrame::GetNumberOfChars()
{
return mCharacterData.Length();
}
NS_IMETHODIMP_(float)
nsSVGGlyphFrame::GetComputedTextLength()
{
if (mCharacterData.IsEmpty()) {
return 0.0f;
}
float fragmentLength;
mMetrics->GetComputedTextLength(&fragmentLength);
return fragmentLength;
}
NS_IMETHODIMP_(float)
nsSVGGlyphFrame::GetSubStringLength(PRUint32 charnum, PRUint32 fragmentChars)
{
float fragmentLength;
mMetrics->GetSubStringLength(charnum,
fragmentChars,
&fragmentLength);
return fragmentLength;
}
NS_IMETHODIMP_(PRInt32)
nsSVGGlyphFrame::GetCharNumAtPosition(nsIDOMSVGPoint *point)
{
PRInt32 index;
mMetrics->GetCharNumAtPosition(point, &index);
return index;
}
NS_IMETHODIMP_(nsISVGGlyphFragmentLeaf *)
nsSVGGlyphFrame::GetFirstGlyphFragment()
{
@ -880,7 +904,6 @@ nsSVGGlyphFrame::BuildGlyphFragmentTree(PRUint32 charNum, PRBool lastBranch)
// XXX actually we should be building a new fragment for each chunk here...
mCharOffset = charNum;
nsCOMPtr<nsITextContent> tc = do_QueryInterface(mContent);
if (tc->TextLength() == 0) {
@ -893,9 +916,9 @@ nsSVGGlyphFrame::BuildGlyphFragmentTree(PRUint32 charNum, PRBool lastBranch)
mCharacterData.Truncate();
tc->AppendTextTo(mCharacterData);
mCharacterData.CompressWhitespace(charNum==0, lastBranch);
mCharacterData.CompressWhitespace(charNum == 0, lastBranch);
return charNum+mCharacterData.Length();
return charNum + mCharacterData.Length();
}
NS_IMETHODIMP_(void)

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

@ -124,13 +124,9 @@ public:
// nsISVGGlyphFragmentLeaf interface:
NS_IMETHOD_(void) SetGlyphPosition(float x, float y);
NS_IMETHOD_(float) GetGlyphPositionX();
NS_IMETHOD_(float) GetGlyphPositionY();
NS_IMETHOD GetGlyphMetrics(nsISVGRendererGlyphMetrics** metrics);
NS_IMETHOD_(PRBool) IsStartOfChunk(); // == is new absolutely positioned chunk.
NS_IMETHOD_(void) GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y);
NS_IMETHOD_(PRUint32) GetNumberOfChars();
NS_IMETHOD_(PRUint32) GetCharNumberOffset();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetX();
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetY();
@ -140,6 +136,10 @@ public:
NS_IMETHOD_(PRBool) IsAbsolutelyPositioned();
// nsISVGGlyphFragmentNode interface:
NS_IMETHOD_(PRUint32) GetNumberOfChars();
NS_IMETHOD_(float) GetComputedTextLength();
NS_IMETHOD_(float) GetSubStringLength(PRUint32 charnum, PRUint32 fragmentChars);
NS_IMETHOD_(PRInt32) GetCharNumAtPosition(nsIDOMSVGPoint *point);
NS_IMETHOD_(nsISVGGlyphFragmentLeaf *) GetFirstGlyphFragment();
NS_IMETHOD_(nsISVGGlyphFragmentLeaf *) GetNextGlyphFragment();
NS_IMETHOD_(PRUint32) BuildGlyphFragmentTree(PRUint32 charNum, PRBool lastBranch);
@ -158,7 +158,6 @@ protected:
nsCOMPtr<nsISVGRendererGlyphGeometry> mGeometry;
nsCOMPtr<nsISVGRendererGlyphMetrics> mMetrics;
float mX, mY;
PRUint32 mCharOffset;
PRPackedBool mFragmentTreeDirty;
};

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

@ -38,7 +38,6 @@
#include "nsSVGTSpanFrame.h"
#include "nsSVGUtils.h"
#include "nsDOMError.h"
//----------------------------------------------------------------------
// Implementation
@ -68,7 +67,7 @@ NS_NewSVGTSpanFrame(nsIPresShell* aPresShell, nsIContent* aContent,
nsSVGTSpanFrame::nsSVGTSpanFrame(nsStyleContext* aContext)
: nsSVGTSpanFrameBase(aContext),
mCharOffset(0), mFragmentTreeDirty(PR_FALSE), mPropagateTransform(PR_TRUE)
mFragmentTreeDirty(PR_FALSE), mPropagateTransform(PR_TRUE)
{
}
@ -131,80 +130,54 @@ nsSVGTSpanFrame::AttributeChanged(PRInt32 aNameSpaceID,
NS_IMETHODIMP
nsSVGTSpanFrame::GetNumberOfChars(PRInt32 *_retval)
{
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
*_retval = nsSVGUtils::GetNumberOfChars(&mFrames);
if (node)
return nsSVGUtils::GetNumberOfChars(node, _retval);
*_retval = 0;
return NS_OK;
}
NS_IMETHODIMP
nsSVGTSpanFrame::GetComputedTextLength(float *_retval)
{
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
*_retval = nsSVGUtils::GetComputedTextLength(&mFrames);
if (node)
return nsSVGUtils::GetComputedTextLength(node, _retval);
*_retval = 0.0;
return NS_OK;
}
NS_IMETHODIMP
nsSVGTSpanFrame::GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval)
{
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (node)
return nsSVGUtils::GetSubStringLength(node, charnum, nchars, _retval);
*_retval = 0.0;
return NS_OK;
return nsSVGUtils::GetSubStringLength(&mFrames, charnum, nchars, _retval);
}
NS_IMETHODIMP
nsSVGTSpanFrame::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (!node) return NS_ERROR_DOM_INDEX_SIZE_ERR;
return nsSVGUtils::GetStartPositionOfChar(node, charnum, _retval);
return nsSVGUtils::GetStartPositionOfChar(&mFrames, charnum, _retval);
}
NS_IMETHODIMP
nsSVGTSpanFrame::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (!node) return NS_ERROR_DOM_INDEX_SIZE_ERR;
return nsSVGUtils::GetEndPositionOfChar(node, charnum, _retval);
return nsSVGUtils::GetEndPositionOfChar(&mFrames, charnum, _retval);
}
NS_IMETHODIMP
nsSVGTSpanFrame::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
{
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (!node) return NS_ERROR_DOM_INDEX_SIZE_ERR;
return nsSVGUtils::GetExtentOfChar(node, charnum, _retval);
return nsSVGUtils::GetExtentOfChar(&mFrames, charnum, _retval);
}
NS_IMETHODIMP
nsSVGTSpanFrame::GetRotationOfChar(PRUint32 charnum, float *_retval)
{
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (!node) return NS_ERROR_DOM_INDEX_SIZE_ERR;
return nsSVGUtils::GetRotationOfChar(node, charnum, _retval);
return nsSVGUtils::GetRotationOfChar(&mFrames, charnum, _retval);
}
NS_IMETHODIMP
nsSVGTSpanFrame::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
{
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
*_retval = nsSVGUtils::GetCharNumAtPosition(&mFrames, point);
if (node)
return nsSVGUtils::GetCharNumAtPosition(node, point, _retval);
*_retval = -1;
return NS_OK;
}
@ -307,6 +280,30 @@ nsSVGTSpanFrame::GetRelativePositionAdjustmentY(float &dy, PRUint32 charNum)
//----------------------------------------------------------------------
// nsISVGGlyphFragmentNode methods:
NS_IMETHODIMP_(PRUint32)
nsSVGTSpanFrame::GetNumberOfChars()
{
return nsSVGUtils::GetNumberOfChars(&mFrames);
}
NS_IMETHODIMP_(float)
nsSVGTSpanFrame::GetComputedTextLength()
{
return nsSVGUtils::GetComputedTextLength(&mFrames);
}
NS_IMETHODIMP_(float)
nsSVGTSpanFrame::GetSubStringLength(PRUint32 charnum, PRUint32 nchars)
{
return nsSVGUtils::GetSubStringLengthNoValidation(&mFrames, charnum, nchars);
}
NS_IMETHODIMP_(PRInt32)
nsSVGTSpanFrame::GetCharNumAtPosition(nsIDOMSVGPoint *point)
{
return nsSVGUtils::GetCharNumAtPosition(&mFrames, point);
}
NS_IMETHODIMP_(nsISVGGlyphFragmentLeaf *)
nsSVGTSpanFrame::GetFirstGlyphFragment()
{
@ -348,21 +345,9 @@ nsSVGTSpanFrame::GetNextGlyphFragment()
NS_IMETHODIMP_(PRUint32)
nsSVGTSpanFrame::BuildGlyphFragmentTree(PRUint32 charNum, PRBool lastBranch)
{
mCharOffset = charNum;
// init children:
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
nsISVGGlyphFragmentNode* next;
while (node) {
next = GetNextGlyphFragmentChildNode(node);
charNum = node->BuildGlyphFragmentTree(charNum, lastBranch && !next);
node = next;
}
return charNum;
return nsSVGUtils::BuildGlyphFragmentTree(&mFrames, charNum, lastBranch);
}
NS_IMETHODIMP_(void)
nsSVGTSpanFrame::NotifyMetricsSuspended()
{
@ -488,32 +473,3 @@ nsSVGTSpanFrame::GetDy()
animLengthList->GetAnimVal(&retval);
return retval;
}
nsISVGGlyphFragmentNode *
nsSVGTSpanFrame::GetFirstGlyphFragmentChildNode()
{
nsISVGGlyphFragmentNode* retval = nsnull;
nsIFrame* frame = mFrames.FirstChild();
while (frame) {
frame->QueryInterface(NS_GET_IID(nsISVGGlyphFragmentNode),(void**)&retval);
if (retval) break;
frame = frame->GetNextSibling();
}
return retval;
}
nsISVGGlyphFragmentNode *
nsSVGTSpanFrame::GetNextGlyphFragmentChildNode(nsISVGGlyphFragmentNode*node)
{
nsISVGGlyphFragmentNode* retval = nsnull;
nsIFrame* frame = nsnull;
node->QueryInterface(NS_GET_IID(nsIFrame), (void**)&frame);
NS_ASSERTION(frame, "interface not implemented");
frame = frame->GetNextSibling();
while (frame) {
frame->QueryInterface(NS_GET_IID(nsISVGGlyphFragmentNode),(void**)&retval);
if (retval) break;
frame = frame->GetNextSibling();
}
return retval;
}

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

@ -137,6 +137,10 @@ public:
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetDy();
// nsISVGGlyphFragmentNode interface:
NS_IMETHOD_(PRUint32) GetNumberOfChars();
NS_IMETHOD_(float) GetComputedTextLength();
NS_IMETHOD_(float) GetSubStringLength(PRUint32 charnum, PRUint32 fragmentChars);
NS_IMETHOD_(PRInt32) GetCharNumAtPosition(nsIDOMSVGPoint *point);
NS_IMETHOD_(nsISVGGlyphFragmentLeaf *) GetFirstGlyphFragment();
NS_IMETHOD_(nsISVGGlyphFragmentLeaf *) GetNextGlyphFragment();
NS_IMETHOD_(PRUint32) BuildGlyphFragmentTree(PRUint32 charNum, PRBool lastBranch);
@ -145,13 +149,8 @@ public:
NS_IMETHOD_(void) NotifyGlyphFragmentTreeSuspended();
NS_IMETHOD_(void) NotifyGlyphFragmentTreeUnsuspended();
protected:
nsISVGGlyphFragmentNode *GetFirstGlyphFragmentChildNode();
nsISVGGlyphFragmentNode *GetNextGlyphFragmentChildNode(nsISVGGlyphFragmentNode*node);
private:
nsCOMPtr<nsIDOMSVGMatrix> mOverrideCTM;
PRUint32 mCharOffset; // index of first character of this node relative to the enclosing <text>-element
PRPackedBool mFragmentTreeDirty;
PRPackedBool mPropagateTransform;
};

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

@ -63,7 +63,6 @@
#include "nsISVGPathFlatten.h"
#include "nsSVGUtils.h"
#include "nsSVGUtils.h"
#include "nsDOMError.h"
#include "nsSVGClipPathFrame.h"
#include "nsISVGRendererSurface.h"
#include "nsINameSpaceManager.h"
@ -165,8 +164,6 @@ protected:
void EnsureFragmentTreeUpToDate();
void UpdateFragmentTree();
void UpdateGlyphPositioning();
nsISVGGlyphFragmentNode *GetFirstGlyphFragmentChildNode();
nsISVGGlyphFragmentNode *GetNextGlyphFragmentChildNode(nsISVGGlyphFragmentNode*node);
enum UpdateState{
unsuspended,
@ -323,12 +320,8 @@ nsSVGTextFrame::GetNumberOfChars(PRInt32 *_retval)
{
EnsureFragmentTreeUpToDate();
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
*_retval = nsSVGUtils::GetNumberOfChars(&mFrames);
if (node)
return nsSVGUtils::GetNumberOfChars(node, _retval);
*_retval = 0;
return NS_OK;
}
@ -337,12 +330,8 @@ nsSVGTextFrame::GetComputedTextLength(float *_retval)
{
EnsureFragmentTreeUpToDate();
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
*_retval = nsSVGUtils::GetComputedTextLength(&mFrames);
if (node)
return nsSVGUtils::GetComputedTextLength(node, _retval);
*_retval = 0.0;
return NS_OK;
}
@ -351,13 +340,7 @@ nsSVGTextFrame::GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_re
{
EnsureFragmentTreeUpToDate();
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (node)
return nsSVGUtils::GetSubStringLength(node, charnum, nchars, _retval);
*_retval = 0.0;
return NS_OK;
return nsSVGUtils::GetSubStringLength(&mFrames, charnum, nchars, _retval);
}
NS_IMETHODIMP
@ -365,9 +348,7 @@ nsSVGTextFrame::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retva
{
EnsureFragmentTreeUpToDate();
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (!node) return NS_ERROR_DOM_INDEX_SIZE_ERR;
return nsSVGUtils::GetStartPositionOfChar(node, charnum, _retval);
return nsSVGUtils::GetStartPositionOfChar(&mFrames, charnum, _retval);
}
NS_IMETHODIMP
@ -375,9 +356,7 @@ nsSVGTextFrame::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
EnsureFragmentTreeUpToDate();
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (!node) return NS_ERROR_DOM_INDEX_SIZE_ERR;
return nsSVGUtils::GetEndPositionOfChar(node, charnum, _retval);
return nsSVGUtils::GetEndPositionOfChar(&mFrames, charnum, _retval);
}
NS_IMETHODIMP
@ -385,9 +364,7 @@ nsSVGTextFrame::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
{
EnsureFragmentTreeUpToDate();
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (!node) return NS_ERROR_DOM_INDEX_SIZE_ERR;
return nsSVGUtils::GetExtentOfChar(node, charnum, _retval);
return nsSVGUtils::GetExtentOfChar(&mFrames, charnum, _retval);
}
NS_IMETHODIMP
@ -395,9 +372,7 @@ nsSVGTextFrame::GetRotationOfChar(PRUint32 charnum, float *_retval)
{
EnsureFragmentTreeUpToDate();
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (!node) return NS_ERROR_DOM_INDEX_SIZE_ERR;
return nsSVGUtils::GetRotationOfChar(node, charnum, _retval);
return nsSVGUtils::GetRotationOfChar(&mFrames, charnum, _retval);
}
NS_IMETHODIMP
@ -405,11 +380,8 @@ nsSVGTextFrame::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
{
EnsureFragmentTreeUpToDate();
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (node)
return nsSVGUtils::GetCharNumAtPosition(node, point, _retval);
*_retval = nsSVGUtils::GetCharNumAtPosition(&mFrames, point);
*_retval = -1;
return NS_OK;
}
@ -704,15 +676,7 @@ nsSVGTextFrame::UpdateFragmentTree()
{
NS_ASSERTION(mFragmentTreeState == unsuspended, "updating during suspension!");
PRUint32 charNum = 0;
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
nsISVGGlyphFragmentNode* next;
while (node) {
next = GetNextGlyphFragmentChildNode(node);
charNum = node->BuildGlyphFragmentTree(charNum, !next);
node = next;
}
nsSVGUtils::BuildGlyphFragmentTree(&mFrames, 0, PR_TRUE);
mFragmentTreeDirty = PR_FALSE;
@ -777,7 +741,8 @@ nsSVGTextFrame::UpdateGlyphPositioning()
{
NS_ASSERTION(mMetricsState == unsuspended, "updating during suspension");
nsISVGGlyphFragmentNode *node = GetFirstGlyphFragmentChildNode();
nsISVGGlyphFragmentNode* node;
node = nsSVGUtils::GetFirstGlyphFragmentChildNode(&mFrames);
if (!node) return;
// we'll align every fragment in this chunk on the dominant-baseline:
@ -957,33 +922,3 @@ nsSVGTextFrame::GetDy()
animLengthList->GetAnimVal(&retval);
return retval;
}
nsISVGGlyphFragmentNode *
nsSVGTextFrame::GetFirstGlyphFragmentChildNode()
{
nsISVGGlyphFragmentNode* retval = nsnull;
nsIFrame* frame = mFrames.FirstChild();
while (frame) {
frame->QueryInterface(NS_GET_IID(nsISVGGlyphFragmentNode),(void**)&retval);
if (retval) break;
frame = frame->GetNextSibling();
}
return retval;
}
nsISVGGlyphFragmentNode *
nsSVGTextFrame::GetNextGlyphFragmentChildNode(nsISVGGlyphFragmentNode*node)
{
nsISVGGlyphFragmentNode* retval = nsnull;
nsIFrame* frame = nsnull;
node->QueryInterface(NS_GET_IID(nsIFrame), (void**)&frame);
NS_ASSERTION(frame, "interface not implemented");
frame = frame->GetNextSibling();
while (frame) {
frame->QueryInterface(NS_GET_IID(nsISVGGlyphFragmentNode),(void**)&retval);
if (retval) break;
frame = frame->GetNextSibling();
}
return retval;
}

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

@ -235,226 +235,278 @@ nsSVGUtils::GetBBox(nsFrameList *aFrames, nsIDOMSVGRect **_retval)
return NS_ERROR_FAILURE;
}
nsresult
nsSVGUtils::GetNumberOfChars(nsISVGGlyphFragmentNode* node,
PRInt32 *_retval)
nsISVGGlyphFragmentNode *
nsSVGUtils::GetFirstGlyphFragmentChildNode(nsFrameList *aFrames)
{
nsISVGGlyphFragmentNode *retval = nsnull;
nsIFrame* kid = aFrames->FirstChild();
while (kid) {
CallQueryInterface(kid, &retval);
if (retval) break;
kid = kid->GetNextSibling();
}
return retval;
}
nsISVGGlyphFragmentNode *
nsSVGUtils::GetNextGlyphFragmentChildNode(nsISVGGlyphFragmentNode *node)
{
nsISVGGlyphFragmentNode *retval = nsnull;
nsIFrame *frame = nsnull;
CallQueryInterface(node, &frame);
NS_ASSERTION(frame, "interface not implemented");
frame = frame->GetNextSibling();
while (frame) {
CallQueryInterface(frame, &retval);
if (retval) break;
frame = frame->GetNextSibling();
}
return retval;
}
PRUint32
nsSVGUtils::BuildGlyphFragmentTree(nsFrameList *aFrames,
PRUint32 charNum,
PRBool lastBranch)
{
// init children:
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode(aFrames);
nsISVGGlyphFragmentNode* next;
while (node) {
next = GetNextGlyphFragmentChildNode(node);
charNum = node->BuildGlyphFragmentTree(charNum, lastBranch && !next);
node = next;
}
return charNum;
}
PRUint32
nsSVGUtils::GetNumberOfChars(nsFrameList *aFrames)
{
PRUint32 nchars = 0;
nsISVGGlyphFragmentLeaf *fragment = node->GetFirstGlyphFragment();
nsISVGGlyphFragmentNode* node;
node = GetFirstGlyphFragmentChildNode(aFrames);
while (fragment) {
nchars += fragment->GetNumberOfChars();
fragment = fragment->GetNextGlyphFragment();
while (node) {
nchars += node->GetNumberOfChars();
node = GetNextGlyphFragmentChildNode(node);
}
*_retval = nchars;
return NS_OK;
return nchars;
}
nsresult
nsSVGUtils::GetComputedTextLength(nsISVGGlyphFragmentNode* node,
float *_retval)
float
nsSVGUtils::GetComputedTextLength(nsFrameList *aFrames)
{
float length = 0.0;
nsISVGGlyphFragmentLeaf *fragment = node->GetFirstGlyphFragment();
float length = 0.0f;
nsISVGGlyphFragmentNode* node;
node = GetFirstGlyphFragmentChildNode(aFrames);
while (fragment) {
if (fragment->GetNumberOfChars() > 0) {
// query the renderer metrics for the length of each fragment
nsCOMPtr<nsISVGRendererGlyphMetrics> metrics;
fragment->GetGlyphMetrics(getter_AddRefs(metrics));
if (!metrics) return NS_ERROR_FAILURE;
float fragmentLength;
nsresult rv = metrics->GetComputedTextLength(&fragmentLength);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
length += fragmentLength;
}
fragment = fragment->GetNextGlyphFragment();
while (node) {
length += node->GetComputedTextLength();
node = GetNextGlyphFragmentChildNode(node);
}
*_retval = length;
return NS_OK;
return length;
}
nsresult
nsSVGUtils::GetSubStringLength(nsISVGGlyphFragmentNode* node,
nsSVGUtils::GetSubStringLength(nsFrameList *aFrames,
PRUint32 charnum,
PRUint32 nchars,
float *_retval)
{
float length = 0.0;
nsISVGGlyphFragmentLeaf *fragment = node->GetFirstGlyphFragment();
while (fragment && nchars) {
PRUint32 count = fragment->GetNumberOfChars();
if (nchars == 0) {
*_retval = 0.0f;
return NS_OK;
}
if (charnum + nchars > nsSVGUtils::GetNumberOfChars(aFrames)) {
*_retval = 0.0f;
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
*_retval = GetSubStringLengthNoValidation(aFrames, charnum, nchars);
return NS_OK;
}
float
nsSVGUtils::GetSubStringLengthNoValidation(nsFrameList *aFrames,
PRUint32 charnum,
PRUint32 nchars)
{
float length = 0.0f;
nsISVGGlyphFragmentNode *node = GetFirstGlyphFragmentChildNode(aFrames);
while (node) {
PRUint32 count = node->GetNumberOfChars();
if (count > charnum) {
// query the renderer metrics for the length of the substring in each fragment
nsCOMPtr<nsISVGRendererGlyphMetrics> metrics;
fragment->GetGlyphMetrics(getter_AddRefs(metrics));
if (!metrics) return NS_ERROR_FAILURE;
PRUint32 fragmentChars = PR_MIN(nchars, count);
float fragmentLength;
nsresult rv = metrics->GetSubStringLength(charnum,
fragmentChars,
&fragmentLength);
if (NS_FAILED(rv)) break;
float fragmentLength = node->GetSubStringLength(charnum, fragmentChars);
length += fragmentLength;
nchars -= fragmentChars;
if (nchars == 0) break;
}
charnum -= PR_MIN(charnum, count);
fragment = fragment->GetNextGlyphFragment();
node = GetNextGlyphFragmentChildNode(node);
}
// substring too long
if (nchars != 0) return NS_ERROR_DOM_INDEX_SIZE_ERR;
*_retval = length;
return NS_OK;
return length;
}
nsresult
nsSVGUtils::GetStartPositionOfChar(nsISVGGlyphFragmentNode* node,
nsSVGUtils::GetStartPositionOfChar(nsFrameList *aFrames,
PRUint32 charnum,
nsIDOMSVGPoint **_retval)
{
*_retval = nsnull;
nsISVGGlyphFragmentLeaf *fragment = GetGlyphFragmentAtCharNum(node, charnum);
if (!fragment) return NS_ERROR_DOM_INDEX_SIZE_ERR;
if (charnum >= nsSVGUtils::GetNumberOfChars(aFrames)) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
nsISVGGlyphFragmentNode *node = GetFirstGlyphFragmentChildNode(aFrames);
if (!node) {
return NS_ERROR_FAILURE;
}
PRUint32 offset;
nsISVGGlyphFragmentLeaf *fragment = GetGlyphFragmentAtCharNum(node, charnum, &offset);
if (!fragment) {
return NS_ERROR_FAILURE;
}
// query the renderer metrics for the start position of the character
nsCOMPtr<nsISVGRendererGlyphMetrics> metrics;
fragment->GetGlyphMetrics(getter_AddRefs(metrics));
if (!metrics) return NS_ERROR_FAILURE;
nsresult rv = metrics->GetStartPositionOfChar(charnum-fragment->GetCharNumberOffset(),
_retval);
if (NS_FAILED(rv)) return NS_ERROR_DOM_INDEX_SIZE_ERR;
if (!metrics) {
return NS_ERROR_FAILURE;
}
// offset the bounds by the position of the fragment:
float x,y;
(*_retval)->GetX(&x);
(*_retval)->GetY(&y);
(*_retval)->SetX(x + fragment->GetGlyphPositionX());
(*_retval)->SetY(y + fragment->GetGlyphPositionY());
return NS_OK;
return metrics->GetStartPositionOfChar(charnum - offset, _retval);
}
nsresult
nsSVGUtils::GetEndPositionOfChar(nsISVGGlyphFragmentNode* node,
nsSVGUtils::GetEndPositionOfChar(nsFrameList *aFrames,
PRUint32 charnum,
nsIDOMSVGPoint **_retval)
{
*_retval = nsnull;
nsISVGGlyphFragmentLeaf *fragment = GetGlyphFragmentAtCharNum(node, charnum);
if (!fragment) return NS_ERROR_DOM_INDEX_SIZE_ERR;
if (charnum >= nsSVGUtils::GetNumberOfChars(aFrames)) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
nsISVGGlyphFragmentNode *node = GetFirstGlyphFragmentChildNode(aFrames);
if (!node) {
return NS_ERROR_FAILURE;
}
PRUint32 offset;
nsISVGGlyphFragmentLeaf *fragment = GetGlyphFragmentAtCharNum(node, charnum, &offset);
if (!fragment) {
return NS_ERROR_FAILURE;
}
// query the renderer metrics for the end position of the character
nsCOMPtr<nsISVGRendererGlyphMetrics> metrics;
fragment->GetGlyphMetrics(getter_AddRefs(metrics));
if (!metrics) return NS_ERROR_FAILURE;
nsresult rv = metrics->GetEndPositionOfChar(charnum-fragment->GetCharNumberOffset(),
_retval);
if (NS_FAILED(rv)) return NS_ERROR_DOM_INDEX_SIZE_ERR;
if (!metrics) {
return NS_ERROR_FAILURE;
}
// offset the bounds by the position of the fragment:
float x,y;
(*_retval)->GetX(&x);
(*_retval)->GetY(&y);
(*_retval)->SetX(x + fragment->GetGlyphPositionX());
(*_retval)->SetY(y + fragment->GetGlyphPositionY());
return NS_OK;
return metrics->GetEndPositionOfChar(charnum - offset, _retval);
}
nsresult
nsSVGUtils::GetExtentOfChar(nsISVGGlyphFragmentNode* node,
nsSVGUtils::GetExtentOfChar(nsFrameList *aFrames,
PRUint32 charnum,
nsIDOMSVGRect **_retval)
{
*_retval = nsnull;
nsISVGGlyphFragmentLeaf *fragment = GetGlyphFragmentAtCharNum(node, charnum);
if (!fragment) return NS_ERROR_DOM_INDEX_SIZE_ERR;
if (charnum >= nsSVGUtils::GetNumberOfChars(aFrames)) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
nsISVGGlyphFragmentNode *node = GetFirstGlyphFragmentChildNode(aFrames);
if (!node) {
return NS_ERROR_FAILURE;
}
PRUint32 offset;
nsISVGGlyphFragmentLeaf *fragment = GetGlyphFragmentAtCharNum(node, charnum, &offset);
if (!fragment) {
return NS_ERROR_FAILURE;
}
// query the renderer metrics for the bounds of the character
nsCOMPtr<nsISVGRendererGlyphMetrics> metrics;
fragment->GetGlyphMetrics(getter_AddRefs(metrics));
if (!metrics) return NS_ERROR_FAILURE;
nsresult rv = metrics->GetExtentOfChar(charnum-fragment->GetCharNumberOffset(),
_retval);
if (NS_FAILED(rv)) return NS_ERROR_DOM_INDEX_SIZE_ERR;
if (!metrics) {
return NS_ERROR_FAILURE;
}
// offset the bounds by the position of the fragment:
float x,y;
(*_retval)->GetX(&x);
(*_retval)->GetY(&y);
(*_retval)->SetX(x + fragment->GetGlyphPositionX());
(*_retval)->SetY(y + fragment->GetGlyphPositionY());
return NS_OK;
return metrics->GetExtentOfChar(charnum - offset, _retval);
}
nsresult
nsSVGUtils::GetRotationOfChar(nsISVGGlyphFragmentNode* node,
nsSVGUtils::GetRotationOfChar(nsFrameList *aFrames,
PRUint32 charnum,
float *_retval)
{
nsISVGGlyphFragmentLeaf *fragment = GetGlyphFragmentAtCharNum(node, charnum);
if (!fragment) return NS_ERROR_DOM_INDEX_SIZE_ERR;
*_retval = 0.0f;
if (charnum >= nsSVGUtils::GetNumberOfChars(aFrames)) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
}
nsISVGGlyphFragmentNode *node = GetFirstGlyphFragmentChildNode(aFrames);
if (!node) {
return NS_ERROR_FAILURE;
}
PRUint32 offset;
nsISVGGlyphFragmentLeaf *fragment = GetGlyphFragmentAtCharNum(node, charnum, &offset);
if (!fragment) {
return NS_ERROR_FAILURE;
}
// query the renderer metrics for the rotation of the character
nsCOMPtr<nsISVGRendererGlyphMetrics> metrics;
fragment->GetGlyphMetrics(getter_AddRefs(metrics));
if (!metrics) return NS_ERROR_FAILURE;
nsresult rv = metrics->GetRotationOfChar(charnum-fragment->GetCharNumberOffset(),
_retval);
if (NS_FAILED(rv)) return NS_ERROR_DOM_INDEX_SIZE_ERR;
return NS_OK;
}
nsresult
nsSVGUtils::GetCharNumAtPosition(nsISVGGlyphFragmentNode* node,
nsIDOMSVGPoint *point,
PRInt32 *_retval)
{
PRInt32 index = -1;
nsISVGGlyphFragmentLeaf *fragment = node->GetFirstGlyphFragment();
while (fragment) {
if (fragment->GetNumberOfChars() > 0) {
// query the renderer metrics for the character position
nsCOMPtr<nsISVGRendererGlyphMetrics> metrics;
fragment->GetGlyphMetrics(getter_AddRefs(metrics));
if (!metrics) return NS_ERROR_FAILURE;
// subtract the fragment offset from the position:
float x,y;
point->GetX(&x);
point->GetY(&y);
nsCOMPtr<nsIDOMSVGPoint> position;
NS_NewSVGPoint(getter_AddRefs(position),
x - fragment->GetGlyphPositionX(),
y - fragment->GetGlyphPositionY());
if (!position)
return NS_ERROR_FAILURE;
nsresult rv = metrics->GetCharNumAtPosition(position, &index);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
// Multiple characters may match, we must return the last one
// so no break here
}
fragment = fragment->GetNextGlyphFragment();
if (!metrics) {
return NS_ERROR_FAILURE;
}
*_retval = index;
return NS_OK;
return metrics->GetRotationOfChar(charnum - offset, _retval);
}
PRInt32
nsSVGUtils::GetCharNumAtPosition(nsFrameList *aFrames,
nsIDOMSVGPoint *point)
{
PRInt32 index = -1;
PRInt32 offset = 0;
nsISVGGlyphFragmentNode *node = GetFirstGlyphFragmentChildNode(aFrames);
while (node) {
PRUint32 count = node->GetNumberOfChars();
if (count > 0) {
PRInt32 charnum = node->GetCharNumAtPosition(point);
if (charnum >= 0) {
index = charnum + offset;
}
offset += count;
// Keep going, multiple characters may match
// and we must return the last one
}
node = GetNextGlyphFragmentChildNode(node);
}
return index;
}
nsRect
@ -551,15 +603,18 @@ nsSVGUtils::GetSurface(nsISVGOuterSVGFrame *aOuterSVGFrame,
nsISVGGlyphFragmentLeaf *
nsSVGUtils::GetGlyphFragmentAtCharNum(nsISVGGlyphFragmentNode* node,
PRUint32 charnum)
PRUint32 charnum,
PRUint32 *offset)
{
nsISVGGlyphFragmentLeaf *fragment = node->GetFirstGlyphFragment();
*offset = 0;
while (fragment) {
PRUint32 count = fragment->GetNumberOfChars();
if (count > charnum)
return fragment;
charnum -= count;
*offset += count;
fragment = fragment->GetNextGlyphFragment();
}

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

@ -125,60 +125,84 @@ public:
*/
static nsresult GetBBox(nsFrameList *aFrames, nsIDOMSVGRect **_retval);
/*
* Returns the first child node for a frame
*/
static nsISVGGlyphFragmentNode *
GetFirstGlyphFragmentChildNode(nsFrameList *aFrames);
/*
* Returns the next child node for a frame
*/
static nsISVGGlyphFragmentNode *
GetNextGlyphFragmentChildNode(nsISVGGlyphFragmentNode *node);
/*
* Build the glyph fragment tree
*/
static PRUint32
nsSVGUtils::BuildGlyphFragmentTree(nsFrameList *aFrames,
PRUint32 charNum,
PRBool lastBranch);
/*
* Returns the number of characters in a string
*/
static nsresult GetNumberOfChars(nsISVGGlyphFragmentNode* node,
PRInt32 *_retval);
static PRUint32 GetNumberOfChars(nsFrameList *aFrames);
/*
* Determines the length of a string
*/
static nsresult GetComputedTextLength(nsISVGGlyphFragmentNode* node,
float *_retval);
static float GetComputedTextLength(nsFrameList *aFrames);
/*
* Determines the length of a substring
*/
static nsresult GetSubStringLength(nsISVGGlyphFragmentNode* node,
static nsresult GetSubStringLength(nsFrameList *aFrames,
PRUint32 charnum,
PRUint32 nchars,
float *_retval);
/*
* Determines the length of a substring
*/
static float GetSubStringLengthNoValidation(nsFrameList *aFrames,
PRUint32 charnum,
PRUint32 nchars);
/*
* Determines the start position of a character
*/
static nsresult GetStartPositionOfChar(nsISVGGlyphFragmentNode* node,
static nsresult GetStartPositionOfChar(nsFrameList *aFrames,
PRUint32 charnum,
nsIDOMSVGPoint **_retval);
/*
* Determines the end position of a character
*/
static nsresult GetEndPositionOfChar(nsISVGGlyphFragmentNode* node,
static nsresult GetEndPositionOfChar(nsFrameList *aFrames,
PRUint32 charnum,
nsIDOMSVGPoint **_retval);
/*
* Determines the bounds of a character
*/
static nsresult GetExtentOfChar(nsISVGGlyphFragmentNode* node,
static nsresult GetExtentOfChar(nsFrameList *aFrames,
PRUint32 charnum,
nsIDOMSVGRect **_retval);
/*
* Determines the rotation of a character
*/
static nsresult GetRotationOfChar(nsISVGGlyphFragmentNode* node,
static nsresult GetRotationOfChar(nsFrameList *aFrames,
PRUint32 charnum,
float *_retval);
/*
* Get the character at the specified position
*/
static nsresult GetCharNumAtPosition(nsISVGGlyphFragmentNode* node,
nsIDOMSVGPoint *point,
PRInt32 *_retval);
static PRInt32 GetCharNumAtPosition(nsFrameList *aFrames,
nsIDOMSVGPoint *point);
/*
* Figures out the worst case invalidation area for a frame, taking
@ -297,7 +321,8 @@ private:
*/
static nsISVGGlyphFragmentLeaf *
GetGlyphFragmentAtCharNum(nsISVGGlyphFragmentNode* node,
PRUint32 charnum);
PRUint32 charnum,
PRUint32 *offset);
};
#endif

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

@ -68,7 +68,7 @@ native nsFont(nsFont);
*
* @nosubgrouping
*/
[uuid(06937879-37a4-4ffb-8b44-917f030f1651)]
[uuid(de843094-3dc6-4b4c-b754-a4b535397792)]
interface nsISVGGlyphMetricsSource : nsISupports
{
/**
@ -92,6 +92,14 @@ interface nsISVGGlyphMetricsSource : nsISupports
void GetCharacterPosition(out nsSVGCharacterPosition aCP);
/** @} */
/**
* @name String positioning information (if no character positions)
* @{
*/
void GetGlyphPosition(out float glyphPositionX, out float glyphPositionY);
/** @} */
/**
* @name Text rendering mode
* @{

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

@ -244,6 +244,8 @@ nsSVGCairoGlyphMetrics::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint
y = cp[charnum].y;
} else {
mSource->GetGlyphPosition(&x, &y);
if (charnum > 0) {
cairo_text_extents_t extent;
@ -253,10 +255,8 @@ nsSVGCairoGlyphMetrics::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint
charnum)).get(),
&extent);
x = extent.x_advance;
y = extent.y_advance;
} else {
x = y = 0.0f;
x += extent.x_advance;
y += extent.y_advance;
}
}
@ -279,12 +279,12 @@ nsSVGCairoGlyphMetrics::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **
SelectFont(mCT);
cairo_text_extents_t extent;
if (cp) {
if (cp[charnum].draw == PR_FALSE)
return NS_ERROR_DOM_INDEX_SIZE_ERR;
cairo_text_extents_t extent;
cairo_text_extents(mCT,
NS_ConvertUTF16toUTF8(Substring(text, charnum, 1)).get(),
&extent);
@ -296,14 +296,15 @@ nsSVGCairoGlyphMetrics::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **
cp[charnum].x + extent.x_advance * c - extent.y_advance * s,
cp[charnum].y + extent.y_advance * c + extent.x_advance * s);
}
cairo_text_extents_t extent;
float x, y;
mSource->GetGlyphPosition(&x, &y);
cairo_text_extents(mCT,
NS_ConvertUTF16toUTF8(Substring(text, 0, charnum + 1)).get(),
&extent);
return NS_NewSVGPoint(_retval, extent.x_advance, extent.y_advance);
return NS_NewSVGPoint(_retval, x + extent.x_advance, y + extent.y_advance);
}
/** Implements nsIDOMSVGRect getExtentOfChar(in unsigned long charnum); */
@ -354,26 +355,28 @@ nsSVGCairoGlyphMetrics::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retva
return NS_NewSVGRect(_retval, xmin, ymin, xmax - xmin, ymax - ymin);
}
float x, y;
mSource->GetGlyphPosition(&x, &y);
x += extent.x_bearing;
y += extent.y_bearing;
cairo_text_extents_t precedingExtent;
if (charnum > 0) {
// add the space taken up by the text which comes before charnum
// to the position of the charnum character
cairo_text_extents(mCT,
NS_ConvertUTF16toUTF8(Substring(text,
0,
charnum)).get(),
&precedingExtent);
} else {
precedingExtent.x_advance = 0.0;
precedingExtent.y_advance = 0.0;
x += precedingExtent.x_advance;
y += precedingExtent.y_advance;
}
// add the space taken up by the text which comes before charnum
// to the position of the charnum character
return NS_NewSVGRect(_retval,
precedingExtent.x_advance + extent.x_bearing,
precedingExtent.y_advance + extent.y_bearing,
extent.width,
extent.height);
return NS_NewSVGRect(_retval, x, y, extent.width, extent.height);
}
/** Implements float getRotationOfChar(in unsigned long charnum); */
@ -405,9 +408,11 @@ nsSVGCairoGlyphMetrics::GetRotationOfChar(PRUint32 charnum, float *_retval)
NS_IMETHODIMP
nsSVGCairoGlyphMetrics::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
{
float x,y;
point->GetX(&x);
point->GetY(&y);
*_retval = -1;
float xPos, yPos;
point->GetX(&xPos);
point->GetY(&yPos);
nsAutoString text;
mSource->GetCharacterData(text);
@ -417,6 +422,11 @@ nsSVGCairoGlyphMetrics::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_re
if (NS_FAILED(mSource->GetCharacterPosition(getter_Transfers(cp))))
return NS_ERROR_FAILURE;
float x, y;
if (!cp) {
mSource->GetGlyphPosition(&x, &y);
}
for (PRUint32 charnum = 0; charnum < text.Length(); charnum++) {
/* character actually on the path? */
if (cp && cp[charnum].draw == PR_FALSE)
@ -438,9 +448,9 @@ nsSVGCairoGlyphMetrics::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_re
0,
charnum)).get(),
&extent);
cairo_move_to(mCT, extent.x_advance, extent.y_advance);
cairo_move_to(mCT, x + extent.x_advance, y + extent.y_advance);
} else {
cairo_move_to(mCT, 0.0, 0.0);
cairo_move_to(mCT, x, y);
}
}
cairo_text_extents_t extent;
@ -455,7 +465,7 @@ nsSVGCairoGlyphMetrics::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_re
cairo_close_path(mCT);
cairo_identity_matrix(mCT);
if (cairo_in_fill(mCT, x, y))
if (cairo_in_fill(mCT, xPos, yPos))
*_retval = charnum;
cairo_set_matrix(mCT, &matrix);