зеркало из https://github.com/mozilla/gecko-dev.git
Bug 937614 - simplify nsSMILParserUtils. r=dholbert
This commit is contained in:
Родитель
13f37acc5c
Коммит
1b917abd1b
|
@ -64,6 +64,7 @@ FAIL_ON_WARNINGS = True
|
|||
LOCAL_INCLUDES += [
|
||||
'../base/src',
|
||||
'../events/src',
|
||||
'../svg/content/src',
|
||||
'/layout/style',
|
||||
]
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче