Bug 314627 - implement SVGTSpanElement.getExtentOfChar.

Patch by longsonr@gmail.com, r=tor, sr=jst.
This commit is contained in:
tor%cs.brown.edu 2005-12-02 23:57:47 +00:00
parent 3dd35f343e
commit ea92cde656
8 changed files with 128 additions and 49 deletions

View File

@ -382,12 +382,10 @@ nsSVGPathElement::GetPathFlatten()
nsIFrame* frame = presShell->GetPrimaryFrameFor(this);
if (!frame) {
NS_ERROR("no frame");
return nsnull;
}
nsISVGPathFlatten* flattener;
CallQueryInterface(frame, &flattener);
NS_ASSERTION(flattener, "wrong frame type");
return flattener;
}

View File

@ -44,6 +44,9 @@
#include "nsSVGLengthList.h"
#include "nsISVGSVGElement.h"
#include "nsSVGCoordCtxProvider.h"
#include "nsISVGTextContentMetrics.h"
#include "nsIFrame.h"
#include "nsIDocument.h"
typedef nsSVGGraphicElement nsSVGTSpanElementBase;
@ -80,6 +83,8 @@ public:
protected:
already_AddRefed<nsISVGTextContentMetrics> GetTextContentMetrics();
// nsIDOMSVGTextPositioning properties:
nsCOMPtr<nsIDOMSVGAnimatedLengthList> mX;
nsCOMPtr<nsIDOMSVGAnimatedLengthList> mY;
@ -297,8 +302,12 @@ NS_IMETHODIMP nsSVGTSpanElement::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSV
/* nsIDOMSVGRect getExtentOfChar (in unsigned long charnum); */
NS_IMETHODIMP nsSVGTSpanElement::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
{
NS_NOTYETIMPLEMENTED("nsSVGTSpanElement::GetExtentOfChar");
return NS_ERROR_NOT_IMPLEMENTED;
*_retval = nsnull;
nsCOMPtr<nsISVGTextContentMetrics> metrics = GetTextContentMetrics();
if (!metrics) return NS_ERROR_FAILURE;
return metrics->GetExtentOfChar(charnum, _retval);
}
/* float getRotationOfChar (in unsigned long charnum); */
@ -401,3 +410,32 @@ void nsSVGTSpanElement::ParentChainChanged()
// recurse into child content:
nsSVGTSpanElementBase::ParentChainChanged();
}
//----------------------------------------------------------------------
// implementation helpers:
already_AddRefed<nsISVGTextContentMetrics>
nsSVGTSpanElement::GetTextContentMetrics()
{
nsIDocument* doc = GetCurrentDoc();
if (!doc) {
NS_ERROR("no document");
return nsnull;
}
nsIPresShell* presShell = doc->GetShellAt(0);
if (!presShell) {
NS_ERROR("no presshell");
return nsnull;
}
nsIFrame* frame = presShell->GetPrimaryFrameFor(this);
if (!frame) {
return nsnull;
}
nsISVGTextContentMetrics* metrics;
CallQueryInterface(frame, &metrics);
return metrics;
}

View File

@ -430,12 +430,10 @@ nsSVGTextElement::GetTextContentMetrics()
nsIFrame* frame = presShell->GetPrimaryFrameFor(this);
if (!frame) {
NS_ERROR("no frame");
return nsnull;
}
nsISVGTextContentMetrics* metrics;
CallQueryInterface(frame, &metrics);
NS_ASSERTION(metrics, "wrong frame type");
return metrics;
}

View File

@ -38,6 +38,7 @@
#include "nsSVGTSpanFrame.h"
#include "nsSVGUtils.h"
#include "nsDOMError.h"
//----------------------------------------------------------------------
// Implementation
@ -168,6 +169,7 @@ NS_INTERFACE_MAP_BEGIN(nsSVGTSpanFrame)
NS_INTERFACE_MAP_ENTRY(nsISVGChildFrame)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsISVGValueObserver)
NS_INTERFACE_MAP_ENTRY(nsISVGTextContentMetrics)
NS_INTERFACE_MAP_END_INHERITING(nsSVGTSpanFrameBase)
@ -296,6 +298,17 @@ nsSVGTSpanFrame::DidModifySVGObservable (nsISVGValue* observable,
}
//----------------------------------------------------------------------
// nsISVGTextContentMetrics
NS_IMETHODIMP
nsSVGTSpanFrame::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
{
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (!node) return NS_ERROR_DOM_INDEX_SIZE_ERR;
return nsSVGUtils::GetExtentOfChar(node, charnum, _retval);
}
//----------------------------------------------------------------------
// nsISVGChildFrame methods

View File

@ -59,6 +59,7 @@
#include "nsISVGGlyphFragmentNode.h"
#include "nsIDOMSVGRect.h"
#include "nsISVGOuterSVGFrame.h"
#include "nsISVGTextContentMetrics.h"
#include "nsSVGRect.h"
#include "nsSVGMatrix.h"
#include "nsINameSpaceManager.h"
@ -73,6 +74,7 @@ class nsSVGTSpanFrame : public nsSVGTSpanFrameBase,
public nsISVGChildFrame,
public nsISVGContainerFrame,
public nsISVGValueObserver,
public nsISVGTextContentMetrics,
public nsSupportsWeakReference
{
friend nsIFrame*
@ -127,6 +129,9 @@ public:
NS_IMETHOD DidModifySVGObservable (nsISVGValue* observable,
nsISVGValue::modificationType aModType);
// nsISVGTextContentMetrics
NS_IMETHOD GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval);
// nsISupportsWeakReference
// implementation inherited from nsSupportsWeakReference

View File

