Bug 318597 - Implement various text, tspan and textPath DOM functions.

Patch by longsonr@gmail.com, r=tor, sr=jst
This commit is contained in:
tor%cs.brown.edu 2006-02-17 21:24:30 +00:00
parent 54c4672ea7
commit 0fc7a7c541
16 changed files with 1150 additions and 101 deletions

View File

@ -45,16 +45,23 @@ class nsIDOMSVGRect;
////////////////////////////////////////////////////////////////////////
// nsISVGTextContentMetrics
// {351AC4D0-22B3-45F5-BA26-8B8CF21EF1D8}
// {CBF0A774-4171-4112-BD9A-F49BEFC0CE18}
#define NS_ISVGTEXTCONTENTMETRICS_IID \
{ 0x351ac4d0, 0x22b3, 0x45f5, { 0xba, 0x26, 0x8b, 0x8c, 0xf2, 0x1e, 0xf1, 0xd8 } }
{ 0xcbf0a774, 0x4171, 0x4112, { 0xbd, 0x9a, 0xf4, 0x9b, 0xef, 0xc0, 0xce, 0x18 } }
class nsISVGTextContentMetrics : public nsISupports
{
public:
static const nsIID& GetIID() { static nsIID iid = NS_ISVGTEXTCONTENTMETRICS_IID; return iid; }
NS_IMETHOD GetNumberOfChars(PRInt32 *_retval)=0;
NS_IMETHOD GetComputedTextLength(float *_retval)=0;
NS_IMETHOD GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval)=0;
NS_IMETHOD GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)=0;
NS_IMETHOD GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)=0;
NS_IMETHOD GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)=0;
NS_IMETHOD GetRotationOfChar(PRUint32 charnum, float *_retval)=0;
NS_IMETHOD GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)=0;
};
#endif // __NS_ISVGTEXTCONTENTMETRICS_H__

View File

@ -36,7 +36,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGGraphicElement.h"
#include "nsSVGStylableElement.h"
#include "nsSVGAtoms.h"
#include "nsIDOMSVGTSpanElement.h"
#include "nsCOMPtr.h"
@ -47,8 +47,9 @@
#include "nsISVGTextContentMetrics.h"
#include "nsIFrame.h"
#include "nsIDocument.h"
#include "nsDOMError.h"
typedef nsSVGGraphicElement nsSVGTSpanElementBase;
typedef nsSVGStylableElement nsSVGTSpanElementBase;
class nsSVGTSpanElement : public nsSVGTSpanElementBase,
public nsIDOMSVGTSpanElement // : nsIDOMSVGTextPositioningElement
@ -82,6 +83,8 @@ public:
virtual void ParentChainChanged();
protected:
// nsSVGElement overrides
virtual PRBool IsEventName(nsIAtom* aName);
already_AddRefed<nsISVGTextContentMetrics> GetTextContentMetrics();
@ -260,43 +263,59 @@ NS_IMETHODIMP nsSVGTSpanElement::GetLengthAdjust(nsIDOMSVGAnimatedEnumeration *
/* long getNumberOfChars (); */
NS_IMETHODIMP nsSVGTSpanElement::GetNumberOfChars(PRInt32 *_retval)
{
NS_NOTYETIMPLEMENTED("nsSVGTSpanElement::GetNumberOfChars");
return NS_ERROR_NOT_IMPLEMENTED;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (metrics)
return metrics->GetNumberOfChars(_retval);
*_retval = 0;
return NS_OK;
}
/* float getComputedTextLength (); */
NS_IMETHODIMP nsSVGTSpanElement::GetComputedTextLength(float *_retval)
{
nsCOMPtr<nsIDOMSVGRect> bbox;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
GetBBox(getter_AddRefs(bbox));
if (bbox)
bbox->GetWidth(_retval);
else
*_retval = 0;
if (metrics)
return metrics->GetComputedTextLength(_retval);
*_retval = 0.0;
return NS_OK;
}
/* float getSubStringLength (in unsigned long charnum, in unsigned long nchars); */
NS_IMETHODIMP nsSVGTSpanElement::GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval)
{
NS_NOTYETIMPLEMENTED("nsSVGTSpanElement::GetSubStringLength");
return NS_ERROR_NOT_IMPLEMENTED;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (metrics)
return metrics->GetSubStringLength(charnum, nchars, _retval);
*_retval = 0.0;
return NS_OK;
}
/* nsIDOMSVGPoint getStartPositionOfChar (in unsigned long charnum); */
NS_IMETHODIMP nsSVGTSpanElement::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
NS_NOTYETIMPLEMENTED("nsSVGTSpanElement::GetStartPositionOfChar");
return NS_ERROR_NOT_IMPLEMENTED;
*_retval = nsnull;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (!metrics) return NS_ERROR_FAILURE;
return metrics->GetStartPositionOfChar(charnum, _retval);
}
/* nsIDOMSVGPoint getEndPositionOfChar (in unsigned long charnum); */
NS_IMETHODIMP nsSVGTSpanElement::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
NS_NOTYETIMPLEMENTED("nsSVGTSpanElement::GetEndPositionOfChar");
return NS_ERROR_NOT_IMPLEMENTED;
*_retval = nsnull;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (!metrics) return NS_ERROR_FAILURE;
return metrics->GetEndPositionOfChar(charnum, _retval);
}
/* nsIDOMSVGRect getExtentOfChar (in unsigned long charnum); */
@ -313,8 +332,13 @@ NS_IMETHODIMP nsSVGTSpanElement::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect
/* float getRotationOfChar (in unsigned long charnum); */
NS_IMETHODIMP nsSVGTSpanElement::GetRotationOfChar(PRUint32 charnum, float *_retval)
{
NS_NOTYETIMPLEMENTED("nsSVGTSpanElement::GetRotationOfChar");
return NS_ERROR_NOT_IMPLEMENTED;
*_retval = 0.0;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (!metrics) return NS_ERROR_FAILURE;
return metrics->GetRotationOfChar(charnum, _retval);
}
/* long getCharNumAtPosition (in nsIDOMSVGPoint point); */
@ -322,11 +346,16 @@ NS_IMETHODIMP nsSVGTSpanElement::GetCharNumAtPosition(nsIDOMSVGPoint *point,
PRInt32 *_retval)
{
// null check when implementing - this method can be used by scripts!
// if (!point)
// return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
if (!point)
return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
NS_NOTYETIMPLEMENTED("nsSVGTSpanElement::GetCharNumAtPosition");
return NS_ERROR_NOT_IMPLEMENTED;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (metrics)
return metrics->GetCharNumAtPosition(point, _retval);
*_retval = -1;
return NS_OK;
}
/* void selectSubString (in unsigned long charnum, in unsigned long nchars); */
@ -411,6 +440,15 @@ void nsSVGTSpanElement::ParentChainChanged()
nsSVGTSpanElementBase::ParentChainChanged();
}
//----------------------------------------------------------------------
// nsSVGElement overrides
PRBool
nsSVGTSpanElement::IsEventName(nsIAtom* aName)
{
return IsGraphicElementEventName(aName);
}
//----------------------------------------------------------------------
// implementation helpers:

