diff --git a/content/svg/content/src/nsSVGLength2.cpp b/content/svg/content/src/nsSVGLength2.cpp index d3181e783106..7e9330c900ee 100644 --- a/content/svg/content/src/nsSVGLength2.cpp +++ b/content/svg/content/src/nsSVGLength2.cpp @@ -36,13 +36,9 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsContentUtils.h" #include "nsSVGLength2.h" -#include "nsGkAtoms.h" #include "prdtoa.h" -#include "nsCRT.h" #include "nsTextFormatter.h" -#include "nsIDOMSVGNumber.h" #include "nsSVGSVGElement.h" NS_IMPL_ADDREF(nsSVGLength2::DOMBaseVal) @@ -72,6 +68,21 @@ NS_INTERFACE_MAP_BEGIN(nsSVGLength2::DOMAnimatedLength) NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(SVGAnimatedLength) NS_INTERFACE_MAP_END +static nsIAtom** const unitMap[] = +{ + nsnull, /* SVG_LENGTHTYPE_UNKNOWN */ + nsnull, /* SVG_LENGTHTYPE_NUMBER */ + &nsGkAtoms::percentage, + &nsGkAtoms::em, + &nsGkAtoms::ex, + &nsGkAtoms::px, + &nsGkAtoms::cm, + &nsGkAtoms::mm, + &nsGkAtoms::in, + &nsGkAtoms::pt, + &nsGkAtoms::pc +}; + /* Helper functions */ static PRBool @@ -85,8 +96,38 @@ IsValidUnitType(PRUint16 unit) } static void -GetValueString(nsAString &aValueAsString, float aValue, PRUint16 aUnitType) +GetUnitString(nsAString& unit, PRUint16 unitType) +{ + if (IsValidUnitType(unitType)) { + if (unitMap[unitType]) { + (*unitMap[unitType])->ToString(unit); + } + return; + } + NS_NOTREACHED("Unknown unit type"); + return; +} + +static PRUint16 +GetUnitTypeForString(const char* unitStr) +{ + if (!unitStr || *unitStr == '\0') + return nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER; + + nsCOMPtr unitAtom = do_GetAtom(unitStr); + + for (int i = 0 ; i < NS_ARRAY_LENGTH(unitMap) ; i++) { + if (unitMap[i] && *unitMap[i] == unitAtom) { + return i; + } + } + + return nsIDOMSVGLength::SVG_LENGTHTYPE_UNKNOWN; +} + +static void +GetValueString(nsAString &aValueAsString, float aValue, PRUint16 aUnitType) { PRUnichar buf[24]; nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar), @@ -94,50 +135,42 @@ GetValueString(nsAString &aValueAsString, float aValue, PRUint16 aUnitType) (double)aValue); aValueAsString.Assign(buf); - nsIAtom* UnitAtom = nsnull; - - switch (aUnitType) { - case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER: - return; - case nsIDOMSVGLength::SVG_LENGTHTYPE_PX: - UnitAtom = nsGkAtoms::px; - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_MM: - UnitAtom = nsGkAtoms::mm; - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_CM: - UnitAtom = nsGkAtoms::cm; - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_IN: - UnitAtom = nsGkAtoms::in; - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_PT: - UnitAtom = nsGkAtoms::pt; - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_PC: - UnitAtom = nsGkAtoms::pc; - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS: - UnitAtom = nsGkAtoms::em; - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS: - UnitAtom = nsGkAtoms::ex; - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE: - UnitAtom = nsGkAtoms::percentage; - break; - default: - NS_NOTREACHED("Unknown unit"); - return; - } - nsAutoString unitString; - UnitAtom->ToString(unitString); + GetUnitString(unitString, aUnitType); aValueAsString.Append(unitString); } +static nsresult +GetValueFromString(const nsAString &aValueAsString, + float *aValue, + PRUint16 *aUnitType) +{ + char *str = ToNewCString(aValueAsString); + if (!str) + return NS_ERROR_OUT_OF_MEMORY; + + nsresult rv = NS_ERROR_FAILURE; + + if (*str) { + char *rest; + *aValue = static_cast(PR_strtod(str, &rest)); + if (rest != str) { + *aUnitType = GetUnitTypeForString(nsCRT::strtok(rest, + "\x20\x9\xD\xA", + &rest)); + if (IsValidUnitType(*aUnitType)) { + rv = NS_OK; + } + } + } + + nsMemory::Free(str); + + return rv; +} + float -nsSVGLength2::GetMMPerPixel(nsSVGSVGElement *aCtx) +nsSVGLength2::GetMMPerPixel(nsSVGSVGElement *aCtx) const { if (!aCtx) return 1; @@ -153,7 +186,7 @@ nsSVGLength2::GetMMPerPixel(nsSVGSVGElement *aCtx) } float -nsSVGLength2::GetAxisLength(nsSVGSVGElement *aCtx) +nsSVGLength2::GetAxisLength(nsSVGSVGElement *aCtx) const { if (!aCtx) return 1; @@ -168,181 +201,51 @@ nsSVGLength2::GetAxisLength(nsSVGSVGElement *aCtx) return d; } -/* Implementation */ - -nsresult -nsSVGLength2::SetBaseValueString(const nsAString &aValueAsString, - nsSVGElement *aSVGElement, - PRBool aDoSetAttr) +float +nsSVGLength2::GetUnitScaleFactor(nsSVGElement *aSVGElement) const { - nsresult rv = NS_OK; - - char *str = ToNewCString(aValueAsString); - if (!str) - return NS_ERROR_OUT_OF_MEMORY; - - char* number = str; - while (*number && isspace(*number)) - ++number; - - if (*number) { - char *rest; - double value = PR_strtod(number, &rest); - if (rest!=number) { - const char* unitStr = nsCRT::strtok(rest, "\x20\x9\xD\xA", &rest); - PRUint16 unitType = nsIDOMSVGLength::SVG_LENGTHTYPE_UNKNOWN; - if (!unitStr || *unitStr=='\0') { - unitType = nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER; - } - else { - nsCOMPtr unitAtom = do_GetAtom(unitStr); - if (unitAtom == nsGkAtoms::px) - unitType = nsIDOMSVGLength::SVG_LENGTHTYPE_PX; - else if (unitAtom == nsGkAtoms::mm) - unitType = nsIDOMSVGLength::SVG_LENGTHTYPE_MM; - else if (unitAtom == nsGkAtoms::cm) - unitType = nsIDOMSVGLength::SVG_LENGTHTYPE_CM; - else if (unitAtom == nsGkAtoms::in) - unitType = nsIDOMSVGLength::SVG_LENGTHTYPE_IN; - else if (unitAtom == nsGkAtoms::pt) - unitType = nsIDOMSVGLength::SVG_LENGTHTYPE_PT; - else if (unitAtom == nsGkAtoms::pc) - unitType = nsIDOMSVGLength::SVG_LENGTHTYPE_PC; - else if (unitAtom == nsGkAtoms::em) - unitType = nsIDOMSVGLength::SVG_LENGTHTYPE_EMS; - else if (unitAtom == nsGkAtoms::ex) - unitType = nsIDOMSVGLength::SVG_LENGTHTYPE_EXS; - else if (unitAtom == nsGkAtoms::percentage) - unitType = nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE; - } - if (IsValidUnitType(unitType)){ - mBaseVal = mAnimVal = (float)value; - mSpecifiedUnitType = unitType; - aSVGElement->DidChangeLength(mAttrEnum, aDoSetAttr); - } - else { // parse error - // not a valid unit type - rv = NS_ERROR_FAILURE; - } - } - else { // parse error - // no number - rv = NS_ERROR_FAILURE; - } + switch (mSpecifiedUnitType) { + case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER: + case nsIDOMSVGLength::SVG_LENGTHTYPE_PX: + return 1; + case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS: + return 1 / GetEmLength(aSVGElement); + case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS: + return 1 / GetExLength(aSVGElement); } - - nsMemory::Free(str); - - return rv; -} -void -nsSVGLength2::GetBaseValueString(nsAString & aValueAsString) -{ - GetValueString(aValueAsString, mBaseVal, mSpecifiedUnitType); -} - -void -nsSVGLength2::GetAnimValueString(nsAString & aValueAsString) -{ - GetValueString(aValueAsString, mAnimVal, mSpecifiedUnitType); + return GetUnitScaleFactor(aSVGElement->GetCtx()); } float -nsSVGLength2::ConvertToUserUnits(float aVal, nsSVGElement *aSVGElement) +nsSVGLength2::GetUnitScaleFactor(nsSVGSVGElement *aCtx) const { switch (mSpecifiedUnitType) { - case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER: - case nsIDOMSVGLength::SVG_LENGTHTYPE_PX: - return aVal; - case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS: - return aVal * GetEmLength(aSVGElement); - case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS: - return aVal * GetExLength(aSVGElement); - default: - return ConvertToUserUnits(aVal, aSVGElement->GetCtx()); + case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER: + case nsIDOMSVGLength::SVG_LENGTHTYPE_PX: + return 1; + case nsIDOMSVGLength::SVG_LENGTHTYPE_MM: + return GetMMPerPixel(aCtx); + case nsIDOMSVGLength::SVG_LENGTHTYPE_CM: + return GetMMPerPixel(aCtx) / 10.0f; + case nsIDOMSVGLength::SVG_LENGTHTYPE_IN: + return GetMMPerPixel(aCtx) / 25.4f; + case nsIDOMSVGLength::SVG_LENGTHTYPE_PT: + return GetMMPerPixel(aCtx) * 72.0f / 25.4f; + case nsIDOMSVGLength::SVG_LENGTHTYPE_PC: + return GetMMPerPixel(aCtx) * 72.0f / 24.4f / 12.0f; + case nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE: + return 100.0f / GetAxisLength(aCtx); + case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS: + return 1 / GetEmLength(aCtx); + case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS: + return 1 / GetExLength(aCtx); + default: + NS_NOTREACHED("Unknown unit type"); + return 0; } } -float -nsSVGLength2::ConvertToUserUnits(float aVal, nsSVGSVGElement *aCtx) -{ - switch (mSpecifiedUnitType) { - case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER: - case nsIDOMSVGLength::SVG_LENGTHTYPE_PX: - return aVal; - case nsIDOMSVGLength::SVG_LENGTHTYPE_MM: - return aVal / GetMMPerPixel(aCtx); - case nsIDOMSVGLength::SVG_LENGTHTYPE_CM: - return aVal * 10.0f / GetMMPerPixel(aCtx); - case nsIDOMSVGLength::SVG_LENGTHTYPE_IN: - return aVal * 25.4f / GetMMPerPixel(aCtx); - case nsIDOMSVGLength::SVG_LENGTHTYPE_PT: - return aVal * 25.4f / 72.0f / GetMMPerPixel(aCtx); - case nsIDOMSVGLength::SVG_LENGTHTYPE_PC: - return aVal * 25.4f * 12.0f / 72.0f / GetMMPerPixel(aCtx); - case nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE: - return aVal * GetAxisLength(aCtx) / 100.0f; - case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS: - return aVal * GetEmLength(aCtx); - case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS: - return aVal * GetExLength(aCtx); - default: - NS_NOTREACHED("Unknown unit type"); - return 0; - } -} - -void -nsSVGLength2::SetBaseValue(float aValue, nsSVGElement *aSVGElement) -{ - nsSVGSVGElement *ctx = nsnull; - - if (mSpecifiedUnitType != nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER && - mSpecifiedUnitType != nsIDOMSVGLength::SVG_LENGTHTYPE_PX && - mSpecifiedUnitType != nsIDOMSVGLength::SVG_LENGTHTYPE_EMS && - mSpecifiedUnitType != nsIDOMSVGLength::SVG_LENGTHTYPE_EXS) - ctx = aSVGElement->GetCtx(); - - switch (mSpecifiedUnitType) { - case nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER: - case nsIDOMSVGLength::SVG_LENGTHTYPE_PX: - mBaseVal = aValue; - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_MM: - mBaseVal = aValue * GetMMPerPixel(ctx); - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_CM: - mBaseVal = aValue * GetMMPerPixel(ctx) / 10.0f; - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_IN: - mBaseVal = aValue * GetMMPerPixel(ctx) / 25.4f; - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_PT: - mBaseVal = aValue * GetMMPerPixel(ctx) * 72.0f / 25.4f; - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_PC: - mBaseVal = aValue * GetMMPerPixel(ctx) * 72.0f / 24.4f / 12.0f; - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE: - mBaseVal = aValue * 100.0f / GetAxisLength(ctx); - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_EMS: - mBaseVal = aValue / GetEmLength(aSVGElement); - break; - case nsIDOMSVGLength::SVG_LENGTHTYPE_EXS: - mBaseVal = aValue / GetExLength(aSVGElement); - break; - default: - NS_NOTREACHED("Unknown unit type"); - mBaseVal = 0; - break; - } - - mAnimVal = mBaseVal; - aSVGElement->DidChangeLength(mAttrEnum, PR_TRUE); -} - void nsSVGLength2::SetBaseValueInSpecifiedUnits(float aValue, nsSVGElement *aSVGElement) @@ -358,9 +261,8 @@ nsSVGLength2::ConvertToSpecifiedUnits(PRUint16 unitType, if (!IsValidUnitType(unitType)) return; - float valueInUserUnits; - valueInUserUnits = GetBaseValue(aSVGElement); - mSpecifiedUnitType = unitType; + float valueInUserUnits = mBaseVal / GetUnitScaleFactor(aSVGElement); + mSpecifiedUnitType = PRUint8(unitType); SetBaseValue(valueInUserUnits, aSVGElement); } @@ -373,7 +275,7 @@ nsSVGLength2::NewValueSpecifiedUnits(PRUint16 unitType, return; mBaseVal = mAnimVal = valueInSpecifiedUnits; - mSpecifiedUnitType = unitType; + mSpecifiedUnitType = PRUint8(unitType); aSVGElement->DidChangeLength(mAttrEnum, PR_TRUE); } @@ -399,6 +301,45 @@ nsSVGLength2::ToDOMAnimVal(nsIDOMSVGLength **aResult, nsSVGElement *aSVGElement) return NS_OK; } +/* Implementation */ + +nsresult +nsSVGLength2::SetBaseValueString(const nsAString &aValueAsString, + nsSVGElement *aSVGElement, + PRBool aDoSetAttr) +{ + float value; + PRUint16 unitType; + + nsresult rv = GetValueFromString(aValueAsString, &value, &unitType); + NS_ENSURE_SUCCESS(rv, rv); + + mBaseVal = mAnimVal = value; + mSpecifiedUnitType = PRUint8(unitType); + aSVGElement->DidChangeLength(mAttrEnum, aDoSetAttr); + + return NS_OK; +} + +void +nsSVGLength2::GetBaseValueString(nsAString & aValueAsString) +{ + GetValueString(aValueAsString, mBaseVal, mSpecifiedUnitType); +} + +void +nsSVGLength2::GetAnimValueString(nsAString & aValueAsString) +{ + GetValueString(aValueAsString, mAnimVal, mSpecifiedUnitType); +} + +void +nsSVGLength2::SetBaseValue(float aValue, nsSVGElement *aSVGElement) +{ + mAnimVal = mBaseVal = aValue * GetUnitScaleFactor(aSVGElement); + aSVGElement->DidChangeLength(mAttrEnum, PR_TRUE); +} + nsresult nsSVGLength2::ToDOMAnimatedLength(nsIDOMSVGAnimatedLength **aResult, nsSVGElement *aSVGElement) diff --git a/content/svg/content/src/nsSVGLength2.h b/content/svg/content/src/nsSVGLength2.h index 6dbf2271b496..e464b55b7821 100644 --- a/content/svg/content/src/nsSVGLength2.h +++ b/content/svg/content/src/nsSVGLength2.h @@ -45,12 +45,6 @@ class nsSVGLength2 { - // Needed to allow member classes access to our data. - // gcc/vc8 allow access without this. - struct DOMBaseVal; - struct DOMAnimVal; - friend struct DOMBaseVal; - friend struct DOMAnimVal; public: void Init(PRUint8 aCtxType = nsSVGUtils::XY, @@ -71,22 +65,20 @@ public: void GetAnimValueString(nsAString& aValue); float GetBaseValue(nsSVGElement* aSVGElement) - { return ConvertToUserUnits(mBaseVal, aSVGElement); } + { return mBaseVal / GetUnitScaleFactor(aSVGElement); } float GetAnimValue(nsSVGElement* aSVGElement) - { return ConvertToUserUnits(mAnimVal, aSVGElement); } + { return mAnimVal / GetUnitScaleFactor(aSVGElement); } - PRUint8 GetCtxType() { return mCtxType; } - PRUint8 GetSpecifiedUnitType() { return mSpecifiedUnitType; } - float GetAnimValInSpecifiedUnits() { return mAnimVal; } - float GetBaseValInSpecifiedUnits() { return mBaseVal; } + PRUint8 GetCtxType() const { return mCtxType; } + PRUint8 GetSpecifiedUnitType() const { return mSpecifiedUnitType; } + float GetAnimValInSpecifiedUnits() const { return mAnimVal; } + float GetBaseValInSpecifiedUnits() const { return mBaseVal; } - float GetBaseValue(nsSVGSVGElement* aProvider) - { return ConvertToUserUnits(mBaseVal, aProvider); } - float GetAnimValue(nsSVGSVGElement* aProvider) - { return ConvertToUserUnits(mAnimVal, aProvider); } + float GetBaseValue(nsSVGSVGElement* aCtx) + { return mBaseVal / GetUnitScaleFactor(aCtx); } + float GetAnimValue(nsSVGSVGElement* aCtx) + { return mAnimVal / GetUnitScaleFactor(aCtx); } - nsresult ToDOMBaseVal(nsIDOMSVGLength **aResult, nsSVGElement* aSVGElement); - nsresult ToDOMAnimVal(nsIDOMSVGLength **aResult, nsSVGElement* aSVGElement); nsresult ToDOMAnimatedLength(nsIDOMSVGAnimatedLength **aResult, nsSVGElement* aSVGElement); @@ -99,19 +91,21 @@ private: PRUint8 mCtxType; // X, Y or Unspecified PRPackedBool mIsAnimated; - float GetMMPerPixel(nsSVGSVGElement *aCtx); - float GetAxisLength(nsSVGSVGElement *aCtx); - float GetEmLength(nsSVGElement *aSVGElement) + float GetMMPerPixel(nsSVGSVGElement *aCtx) const; + float GetAxisLength(nsSVGSVGElement *aCtx) const; + float GetEmLength(nsSVGElement *aSVGElement) const { return nsSVGUtils::GetFontSize(aSVGElement); } - float GetExLength(nsSVGElement *aSVGElement) + float GetExLength(nsSVGElement *aSVGElement) const { return nsSVGUtils::GetFontXHeight(aSVGElement); } - float ConvertToUserUnits(float aValue, nsSVGElement *aSVGElement); - float ConvertToUserUnits(float aValue, nsSVGSVGElement *aProvider); + float GetUnitScaleFactor(nsSVGElement *aSVGElement) const; + float GetUnitScaleFactor(nsSVGSVGElement *aCtx) const; void SetBaseValue(float aValue, nsSVGElement *aSVGElement); void SetBaseValueInSpecifiedUnits(float aValue, nsSVGElement *aSVGElement); void NewValueSpecifiedUnits(PRUint16 aUnitType, float aValue, nsSVGElement *aSVGElement); void ConvertToSpecifiedUnits(PRUint16 aUnitType, nsSVGElement *aSVGElement); + nsresult ToDOMBaseVal(nsIDOMSVGLength **aResult, nsSVGElement* aSVGElement); + nsresult ToDOMAnimVal(nsIDOMSVGLength **aResult, nsSVGElement* aSVGElement); struct DOMBaseVal : public nsIDOMSVGLength {