Bug 406312 - textPath startOffset does not react to DOM changes. r=tor,sr=roc,a1.9=tor

This commit is contained in:
longsonr@gmail.com 2007-12-03 22:51:36 -08:00
parent 90cc1d86f5
commit a48b04f245
6 changed files with 155 additions and 137 deletions

View File

@ -71,6 +71,7 @@ class nsSVGPathElement : public nsSVGPathElementBase,
public nsIDOMSVGAnimatedPathData
{
friend class nsSVGPathFrame;
friend class nsSVGTextPathFrame;
protected:
friend nsresult NS_NewSVGPathElement(nsIContent **aResult,

View File

@ -41,63 +41,9 @@
#include "nsIDOMSVGURIReference.h"
#include "nsISVGTextContentMetrics.h"
#include "nsIFrame.h"
#include "nsSVGTextPathElement.h"
#include "nsSVGAnimatedString.h"
#include "nsSVGEnum.h"
#include "nsDOMError.h"
#include "nsSVGLength2.h"
typedef nsSVGStylableElement nsSVGTextPathElementBase;
class nsSVGTextPathElement : public nsSVGTextPathElementBase,
public nsIDOMSVGTextPathElement,
public nsIDOMSVGURIReference
{
protected:
friend nsresult NS_NewSVGTextPathElement(nsIContent **aResult,
nsINodeInfo *aNodeInfo);
nsSVGTextPathElement(nsINodeInfo* aNodeInfo);
nsresult Init();
public:
// interfaces:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMSVGTEXTPATHELEMENT
NS_DECL_NSIDOMSVGTEXTCONTENTELEMENT
NS_DECL_NSIDOMSVGURIREFERENCE
// xxx If xpcom allowed virtual inheritance we wouldn't need to
// forward here :-(
NS_FORWARD_NSIDOMNODE(nsSVGTextPathElementBase::)
NS_FORWARD_NSIDOMELEMENT(nsSVGTextPathElementBase::)
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGTextPathElementBase::)
// nsIContent interface
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
protected:
virtual LengthAttributesInfo GetLengthInfo();
virtual EnumAttributesInfo GetEnumInfo();
virtual PRBool IsEventName(nsIAtom* aName);
already_AddRefed<nsISVGTextContentMetrics> GetTextContentMetrics();
enum { STARTOFFSET };
nsSVGLength2 mLengthAttributes[1];
static LengthInfo sLengthInfo[1];
enum { METHOD, SPACING };
nsSVGEnum mEnumAttributes[2];
static nsSVGEnumMapping sMethodMap[];
static nsSVGEnumMapping sSpacingMap[];
static EnumInfo sEnumInfo[2];
nsCOMPtr<nsIDOMSVGAnimatedString> mHref;
};
nsSVGElement::LengthInfo nsSVGTextPathElement::sLengthInfo[1] =
{

View File

@ -0,0 +1,99 @@
/* -*- 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 IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2005
* 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_SVGTEXTPATHELEMENT_H__
#define __NS_SVGTEXTPATHELEMENT_H__
#include "nsSVGEnum.h"
#include "nsSVGLength2.h"
typedef nsSVGStylableElement nsSVGTextPathElementBase;
class nsSVGTextPathElement : public nsSVGTextPathElementBase,
public nsIDOMSVGTextPathElement,
public nsIDOMSVGURIReference
{
friend class nsSVGTextPathFrame;
protected:
friend nsresult NS_NewSVGTextPathElement(nsIContent **aResult,
nsINodeInfo *aNodeInfo);
nsSVGTextPathElement(nsINodeInfo* aNodeInfo);
nsresult Init();
public:
// interfaces:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIDOMSVGTEXTPATHELEMENT
NS_DECL_NSIDOMSVGTEXTCONTENTELEMENT
NS_DECL_NSIDOMSVGURIREFERENCE
// xxx If xpcom allowed virtual inheritance we wouldn't need to
// forward here :-(
NS_FORWARD_NSIDOMNODE(nsSVGTextPathElementBase::)
NS_FORWARD_NSIDOMELEMENT(nsSVGTextPathElementBase::)
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGTextPathElementBase::)
// nsIContent interface
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
protected:
virtual LengthAttributesInfo GetLengthInfo();
virtual EnumAttributesInfo GetEnumInfo();
virtual PRBool IsEventName(nsIAtom* aName);
already_AddRefed<nsISVGTextContentMetrics> GetTextContentMetrics();
enum { STARTOFFSET };
nsSVGLength2 mLengthAttributes[1];
static LengthInfo sLengthInfo[1];
enum { METHOD, SPACING };
nsSVGEnum mEnumAttributes[2];
static nsSVGEnumMapping sMethodMap[];
static nsSVGEnumMapping sSpacingMap[];
static EnumInfo sEnumInfo[2];
nsCOMPtr<nsIDOMSVGAnimatedString> mHref;
};
#endif

View File

@ -322,45 +322,6 @@ GetSingleValue(nsISVGGlyphFragmentLeaf *fragment,
nsCOMPtr<nsIDOMSVGLength> length;
list->GetItem(0, getter_AddRefs(length));
length->GetValue(val);
nsSVGTextPathFrame *textPath = fragment->FindTextPathParent();
if (textPath) {
nsRefPtr<gfxFlattenedPath> data = textPath->GetFlattenedPath();
if (!data)
return;
nsIFrame *pathFrame = textPath->GetPathFrame();
if (!pathFrame)
return;
/* check for % sizing of textpath */
PRUint16 type;
length->GetUnitType(&type);
if (type == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE) {
float percent;
length->GetValueInSpecifiedUnits(&percent);
*val = data->GetLength()*percent/100.0f;
} else if (pathFrame->GetContent()->HasAttr(kNameSpaceID_None,
nsGkAtoms::pathLength)) {
nsCOMPtr<nsIDOMSVGPathElement> pathElement =
do_QueryInterface(pathFrame->GetContent());
if (!pathElement)
return;
nsIDOMSVGAnimatedNumber* pathLength;
pathElement->GetPathLength(&pathLength);
if (!pathLength)
return;
float pl;
pathLength->GetAnimVal(&pl);
if (pl)
*val *= data->GetLength() / pl;
else
*val = 0;
}
}
}
}
@ -439,6 +400,12 @@ nsSVGTextFrame::UpdateGlyphPositioning()
GetSingleValue(firstFragment, list, &y);
}
// check for startOffset on textPath
nsSVGTextPathFrame *textPath = firstFragment->FindTextPathParent();
if (textPath) {
x = textPath->GetStartOffset();
}
// determine x offset based on text_anchor:
PRUint8 anchor = firstFragment->GetTextAnchor();

