зеркало из https://github.com/mozilla/gecko-dev.git
Bug 339039 - Text spans return incorrect number of characters with getNumberOfChars(). r=tor,sr=roc
This commit is contained in:
Родитель
6a60ce6050
Коммит
dedc74de85
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче