mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Bug 314627 - implement SVGTSpanElement.getExtentOfChar.
Patch by longsonr@gmail.com, r=tor, sr=jst.
This commit is contained in:
parent
3dd35f343e
commit
ea92cde656
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user