Bug 361920 - Incorrect unit conversion for SVGLength created through createSVGLength. r+sr=roc

This commit is contained in:
Robert Longson 2009-02-23 11:24:05 +00:00
parent 486b0aefbb
commit a094eff461
13 changed files with 214 additions and 86 deletions

View File

@ -361,28 +361,6 @@ nsSVGAnimationElement::GetTimeContainer()
return result;
}
nsIContent*
nsSVGAnimationElement::GetParentElement()
{
nsCOMPtr<nsIContent> result;
nsBindingManager* bindingManager = nsnull;
nsIDocument* ownerDoc = GetOwnerDoc();
if (ownerDoc)
bindingManager = ownerDoc->BindingManager();
if (bindingManager)
// we have a binding manager -- do we have an anonymous parent?
result = bindingManager->GetInsertionParent(this);
if (!result)
// if we didn't find an anonymous parent, use the explicit one,
// whether it's null or not...
result = GetParent();
return result;
}
// nsIDOMElementTimeControl
/* void beginElement (); */
NS_IMETHODIMP

View File

@ -91,9 +91,6 @@ public:
virtual nsSMILTimeContainer* GetTimeContainer();
protected:
// Implementation helpers
nsIContent* GetParentElement();
nsSMILTimedElement mTimedElement;
nsSMILTimeContainer* mTimedDocumentRoot;
};

View File

