Bug 386416 - Integer and Number pair attributes such as the order attribute of feConvolveMatrix should allow an optional comma as separator. r=tor,sr+a=roc

This commit is contained in:
longsonr@gmail.com 2007-10-15 05:06:17 -07:00
parent 21584561f2
commit 9cfc5cc86a
6 changed files with 149 additions and 153 deletions

View File

@ -86,6 +86,7 @@
#include "nsIDOMSVGAnimatedRect.h"
#include "nsSVGRect.h"
#include "nsSVGAnimatedString.h"
#include "prdtoa.h"
#include <stdarg.h>
nsSVGEnumMapping nsSVGElement::sSVGUnitTypesMap[] = {
@ -1163,6 +1164,106 @@ nsSVGElement::DidChangeEnum(PRUint8 aAttrEnum, PRBool aDoSetAttr)
newStr, PR_TRUE);
}
PRBool
nsSVGElement::ParseNumberOptionalNumber(nsIAtom* aAttribute, const nsAString& aValue,
PRUint32 aIndex1, PRUint32 aIndex2,
nsAttrValue& aResult)
{
NS_ConvertUTF16toUTF8 value(aValue);
const char *str = value.get();
PRBool parseError = NS_IsAsciiWhitespace(*str);
float x, y;
if (!parseError) {
char *rest;
x = y = float(PR_strtod(str, &rest));
if (str == rest) {
//first value was illformed
parseError = PR_TRUE;
} else if (*rest != '\0') {
while (NS_IsAsciiWhitespace(*rest)) {
++rest;
}
if (*rest == ',') {
++rest;
}
y = float(PR_strtod(rest, &rest));
if (*rest != '\0') {
//second value was illformed or there was trailing content
parseError = PR_TRUE;
}
}
}
NumberAttributesInfo numberInfo = GetNumberInfo();
if (parseError) {
ReportAttributeParseFailure(GetOwnerDoc(), aAttribute, aValue);
x = numberInfo.mNumberInfo[aIndex1].mDefaultValue;
y = numberInfo.mNumberInfo[aIndex2].mDefaultValue;
} else {
aResult.SetTo(aValue);
}
numberInfo.mNumbers[aIndex1].SetBaseValue(x, this, PR_FALSE);
numberInfo.mNumbers[aIndex2].SetBaseValue(y, this, PR_FALSE);
return (!parseError);
}
PRBool
nsSVGElement::ParseIntegerOptionalInteger(nsIAtom* aAttribute, const nsAString& aValue,
PRUint32 aIndex1, PRUint32 aIndex2,
nsAttrValue& aResult)
{
NS_ConvertUTF16toUTF8 value(aValue);
const char *str = value.get();
PRBool parseError = NS_IsAsciiWhitespace(*str);
PRInt32 x, y;
if (!parseError) {
char *rest;
x = y = strtol(str, &rest, 10);
if (str == rest) {
//first value was illformed
parseError = PR_TRUE;
} else if (*rest != '\0') {
while (NS_IsAsciiWhitespace(*rest)) {
++rest;
}
if (*rest == ',') {
++rest;
}
y = strtol(rest, &rest, 10);
if (*rest != '\0') {
//second value was illformed or there was trailing content
parseError = PR_TRUE;
}
}
}
IntegerAttributesInfo integerInfo = GetIntegerInfo();
if (parseError) {
ReportAttributeParseFailure(GetOwnerDoc(), aAttribute, aValue);
x = integerInfo.mIntegerInfo[aIndex1].mDefaultValue;
y = integerInfo.mIntegerInfo[aIndex2].mDefaultValue;
} else {
aResult.SetTo(aValue);
}
integerInfo.mIntegers[aIndex1].SetBaseValue(x, this, PR_FALSE);
integerInfo.mIntegers[aIndex2].SetBaseValue(y, this, PR_FALSE);
return (!parseError);
}
nsresult
nsSVGElement::ReportAttributeParseFailure(nsIDocument* aDocument,
nsIAtom* aAttribute,

View File

@ -267,6 +267,18 @@ protected:
static nsSVGEnumMapping sSVGUnitTypesMap[];
/* read <number-optional-number> */
PRBool
ParseNumberOptionalNumber(nsIAtom* aAttribute, const nsAString& aValue,
PRUint32 aIndex1, PRUint32 aIndex2,
nsAttrValue& aResult);
/* read <integer-optional-integer> */
PRBool
ParseIntegerOptionalInteger(nsIAtom* aAttribute, const nsAString& aValue,
PRUint32 aIndex1, PRUint32 aIndex2,
nsAttrValue& aResult);
static nsresult ReportAttributeParseFailure(nsIDocument* aDocument,
nsIAtom* aAttribute,
const nsAString& aValue);

View File

@ -196,35 +196,18 @@ nsSVGFilterElement::GetHref(nsIDOMSVGAnimatedString * *aHref)
//----------------------------------------------------------------------
// nsIContent methods
nsresult
nsSVGFilterElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify)
PRBool
nsSVGFilterElement::ParseAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue,
nsAttrValue& aResult)
{
nsresult rv = nsSVGFilterElementBase::SetAttr(aNameSpaceID, aName, aPrefix,
aValue, aNotify);
if (aName == nsGkAtoms::filterRes && aNameSpaceID == kNameSpaceID_None) {
PRUint32 resX, resY;
char *str;
str = ToNewCString(aValue);
int num = sscanf(str, "%d %d\n", &resX, &resY);
switch (num) {
case 2:
mIntegerAttributes[FILTERRES_X].SetBaseValue(resX, this, PR_FALSE);
mIntegerAttributes[FILTERRES_Y].SetBaseValue(resY, this, PR_FALSE);
break;
case 1:
mIntegerAttributes[FILTERRES_X].SetBaseValue(resX, this, PR_FALSE);
mIntegerAttributes[FILTERRES_Y].SetBaseValue(resX, this, PR_FALSE);
break;
default:
break;
}
nsMemory::Free(str);
return ParseIntegerOptionalInteger(aName, aValue,
FILTERRES_X, FILTERRES_Y,
aResult);
}
return rv;
return nsSVGFilterElementBase::ParseAttribute(aNameSpaceID, aName,
aValue, aResult);
}
NS_IMETHODIMP_(PRBool)