View File

@ -48,6 +48,7 @@
#include "nsIPresShell.h"
#include "nsIFrame.h"
#include "nsIDocument.h"
#include "nsDOMError.h"
typedef nsSVGGraphicElement nsSVGTextElementBase;
@ -261,43 +262,59 @@ NS_IMETHODIMP nsSVGTextElement::GetLengthAdjust(nsIDOMSVGAnimatedEnumeration * *
/* long getNumberOfChars (); */
NS_IMETHODIMP nsSVGTextElement::GetNumberOfChars(PRInt32 *_retval)
{
NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetNumberOfChars");
return NS_ERROR_NOT_IMPLEMENTED;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (metrics)
return metrics->GetNumberOfChars(_retval);
*_retval = 0;
return NS_OK;
}
/* float getComputedTextLength (); */
NS_IMETHODIMP nsSVGTextElement::GetComputedTextLength(float *_retval)
{
nsCOMPtr<nsIDOMSVGRect> bbox;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
GetBBox(getter_AddRefs(bbox));
if (bbox)
bbox->GetWidth(_retval);
else
*_retval = 0;
if (metrics)
return metrics->GetComputedTextLength(_retval);
*_retval = 0.0;
return NS_OK;
}
/* float getSubStringLength (in unsigned long charnum, in unsigned long nchars); */
NS_IMETHODIMP nsSVGTextElement::GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval)
{
NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetSubStringLength");
return NS_ERROR_NOT_IMPLEMENTED;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (metrics)
return metrics->GetSubStringLength(charnum, nchars, _retval);
*_retval = 0.0;
return NS_OK;
}
/* nsIDOMSVGPoint getStartPositionOfChar (in unsigned long charnum); */
NS_IMETHODIMP nsSVGTextElement::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetStartPositionOfChar");
return NS_ERROR_NOT_IMPLEMENTED;
*_retval = nsnull;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (!metrics) return NS_ERROR_FAILURE;
return metrics->GetStartPositionOfChar(charnum, _retval);
}
/* nsIDOMSVGPoint getEndPositionOfChar (in unsigned long charnum); */
NS_IMETHODIMP nsSVGTextElement::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetEndPositionOfChar");
return NS_ERROR_NOT_IMPLEMENTED;
*_retval = nsnull;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (!metrics) return NS_ERROR_FAILURE;
return metrics->GetEndPositionOfChar(charnum, _retval);
}
/* nsIDOMSVGRect getExtentOfChar (in unsigned long charnum); */
@ -314,19 +331,29 @@ NS_IMETHODIMP nsSVGTextElement::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect
/* float getRotationOfChar (in unsigned long charnum); */
NS_IMETHODIMP nsSVGTextElement::GetRotationOfChar(PRUint32 charnum, float *_retval)
{
NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetRotationOfChar");
return NS_ERROR_NOT_IMPLEMENTED;
*_retval = 0.0;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (!metrics) return NS_ERROR_FAILURE;
return metrics->GetRotationOfChar(charnum, _retval);
}
/* long getCharNumAtPosition (in nsIDOMSVGPoint point); */
NS_IMETHODIMP nsSVGTextElement::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
{
// null check when implementing - this method can be used by scripts!
// if (!element)
// return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
if (!point)
return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetCharNumAtPosition");
return NS_ERROR_NOT_IMPLEMENTED;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (metrics)
return metrics->GetCharNumAtPosition(point, _retval);
*_retval = -1;
return NS_OK;
}
/* void selectSubString (in unsigned long charnum, in unsigned long nchars); */

View File