View File

@ -44,6 +44,7 @@
#include "nsContentUtils.h"
#include "nsIDOMSVGAnimatedPathData.h"
#include "nsSVGPathElement.h"
#include "nsSVGTextPathElement.h"
NS_IMPL_ISUPPORTS1(nsSVGPathListener, nsIMutationObserver)
@ -103,40 +104,6 @@ nsSVGTextPathFrame::Init(nsIContent* aContent,
{
nsSVGTextPathFrameBase::Init(aContent, aParent, aPrevInFlow);
nsCOMPtr<nsIDOMSVGTextPathElement> tpath = do_QueryInterface(mContent);
{
nsCOMPtr<nsIDOMSVGAnimatedLength> length;
tpath->GetStartOffset(getter_AddRefs(length));
// XXX: Gross hack as stand-in until length lists converted
#ifdef DEBUG_tor
fprintf(stderr,
"### Using nsSVGTextPathFrame mStartOffset hack - fix me\n");
#endif
nsCOMPtr<nsIDOMSVGLength> offset;
length->GetAnimVal(getter_AddRefs(offset));
PRUint16 type;
float value;
offset->GetUnitType(&type);
offset->GetValueInSpecifiedUnits(&value);
nsCOMPtr<nsISVGLength> l;
NS_NewSVGLength(getter_AddRefs(l), value, type);
mStartOffset = l;
NS_ASSERTION(mStartOffset, "no startOffset");
if (!mStartOffset)
return NS_ERROR_FAILURE;
NS_NewSVGLengthList(getter_AddRefs(mX),
static_cast<nsSVGElement*>(mContent),
nsSVGUtils::X);
if (mX) {
nsCOMPtr<nsIDOMSVGLength> length;
mX->AppendItem(mStartOffset, getter_AddRefs(length));
}
}
{
nsCOMPtr<nsIDOMSVGURIReference> aRef = do_QueryInterface(mContent);
if (aRef)
@ -158,9 +125,7 @@ nsSVGTextPathFrame::GetType() const
NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>)
nsSVGTextPathFrame::GetX()
{
nsIDOMSVGLengthList *retval = mX;
NS_IF_ADDREF(retval);
return retval;
return nsnull;
}
NS_IMETHODIMP_(already_AddRefed<nsIDOMSVGLengthList>)
@ -208,9 +173,13 @@ already_AddRefed<gfxFlattenedPath>
nsSVGTextPathFrame::GetFlattenedPath()
{
nsIFrame *path = GetPathFrame();
if (!path)
return nsnull;
return path ? GetFlattenedPath(path) : nsnull;
}
already_AddRefed<gfxFlattenedPath>
nsSVGTextPathFrame::GetFlattenedPath(nsIFrame *path)
{
NS_PRECONDITION(path, "Unexpected null path");
nsSVGPathGeometryElement *element = static_cast<nsSVGPathGeometryElement*>
(path->GetContent());
@ -223,6 +192,42 @@ nsSVGTextPathFrame::GetFlattenedPath()
return element->GetFlattenedPath(localTM);
}
gfxFloat
nsSVGTextPathFrame::GetStartOffset()
{
nsSVGTextPathElement *tp = static_cast<nsSVGTextPathElement*>(mContent);
nsSVGLength2 *length = &tp->mLengthAttributes[nsSVGTextPathElement::STARTOFFSET];
float val = length->GetAnimValInSpecifiedUnits();
if (val == 0.0f)
return 0.0;
if (length->GetSpecifiedUnitType() ==
nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE) {
nsRefPtr<gfxFlattenedPath> data = GetFlattenedPath();
return data ? (val * data->GetLength() / 100.0) : 0.0;
} else {
return val * GetPathScale();
}
}
gfxFloat
nsSVGTextPathFrame::GetPathScale()
{
nsIFrame *pathFrame = GetPathFrame();
if (!pathFrame)
return 1.0;
nsSVGPathElement *path = static_cast<nsSVGPathElement*>(pathFrame->GetContent());
float pl = path->mPathLength.GetAnimValue();
if (pl == 0.0f)
return 1.0;
nsRefPtr<gfxFlattenedPath> data = GetFlattenedPath(pathFrame);
return data ? data->GetLength() / pl : 1.0;
}
//----------------------------------------------------------------------
// nsIFrame methods

View File

@ -99,6 +99,8 @@ public:
already_AddRefed<gfxFlattenedPath> GetFlattenedPath();
nsIFrame *GetPathFrame();
gfxFloat GetStartOffset();
gfxFloat GetPathScale();
protected:
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetX();
@ -107,13 +109,11 @@ protected:
NS_IMETHOD_(already_AddRefed<nsIDOMSVGLengthList>) GetDy();
private:
already_AddRefed<gfxFlattenedPath> GetFlattenedPath(nsIFrame *path);
nsCOMPtr<nsIDOMSVGLength> mStartOffset;
nsCOMPtr<nsIDOMSVGAnimatedString> mHref;
nsRefPtr<nsSVGPathListener> mPathListener;
nsCOMPtr<nsIDOMSVGLengthList> mX;
friend class nsSVGPathListener;
};