View File

@ -77,15 +77,15 @@ public:
NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFilterElementBase::)
// nsIContent
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
protected:
virtual PRBool ParseAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue,
nsAttrValue& aResult);
virtual LengthAttributesInfo GetLengthInfo();
virtual IntegerAttributesInfo GetIntegerInfo();
virtual EnumAttributesInfo GetEnumInfo();

View File

@ -55,7 +55,6 @@
#include "nsISVGValueUtils.h"
#include "nsSVGFilters.h"
#include "nsSVGUtils.h"
#include "prdtoa.h"
#include "nsStyleContext.h"
#include "nsIDocument.h"
#include "nsIFrame.h"
@ -300,52 +299,6 @@ nsSVGFE::Init()
return NS_OK;
}
PRBool
nsSVGFE::ScanDualValueAttribute(const nsAString& aValue, nsIAtom* aAttribute,
nsSVGNumber2* aNum1, nsSVGNumber2* aNum2,
NumberInfo* aInfo1, NumberInfo* aInfo2,
nsAttrValue& aResult)
{
float x = 0.0f, y = 0.0f;
char *rest;
PRBool parseError = PR_FALSE;
NS_ConvertUTF16toUTF8 value(aValue);
value.CompressWhitespace(PR_FALSE, PR_TRUE);
const char *str = value.get();
x = static_cast<float>(PR_strtod(str, &rest));
if (str == rest) {
//first value was illformed
parseError = PR_TRUE;
} else {
if (*rest == '\0') {
//second value was not supplied
y = x;
} else {
y = static_cast<float>(PR_strtod(rest, &rest));
if (*rest != '\0') {
//second value was illformed or there was trailing content
parseError = PR_TRUE;
}
}
}
if (parseError) {
ReportAttributeParseFailure(GetOwnerDoc(), aAttribute, aValue);
x = aInfo1->mDefaultValue;
y = aInfo2->mDefaultValue;
}
aNum1->SetBaseValue(x, this, PR_FALSE);
aNum2->SetBaseValue(y, this, PR_FALSE);
if (parseError)
return PR_FALSE;
aResult.SetTo(aValue);
return PR_TRUE;
}
nsresult
nsSVGFE::SetupScalingFilter(nsSVGFilterInstance *aInstance,
nsSVGFilterResource *aResource,
@ -643,12 +596,9 @@ nsSVGFEGaussianBlurElement::ParseAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
nsAttrValue& aResult)
{
if (aName == nsGkAtoms::stdDeviation && aNameSpaceID == kNameSpaceID_None) {
return ScanDualValueAttribute(aValue, nsGkAtoms::stdDeviation,
&mNumberAttributes[STD_DEV_X],
&mNumberAttributes[STD_DEV_Y],
&sNumberInfo[STD_DEV_X],
&sNumberInfo[STD_DEV_Y],
aResult);
return ParseNumberOptionalNumber(aName, aValue,
STD_DEV_X, STD_DEV_Y,
aResult);
}
return nsSVGFEGaussianBlurElementBase::ParseAttribute(aNameSpaceID, aName,
aValue, aResult);
@ -3203,12 +3153,9 @@ nsSVGFETurbulenceElement::ParseAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
nsAttrValue& aResult)
{
if (aName == nsGkAtoms::baseFrequency && aNameSpaceID == kNameSpaceID_None) {
return ScanDualValueAttribute(aValue, nsGkAtoms::baseFrequency,
&mNumberAttributes[BASE_FREQ_X],
&mNumberAttributes[BASE_FREQ_Y],
&sNumberInfo[BASE_FREQ_X],
&sNumberInfo[BASE_FREQ_Y],
aResult);
return ParseNumberOptionalNumber(aName, aValue,
BASE_FREQ_X, BASE_FREQ_Y,
aResult);
}
return nsSVGFETurbulenceElementBase::ParseAttribute(aNameSpaceID, aName,
aValue, aResult);
@ -3658,12 +3605,9 @@ nsSVGFEMorphologyElement::ParseAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
nsAttrValue& aResult)
{
if (aName == nsGkAtoms::radius && aNameSpaceID == kNameSpaceID_None) {
return ScanDualValueAttribute(aValue, nsGkAtoms::radius,
&mNumberAttributes[RADIUS_X],
&mNumberAttributes[RADIUS_Y],
&sNumberInfo[RADIUS_X],
&sNumberInfo[RADIUS_Y],
aResult);
return ParseNumberOptionalNumber(aName, aValue,
RADIUS_X, RADIUS_Y,
aResult);
}
return nsSVGFEMorphologyElementBase::ParseAttribute(aNameSpaceID, aName,
aValue, aResult);
@ -4038,54 +3982,17 @@ nsSVGFEConvolveMatrixElement::ParseAttribute(PRInt32 aNameSpaceID, nsIAtom* aNam
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aName == nsGkAtoms::order && aNameSpaceID == kNameSpaceID_None) {
PRInt32 x = 0, y = 0;
char *rest;
PRBool parseError = PR_FALSE;
NS_ConvertUTF16toUTF8 value(aValue);
value.CompressWhitespace(PR_FALSE, PR_TRUE);
const char *str = value.get();
x = strtol(str, &rest, 10);
if (str == rest) {
//first value was illformed
parseError = PR_TRUE;
} else {
if (*rest == '\0') {
//second value was not supplied
y = x;
} else {
y = strtol(rest, &rest, 10);
if (*rest != '\0') {
//second value was illformed or there was trailing content
parseError = PR_TRUE;
}
}
if (aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::order) {
return ParseIntegerOptionalInteger(aName, aValue,
ORDER_X, ORDER_Y,
aResult);
}
if (parseError) {
ReportAttributeParseFailure(GetOwnerDoc(), aName, aValue);
x = sIntegerInfo[ORDER_X].mDefaultValue;
y = sIntegerInfo[ORDER_Y].mDefaultValue;
if (aName == nsGkAtoms::kernelUnitLength) {
return ParseNumberOptionalNumber(aName, aValue,
KERNEL_UNIT_LENGTH_X, KERNEL_UNIT_LENGTH_Y,
aResult);
}
mIntegerAttributes[ORDER_X].SetBaseValue(x, this, PR_FALSE);
mIntegerAttributes[ORDER_Y].SetBaseValue(y, this, PR_FALSE);
if (parseError)
return PR_FALSE;
aResult.SetTo(aValue);
return PR_TRUE;
}
if (aName == nsGkAtoms::kernelUnitLength && aNameSpaceID == kNameSpaceID_None) {
return ScanDualValueAttribute(aValue, nsGkAtoms::kernelUnitLength,
&mNumberAttributes[KERNEL_UNIT_LENGTH_X],
&mNumberAttributes[KERNEL_UNIT_LENGTH_Y],
&sNumberInfo[KERNEL_UNIT_LENGTH_X],
&sNumberInfo[KERNEL_UNIT_LENGTH_Y],
aResult);
}
return nsSVGFEConvolveMatrixElementBase::ParseAttribute(aNameSpaceID, aName,
@ -4710,15 +4617,13 @@ nsSVGFELightingElement::ParseAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
nsAttrValue& aResult)
{
if (aName == nsGkAtoms::kernelUnitLength && aNameSpaceID == kNameSpaceID_None) {
return ScanDualValueAttribute(aValue, nsGkAtoms::radius,
&mNumberAttributes[KERNEL_UNIT_LENGTH_X],
&mNumberAttributes[KERNEL_UNIT_LENGTH_Y],
&sNumberInfo[KERNEL_UNIT_LENGTH_X],
&sNumberInfo[KERNEL_UNIT_LENGTH_Y],
aResult);
return ParseNumberOptionalNumber(aName, aValue,
KERNEL_UNIT_LENGTH_X, KERNEL_UNIT_LENGTH_Y,
aResult);
}
return nsSVGFELightingElementBase::ParseAttribute(aNameSpaceID, aName,
aValue, aResult);
aValue, aResult);
}
NS_IMETHODIMP

View File

@ -55,11 +55,6 @@ protected:
nsSVGFE(nsINodeInfo *aNodeInfo) : nsSVGFEBase(aNodeInfo) {}
nsresult Init();
PRBool ScanDualValueAttribute(const nsAString& aValue, nsIAtom* aAttribute,
nsSVGNumber2* aNum1, nsSVGNumber2* aNum2,
NumberInfo* aInfo1, NumberInfo* aInfo2,
nsAttrValue& aResult);
struct ScaleInfo {
nsRefPtr<gfxImageSurface> mRealSource;
nsRefPtr<gfxImageSurface> mRealTarget;