@ -40,10 +40,14 @@
#include "nsIDOMSVGTextPathElement.h"
#include "nsSVGLength.h"
#include "nsIDOMSVGURIReference.h"
#include "nsISVGTextContentMetrics.h"
#include "nsIFrame.h"
#include "nsIDocument.h"
#include "nsSVGAnimatedLength.h"
#include "nsSVGAnimatedString.h"
#include "nsSVGAnimatedEnumeration.h"
#include "nsSVGEnum.h"
#include "nsDOMError.h"
typedef nsSVGStylableElement nsSVGTextPathElementBase;
@ -79,6 +83,8 @@ protected:
// nsSVGElement overrides
virtual PRBool IsEventName(nsIAtom* aName);
already_AddRefed<nsISVGTextContentMetrics> GetTextContentMetrics();
nsCOMPtr<nsIDOMSVGAnimatedLength> mStartOffset;
nsCOMPtr<nsIDOMSVGAnimatedEnumeration> mMethod;
nsCOMPtr<nsIDOMSVGAnimatedEnumeration> mSpacing;
@ -237,82 +243,119 @@ NS_IMETHODIMP nsSVGTextPathElement::GetSpacing(nsIDOMSVGAnimatedEnumeration * *a
/* readonly attribute nsIDOMSVGAnimatedLength textLength; */
NS_IMETHODIMP nsSVGTextPathElement::GetTextLength(nsIDOMSVGAnimatedLength * *aTextLength)
{
NS_NOTYETIMPLEMENTED("write me!");
NS_NOTYETIMPLEMENTED("nsSVGTextPathElement::GetTextLength!");
return NS_ERROR_UNEXPECTED;
}
/* readonly attribute nsIDOMSVGAnimatedEnumeration lengthAdjust; */
NS_IMETHODIMP nsSVGTextPathElement::GetLengthAdjust(nsIDOMSVGAnimatedEnumeration * *aLengthAdjust)
{
NS_NOTYETIMPLEMENTED("write me!");
NS_NOTYETIMPLEMENTED("nsSVGTextPathElement::GetLengthAdjust!");
return NS_ERROR_UNEXPECTED;
}
/* long getNumberOfChars (); */
NS_IMETHODIMP nsSVGTextPathElement::GetNumberOfChars(PRInt32 *_retval)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (metrics)
return metrics->GetNumberOfChars(_retval);
*_retval = 0;
return NS_OK;
}
/* float getComputedTextLength (); */
NS_IMETHODIMP nsSVGTextPathElement::GetComputedTextLength(float *_retval)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (metrics)
return metrics->GetComputedTextLength(_retval);
*_retval = 0.0;
return NS_OK;
}
/* float getSubStringLength (in unsigned long charnum, in unsigned long nchars); */
NS_IMETHODIMP nsSVGTextPathElement::GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (metrics)
return metrics->GetSubStringLength(charnum, nchars, _retval);
*_retval = 0.0;
return NS_OK;
}
/* nsIDOMSVGPoint getStartPositionOfChar (in unsigned long charnum); */
NS_IMETHODIMP nsSVGTextPathElement::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_UNEXPECTED;
*_retval = nsnull;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (!metrics) return NS_ERROR_FAILURE;
return metrics->GetStartPositionOfChar(charnum, _retval);
}
/* nsIDOMSVGPoint getEndPositionOfChar (in unsigned long charnum); */
NS_IMETHODIMP nsSVGTextPathElement::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_UNEXPECTED;
*_retval = nsnull;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (!metrics) return NS_ERROR_FAILURE;
return metrics->GetEndPositionOfChar(charnum, _retval);
}
/* nsIDOMSVGRect getExtentOfChar (in unsigned long charnum); */
NS_IMETHODIMP nsSVGTextPathElement::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_UNEXPECTED;
*_retval = nsnull;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (!metrics) return NS_ERROR_FAILURE;
return metrics->GetExtentOfChar(charnum, _retval);
}
/* float getRotationOfChar (in unsigned long charnum); */
NS_IMETHODIMP nsSVGTextPathElement::GetRotationOfChar(PRUint32 charnum, float *_retval)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_UNEXPECTED;
*_retval = 0.0;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (!metrics) return NS_ERROR_FAILURE;
return metrics->GetRotationOfChar(charnum, _retval);
}
/* long getCharNumAtPosition (in nsIDOMSVGPoint point); */
NS_IMETHODIMP nsSVGTextPathElement::GetCharNumAtPosition(nsIDOMSVGPoint *point,
PRInt32 *_retval)
PRInt32 *_retval)
{
// null check when implementing - this method can be used by scripts!
// if (!point)
// return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
if (!point)
return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (metrics)
return metrics->GetCharNumAtPosition(point, _retval);
*_retval = -1;
return NS_OK;
}
/* void selectSubString (in unsigned long charnum, in unsigned long nchars); */
NS_IMETHODIMP nsSVGTextPathElement::SelectSubString(PRUint32 charnum, PRUint32 nchars)
{
NS_NOTYETIMPLEMENTED("write me!");
NS_NOTYETIMPLEMENTED("nsSVGTextPathElement::SelectSubString!");
return NS_ERROR_UNEXPECTED;
}
@ -341,3 +384,32 @@ nsSVGTextPathElement::IsEventName(nsIAtom* aName)
{
return IsGraphicElementEventName(aName);
}
//----------------------------------------------------------------------
// implementation helpers:
already_AddRefed<nsISVGTextContentMetrics>
nsSVGTextPathElement::GetTextContentMetrics()
{
nsIDocument* doc = GetCurrentDoc();
if (!doc) {
NS_ERROR("no document");
return nsnull;
}
nsIPresShell* presShell = doc->GetShellAt(0);
if (!presShell) {
NS_ERROR("no presshell");
return nsnull;
}
nsIFrame* frame = presShell->GetPrimaryFrameFor(this);
if (!frame) {
return nsnull;
}
nsISVGTextContentMetrics* metrics;
CallQueryInterface(frame, &metrics);
return metrics;
}

View File

@ -46,4 +46,11 @@
#define NS_SVGRECT_CONTRACTID \
"@mozilla.org/svg/rect;1"
// {F1950C48-C095-4acd-954A-9A55410E54A3}
#define NS_SVGPOINT_CID \
{ 0xf1950c48, 0xc095, 0x4acd, { 0x95, 0x4a, 0x9a, 0x55, 0x41, 0xe, 0x54, 0xa3 } }
#define NS_SVGPOINT_CONTRACTID \
"@mozilla.org/svg/point;1"
#endif // __NS_SVGTYPECIDS_H__

View File

