зеркало из https://github.com/mozilla/pjs.git
Bug 318597 - Implement various text, tspan and textPath DOM functions.
Patch by longsonr@gmail.com, r=tor, sr=jst
This commit is contained in:
Родитель
a3fe4b5872
Коммит
99da05b854
|
@ -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__
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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); */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Mozilla SVG project.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Crocodile Clips Ltd..
|
||||
* Portions created by the Initial Developer are Copyright (C) 2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NS_SVGTYPECIDS_H__
|
||||
#define __NS_SVGTYPECIDS_H__
|
||||
|
||||
// {AAD39B18-B9D3-45E1-B5A6-80C0EB12B23E}
|
||||
#define NS_SVGRECT_CID \
|
||||
{ 0xaad39b18, 0xb9d3, 0x45e1, { 0xb5, 0xa6, 0x80, 0xc0, 0xeb, 0x12, 0xb2, 0x3e } }
|
||||
|
||||
#define NS_SVGRECT_CONTRACTID \
|
||||
"@mozilla.org/svg/rect;1"
|
||||
|
||||
#endif // __NS_SVGTYPECIDS_H__
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -1,184 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Mozilla SVG project.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Crocodile Clips Ltd..
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Alex Fritze <alex.fritze@crocodile-clips.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsISVGGlyphMetricsSource.h"
|
||||
#include "nsISVGRendererGlyphMetrics.h"
|
||||
#include "nsPromiseFlatString.h"
|
||||
#include "nsFont.h"
|
||||
#include "nsIFontMetrics.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "float.h"
|
||||
#include "nsIDOMSVGMatrix.h"
|
||||
#include "nsIDOMSVGRect.h"
|
||||
#include "nsSVGTypeCIDs.h"
|
||||
#include "nsIComponentManager.h"
|
||||
|
||||
/**
|
||||
* \addtogroup libart_renderer Libart Rendering Engine
|
||||
* @{
|
||||
*/
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Default Libart glyph metrics implementation.
|
||||
*/
|
||||
class nsSVGLibartGlyphMetrics : public nsISVGRendererGlyphMetrics
|
||||
{
|
||||
protected:
|
||||
friend nsresult NS_NewSVGLibartGlyphMetricsDefault(nsISVGRendererGlyphMetrics **result,
|
||||
nsISVGGlyphMetricsSource *src);
|
||||
|
||||
nsSVGLibartGlyphMetrics(nsISVGGlyphMetricsSource *src);
|
||||
~nsSVGLibartGlyphMetrics();
|
||||
public:
|
||||
// nsISupports interface:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsISVGRendererGlyphMetrics interface:
|
||||
NS_DECL_NSISVGRENDERERGLYPHMETRICS
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// implementation:
|
||||
|
||||
nsSVGLibartGlyphMetrics::nsSVGLibartGlyphMetrics(nsISVGGlyphMetricsSource *src)
|
||||
{
|
||||
}
|
||||
|
||||
nsSVGLibartGlyphMetrics::~nsSVGLibartGlyphMetrics()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewSVGLibartGlyphMetricsDefault(nsISVGRendererGlyphMetrics **result,
|
||||
nsISVGGlyphMetricsSource *src)
|
||||
{
|
||||
*result = new nsSVGLibartGlyphMetrics(src);
|
||||
if (!*result) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsISupports methods:
|
||||
|
||||
NS_IMPL_ADDREF(nsSVGLibartGlyphMetrics)
|
||||
NS_IMPL_RELEASE(nsSVGLibartGlyphMetrics)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsSVGLibartGlyphMetrics)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISVGRendererGlyphMetrics)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsISVGRendererGlyphMetrics methods:
|
||||
|
||||
/** Implements float getBaselineOffset(in unsigned short baselineIdentifier); */
|
||||
NS_IMETHODIMP
|
||||
nsSVGLibartGlyphMetrics::GetBaselineOffset(PRUint16 baselineIdentifier, float *_retval)
|
||||
{
|
||||
*_retval = 0.0f;
|
||||
|
||||
switch (baselineIdentifier) {
|
||||
case BASELINE_TEXT_BEFORE_EDGE:
|
||||
break;
|
||||
case BASELINE_TEXT_AFTER_EDGE:
|
||||
break;
|
||||
case BASELINE_CENTRAL:
|
||||
case BASELINE_MIDDLE:
|
||||
break;
|
||||
case BASELINE_ALPHABETIC:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/** Implements readonly attribute float #advance; */
|
||||
NS_IMETHODIMP
|
||||
nsSVGLibartGlyphMetrics::GetAdvance(float *aAdvance)
|
||||
{
|
||||
*aAdvance = 0.0f;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGLibartGlyphMetrics::GetAdvanceOfChar(PRUint32 charnum, float *advance)
|
||||
{
|
||||
*advance = 0.0f;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** Implements [noscript] nsIDOMSVGRect getExtentOfChar(in unsigned long charnum); */
|
||||
NS_IMETHODIMP
|
||||
nsSVGLibartGlyphMetrics::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
|
||||
{
|
||||
*_retval = nsnull;
|
||||
|
||||
nsCOMPtr<nsIDOMSVGRect> rect = do_CreateInstance(NS_SVGRECT_CONTRACTID);
|
||||
|
||||
NS_ASSERTION(rect, "could not create rect");
|
||||
if (!rect) return NS_ERROR_FAILURE;
|
||||
|
||||
rect->SetX(0);
|
||||
rect->SetY(0);
|
||||
rect->SetWidth(0);
|
||||
rect->SetHeight(0);
|
||||
|
||||
*_retval = rect;
|
||||
NS_ADDREF(*_retval);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** Implements boolean update(in unsigned long updatemask); */
|
||||
NS_IMETHODIMP
|
||||
nsSVGLibartGlyphMetrics::Update(PRUint32 updatemask, PRBool *_retval)
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
@ -1,528 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Mozilla SVG project.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Leon Sha <leon.sha@sun.com>
|
||||
* Alex Fritze <alex@croczilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsISVGGlyphMetricsSource.h"
|
||||
#include "nsISVGRendererGlyphMetrics.h"
|
||||
#include "nsPromiseFlatString.h"
|
||||
#include "nsFont.h"
|
||||
#include "nsIFontMetrics.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "float.h"
|
||||
#include "nsIDOMSVGMatrix.h"
|
||||
#include "nsIDOMSVGRect.h"
|
||||
#include "nsSVGTypeCIDs.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsISVGLibartGlyphMetricsFT.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
#include "nsSVGLibartFreetype.h"
|
||||
#include "libart-incs.h"
|
||||
#include "nsArray.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
/**
|
||||
* \addtogroup libart_renderer Libart Rendering Engine
|
||||
* @{
|
||||
*/
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Libart freetype-based glyph metrics implementation.
|
||||
* Conditionally compiled in for freetype-enabled builds only.
|
||||
*/
|
||||
class nsSVGLibartGlyphMetricsFT : public nsISVGLibartGlyphMetricsFT
|
||||
{
|
||||
protected:
|
||||
friend nsresult NS_NewSVGLibartGlyphMetricsFT(nsISVGRendererGlyphMetrics **result,
|
||||
nsISVGGlyphMetricsSource *src);
|
||||
friend void NS_InitSVGLibartGlyphMetricsFTGlobals();
|
||||
friend void NS_FreeSVGLibartGlyphMetricsFTGlobals();
|
||||
|
||||
nsSVGLibartGlyphMetricsFT(nsISVGGlyphMetricsSource *src);
|
||||
~nsSVGLibartGlyphMetricsFT();
|
||||
|
||||
// nsISupports interface:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsISVGRendererGlyphMetrics interface:
|
||||
NS_DECL_NSISVGRENDERERGLYPHMETRICS
|
||||
|
||||
// nsISVGLibartGlyphMetrics interface:
|
||||
NS_IMETHOD_(FT_Face) GetFTFace();
|
||||
NS_IMETHOD_(float) GetPixelScale();
|
||||
NS_IMETHOD_(float) GetTwipsToPixels();
|
||||
NS_IMETHOD_(const FT_BBox*) GetBoundingBox();
|
||||
NS_IMETHOD_(PRUint32) GetGlyphCount();
|
||||
NS_IMETHOD_(FT_Glyph) GetGlyphAt(PRUint32 pos);
|
||||
|
||||
// helpers :
|
||||
void InitializeFace();
|
||||
void ClearFace() { mFace = nsnull; }
|
||||
void InitializeGlyphArray();
|
||||
void ClearGlyphArray();
|
||||
private:
|
||||
FT_Face mFace;
|
||||
|
||||
struct GlyphDescriptor {
|
||||
GlyphDescriptor() : index(0), image(nsnull) {};
|
||||
~GlyphDescriptor() { if (image) nsSVGLibartFreetype::ft2->DoneGlyph(image); }
|
||||
FT_UInt index; // glyph index
|
||||
FT_Glyph image; // glyph image translated to correct position within string
|
||||
};
|
||||
|
||||
GlyphDescriptor *mGlyphArray;
|
||||
PRUint32 mGlyphArrayLength;
|
||||
FT_BBox mBBox;
|
||||
|
||||
nsCOMPtr<nsISVGGlyphMetricsSource> mSource;
|
||||
|
||||
public:
|
||||
static nsDataHashtable<nsStringHashKey,const nsString*> sFontAliases;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsSVGLibartGlyphMetricsFT implementation:
|
||||
|
||||
nsDataHashtable<nsStringHashKey,const nsString*>
|
||||
nsSVGLibartGlyphMetricsFT::sFontAliases;
|
||||
|
||||
|
||||
nsSVGLibartGlyphMetricsFT::nsSVGLibartGlyphMetricsFT(nsISVGGlyphMetricsSource *src)
|
||||
: mSource(src), mFace(nsnull), mGlyphArray(nsnull), mGlyphArrayLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
nsSVGLibartGlyphMetricsFT::~nsSVGLibartGlyphMetricsFT()
|
||||
{
|
||||
ClearGlyphArray();
|
||||
ClearFace();
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewSVGLibartGlyphMetricsFT(nsISVGRendererGlyphMetrics **result,
|
||||
nsISVGGlyphMetricsSource *src)
|
||||
{
|
||||
*result = new nsSVGLibartGlyphMetricsFT(src);
|
||||
if (!*result) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void NS_InitSVGLibartGlyphMetricsFTGlobals()
|
||||
{
|
||||
|
||||
NS_ASSERTION(!nsSVGLibartGlyphMetricsFT::sFontAliases.IsInitialized(),
|
||||
"font aliases already initialized");
|
||||
nsSVGLibartGlyphMetricsFT::sFontAliases.Init(3);
|
||||
|
||||
static NS_NAMED_LITERAL_STRING(arial, "arial");
|
||||
nsSVGLibartGlyphMetricsFT::sFontAliases.Put(NS_LITERAL_STRING("helvetica"),
|
||||
&arial);
|
||||
|
||||
static NS_NAMED_LITERAL_STRING(courier, "courier new");
|
||||
nsSVGLibartGlyphMetricsFT::sFontAliases.Put(NS_LITERAL_STRING("courier"),
|
||||
&courier);
|
||||
|
||||
static NS_NAMED_LITERAL_STRING(times, "times new roman");
|
||||
nsSVGLibartGlyphMetricsFT::sFontAliases.Put(NS_LITERAL_STRING("times"),
|
||||
×);
|
||||
}
|
||||
|
||||
void NS_FreeSVGLibartGlyphMetricsFTGlobals()
|
||||
{
|
||||
NS_ASSERTION(nsSVGLibartGlyphMetricsFT::sFontAliases.IsInitialized(),
|
||||
"font aliases never initialized");
|
||||
nsSVGLibartGlyphMetricsFT::sFontAliases.Clear();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsISupports methods:
|
||||
|
||||
NS_IMPL_ADDREF(nsSVGLibartGlyphMetricsFT)
|
||||
NS_IMPL_RELEASE(nsSVGLibartGlyphMetricsFT)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsSVGLibartGlyphMetricsFT)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISVGRendererGlyphMetrics)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISVGLibartGlyphMetricsFT)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsISVGRendererGlyphMetrics methods:
|
||||
|
||||
/** Implements float getBaselineOffset(in unsigned short baselineIdentifier); */
|
||||
NS_IMETHODIMP
|
||||
nsSVGLibartGlyphMetricsFT::GetBaselineOffset(PRUint16 baselineIdentifier, float *_retval)
|
||||
{
|
||||
*_retval = 0.0f;
|
||||
|
||||
switch (baselineIdentifier) {
|
||||
case BASELINE_TEXT_BEFORE_EDGE:
|
||||
break;
|
||||
case BASELINE_TEXT_AFTER_EDGE:
|
||||
break;
|
||||
case BASELINE_CENTRAL:
|
||||
case BASELINE_MIDDLE:
|
||||
break;
|
||||
case BASELINE_ALPHABETIC:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/** Implements readonly attribute float #advance; */
|
||||
NS_IMETHODIMP
|
||||
nsSVGLibartGlyphMetricsFT::GetAdvance(float *aAdvance)
|
||||
{
|
||||
InitializeGlyphArray();
|
||||
*aAdvance = mBBox.xMax-mBBox.yMin;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGLibartGlyphMetrics::GetAdvanceOfChar(PRUint32 charnum, float *advance)
|
||||
{
|
||||
*advance = 0.0f;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/** Implements [noscript] nsIDOMSVGRect getExtentOfChar(in unsigned long charnum); */
|
||||
NS_IMETHODIMP
|
||||
nsSVGLibartGlyphMetricsFT::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
|
||||
{
|
||||
*_retval = nsnull;
|
||||
|
||||
nsCOMPtr<nsIDOMSVGRect> rect = do_CreateInstance(NS_SVGRECT_CONTRACTID);
|
||||
|
||||
NS_ASSERTION(rect, "could not create rect");
|
||||
if (!rect) return NS_ERROR_FAILURE;
|
||||
|
||||
rect->SetX(0);
|
||||
rect->SetY(0);
|
||||
rect->SetWidth(0);
|
||||
rect->SetHeight(0);
|
||||
|
||||
*_retval = rect;
|
||||
NS_ADDREF(*_retval);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** Implements boolean update(in unsigned long updatemask); */
|
||||
NS_IMETHODIMP
|
||||
nsSVGLibartGlyphMetricsFT::Update(PRUint32 updatemask, PRBool *_retval)
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsISVGLibartGlyphMetrics methods:
|
||||
|
||||
NS_IMETHODIMP_(FT_Face)
|
||||
nsSVGLibartGlyphMetricsFT::GetFTFace()
|
||||
{
|
||||
InitializeFace();
|
||||
return mFace;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(float)
|
||||
nsSVGLibartGlyphMetricsFT::GetPixelScale()
|
||||
{
|
||||
nsCOMPtr<nsPresContext> presContext;
|
||||
mSource->GetPresContext(getter_AddRefs(presContext));
|
||||
if (!presContext) {
|
||||
NS_ERROR("null prescontext");
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
nsIDeviceContext* devicecontext = presContext->DeviceContext();
|
||||
|
||||
float scale;
|
||||
devicecontext->GetCanonicalPixelScale(scale);
|
||||
return scale;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(float)
|
||||
nsSVGLibartGlyphMetricsFT::GetTwipsToPixels()
|
||||
{
|
||||
nsCOMPtr<nsPresContext> presContext;
|
||||
mSource->GetPresContext(getter_AddRefs(presContext));
|
||||
if (!presContext) {
|
||||
NS_ERROR("null prescontext");
|
||||
return 1.0f;
|
||||
}
|
||||
float twipstopixel;
|
||||
twipstopixel = presContext->TwipsToPixels();
|
||||
return twipstopixel;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(const FT_BBox*)
|
||||
nsSVGLibartGlyphMetricsFT::GetBoundingBox()
|
||||
{
|
||||
InitializeGlyphArray();
|
||||
return &mBBox;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(PRUint32)
|
||||
nsSVGLibartGlyphMetricsFT::GetGlyphCount()
|
||||
{
|
||||
InitializeGlyphArray();
|
||||
return mGlyphArrayLength;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(FT_Glyph)
|
||||
nsSVGLibartGlyphMetricsFT::GetGlyphAt(PRUint32 pos)
|
||||
{
|
||||
NS_ASSERTION(pos<mGlyphArrayLength, "out of range");
|
||||
return mGlyphArray[pos].image;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation helpers:
|
||||
|
||||
|
||||
struct FindFontStruct {
|
||||
nsCOMPtr<nsITrueTypeFontCatalogEntry> font_entry;
|
||||
nsFont font;
|
||||
};
|
||||
|
||||
static PRBool
|
||||
FindFont(const nsString& aFamily, PRBool aGeneric, void *aData)
|
||||
{
|
||||
PRBool retval = PR_TRUE;
|
||||
|
||||
FindFontStruct* font_data = (FindFontStruct*) aData;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("trying to instantiate font %s, generic=%d\n", NS_ConvertUTF16toUTF8(aFamily).get(),
|
||||
aGeneric);
|
||||
#endif
|
||||
|
||||
nsCAutoString family_name;
|
||||
|
||||
if (aGeneric) {
|
||||
PRUint8 id;
|
||||
nsFont::GetGenericID(aFamily, &id);
|
||||
switch (id) {
|
||||
case kGenericFont_serif:
|
||||
family_name.AssignLiteral("times new roman");
|
||||
break;
|
||||
case kGenericFont_monospace:
|
||||
family_name.AssignLiteral("courier new");
|
||||
break;
|
||||
case kGenericFont_sans_serif:
|
||||
default:
|
||||
family_name.AssignLiteral("arial");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
family_name = NS_ConvertUTF16toUTF8(aFamily);
|
||||
ToLowerCase(family_name);
|
||||
}
|
||||
|
||||
nsCAutoString language;
|
||||
PRUint16 slant = nsIFontCatalogService::kFCSlantRoman;
|
||||
if (font_data->font.style && NS_FONT_STYLE_ITALIC)
|
||||
slant = nsIFontCatalogService::kFCSlantItalic;
|
||||
|
||||
nsCOMPtr<nsIArray> arr;
|
||||
nsSVGLibartFreetype::fontCatalog->GetFontCatalogEntries(family_name,
|
||||
language,
|
||||
font_data->font.weight,
|
||||
nsIFontCatalogService::kFCWeightAny,
|
||||
slant,
|
||||
nsIFontCatalogService::kFCSpacingAny,
|
||||
getter_AddRefs(arr));
|
||||
PRUint32 count;
|
||||
arr->GetLength(&count);
|
||||
#ifdef DEBUG
|
||||
printf("FindFont(%s): number of fonts found: %d\n", family_name.get(), count);
|
||||
#endif
|
||||
if (count>0) {
|
||||
retval = PR_FALSE; // break
|
||||
// just take the first one for now:
|
||||
arr->QueryElementAt(0, NS_GET_IID(nsITrueTypeFontCatalogEntry),
|
||||
getter_AddRefs(font_data->font_entry));
|
||||
}
|
||||
else {
|
||||
// try alias if there is one:
|
||||
const nsString *alias = nsnull;
|
||||
nsSVGLibartGlyphMetricsFT::sFontAliases.Get(NS_ConvertUTF8toUTF16(family_name),
|
||||
&alias);
|
||||
if (alias) {
|
||||
// XXX this might cause a stack-overflow if there are cyclic
|
||||
// aliases in sFontAliases
|
||||
retval = FindFont(*alias, PR_FALSE, aData);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGLibartGlyphMetricsFT::InitializeFace()
|
||||
{
|
||||
if (mFace) return; // already initialized
|
||||
|
||||
FindFontStruct font_data;
|
||||
mSource->GetFont(&font_data.font);
|
||||
|
||||
font_data.font.EnumerateFamilies(FindFont, (void*)&font_data);
|
||||
|
||||
if (!font_data.font_entry) {
|
||||
// try to find *any* font
|
||||
FindFont(EmptyString(), PR_FALSE, (void*)&font_data);
|
||||
}
|
||||
|
||||
if (!font_data.font_entry) {
|
||||
NS_ERROR("svg libart renderer can't find a font (let alone a suitable one)");
|
||||
return;
|
||||
}
|
||||
|
||||
FTC_Image_Desc imageDesc;
|
||||
imageDesc.font.face_id=(void*)font_data.font_entry.get(); // XXX do we need to addref?
|
||||
float twipstopixel = GetTwipsToPixels();
|
||||
float scale = GetPixelScale();
|
||||
imageDesc.font.pix_width = (int)((float)(font_data.font.size)*twipstopixel/scale);
|
||||
imageDesc.font.pix_height = (int)((float)(font_data.font.size)*twipstopixel/scale);
|
||||
imageDesc.image_type |= ftc_image_grays;
|
||||
|
||||
// get the face
|
||||
nsresult rv;
|
||||
FTC_Manager mgr;
|
||||
nsSVGLibartFreetype::ft2->GetFTCacheManager(&mgr);
|
||||
rv = nsSVGLibartFreetype::ft2->ManagerLookupSize(mgr, &imageDesc.font, &mFace, nsnull);
|
||||
NS_ASSERTION(mFace, "failed to get face/size");
|
||||
}
|
||||
|
||||
void nsSVGLibartGlyphMetricsFT::InitializeGlyphArray()
|
||||
{
|
||||
if (mGlyphArray) return; // already initialized
|
||||
|
||||
InitializeFace();
|
||||
if (!mFace) {
|
||||
NS_ERROR("no face");
|
||||
return;
|
||||
}
|
||||
FT_GlyphSlot glyphslot=mFace->glyph;
|
||||
|
||||
mBBox.xMin = mBBox.yMin = 3200;
|
||||
mBBox.xMax = mBBox.yMax = -3200;
|
||||
|
||||
nsAutoString text;
|
||||
mSource->GetCharacterData(text);
|
||||
mGlyphArrayLength = text.Length();
|
||||
if (mGlyphArrayLength == 0) return;
|
||||
|
||||
mGlyphArray = new GlyphDescriptor[mGlyphArrayLength];
|
||||
NS_ASSERTION(mGlyphArray, "could not allocate glyph descriptor array");
|
||||
|
||||
GlyphDescriptor* glyph = mGlyphArray;
|
||||
bool use_kerning = FT_HAS_KERNING(mFace);
|
||||
FT_UInt previous_glyph = 0;
|
||||
FT_Vector pen; // pen position in 26.6 format
|
||||
pen.x = 0;
|
||||
pen.y = 0;
|
||||
|
||||
nsAString::const_iterator start, end;
|
||||
text.BeginReading(start);
|
||||
text.EndReading(end);
|
||||
PRUint32 size;
|
||||
|
||||
for ( ; start!=end; start.advance(size)) {
|
||||
const PRUnichar* buf = start.get();
|
||||
size = start.size_forward();
|
||||
// fragment at 'buf' is 'size' characters long
|
||||
for (PRUint32 i=0; i<size; ++i) {
|
||||
nsSVGLibartFreetype::ft2->GetCharIndex(mFace, buf[i], &glyph->index);
|
||||
|
||||
if (use_kerning && previous_glyph && glyph->index) {
|
||||
FT_Vector delta;
|
||||
nsSVGLibartFreetype::ft2->GetKerning(mFace, previous_glyph,
|
||||
glyph->index,
|
||||
FT_KERNING_DEFAULT,
|
||||
&delta);
|
||||
pen.x += delta.x;
|
||||
}
|
||||
|
||||
// load glyph into the face's shared glyph slot:
|
||||
if (NS_FAILED(nsSVGLibartFreetype::ft2->LoadGlyph(mFace,
|
||||
glyph->index,
|
||||
FT_LOAD_DEFAULT))) {
|
||||
NS_ERROR("error loading glyph");
|
||||
continue;
|
||||
}
|
||||
|
||||
// copy glyph image into array:
|
||||
if (NS_FAILED(nsSVGLibartFreetype::ft2->GetGlyph(glyphslot, &glyph->image))) {
|
||||
NS_ERROR("error copying glyph");
|
||||
continue;
|
||||
}
|
||||
|
||||
// translate glyph image to correct location within string:
|
||||
nsSVGLibartFreetype::ft2->GlyphTransform(glyph->image, 0, &pen);
|
||||
|
||||
// update the string's bounding box:
|
||||
FT_BBox glyph_bbox;
|
||||
nsSVGLibartFreetype::ft2->GlyphGetCBox(glyph->image, ft_glyph_bbox_pixels, &glyph_bbox);
|
||||
mBBox.xMin = PR_MIN(mBBox.xMin, glyph_bbox.xMin);
|
||||
mBBox.xMax = PR_MAX(mBBox.xMax, glyph_bbox.xMax);
|
||||
mBBox.yMin = PR_MIN(mBBox.yMin, glyph_bbox.yMin);
|
||||
mBBox.yMax = PR_MAX(mBBox.yMax, glyph_bbox.yMax);
|
||||
|
||||
pen.x += glyphslot->advance.x;
|
||||
previous_glyph = glyph->index;
|
||||
++glyph;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsSVGLibartGlyphMetricsFT::ClearGlyphArray()
|
||||
{
|
||||
if (mGlyphArray)
|
||||
delete[] mGlyphArray;
|
||||
mGlyphArray = nsnull;
|
||||
}
|
Загрузка…
Ссылка в новой задаче