Bug 937614 - simplify nsSMILParserUtils. r=dholbert

This commit is contained in:
Robert Longson 2013-11-25 19:46:20 +00:00
parent 972fb7840f
commit 5bfde7b612
15 changed files with 714 additions and 853 deletions

View File

@ -64,6 +64,7 @@ FAIL_ON_WARNINGS = True
LOCAL_INCLUDES += [
'../base/src',
'../events/src',
'../svg/content/src',
'/layout/style',
]

View File

@ -754,11 +754,11 @@ nsSMILAnimationFunction::GetValues(const nsISMILAttr& aSMILAttr,
nsAutoString attValue;
GetAttr(nsGkAtoms::values, attValue);
bool preventCachingOfSandwich = false;
nsresult rv = nsSMILParserUtils::ParseValues(attValue, mAnimationElement,
aSMILAttr, result,
preventCachingOfSandwich);
if (NS_FAILED(rv))
return rv;
if (!nsSMILParserUtils::ParseValues(attValue, mAnimationElement,
aSMILAttr, result,
preventCachingOfSandwich)) {
return NS_ERROR_FAILURE;
}
if (preventCachingOfSandwich) {
mValueNeedsReparsingEverySample = true;
@ -1014,29 +1014,14 @@ nsSMILAnimationFunction::SetKeySplines(const nsAString& aKeySplines,
mKeySplines.Clear();
aResult.SetTo(aKeySplines);
nsTArray<double> keySplines;
nsresult rv = nsSMILParserUtils::ParseKeySplines(aKeySplines, keySplines);
if (keySplines.Length() < 1 || keySplines.Length() % 4)
rv = NS_ERROR_FAILURE;
if (NS_SUCCEEDED(rv))
{
mKeySplines.SetCapacity(keySplines.Length() % 4);
for (uint32_t i = 0; i < keySplines.Length() && NS_SUCCEEDED(rv); i += 4)
{
if (!mKeySplines.AppendElement(nsSMILKeySpline(keySplines[i],
keySplines[i+1],
keySplines[i+2],
keySplines[i+3]))) {
rv = NS_ERROR_OUT_OF_MEMORY;
}
}
}
mHasChanged = true;
return rv;
if (!nsSMILParserUtils::ParseKeySplines(aKeySplines, mKeySplines)) {
mKeySplines.Clear();
return NS_ERROR_FAILURE;
}
return NS_OK;
}
void
@ -1054,18 +1039,14 @@ nsSMILAnimationFunction::SetKeyTimes(const nsAString& aKeyTimes,
mKeyTimes.Clear();
aResult.SetTo(aKeyTimes);
nsresult rv =
nsSMILParserUtils::ParseSemicolonDelimitedProgressList(aKeyTimes, true,
mKeyTimes);
if (NS_SUCCEEDED(rv) && mKeyTimes.Length() < 1)
rv = NS_ERROR_FAILURE;
if (NS_FAILED(rv))
mKeyTimes.Clear();
mHasChanged = true;
if (!nsSMILParserUtils::ParseSemicolonDelimitedProgressList(aKeyTimes, true,
mKeyTimes)) {
mKeyTimes.Clear();
return NS_ERROR_FAILURE;
}
return NS_OK;
}

View File

@ -251,7 +251,7 @@ public:
protected:
// Typedefs
typedef nsTArray<nsSMILValue> nsSMILValueArray;
typedef FallibleTArray<nsSMILValue> nsSMILValueArray;
// Types
enum nsSMILCalcMode
@ -398,8 +398,8 @@ protected:
static nsAttrValue::EnumTable sCalcModeTable[];
static nsAttrValue::EnumTable sAccumulateTable[];
nsTArray<double> mKeyTimes;
nsTArray<nsSMILKeySpline> mKeySplines;
FallibleTArray<double> mKeyTimes;
FallibleTArray<nsSMILKeySpline> mKeySplines;
// These are the parameters provided by the previous sample. Currently we
// perform lazy calculation. That is, we only calculate the result if and when

File diff suppressed because it is too large Load Diff

View File

@ -6,11 +6,11 @@
#ifndef NS_SMILPARSERUTILS_H_
#define NS_SMILPARSERUTILS_H_
#include "nscore.h"
#include "nsTArray.h"
#include "nsString.h"
#include "nsStringFwd.h"
class nsISMILAttr;
class nsSMILKeySpline;
class nsSMILTimeValue;
class nsSMILValue;
class nsSMILRepeatCount;
@ -31,72 +31,49 @@ class nsSMILParserUtils
{
public:
// Abstract helper-class for assisting in parsing |values| attribute
class GenericValueParser {
class MOZ_STACK_CLASS GenericValueParser {
public:
virtual nsresult Parse(const nsAString& aValueStr) = 0;
virtual bool Parse(const nsAString& aValueStr) = 0;
};
static nsresult ParseKeySplines(const nsAString& aSpec,
nsTArray<double>& aSplineArray);
static const nsDependentSubstring TrimWhitespace(const nsAString& aString);
static bool ParseKeySplines(const nsAString& aSpec,
FallibleTArray<nsSMILKeySpline>& aKeySplines);
// Used for parsing the |keyTimes| and |keyPoints| attributes.
static nsresult ParseSemicolonDelimitedProgressList(const nsAString& aSpec,
bool aNonDecreasing,
nsTArray<double>& aArray);
static bool ParseSemicolonDelimitedProgressList(const nsAString& aSpec,
bool aNonDecreasing,
FallibleTArray<double>& aArray);
static nsresult ParseValues(const nsAString& aSpec,
const mozilla::dom::SVGAnimationElement* aSrcElement,
const nsISMILAttr& aAttribute,
nsTArray<nsSMILValue>& aValuesArray,
bool& aPreventCachingOfSandwich);
static bool ParseValues(const nsAString& aSpec,
const mozilla::dom::SVGAnimationElement* aSrcElement,
const nsISMILAttr& aAttribute,
FallibleTArray<nsSMILValue>& aValuesArray,
bool& aPreventCachingOfSandwich);
// Generic method that will run some code on each sub-section of an animation
// element's "values" list.
static nsresult ParseValuesGeneric(const nsAString& aSpec,
GenericValueParser& aParser);
static bool ParseValuesGeneric(const nsAString& aSpec,
GenericValueParser& aParser);
static nsresult ParseRepeatCount(const nsAString& aSpec,
nsSMILRepeatCount& aResult);
static bool ParseRepeatCount(const nsAString& aSpec,
nsSMILRepeatCount& aResult);
static nsresult ParseTimeValueSpecParams(const nsAString& aSpec,
nsSMILTimeValueSpecParams& aResult);
// Used with ParseClockValue. Allow + or - before a clock value.
static const int8_t kClockValueAllowSign = 1;
// Used with ParseClockValue. Allow "indefinite" in a clock value
static const int8_t kClockValueAllowIndefinite = 2;
static bool ParseTimeValueSpecParams(const nsAString& aSpec,
nsSMILTimeValueSpecParams& aResult);
/*
* This method can actually parse more than a clock value as defined in the
* SMIL Animation specification. It can also parse:
* - the + or - before an offset
* - the special value "indefinite"
* - the special value "media"
*
* Because the value "media" cannot be represented as part of an
* nsSMILTimeValue and has different meanings depending on where it is used,
* it is passed out as a separate parameter (which can be set to nullptr if the
* media attribute is not allowed).
* Parses a clock value as defined in the SMIL Animation specification.
* If parsing succeeds the returned value will be a non-negative, definite
* time value i.e. IsDefinite will return true.
*
* @param aSpec The string containing a clock value, e.g. "10s"
* @param aResult The parsed result. May be nullptr (e.g. if this method is
* being called just to test if aSpec is a valid clock value).
* [OUT]
* @param aFlags A combination of the kClockValue* bit flags OR'ed together
* to define what additional syntax is allowed.
* @param aIsMedia Optional out parameter which, if not null, will be set to
* true if the value is the string "media", false
* otherwise. If it is null, the string "media" is not
* allowed.
*
* @return NS_OK if aSpec was successfully parsed as a valid clock value
* (according to aFlags), an error code otherwise.
* @param aResult The parsed result. [OUT]
* @return true if parsing succeeded, otherwise false.
*/
static nsresult ParseClockValue(const nsAString& aSpec,
nsSMILTimeValue* aResult,
uint32_t aFlags = 0,
bool* aIsMedia = nullptr);
static bool ParseClockValue(const nsAString& aSpec,
nsSMILTimeValue* aResult);
/*
* This method checks whether the given string looks like a negative number.

View File

@ -68,11 +68,9 @@ nsSMILTimeValueSpec::SetSpec(const nsAString& aStringSpec,
Element* aContextNode)
{
nsSMILTimeValueSpecParams params;
nsresult rv =
nsSMILParserUtils::ParseTimeValueSpecParams(aStringSpec, params);
if (NS_FAILED(rv))
return rv;
if (!nsSMILParserUtils::ParseTimeValueSpecParams(aStringSpec, params))
return NS_ERROR_FAILURE;
mParams = params;
@ -94,7 +92,7 @@ nsSMILTimeValueSpec::SetSpec(const nsAString& aStringSpec,
ResolveReferences(aContextNode);
return rv;
return NS_OK;
}
void

View File

@ -906,31 +906,22 @@ nsresult
nsSMILTimedElement::SetSimpleDuration(const nsAString& aDurSpec)
{
nsSMILTimeValue duration;
bool isMedia;
nsresult rv;
rv = nsSMILParserUtils::ParseClockValue(aDurSpec, &duration,
nsSMILParserUtils::kClockValueAllowIndefinite, &isMedia);
const nsAString& dur = nsSMILParserUtils::TrimWhitespace(aDurSpec);
if (NS_FAILED(rv)) {
mSimpleDur.SetIndefinite();
return NS_ERROR_FAILURE;
}
if (duration.IsDefinite() && duration.GetMillis() == 0L) {
mSimpleDur.SetIndefinite();
return NS_ERROR_FAILURE;
}
//
// SVG-specific: "For SVG's animation elements, if "media" is specified, the
// attribute will be ignored." (SVG 1.1, section 19.2.6)
//
if (isMedia)
if (dur.EqualsLiteral("media") || dur.EqualsLiteral("indefinite")) {
duration.SetIndefinite();
} else {
if (!nsSMILParserUtils::ParseClockValue(dur, &duration) ||
duration.GetMillis() == 0L) {
mSimpleDur.SetIndefinite();
return NS_ERROR_FAILURE;
}
}
// mSimpleDur should never be unresolved. ParseClockValue will either set
// duration to resolved/indefinite/media or will return a failure code.
// duration to resolved or will return false.
NS_ABORT_IF_FALSE(duration.IsResolved(),
"Setting unresolved simple duration");
@ -951,24 +942,19 @@ nsresult
nsSMILTimedElement::SetMin(const nsAString& aMinSpec)
{
nsSMILTimeValue duration;
bool isMedia;
nsresult rv;
rv = nsSMILParserUtils::ParseClockValue(aMinSpec, &duration, 0, &isMedia);
const nsAString& min = nsSMILParserUtils::TrimWhitespace(aMinSpec);
if (isMedia) {
if (min.EqualsLiteral("media")) {
duration.SetMillis(0L);
} else {
if (!nsSMILParserUtils::ParseClockValue(min, &duration)) {
mMin.SetMillis(0L);
return NS_ERROR_FAILURE;
}
}
if (NS_FAILED(rv) || !duration.IsDefinite()) {
mMin.SetMillis(0L);
return NS_ERROR_FAILURE;
}
if (duration.GetMillis() < 0L) {
mMin.SetMillis(0L);
return NS_ERROR_FAILURE;
}
NS_ABORT_IF_FALSE(duration.GetMillis() >= 0L, "Invalid duration");
mMin = duration;
UpdateCurrentInterval();
@ -987,23 +973,18 @@ nsresult
nsSMILTimedElement::SetMax(const nsAString& aMaxSpec)
{
nsSMILTimeValue duration;
bool isMedia;
nsresult rv;
rv = nsSMILParserUtils::ParseClockValue(aMaxSpec, &duration,
nsSMILParserUtils::kClockValueAllowIndefinite, &isMedia);
const nsAString& max = nsSMILParserUtils::TrimWhitespace(aMaxSpec);
if (isMedia)
if (max.EqualsLiteral("media") || max.EqualsLiteral("indefinite")) {
duration.SetIndefinite();
if (NS_FAILED(rv) || !duration.IsResolved()) {
mMax.SetIndefinite();
return NS_ERROR_FAILURE;
}
if (duration.IsDefinite() && duration.GetMillis() <= 0L) {
mMax.SetIndefinite();
return NS_ERROR_FAILURE;
} else {
if (!nsSMILParserUtils::ParseClockValue(max, &duration) ||
duration.GetMillis() == 0L) {
mMax.SetIndefinite();
return NS_ERROR_FAILURE;
}
NS_ABORT_IF_FALSE(duration.GetMillis() > 0L, "Invalid duration");
}
mMax = duration;
@ -1043,18 +1024,15 @@ nsresult
nsSMILTimedElement::SetRepeatCount(const nsAString& aRepeatCountSpec)
{
nsSMILRepeatCount newRepeatCount;
nsresult rv =
nsSMILParserUtils::ParseRepeatCount(aRepeatCountSpec, newRepeatCount);
if (NS_SUCCEEDED(rv)) {
if (nsSMILParserUtils::ParseRepeatCount(aRepeatCountSpec, newRepeatCount)) {
mRepeatCount = newRepeatCount;
} else {
mRepeatCount.Unset();
UpdateCurrentInterval();
return NS_OK;
}
mRepeatCount.Unset();
UpdateCurrentInterval();
return rv;
return NS_ERROR_FAILURE;
}
void
@ -1067,15 +1045,18 @@ nsSMILTimedElement::UnsetRepeatCount()
nsresult
nsSMILTimedElement::SetRepeatDur(const nsAString& aRepeatDurSpec)
{
nsresult rv;
nsSMILTimeValue duration;
rv = nsSMILParserUtils::ParseClockValue(aRepeatDurSpec, &duration,
nsSMILParserUtils::kClockValueAllowIndefinite);
const nsAString& repeatDur =
nsSMILParserUtils::TrimWhitespace(aRepeatDurSpec);
if (NS_FAILED(rv) || !duration.IsResolved()) {
mRepeatDur.SetUnresolved();
return NS_ERROR_FAILURE;
if (repeatDur.EqualsLiteral("indefinite")) {
duration.SetIndefinite();
} else {
if (!nsSMILParserUtils::ParseClockValue(repeatDur, &duration)) {
mRepeatDur.SetUnresolved();
return NS_ERROR_FAILURE;
}
}
mRepeatDur = duration;

View File

@ -368,97 +368,70 @@ SVGContentUtils::GetViewBoxTransform(float aViewportWidth, float aViewportHeight
return gfxMatrix(a, 0.0f, 0.0f, d, e, f);
}
/**
* True if 'aCh' is a decimal digit.
*/
static inline bool
IsDigit(PRUnichar aCh)
static bool
ParseNumber(RangedPtr<const PRUnichar>& aIter,
const RangedPtr<const PRUnichar>& aEnd,
double& aValue)
{
return aCh >= '0' && aCh <= '9';
}
/**
* Assuming that 'aCh' is a decimal digit, return its numeric value.
*/
static inline uint32_t
DecimalDigitValue(PRUnichar aCh)
{
MOZ_ASSERT(IsDigit(aCh), "Digit expected");
return aCh - '0';
}
template<class floatType>
bool
SVGContentUtils::ParseNumber(RangedPtr<const PRUnichar>& aIter,
const RangedPtr<const PRUnichar>& aEnd,
floatType& aValue)
{
if (aIter == aEnd) {
int32_t sign;
if (!SVGContentUtils::ParseOptionalSign(aIter, aEnd, sign)) {
return false;
}
RangedPtr<const PRUnichar> iter(aIter);
// Sign of the mantissa (-1 or 1).
int32_t sign = *iter == '-' ? -1 : 1;
if (*iter == '-' || *iter == '+') {
++iter;
if (iter == aEnd) {
return false;
}
}
// Absolute value of the integer part of the mantissa.
floatType intPart = floatType(0);
double intPart = 0.0;
bool gotDot = *iter == '.';
bool gotDot = *aIter == '.';
if (!gotDot) {
if (!IsDigit(*iter)) {
if (!SVGContentUtils::IsDigit(*aIter)) {
return false;
}
do {
intPart = floatType(10) * intPart + DecimalDigitValue(*iter);
++iter;
} while (iter != aEnd && IsDigit(*iter));
intPart = 10.0 * intPart + SVGContentUtils::DecimalDigitValue(*aIter);
++aIter;
} while (aIter != aEnd && SVGContentUtils::IsDigit(*aIter));
if (iter != aEnd) {
gotDot = *iter == '.';
if (aIter != aEnd) {
gotDot = *aIter == '.';
}
}
// Fractional part of the mantissa.
floatType fracPart = floatType(0);
double fracPart = 0.0;
if (gotDot) {
++iter;
if (iter == aEnd || !IsDigit(*iter)) {
++aIter;
if (aIter == aEnd || !SVGContentUtils::IsDigit(*aIter)) {
return false;
}
// Power of ten by which we need to divide our next digit
floatType divisor = floatType(10);
// Power of ten by which we need to divide the fraction
double divisor = 1.0;
do {
fracPart += DecimalDigitValue(*iter) / divisor;
divisor *= 10;
++iter;
} while (iter != aEnd && IsDigit(*iter));
fracPart = 10.0 * fracPart + SVGContentUtils::DecimalDigitValue(*aIter);
divisor *= 10.0;
++aIter;
} while (aIter != aEnd && SVGContentUtils::IsDigit(*aIter));
fracPart /= divisor;
}
bool gotE = false;
int32_t exponent = 0;
int32_t expSign;
if (iter != aEnd && (*iter == 'e' || *iter == 'E')) {
if (aIter != aEnd && (*aIter == 'e' || *aIter == 'E')) {
RangedPtr<const PRUnichar> expIter(iter);
RangedPtr<const PRUnichar> expIter(aIter);
++expIter;
if (expIter != aEnd) {
expSign = *expIter == '-' ? -1 : 1;
if (*expIter == '-' || *expIter == '+') {
++expIter;
if (expIter != aEnd && IsDigit(*expIter)) {
if (expIter != aEnd && SVGContentUtils::IsDigit(*expIter)) {
// At this point we're sure this is an exponent
// and not the start of a unit such as em or ex.
gotE = true;
@ -467,24 +440,40 @@ SVGContentUtils::ParseNumber(RangedPtr<const PRUnichar>& aIter,
}
if (gotE) {
iter = expIter;
aIter = expIter;
do {
exponent = 10 * exponent + DecimalDigitValue(*iter);
++iter;
} while (iter != aEnd && IsDigit(*iter));
exponent = 10.0 * exponent + SVGContentUtils::DecimalDigitValue(*aIter);
++aIter;
} while (aIter != aEnd && SVGContentUtils::IsDigit(*aIter));
}
}
// Assemble the number
floatType value = sign * (intPart + fracPart);
aValue = sign * (intPart + fracPart);
if (gotE) {
value *= pow(floatType(10), floatType(expSign * exponent));
aValue *= pow(10.0, expSign * exponent);
}
if (!NS_finite(value)) {
return true;
}
template<class floatType>
bool
SVGContentUtils::ParseNumber(RangedPtr<const PRUnichar>& aIter,
const RangedPtr<const PRUnichar>& aEnd,
floatType& aValue)
{
RangedPtr<const PRUnichar> iter(aIter);
double value;
if (!::ParseNumber(iter, aEnd, value)) {
return false;
}
floatType floatValue = floatType(value);
if (!NS_finite(floatValue)) {
return false;
}
aValue = floatValue;
aIter = iter;
aValue = value;
return true;
}
@ -492,6 +481,7 @@ template bool
SVGContentUtils::ParseNumber<float>(RangedPtr<const PRUnichar>& aIter,
const RangedPtr<const PRUnichar>& aEnd,
float& aValue);
template bool
SVGContentUtils::ParseNumber<double>(RangedPtr<const PRUnichar>& aIter,
const RangedPtr<const PRUnichar>& aEnd,
@ -528,6 +518,40 @@ template bool
SVGContentUtils::ParseNumber<double>(const nsAString& aString,
double& aValue);
/* static */
bool
SVGContentUtils::ParseInteger(RangedPtr<const PRUnichar>& aIter,
const RangedPtr<const PRUnichar>& aEnd,
int32_t& aValue)
{
RangedPtr<const PRUnichar> iter(aIter);
int32_t sign;
if (!ParseOptionalSign(iter, aEnd, sign)) {
return false;
}
if (!IsDigit(*iter)) {
return false;
}
int64_t value = 0;
do {
if (value <= std::numeric_limits<int32_t>::max()) {
value = 10 * value + DecimalDigitValue(*iter);
}
++iter;
} while (iter != aEnd && IsDigit(*iter));
aIter = iter;
aValue = int32_t(clamped(sign * value,
int64_t(std::numeric_limits<int32_t>::min()),
int64_t(std::numeric_limits<int32_t>::max())));
return true;
}
/* static */
bool
SVGContentUtils::ParseInteger(const nsAString& aString,
int32_t& aValue)
@ -535,35 +559,7 @@ SVGContentUtils::ParseInteger(const nsAString& aString,
RangedPtr<const PRUnichar> iter = GetStartRangedPtr(aString);
const RangedPtr<const PRUnichar> end = GetEndRangedPtr(aString);
if (iter == end) {
return false;
}
int32_t sign = *iter == '-' ? -1 : 1;
if (*iter == '-' || *iter == '+') {
++iter;
if (iter == end) {
return false;
}
}
int64_t value = 0;
do {
if (!IsDigit(*iter)) {
return false;
}
if (value <= std::numeric_limits<int32_t>::max()) {
value = 10 * value + DecimalDigitValue(*iter);
}
++iter;
} while (iter != end);
aValue = int32_t(clamped(sign * value,
int64_t(std::numeric_limits<int32_t>::min()),
int64_t(std::numeric_limits<int32_t>::max())));
return true;
return ParseInteger(iter, end, aValue) && iter == end;
}
float

View File

@ -141,6 +141,52 @@ public:
static mozilla::RangedPtr<const PRUnichar>
GetEndRangedPtr(const nsAString& aString);
/**
* True if 'aCh' is a decimal digit.
*/
static inline bool IsDigit(PRUnichar aCh)
{
return aCh >= '0' && aCh <= '9';
}
/**
* Assuming that 'aCh' is a decimal digit, return its numeric value.
*/
static inline uint32_t DecimalDigitValue(PRUnichar aCh)
{
MOZ_ASSERT(IsDigit(aCh), "Digit expected");
return aCh - '0';
}
/**
* Parses the sign (+ or -) of a number and moves aIter to the next
* character if a sign is found.
* @param aSignMultiplier [outparam] -1 if the sign is negative otherwise 1
* @return false if we hit the end of the string (i.e. if aIter is initially
* at aEnd, or if we reach aEnd right after the sign character).
*/
static inline bool
ParseOptionalSign(mozilla::RangedPtr<const PRUnichar>& aIter,
const mozilla::RangedPtr<const PRUnichar>& aEnd,
int32_t& aSignMultiplier)
{
if (aIter == aEnd) {
return false;
}
aSignMultiplier = *aIter == '-' ? -1 : 1;
mozilla::RangedPtr<const PRUnichar> iter(aIter);
if (*iter == '-' || *iter == '+') {
++iter;
if (iter == aEnd) {
return false;
}
}
aIter = iter;
return true;
}
/**
* Parse a number of the form:
* number ::= integer ([Ee] integer)? | [+-]? [0-9]* "." [0-9]+ ([Ee] integer)?
@ -167,10 +213,21 @@ public:
/**
* Parse an integer of the form:
* integer ::= [+-]? [0-9]+
* Parsing fails if the number cannot be represented by an int32_t.
* The returned number is clamped to an int32_t if outside that range.
* If parsing succeeds, aIter is updated so that it points to the character
* after the end of the number, otherwise it is left unchanged
*/
static bool
ParseInteger(const nsAString& aString, int32_t& aValue);
static bool ParseInteger(mozilla::RangedPtr<const PRUnichar>& aIter,
const mozilla::RangedPtr<const PRUnichar>& aEnd,
int32_t& aValue);
/**
* Parse an integer of the form:
* integer ::= [+-]? [0-9]+
* The returned number is clamped to an int32_t if outside that range.
* Parsing fails if there is anything left over after the number.
*/
static bool ParseInteger(const nsAString& aString, int32_t& aValue);
/**
* Converts an nsStyleCoord into a userspace value. Handles units

View File

@ -168,8 +168,7 @@ SVGMotionSMILAnimationFunction::
const nsAString& valuesStr = GetAttr(nsGkAtoms::values)->GetStringValue();
SVGMotionSMILPathUtils::MotionValueParser parser(&pathGenerator,
&mPathVertices);
success =
NS_SUCCEEDED(nsSMILParserUtils::ParseValuesGeneric(valuesStr, parser));
success = nsSMILParserUtils::ParseValuesGeneric(valuesStr, parser);
} else if (HasAttr(nsGkAtoms::to) || HasAttr(nsGkAtoms::by)) {
// Apply 'from' value (or a dummy 0,0 'from' value)
if (HasAttr(nsGkAtoms::from)) {
@ -296,8 +295,8 @@ bool
SVGMotionSMILAnimationFunction::
GenerateValuesForPathAndPoints(Path* aPath,
bool aIsKeyPoints,
nsTArray<double>& aPointDistances,
nsTArray<nsSMILValue>& aResult)
FallibleTArray<double>& aPointDistances,
nsSMILValueArray& aResult)
{
NS_ABORT_IF_FALSE(aResult.IsEmpty(), "outparam is non-empty");
@ -335,9 +334,9 @@ SVGMotionSMILAnimationFunction::GetValues(const nsISMILAttr& aSMILAttr,
// Now: Make the actual list of nsSMILValues (using keyPoints, if set)
bool isUsingKeyPoints = !mKeyPoints.IsEmpty();
bool success = GenerateValuesForPathAndPoints(mPath, isUsingKeyPoints,
isUsingKeyPoints ?
isUsingKeyPoints ?
mKeyPoints : mPathVertices,
aResult);
aResult);
if (!success) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -402,19 +401,14 @@ SVGMotionSMILAnimationFunction::SetKeyPoints(const nsAString& aKeyPoints,
mKeyPoints.Clear();
aResult.SetTo(aKeyPoints);
nsresult rv =
nsSMILParserUtils::ParseSemicolonDelimitedProgressList(aKeyPoints, false,
mKeyPoints);
if (NS_SUCCEEDED(rv) && mKeyPoints.Length() < 1)
rv = NS_ERROR_FAILURE;
if (NS_FAILED(rv)) {
mKeyPoints.Clear();
}
mHasChanged = true;
if (!nsSMILParserUtils::ParseSemicolonDelimitedProgressList(aKeyPoints, false,
mKeyPoints)) {
mKeyPoints.Clear();
return NS_ERROR_FAILURE;
}
return NS_OK;
}

View File

@ -83,19 +83,19 @@ protected:
void RebuildPathAndVerticesFromBasicAttrs(const nsIContent* aContextElem);
bool GenerateValuesForPathAndPoints(Path* aPath,
bool aIsKeyPoints,
nsTArray<double>& aPointDistances,
nsTArray<nsSMILValue>& aResult);
FallibleTArray<double>& aPointDistances,
nsSMILValueArray& aResult);
// Members
// -------
nsTArray<double> mKeyPoints; // parsed from "keyPoints" attribute.
FallibleTArray<double> mKeyPoints; // parsed from "keyPoints" attribute.
RotateType mRotateType; // auto, auto-reverse, or explicit.
float mRotateAngle; // the angle value, if explicit.
PathSourceType mPathSourceType; // source of our Path.
RefPtr<Path> mPath; // representation of motion path.
nsTArray<double> mPathVertices; // distances of vertices along path.
FallibleTArray<double> mPathVertices; // distances of vertices along path.
bool mIsPathStale;
};

View File

@ -126,7 +126,7 @@ SVGMotionSMILPathUtils::PathGenerator::
//----------------------------------------------------------------------
// MotionValueParser methods
nsresult
bool
SVGMotionSMILPathUtils::MotionValueParser::
Parse(const nsAString& aValueStr)
{
@ -145,7 +145,7 @@ SVGMotionSMILPathUtils::MotionValueParser::
success = !!mPointDistances->AppendElement(mDistanceSoFar);
}
}
return success ? NS_OK : NS_ERROR_FAILURE;
return success;
}
} // namespace mozilla

View File

@ -76,11 +76,12 @@ public:
// Class to assist in passing each subcomponent of a |values| attribute to
// a PathGenerator, for generating a corresponding Path.
class MotionValueParser : public nsSMILParserUtils::GenericValueParser
class MOZ_STACK_CLASS MotionValueParser :
public nsSMILParserUtils::GenericValueParser
{
public:
MotionValueParser(PathGenerator* aPathGenerator,
nsTArray<double>* aPointDistances)
FallibleTArray<double>* aPointDistances)
: mPathGenerator(aPathGenerator),
mPointDistances(aPointDistances),
mDistanceSoFar(0.0)
@ -90,12 +91,12 @@ public:
}
// nsSMILParserUtils::GenericValueParser interface
virtual nsresult Parse(const nsAString& aValueStr) MOZ_OVERRIDE;
virtual bool Parse(const nsAString& aValueStr) MOZ_OVERRIDE;
protected:
PathGenerator* mPathGenerator;
nsTArray<double>* mPointDistances;
double mDistanceSoFar;
PathGenerator* mPathGenerator;
FallibleTArray<double>* mPointDistances;
double mDistanceSoFar;
};
};

View File

@ -151,7 +151,7 @@ SVGPathData::GetSegmentLengths(nsTArray<double> *aLengths) const
}
bool
SVGPathData::GetDistancesFromOriginToEndsOfVisibleSegments(nsTArray<double> *aOutput) const
SVGPathData::GetDistancesFromOriginToEndsOfVisibleSegments(FallibleTArray<double> *aOutput) const
{
SVGPathTraversalState state;

View File

@ -156,7 +156,7 @@ public:
/**
* Returns true, except on OOM, in which case returns false.
*/
bool GetDistancesFromOriginToEndsOfVisibleSegments(nsTArray<double> *aArray) const;
bool GetDistancesFromOriginToEndsOfVisibleSegments(FallibleTArray<double> *aArray) const;
/**
* This returns a path without the extra little line segments that