@ -216,6 +216,7 @@ static void Shutdown();
#include "nsSVGTypeCIDs.h"
#include "nsISVGRenderer.h"
#include "nsSVGRect.h"
#include "nsSVGPoint.h"
#include "nsSVGUtils.h"
#ifdef MOZ_SVG_RENDERER_LIBART
@ -615,6 +616,7 @@ MAKE_CTOR(CreateXMLContentBuilder, nsIXMLContentBuilder, NS_NewXML
#endif
#ifdef MOZ_SVG
MAKE_CTOR(CreateSVGRect, nsIDOMSVGRect, NS_NewSVGRect)
MAKE_CTOR(CreateSVGPoint, nsIDOMSVGPoint, NS_NewSVGPoint)
#endif
NS_GENERIC_FACTORY_CONSTRUCTOR(nsContentHTTPStartup)
MAKE_CTOR(CreateContentDLF, nsIDocumentLoaderFactory, NS_NewContentDocumentLoaderFactory)
@ -1279,6 +1281,10 @@ static const nsModuleComponentInfo gComponents[] = {
NS_SVGRECT_CID,
NS_SVGRECT_CONTRACTID,
CreateSVGRect },
{ "SVG Point",
NS_SVGPOINT_CID,
NS_SVGPOINT_CONTRACTID,
CreateSVGPoint },
#endif
{ "Content HTTP Startup Listener",

View File

@ -297,6 +297,58 @@ nsSVGTSpanFrame::DidModifySVGObservable (nsISVGValue* observable,
//----------------------------------------------------------------------
// nsISVGTextContentMetrics
NS_IMETHODIMP
nsSVGTSpanFrame::GetNumberOfChars(PRInt32 *_retval)
{
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (node)
return nsSVGUtils::GetNumberOfChars(node, _retval);
*_retval = 0;
return NS_OK;
}
NS_IMETHODIMP
nsSVGTSpanFrame::GetComputedTextLength(float *_retval)
{
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
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;
}
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);
}
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);
}
NS_IMETHODIMP
nsSVGTSpanFrame::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
{
@ -305,6 +357,26 @@ nsSVGTSpanFrame::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
return nsSVGUtils::GetExtentOfChar(node, 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);
}
NS_IMETHODIMP
nsSVGTSpanFrame::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
{
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (node)
return nsSVGUtils::GetCharNumAtPosition(node, point, _retval);
*_retval = -1;
return NS_OK;
}
//----------------------------------------------------------------------
// nsISVGChildFrame methods

View File

@ -128,7 +128,14 @@ public:
nsISVGValue::modificationType aModType);
// nsISVGTextContentMetrics
NS_IMETHOD GetNumberOfChars(PRInt32 *_retval);
NS_IMETHOD GetComputedTextLength(float *_retval);
NS_IMETHOD GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval);
NS_IMETHOD GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval);
NS_IMETHOD GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval);
NS_IMETHOD GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval);
NS_IMETHOD GetRotationOfChar(PRUint32 charnum, float *_retval);
NS_IMETHOD GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval);
// nsISupportsWeakReference
// implementation inherited from nsSupportsWeakReference

View File

@ -140,7 +140,14 @@ public:
nsISVGValue::modificationType aModType);
// nsISVGTextContentMetrics
NS_IMETHOD GetNumberOfChars(PRInt32 *_retval);
NS_IMETHOD GetComputedTextLength(float *_retval);
NS_IMETHOD GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval);
NS_IMETHOD GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval);
NS_IMETHOD GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval);
NS_IMETHOD GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval);
NS_IMETHOD GetRotationOfChar(PRUint32 charnum, float *_retval);
NS_IMETHOD GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval);
// nsISupportsWeakReference
// implementation inherited from nsSupportsWeakReference
@ -527,6 +534,68 @@ nsSVGTextFrame::DidModifySVGObservable (nsISVGValue* observable,
//----------------------------------------------------------------------
// nsISVGTextContentMetrics
NS_IMETHODIMP
nsSVGTextFrame::GetNumberOfChars(PRInt32 *_retval)
{
EnsureFragmentTreeUpToDate();
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (node)
return nsSVGUtils::GetNumberOfChars(node, _retval);
*_retval = 0;
return NS_OK;
}
NS_IMETHODIMP
nsSVGTextFrame::GetComputedTextLength(float *_retval)
{
EnsureFragmentTreeUpToDate();
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (node)
return nsSVGUtils::GetComputedTextLength(node, _retval);
*_retval = 0.0;
return NS_OK;
}
NS_IMETHODIMP
nsSVGTextFrame::GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval)
{
EnsureFragmentTreeUpToDate();
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (node)
return nsSVGUtils::GetSubStringLength(node, charnum, nchars, _retval);
*_retval = 0.0;
return NS_OK;
}
NS_IMETHODIMP
nsSVGTextFrame::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
EnsureFragmentTreeUpToDate();
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (!node) return NS_ERROR_DOM_INDEX_SIZE_ERR;
return nsSVGUtils::GetStartPositionOfChar(node, charnum, _retval);
}
NS_IMETHODIMP
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);
}
NS_IMETHODIMP
nsSVGTextFrame::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
{
@ -537,6 +606,29 @@ nsSVGTextFrame::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
return nsSVGUtils::GetExtentOfChar(node, charnum, _retval);
}
NS_IMETHODIMP
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);
}
NS_IMETHODIMP
nsSVGTextFrame::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
{
EnsureFragmentTreeUpToDate();
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (node)
return nsSVGUtils::GetCharNumAtPosition(node, point, _retval);
*_retval = -1;
return NS_OK;
}
//----------------------------------------------------------------------
// nsISVGChildFrame methods

View File

