Bug 397916 - Simplify nsSVGLength2. r=tor,sr+a=roc

This commit is contained in:
longsonr@gmail.com 2007-10-03 02:02:19 -07:00
Родитель c6723751aa
Коммит fb0578606a
2 изменённых файлов: 172 добавлений и 237 удалений

Просмотреть файл

@ -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<nsIAtom> 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<float>(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<nsIAtom> 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)

Просмотреть файл

@ -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
{