@ -197,6 +197,35 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGElementBase)
//----------------------------------------------------------------------
// Implementation
nsIContent*
nsSVGElement::GetParentElement()
{
nsCOMPtr<nsIContent> result;
nsBindingManager* bindingManager = nsnull;
// XXXbz I _think_ this is right. We want to be using the binding manager
// that would have attached the binding that gives us our anonymous parent.
// That's the binding manager for the document we actually belong to, which
// is our owner doc.
nsIDocument* ownerDoc = GetOwnerDoc();
if (ownerDoc) {
bindingManager = ownerDoc->BindingManager();
}
if (bindingManager) {
// we have a binding manager -- do we have an anonymous parent?
result = bindingManager->GetInsertionParent(this);
}
if (!result) {
// if we didn't find an anonymous parent, use the explicit one,
// whether it's null or not...
result = GetParent();
}
return result;
}
//----------------------------------------------------------------------
// nsIContent methods
@ -262,22 +291,8 @@ nsSVGElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
aName == nsGkAtoms::requiredExtensions ||
aName == nsGkAtoms::systemLanguage)) {
nsIContent* parent = nsnull;
nsIContent* parent = GetParentElement();
nsIContent* bindingParent = GetBindingParent();
if (bindingParent) {
nsIDocument* doc = bindingParent->GetOwnerDoc();
if (doc) {
parent = doc->BindingManager()->GetInsertionParent(bindingParent);
}
}
if (!parent) {
// if we didn't find an anonymous parent, use the explicit one,
// whether it's null or not...
parent = GetParent();
}
if (parent &&
parent->NodeInfo()->Equals(nsGkAtoms::svgSwitch, kNameSpaceID_SVG)) {
static_cast<nsSVGSwitchElement*>(parent)->MaybeInvalidate();

View File

@ -134,10 +134,12 @@ public:
// nsISupportsWeakReference
// implementation inherited from nsSupportsWeakReference
nsIContent* GetParentElement();
// Gets the element that establishes the rectangular viewport against which
// we should resolve percentage lengths (our "coordinate context"). Returns
// nsnull for outer <svg> or SVG without an <svg> parent (invalid SVG).
nsSVGSVGElement* GetCtx();
// nsnull SVG without an <svg> parent (invalid SVG).
virtual nsSVGSVGElement* GetCtx();
virtual void DidChangeLength(PRUint8 aAttrEnum, PRBool aDoSetAttr);
virtual void DidChangeNumber(PRUint8 aAttrEnum, PRBool aDoSetAttr);

View File

@ -36,7 +36,6 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsSVGLength.h"
#include "nsCOMPtr.h"
#include "nsSVGForeignObjectElement.h"

View File

@ -58,14 +58,9 @@ class nsSVGLength : public nsISVGLength,
public nsSVGValue
{
protected:
friend nsresult NS_NewSVGLength(nsISVGLength** result,
float value,
PRUint16 unit);
friend nsresult NS_NewSVGLength(nsISVGLength** result,
const nsAString &value);
nsSVGLength(float value, PRUint16 unit);
nsSVGLength();
public:
@ -103,18 +98,6 @@ protected:
//----------------------------------------------------------------------
// Implementation
nsresult
NS_NewSVGLength(nsISVGLength** result,
float value,
PRUint16 unit)
{
*result = new nsSVGLength(value, unit);
if (!*result)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*result);
return NS_OK;
}
nsresult
NS_NewSVGLength(nsISVGLength** result,
const nsAString &value)
@ -134,14 +117,6 @@ NS_NewSVGLength(nsISVGLength** result,
}
nsSVGLength::nsSVGLength(float value,
PRUint16 unit)
: mValueInSpecifiedUnits(value),
mSpecifiedUnitType(unit),
mCtxType(0)
{
}
nsSVGLength::nsSVGLength()
{
}

View File

@ -42,18 +42,8 @@
#include "nsISVGLength.h"
#include "nsAString.h"
nsresult
NS_NewSVGLength(nsISVGLength** result,
float value=0.0f,
PRUint16 unit=nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER);
nsresult
NS_NewSVGLength(nsISVGLength** result,
const nsAString &value);
// XXX we'll need this prototype-based stuff to support unsetting:
//nsresult NS_NewSVGLength(nsIDOMSVGLength** result,
// nsIDOMSVGLength* prototype);
#endif //__NS_SVGLENGTH_H__

View File

@ -47,12 +47,56 @@
#include "nsSMILFloatType.h"
#endif // MOZ_SMIL
class DOMSVGLength : public nsIDOMSVGLength
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(DOMSVGLength)
DOMSVGLength(nsSVGElement *aSVGElement)
: mSVGElement(aSVGElement)
{ mVal.Init(); }
NS_IMETHOD GetUnitType(PRUint16* aResult)
{ *aResult = mVal.mSpecifiedUnitType; return NS_OK; }
NS_IMETHOD GetValue(float* aResult)
{ *aResult = mVal.GetBaseValue(mSVGElement); return NS_OK; }
NS_IMETHOD SetValue(float aValue)
{ NS_ENSURE_FINITE(aValue, NS_ERROR_ILLEGAL_VALUE);
mVal.mBaseVal =
aValue * mVal.GetUnitScaleFactor(mSVGElement, mVal.mSpecifiedUnitType);
return NS_OK; }
NS_IMETHOD GetValueInSpecifiedUnits(float* aResult)
{ *aResult = mVal.mBaseVal; return NS_OK; }
NS_IMETHOD SetValueInSpecifiedUnits(float aValue)
{ NS_ENSURE_FINITE(aValue, NS_ERROR_ILLEGAL_VALUE);
mVal.mBaseVal = aValue;
return NS_OK; }
NS_IMETHOD SetValueAsString(const nsAString& aValueAsString);
NS_IMETHOD GetValueAsString(nsAString& aValue)
{ mVal.GetBaseValueString(aValue); return NS_OK; }
NS_IMETHOD NewValueSpecifiedUnits(PRUint16 unitType,
float valueInSpecifiedUnits);
NS_IMETHOD ConvertToSpecifiedUnits(PRUint16 unitType);
private:
nsSVGLength2 mVal;
nsRefPtr<nsSVGElement> mSVGElement;
};
NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGLength2::DOMBaseVal, mSVGElement)
NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGLength2::DOMAnimVal, mSVGElement)
NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGLength2::DOMAnimatedLength, mSVGElement)
NS_SVG_VAL_IMPL_CYCLE_COLLECTION(DOMSVGLength, mSVGElement)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGLength2::DOMBaseVal)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGLength2::DOMBaseVal)
@ -62,6 +106,9 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGLength2::DOMAnimVal)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGLength2::DOMAnimatedLength)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGLength2::DOMAnimatedLength)
NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGLength)
NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGLength)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGLength2::DOMBaseVal)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLength)
NS_INTERFACE_MAP_ENTRY(nsISupports)
@ -80,6 +127,12 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGLength2::DOMAnimatedLength)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedLength)
NS_INTERFACE_MAP_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGLength)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGLength)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGLength)
NS_INTERFACE_MAP_END
static nsIAtom** const unitMap[] =
{
nsnull, /* SVG_LENGTHTYPE_UNKNOWN */
@ -175,6 +228,49 @@ GetValueFromString(const nsAString &aValueAsString,
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
DOMSVGLength::SetValueAsString(const nsAString& aValueAsString)
{
float value;
PRUint16 unitType;
nsresult rv = GetValueFromString(aValueAsString, &value, &unitType);
if (NS_FAILED(rv)) {
return rv;
}
mVal.mBaseVal = value;
mVal.mSpecifiedUnitType = PRUint8(unitType);
return NS_OK;
}
NS_IMETHODIMP
DOMSVGLength::NewValueSpecifiedUnits(PRUint16 unitType,
float valueInSpecifiedUnits)
{
NS_ENSURE_FINITE(valueInSpecifiedUnits, NS_ERROR_ILLEGAL_VALUE);
if (!IsValidUnitType(unitType))
return NS_OK;
mVal.mBaseVal = valueInSpecifiedUnits;
mVal.mSpecifiedUnitType = PRUint8(unitType);
return NS_OK;
}
NS_IMETHODIMP
DOMSVGLength::ConvertToSpecifiedUnits(PRUint16 unitType)
{
if (!IsValidUnitType(unitType))
return NS_OK;
float valueInUserUnits =
mVal.mBaseVal / mVal.GetUnitScaleFactor(mSVGElement, mVal.mSpecifiedUnitType);
mVal.mSpecifiedUnitType = PRUint8(unitType);
mVal.mBaseVal =
valueInUserUnits * mVal.GetUnitScaleFactor(mSVGElement, mVal.mSpecifiedUnitType);
return NS_OK;
}
float
nsSVGLength2::GetMMPerPixel(nsSVGSVGElement *aCtx) const
{
@ -458,6 +554,17 @@ nsSVGLength2::ToDOMAnimatedLength(nsIDOMSVGAnimatedLength **aResult,
return NS_OK;
}
nsresult
NS_NewDOMSVGLength(nsIDOMSVGLength** aResult, nsSVGElement *aSVGElement)
{
*aResult = new DOMSVGLength(aSVGElement);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}
#ifdef MOZ_SMIL
nsISMILAttr*
nsSVGLength2::ToSMILAttr(nsSVGElement *aSVGElement)

View File

@ -53,6 +53,7 @@ class nsIFrame;
class nsSVGLength2
{
friend class DOMSVGLength;
public:
void Init(PRUint8 aCtxType = nsSVGUtils::XY,
@ -289,4 +290,7 @@ private:
#endif // MOZ_SMIL
};
nsresult
NS_NewDOMSVGLength(nsIDOMSVGLength** result, nsSVGElement *aSVGElement);
#endif // __NS_SVGLENGTH2_H__

View File

@ -38,17 +38,44 @@
#include "nsTextFormatter.h"
#include "prdtoa.h"
class DOMSVGNumber : public nsIDOMSVGNumber
{
public:
NS_DECL_ISUPPORTS
DOMSVGNumber() {}
NS_IMETHOD GetValue(float* aResult)
{ *aResult = mVal; return NS_OK; }
NS_IMETHOD SetValue(float aValue)
{ NS_ENSURE_FINITE(aValue, NS_ERROR_ILLEGAL_VALUE);
mVal = aValue;
return NS_OK; }
private:
float mVal;
};
NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGNumber2::DOMAnimatedNumber, mSVGElement)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGNumber2::DOMAnimatedNumber)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGNumber2::DOMAnimatedNumber)
NS_IMPL_ADDREF(DOMSVGNumber)
NS_IMPL_RELEASE(DOMSVGNumber)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGNumber2::DOMAnimatedNumber)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedNumber)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedNumber)
NS_INTERFACE_MAP_END
NS_INTERFACE_MAP_BEGIN(DOMSVGNumber)
NS_INTERFACE_MAP_ENTRY(nsIDOMSVGNumber)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGNumber)
NS_INTERFACE_MAP_END
/* Implementation */
nsresult
@ -101,3 +128,13 @@ nsSVGNumber2::ToDOMAnimatedNumber(nsIDOMSVGAnimatedNumber **aResult,
return NS_OK;
}
nsresult
NS_NewDOMSVGNumber(nsIDOMSVGNumber** aResult)
{
*aResult = new DOMSVGNumber();
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

View File

@ -44,6 +44,7 @@
class nsSVGNumber2
{
friend class DOMSVGNumber;
public:
void Init(PRUint8 aAttrEnum = 0xff, float aValue = 0) {
@ -96,4 +97,8 @@ private:
};
};
nsresult
NS_NewDOMSVGNumber(nsIDOMSVGNumber** result);
#endif //__NS_SVGNUMBER2_H__

View File

@ -39,7 +39,8 @@
* ***** END LICENSE BLOCK ***** */
#include "nsGkAtoms.h"
#include "nsSVGLength.h"
#include "nsSVGNumber2.h"
#include "nsSVGLength2.h"
#include "nsSVGAngle.h"
#include "nsCOMPtr.h"
#include "nsIPresShell.h"
@ -179,6 +180,15 @@ nsSVGSVGElement::Init()
return rv;
}
PRBool
nsSVGSVGElement::IsOutermostSVGElement()
{
nsIContent *parent = GetParentElement();
return !parent || parent->GetNameSpaceID() != kNameSpaceID_SVG ||
parent->Tag() == nsGkAtoms::foreignObject;
}
//----------------------------------------------------------------------
// nsIDOMNode methods
@ -623,14 +633,14 @@ nsSVGSVGElement::DeSelectAll()
NS_IMETHODIMP
nsSVGSVGElement::CreateSVGNumber(nsIDOMSVGNumber **_retval)
{
return NS_NewSVGNumber(_retval);
return NS_NewDOMSVGNumber(_retval);
}
/* nsIDOMSVGLength createSVGLength (); */
NS_IMETHODIMP
nsSVGSVGElement::CreateSVGLength(nsIDOMSVGLength **_retval)
{
return NS_NewSVGLength(reinterpret_cast<nsISVGLength**>(_retval));
return NS_NewDOMSVGLength(_retval, this);
}
/* nsIDOMSVGAngle createSVGAngle (); */
@ -1282,7 +1292,7 @@ nsSVGSVGElement::GetViewboxToViewportTransform(nsIDOMSVGMatrix **_retval)
float viewportWidth, viewportHeight;
nsSVGSVGElement *ctx = GetCtx();
if (!ctx) {
if (ctx == this) {
// outer svg
viewportWidth = mViewportWidth;
viewportHeight = mViewportHeight;
@ -1467,12 +1477,13 @@ nsSVGSVGElement::GetLength(PRUint8 aCtxType)
h = viewbox.height;
} else {
nsSVGSVGElement *ctx = GetCtx();
if (ctx) {
w = mLengthAttributes[WIDTH].GetAnimValue(ctx);
h = mLengthAttributes[HEIGHT].GetAnimValue(ctx);
} else {
if (ctx == this) {
// outer svg
w = mViewportWidth;
h = mViewportHeight;
} else {
w = mLengthAttributes[WIDTH].GetAnimValue(ctx);
h = mLengthAttributes[HEIGHT].GetAnimValue(ctx);
}
}

View File

@ -104,6 +104,12 @@ public:
NS_FORWARD_NSIDOMELEMENT(nsSVGSVGElementBase::)
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGSVGElementBase::)
// Gets the element that establishes the rectangular viewport against which
// we should resolve percentage lengths (our "coordinate context").
virtual nsSVGSVGElement* GetCtx() {
return IsOutermostSVGElement() ? this : nsSVGSVGElementBase::GetCtx();
}
// helper methods for implementing SVGZoomEvent:
nsresult GetCurrentScaleNumber(nsIDOMSVGNumber **aResult);
@ -162,6 +168,8 @@ public:
float GetMMPerPx(PRUint8 mCtxType = 0);
// public helpers:
PRBool IsOutermostSVGElement();
nsresult GetViewboxToViewportTransform(nsIDOMSVGMatrix **_retval);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;