@ -68,6 +68,7 @@
#include "nsSVGUtils.h"
#include "nsSVGFilterFrame.h"
#include "nsSVGUtils.h"
#include "nsDOMError.h"
typedef nsContainerFrame nsSVGTextFrameBase;
@ -191,7 +192,6 @@ protected:
already_AddRefed<nsIDOMSVGAnimatedTransformList> GetTransform();
nsISVGGlyphFragmentNode *GetFirstGlyphFragmentChildNode();
nsISVGGlyphFragmentNode *GetNextGlyphFragmentChildNode(nsISVGGlyphFragmentNode*node);
nsISVGGlyphFragmentLeaf *GetGlyphFragmentAtCharNum(PRUint32 charnum);
enum UpdateState{
unsuspended,
@ -533,29 +533,11 @@ nsSVGTextFrame::DidModifySVGObservable (nsISVGValue* observable,
NS_IMETHODIMP
nsSVGTextFrame::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
{
*_retval = nsnull;
EnsureFragmentTreeUpToDate();
nsISVGGlyphFragmentLeaf *fragment = GetGlyphFragmentAtCharNum(charnum);
if (!fragment) return NS_ERROR_FAILURE; // xxx return some index-out-of-range error
// query the renderer metrics for the bounds of the character
nsCOMPtr<nsISVGRendererGlyphMetrics> metrics;
fragment->GetGlyphMetrics(getter_AddRefs(metrics));
if (!metrics) return NS_ERROR_FAILURE;
nsresult rv = metrics->GetExtentOfChar(charnum-fragment->GetCharNumberOffset(),
_retval);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
// offset the bounds by the position of the fragment:
float x,y;
(*_retval)->GetX(&x);
(*_retval)->GetY(&y);
(*_retval)->SetX(x+fragment->GetGlyphPositionX());
(*_retval)->SetY(y+fragment->GetGlyphPositionY());
return NS_OK;
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (!node) return NS_ERROR_DOM_INDEX_SIZE_ERR;
return nsSVGUtils::GetExtentOfChar(node, charnum, _retval);
}
@ -1316,24 +1298,3 @@ nsSVGTextFrame::GetNextGlyphFragmentChildNode(nsISVGGlyphFragmentNode*node)
return retval;
}
nsISVGGlyphFragmentLeaf *
nsSVGTextFrame::GetGlyphFragmentAtCharNum(PRUint32 charnum)
{
nsISVGGlyphFragmentLeaf *fragment = nsnull;
{
nsISVGGlyphFragmentNode* node = GetFirstGlyphFragmentChildNode();
if (!node) return nsnull;
fragment = node->GetFirstGlyphFragment();
}
while(fragment) {
PRUint32 count = fragment->GetNumberOfChars();
if (count>charnum)
return fragment;
charnum-=count;
fragment = fragment->GetNextGlyphFragment();
}
// not found
return nsnull;
}

View File

@ -49,6 +49,8 @@
#include "nsIPresShell.h"
#include "nsSVGUtils.h"
#include "nsISVGGeometrySource.h"
#include "nsISVGGlyphFragmentLeaf.h"
#include "nsISVGRendererGlyphMetrics.h"
#include "nsNetUtil.h"
#include "nsIDOMSVGRect.h"
#include "nsFrameList.h"
@ -61,6 +63,7 @@
#include "nsISVGChildFrame.h"
#include "nsIDOMSVGPoint.h"
#include "nsSVGPoint.h"
#include "nsDOMError.h"
#if defined(MOZ_SVG_RENDERER_GDIPLUS)
#include <windows.h>
@ -253,6 +256,34 @@ nsSVGUtils::GetBBox(nsFrameList *aFrames, nsIDOMSVGRect **_retval)
return NS_ERROR_FAILURE;
}
nsresult
nsSVGUtils::GetExtentOfChar(nsISVGGlyphFragmentNode* node,
PRUint32 charnum,
nsIDOMSVGRect **_retval)
{
*_retval = nsnull;
nsISVGGlyphFragmentLeaf *fragment = GetGlyphFragmentAtCharNum(node, charnum);
if (!fragment) return NS_ERROR_DOM_INDEX_SIZE_ERR;
// 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;
nsresult rv = metrics->GetExtentOfChar(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;
}
void
nsSVGUtils::FindFilterInvalidation(nsIFrame *aFrame,
nsISVGRendererRegion **aRegion)
@ -361,3 +392,21 @@ nsSVGUtils::TransformPoint(nsIDOMSVGMatrix *matrix,
xfpoint->GetX(x);
xfpoint->GetY(y);
}
nsISVGGlyphFragmentLeaf *
nsSVGUtils::GetGlyphFragmentAtCharNum(nsISVGGlyphFragmentNode* node,
PRUint32 charnum)
{
nsISVGGlyphFragmentLeaf *fragment = node->GetFirstGlyphFragment();
while(fragment) {
PRUint32 count = fragment->GetNumberOfChars();
if (count>charnum)
return fragment;
charnum-=count;
fragment = fragment->GetNextGlyphFragment();
}
// not found
return nsnull;
}

View File

@ -48,6 +48,8 @@ class nsFrameList;
class nsIFrame;
struct nsStyleSVGPaint;
class nsISVGRendererRegion;
class nsISVGGlyphFragmentLeaf;
class nsISVGGlyphFragmentNode;
class nsIDOMSVGLength;
class nsIDOMSVGMatrix;
class nsIURI;
@ -86,6 +88,13 @@ public:
*/
static nsresult GetBBox(nsFrameList *aFrames, nsIDOMSVGRect **_retval);
/*
* Determines the bounds of a character
*/
static nsresult GetExtentOfChar(nsISVGGlyphFragmentNode* node,
PRUint32 charnum,
nsIDOMSVGRect **_retval);
/*
* Figures out the worst case invalidation area for a frame, taking
* into account filters. Null return if no filter in the hierarcy.
@ -118,6 +127,14 @@ public:
static void
TransformPoint(nsIDOMSVGMatrix *matrix,
float *x, float *y);
private:
/*
* Returns the glyph fragment containing a particular character
*/
static nsISVGGlyphFragmentLeaf *
GetGlyphFragmentAtCharNum(nsISVGGlyphFragmentNode* node,
PRUint32 charnum);
};
#endif