@ -259,6 +259,141 @@ nsSVGUtils::GetBBox(nsFrameList *aFrames, nsIDOMSVGRect **_retval)
return NS_ERROR_FAILURE;
}
nsresult
nsSVGUtils::GetNumberOfChars(nsISVGGlyphFragmentNode* node,
PRInt32 *_retval)
{
PRUint32 nchars = 0;
nsISVGGlyphFragmentLeaf *fragment = node->GetFirstGlyphFragment();
while (fragment) {
nchars += fragment->GetNumberOfChars();
fragment = fragment->GetNextGlyphFragment();
}
*_retval = nchars;
return NS_OK;
}
nsresult
nsSVGUtils::GetComputedTextLength(nsISVGGlyphFragmentNode* node,
float *_retval)
{
float length = 0.0;
nsISVGGlyphFragmentLeaf *fragment = node->GetFirstGlyphFragment();
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();
}
*_retval = length;
return NS_OK;
}
nsresult
nsSVGUtils::GetSubStringLength(nsISVGGlyphFragmentNode* node,
PRUint32 charnum,
PRUint32 nchars,
float *_retval)
{
float length = 0.0;
nsISVGGlyphFragmentLeaf *fragment = node->GetFirstGlyphFragment();
while (fragment && nchars) {
PRUint32 count = fragment->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;
length += fragmentLength;
nchars -= fragmentChars;
if (nchars == 0) break;
}
charnum -= PR_MIN(charnum, count);
fragment = fragment->GetNextGlyphFragment();
}
// substring too long
if (nchars != 0) return NS_ERROR_DOM_INDEX_SIZE_ERR;
*_retval = length;
return NS_OK;
}
nsresult
nsSVGUtils::GetStartPositionOfChar(nsISVGGlyphFragmentNode* node,
PRUint32 charnum,
nsIDOMSVGPoint **_retval)
{
*_retval = nsnull;
nsISVGGlyphFragmentLeaf *fragment = GetGlyphFragmentAtCharNum(node, charnum);
if (!fragment) return NS_ERROR_DOM_INDEX_SIZE_ERR;
// 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;
// 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;
}
nsresult
nsSVGUtils::GetEndPositionOfChar(nsISVGGlyphFragmentNode* node,
PRUint32 charnum,
nsIDOMSVGPoint **_retval)
{
*_retval = nsnull;
nsISVGGlyphFragmentLeaf *fragment = GetGlyphFragmentAtCharNum(node, charnum);
if (!fragment) return NS_ERROR_DOM_INDEX_SIZE_ERR;
// 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;
// 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;
}
nsresult
nsSVGUtils::GetExtentOfChar(nsISVGGlyphFragmentNode* node,
PRUint32 charnum,
@ -272,7 +407,7 @@ nsSVGUtils::GetExtentOfChar(nsISVGGlyphFragmentNode* node,
// query the renderer metrics for the bounds of the character
nsCOMPtr<nsISVGRendererGlyphMetrics> metrics;
fragment->GetGlyphMetrics(getter_AddRefs(metrics));
if (!metrics) return NS_ERROR_DOM_INDEX_SIZE_ERR;
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;
@ -281,12 +416,71 @@ nsSVGUtils::GetExtentOfChar(nsISVGGlyphFragmentNode* node,
float x,y;
(*_retval)->GetX(&x);
(*_retval)->GetY(&y);
(*_retval)->SetX(x+fragment->GetGlyphPositionX());
(*_retval)->SetY(y+fragment->GetGlyphPositionY());
(*_retval)->SetX(x + fragment->GetGlyphPositionX());
(*_retval)->SetY(y + fragment->GetGlyphPositionY());
return NS_OK;
}
nsresult
nsSVGUtils::GetRotationOfChar(nsISVGGlyphFragmentNode* node,
PRUint32 charnum,
float *_retval)
{
nsISVGGlyphFragmentLeaf *fragment = GetGlyphFragmentAtCharNum(node, charnum);
if (!fragment) return NS_ERROR_DOM_INDEX_SIZE_ERR;
// 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();
}
*_retval = index;
return NS_OK;
}
void
nsSVGUtils::FindFilterInvalidation(nsIFrame *aFrame,
nsISVGRendererRegion **aRegion)
@ -418,11 +612,11 @@ nsSVGUtils::GetGlyphFragmentAtCharNum(nsISVGGlyphFragmentNode* node,
{
nsISVGGlyphFragmentLeaf *fragment = node->GetFirstGlyphFragment();
while(fragment) {
while (fragment) {
PRUint32 count = fragment->GetNumberOfChars();
if (count>charnum)
if (count > charnum)
return fragment;
charnum-=count;
charnum -= count;
fragment = fragment->GetNextGlyphFragment();
}

View File

@ -47,6 +47,7 @@ class nsPresContext;
class nsIContent;
class nsStyleCoord;
class nsIDOMSVGRect;
class nsIDOMSVGPoint;
class nsFrameList;
class nsIFrame;
struct nsStyleSVGPaint;
@ -103,6 +104,40 @@ public:
*/
static nsresult GetBBox(nsFrameList *aFrames, nsIDOMSVGRect **_retval);
/*
* Returns the number of characters in a string
*/
static nsresult GetNumberOfChars(nsISVGGlyphFragmentNode* node,
PRInt32 *_retval);
/*
* Determines the length of a string
*/
static nsresult GetComputedTextLength(nsISVGGlyphFragmentNode* node,
float *_retval);
/*
* Determines the length of a substring
*/
static nsresult GetSubStringLength(nsISVGGlyphFragmentNode* node,
PRUint32 charnum,
PRUint32 nchars,
float *_retval);
/*
* Determines the start position of a character
*/
static nsresult GetStartPositionOfChar(nsISVGGlyphFragmentNode* node,
PRUint32 charnum,
nsIDOMSVGPoint **_retval);
/*
* Determines the end position of a character
*/
static nsresult GetEndPositionOfChar(nsISVGGlyphFragmentNode* node,
PRUint32 charnum,
nsIDOMSVGPoint **_retval);
/*
* Determines the bounds of a character
*/
@ -110,6 +145,20 @@ public:
PRUint32 charnum,
nsIDOMSVGRect **_retval);
/*
* Determines the rotation of a character
*/
static nsresult GetRotationOfChar(nsISVGGlyphFragmentNode* node,
PRUint32 charnum,
float *_retval);
/*
* Get the character at the specified position
*/
static nsresult GetCharNumAtPosition(nsISVGGlyphFragmentNode* node,
nsIDOMSVGPoint *point,
PRInt32 *_retval);
/*
* Figures out the worst case invalidation area for a frame, taking
* into account filters. Null return if no filter in the hierarcy.

View File

@ -39,6 +39,7 @@
#include "nsISupports.idl"
interface nsIDOMSVGRect;
interface nsIDOMSVGPoint;
/**
* \addtogroup renderer_interfaces Rendering Engine Interfaces
@ -62,7 +63,7 @@ interface nsIDOMSVGRect;
* nsISVGGlyphMetricsSource::font, nsISVGGlyphMetricsSource::canvasTM, and
* other relevant style such as nsISVGGlyphMetricsSource::strokeWidth.
*/
[scriptable, uuid(2cdc98a4-594f-42a7-970c-e4dcb7a72aa0)]
[scriptable, uuid(f1950c48-c095-4acd-954a-9a55410e54a3)]
interface nsISVGRendererGlyphMetrics : nsISupports
{
/**
@ -70,6 +71,43 @@ interface nsISVGRendererGlyphMetrics : nsISupports
*/
readonly attribute float advance;
/**
* Get the length of a string.
*
* @return The length of the substring in pixel coordinates
*/
float getComputedTextLength();
/**
* Get the length of a substring.
*
* @param charnum The index of the first character in
* nsISVGGlyphMetricsSource::characterData
* @param nchars The number of characters
* @return The length of the substring in pixel coordinates
*/
float getSubStringLength(in unsigned long charnum, in unsigned long nchars);
/**
* Get the untransformed start position of a glyph
*
* @param charnum The index of the character in
* nsISVGGlyphMetricsSource::characterData whose start position
* is to be determined
* @return The start position in pixel coordinates
*/
nsIDOMSVGPoint getStartPositionOfChar(in unsigned long charnum);
/**
* Get the untransformed end position of a glyph
*
* @param charnum The index of the character in
* nsISVGGlyphMetricsSource::characterData whose end position
* is to be determined
* @return The end position in pixel coordinates
*/
nsIDOMSVGPoint getEndPositionOfChar(in unsigned long charnum);
/**
* Get the untransformed bounding box of an individual glyph.
*
@ -80,6 +118,24 @@ interface nsISVGRendererGlyphMetrics : nsISupports
*/
nsIDOMSVGRect getExtentOfChar(in unsigned long charnum);
/**
* Get the untransformed rotation
*
* @param charnum The index of the character in
* nsISVGGlyphMetricsSource::characterData whose rotation
* is to be determined
* @return The rotation
*/
float getRotationOfChar(in unsigned long charnum);
/**
* Get the character at the specified position
*
* @param point The point to check
* @return The rotation
*/
long GetCharNumAtPosition(in nsIDOMSVGPoint point);
/**
* Get the advance of an individual glyph.
*/

View File

@ -47,9 +47,11 @@
#include "nsISVGCairoGlyphMetrics.h"
#include "nsSVGCairoGlyphMetrics.h"
#include "nsIDOMSVGMatrix.h"
#include "nsIDOMSVGPoint.h"
#include "nsIDOMSVGRect.h"
#include "nsSVGTypeCIDs.h"
#include "nsIComponentManager.h"
#include "nsSVGUtils.h"
#include <cairo.h>
extern cairo_surface_t *gSVGCairoDummySurface;
@ -175,47 +177,310 @@ nsSVGCairoGlyphMetrics::GetAdvance(float *aAdvance)
}
/** Implements float getComputedTextLength(in unsigned long charnum, in unsigned long nchars); */
NS_IMETHODIMP
nsSVGCairoGlyphMetrics::GetComputedTextLength(float *_retval)
{
nsAutoString text;
mSource->GetCharacterData(text);
SelectFont(mCT);
cairo_text_extents_t extent;
cairo_text_extents(mCT,
NS_ConvertUTF16toUTF8(text).get(),
&extent);
*_retval = abs(extent.x_advance) + abs(extent.y_advance);
return NS_OK;
}
/** Implements float getSubStringLength(in unsigned long charnum, in unsigned long nchars); */
NS_IMETHODIMP
nsSVGCairoGlyphMetrics::GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval)
{
nsAutoString text;
mSource->GetCharacterData(text);
SelectFont(mCT);
cairo_text_extents_t extent;
cairo_text_extents(mCT,
NS_ConvertUTF16toUTF8(Substring(text, charnum, nchars)).get(),
&extent);
*_retval = abs(extent.x_advance) + abs(extent.y_advance);
return NS_OK;
}
/** Implements nsIDOMSVGRect getStartPositionOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGCairoGlyphMetrics::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
*_retval = nsnull;
nsAutoString text;
mSource->GetCharacterData(text);
nsCOMPtr<nsIDOMSVGPoint> point = do_CreateInstance(NS_SVGPOINT_CONTRACTID);
NS_ASSERTION(point, "could not create point");
if (!point)
return NS_ERROR_FAILURE;
nsSVGCharacterPosition *cp;
if (NS_FAILED(mSource->GetCharacterPosition(&cp)))
return NS_ERROR_FAILURE;
SelectFont(mCT);
if (cp) {
point->SetX(cp[charnum].x);
point->SetY(cp[charnum].y);
delete [] cp;
} else {
if (charnum > 0) {
cairo_text_extents_t extent;
cairo_text_extents(mCT,
NS_ConvertUTF16toUTF8(Substring(text,
0,
charnum)).get(),
&extent);
point->SetX(extent.x_advance);
point->SetY(extent.y_advance);
} else {
point->SetX(0.0);
point->SetY(0.0);
}
}
*_retval = point;
NS_ADDREF(*_retval);
return NS_OK;
}
/** Implements nsIDOMSVGRect getEndPositionOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGCairoGlyphMetrics::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
*_retval = nsnull;
nsAutoString text;
mSource->GetCharacterData(text);
nsCOMPtr<nsIDOMSVGPoint> point = do_CreateInstance(NS_SVGPOINT_CONTRACTID);
NS_ASSERTION(point, "could not create point");
if (!point)
return NS_ERROR_FAILURE;
nsSVGCharacterPosition *cp;
if (NS_FAILED(mSource->GetCharacterPosition(&cp)))
return NS_ERROR_FAILURE;
SelectFont(mCT);
if (cp) {
cairo_text_extents_t extent;
cairo_text_extents(mCT,
NS_ConvertUTF16toUTF8(Substring(text, charnum, 1)).get(),
&extent);
float s = sin(cp[charnum].angle);
float c = cos(cp[charnum].angle);
point->SetX(cp[charnum].x + extent.x_advance * c - extent.y_advance * s);
point->SetY(cp[charnum].y + extent.y_advance * c + extent.x_advance * s);
delete [] cp;
} else {
cairo_text_extents_t extent;
cairo_text_extents(mCT,
NS_ConvertUTF16toUTF8(Substring(text, 0, charnum + 1)).get(),
&extent);
point->SetX(extent.x_advance);
point->SetY(extent.y_advance);
}
*_retval = point;
NS_ADDREF(*_retval);
return NS_OK;
}
/** Implements nsIDOMSVGRect getExtentOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGCairoGlyphMetrics::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
{
*_retval = nsnull;
cairo_text_extents_t preceding_extent, charnum_extent;
nsAutoString text;
mSource->GetCharacterData(text);
SelectFont(mCT);
if (charnum > 0) {
cairo_text_extents(mCT,
NS_ConvertUTF16toUTF8(Substring(text,
0,
charnum)).get(),
&preceding_extent);
} else {
preceding_extent.x_advance = 0.0;
preceding_extent.y_advance = 0.0;
}
cairo_text_extents(mCT,
NS_ConvertUTF16toUTF8(Substring(text, charnum, 1)).get(),
&charnum_extent);
nsCOMPtr<nsIDOMSVGRect> rect = do_CreateInstance(NS_SVGRECT_CONTRACTID);
NS_ASSERTION(rect, "could not create rect");
if (!rect) return NS_ERROR_FAILURE;
if (!rect) {
return NS_ERROR_FAILURE;
}
// add the space taken up by the text which comes before charnum
// to the position of the charnum character
rect->SetX(preceding_extent.x_advance + charnum_extent.x_bearing);
rect->SetY(preceding_extent.y_advance + charnum_extent.y_bearing);
rect->SetWidth(charnum_extent.width);
rect->SetHeight(charnum_extent.height);
nsSVGCharacterPosition *cp;
if (NS_FAILED(mSource->GetCharacterPosition(&cp)))
return NS_ERROR_FAILURE;
SelectFont(mCT);
cairo_text_extents_t extent;
cairo_text_extents(mCT,
NS_ConvertUTF16toUTF8(Substring(text, charnum, 1)).get(),
&extent);
if (cp) {
cairo_matrix_t matrix;
cairo_get_matrix(mCT, &matrix);
cairo_new_path(mCT);
cairo_move_to(mCT, cp[charnum].x, cp[charnum].y);
cairo_rotate(mCT, cp[charnum].angle);
delete [] cp;
cairo_rel_move_to(mCT, extent.x_bearing, extent.y_bearing);
cairo_rel_line_to(mCT, extent.width, 0);
cairo_rel_line_to(mCT, 0, extent.height);
cairo_rel_line_to(mCT, -extent.width, 0);
cairo_close_path(mCT);
double xmin, ymin, xmax, ymax;
cairo_fill_extents(mCT, &xmin, &ymin, &xmax, &ymax);
cairo_user_to_device(mCT, &xmin, &ymin);
cairo_user_to_device(mCT, &xmax, &ymax);
cairo_set_matrix(mCT, &matrix);
rect->SetX(xmin);
rect->SetY(ymin);
rect->SetWidth(xmax - xmin);
rect->SetHeight(ymax - ymin);
} else {
cairo_text_extents_t precedingExtent;
if (charnum > 0) {
cairo_text_extents(mCT,
NS_ConvertUTF16toUTF8(Substring(text,
0,
charnum)).get(),
&precedingExtent);
} else {
precedingExtent.x_advance = 0.0;
precedingExtent.y_advance = 0.0;
}
// add the space taken up by the text which comes before charnum
// to the position of the charnum character
rect->SetX(precedingExtent.x_advance + extent.x_bearing);
rect->SetY(precedingExtent.y_advance + extent.y_bearing);
rect->SetWidth(extent.width);
rect->SetHeight(extent.height);
}
*_retval = rect;
NS_ADDREF(*_retval);
return NS_OK;
}
/** Implements float getRotationOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGCairoGlyphMetrics::GetRotationOfChar(PRUint32 charnum, float *_retval)
{
const double radPerDeg = M_PI/180.0;
nsAutoString text;
mSource->GetCharacterData(text);
nsSVGCharacterPosition *cp;
if (NS_FAILED(mSource->GetCharacterPosition(&cp)))
return NS_ERROR_FAILURE;
if (cp) {
*_retval = cp[charnum].angle / radPerDeg;
delete [] cp;
} else {
*_retval = 0.0;
}
return NS_OK;
}
/** Implements long GetCharNumAtPosition(in nsIDOMSVGPoint point); */
NS_IMETHODIMP
nsSVGCairoGlyphMetrics::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
{
float x,y;
point->GetX(&x);
point->GetY(&y);
nsAutoString text;
mSource->GetCharacterData(text);
nsSVGCharacterPosition *cp;
if (NS_FAILED(mSource->GetCharacterPosition(&cp)))
return NS_ERROR_FAILURE;
for (PRUint32 charnum = 0; charnum < text.Length(); charnum++) {
cairo_matrix_t matrix;
cairo_get_matrix(mCT, &matrix);
cairo_new_path(mCT);
if (cp) {
cairo_move_to(mCT, cp[charnum].x, cp[charnum].y);
cairo_rotate(mCT, cp[charnum].angle);
} else {
if (charnum > 0) {
cairo_text_extents_t extent;
cairo_text_extents(mCT,
NS_ConvertUTF16toUTF8(Substring(text,
0,
charnum)).get(),
&extent);
cairo_move_to(mCT, extent.x_advance, extent.y_advance);
} else {
cairo_move_to(mCT, 0.0, 0.0);
}
}
cairo_text_extents_t extent;
cairo_text_extents(mCT,
NS_ConvertUTF16toUTF8(Substring(text, charnum, 1)).get(),
&extent);
cairo_rel_move_to(mCT, extent.x_bearing, extent.y_bearing);
cairo_rel_line_to(mCT, extent.width, 0);
cairo_rel_line_to(mCT, 0, extent.height);
cairo_rel_line_to(mCT, -extent.width, 0);
cairo_close_path(mCT);
cairo_identity_matrix(mCT);
if (cairo_in_fill(mCT, x, y))
*_retval = charnum;
cairo_set_matrix(mCT, &matrix);
}
delete [] cp;
return NS_OK;
}

View File

@ -56,6 +56,7 @@ using namespace Gdiplus;
#include "float.h"
#include "nsIDOMSVGMatrix.h"
#include "nsIDOMSVGRect.h"
#include "nsIDOMSVGPoint.h"
#include "nsSVGTypeCIDs.h"
#include "nsIComponentManager.h"
#include "nsDataHashtable.h"
@ -302,6 +303,49 @@ nsSVGGDIPlusGlyphMetrics::GetAdvance(float *aAdvance)
return NS_OK;
}
/** Implements float getComputedTextLength(in unsigned long charnum, in unsigned long nchars); */
NS_IMETHODIMP
nsSVGGDIPlusGlyphMetrics::GetComputedTextLength(float *_retval)
{
nsAutoString text;
mSource->GetCharacterData(text);
RectF bounds;
GetSubBoundingRect(0, text.Length(), &bounds);
*_retval = bounds.Width;
return NS_OK;
}
/** Implements float getSubStringLength(in unsigned long charnum, in unsigned long nchars); */
NS_IMETHODIMP
nsSVGGDIPlusGlyphMetrics::GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval)
{
nsAutoString text;
mSource->GetCharacterData(text);
RectF bounds;
GetSubBoundingRect(charnum, nchars, &bounds);
*_retval = bounds.Width;
return NS_OK;
}
/** Implements nsIDOMSVGRect getStartPositionOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGGDIPlusGlyphMetrics::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
*_retval = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements nsIDOMSVGRect getEndPositionOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGGDIPlusGlyphMetrics::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
*_retval = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements nsIDOMSVGRect getExtentOfChar(in unsigned long charnum); */
NS_IMETHODIMP
@ -328,6 +372,22 @@ nsSVGGDIPlusGlyphMetrics::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_ret
return NS_OK;
}
/** Implements float getRotationOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGGDIPlusGlyphMetrics::GetRotationOfChar(PRUint32 charnum, float *_retval)
{
*_retval = 0.0;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements long GetCharNumAtPosition(in nsIDOMSVGPoint point); */
NS_IMETHODIMP
nsSVGGDIPlusGlyphMetrics::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
{
*_retval = -1;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsSVGGDIPlusGlyphMetrics::GetAdvanceOfChar(PRUint32 charnum, float *advance)
{

View File

@ -46,6 +46,7 @@
#include "float.h"
#include "nsIDOMSVGMatrix.h"
#include "nsIDOMSVGRect.h"
#include "nsIDOMSVGPoint.h"
#include "nsSVGTypeCIDs.h"
#include "nsIComponentManager.h"
@ -152,6 +153,38 @@ nsSVGLibartGlyphMetrics::GetAdvanceOfChar(PRUint32 charnum, float *advance)
return NS_OK;
}
/** Implements float getComputedTextLength(in unsigned long charnum, in unsigned long nchars); */
NS_IMETHODIMP
nsSVGLibartGlyphMetrics::GetComputedTextLength(float *_retval)
{
*_retval = 0.0;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements float getSubStringLength(in unsigned long charnum, in unsigned long nchars); */
NS_IMETHODIMP
nsSVGLibartGlyphMetrics::GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval)
{
*_retval = 0.0;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements nsIDOMSVGRect getStartPositionOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGLibartGlyphMetrics::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
*_retval = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements nsIDOMSVGRect getEndPositionOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGLibartGlyphMetrics::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
*_retval = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements [noscript] nsIDOMSVGRect getExtentOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGLibartGlyphMetrics::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
@ -174,6 +207,22 @@ nsSVGLibartGlyphMetrics::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retv
return NS_OK;
}
/** Implements float getRotationOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGLibartGlyphMetrics::GetRotationOfChar(PRUint32 charnum, float *_retval)
{
*_retval = 0.0;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements long GetCharNumAtPosition(in nsIDOMSVGPoint point); */
NS_IMETHODIMP
nsSVGLibartGlyphMetrics::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
{
*_retval = -1;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements boolean update(in unsigned long updatemask); */
NS_IMETHODIMP
nsSVGLibartGlyphMetrics::Update(PRUint32 updatemask, PRBool *_retval)

View File

@ -47,6 +47,7 @@
#include "float.h"
#include "nsIDOMSVGMatrix.h"
#include "nsIDOMSVGRect.h"
#include "nsIDOMSVGPoint.h"
#include "nsSVGTypeCIDs.h"
#include "nsIComponentManager.h"
#include "nsISVGLibartGlyphMetricsFT.h"
@ -221,12 +222,44 @@ nsSVGLibartGlyphMetricsFT::GetAdvance(float *aAdvance)
}
NS_IMETHODIMP
nsSVGLibartGlyphMetrics::GetAdvanceOfChar(PRUint32 charnum, float *advance)
nsSVGLibartGlyphMetricsFT::GetAdvanceOfChar(PRUint32 charnum, float *advance)
{
*advance = 0.0f;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements float getComputedTextLength(in unsigned long charnum, in unsigned long nchars); */
NS_IMETHODIMP
nsSVGLibartGlyphMetricsFT::GetComputedTextLength(float *_retval)
{
*_retval = 0.0;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements float getSubStringLength(in unsigned long charnum, in unsigned long nchars); */
NS_IMETHODIMP
nsSVGLibartGlyphMetricsFT::GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval)
{
*_retval = 0.0;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements nsIDOMSVGRect getStartPositionOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGLibartGlyphMetricsFT::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
*_retval = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements nsIDOMSVGRect getEndPositionOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGLibartGlyphMetricsFT::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
{
*_retval = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements [noscript] nsIDOMSVGRect getExtentOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGLibartGlyphMetricsFT::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
@ -249,6 +282,21 @@ nsSVGLibartGlyphMetricsFT::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_re
return NS_OK;
}
/** Implements float getRotationOfChar(in unsigned long charnum); */
NS_IMETHODIMP
nsSVGLibartGlyphMetricsFT::GetRotationOfChar(PRUint32 charnum, float *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements long GetCharNumAtPosition(in nsIDOMSVGPoint point); */
NS_IMETHODIMP
nsSVGLibartGlyphMetricsFT::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
{
*_retval = -1;
return NS_ERROR_NOT_IMPLEMENTED;
}
/** Implements boolean update(in unsigned long updatemask); */
NS_IMETHODIMP
nsSVGLibartGlyphMetricsFT::Update(PRUint32 updatemask, PRBool *_retval)