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
Родитель a3fe4b5872
Коммит 99da05b854
16 изменённых файлов: 1045 добавлений и 861 удалений

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

@ -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"),
&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;
}