forked from mirrors/gecko-dev
Bug 733744 - don't round short durations to zero r=birtles
Differential Revision: https://phabricator.services.mozilla.com/D195971
This commit is contained in:
parent
58cb4c95a3
commit
2e1f916689
6 changed files with 53 additions and 26 deletions
|
|
@ -9,7 +9,6 @@
|
|||
#include "mozilla/SMILAttr.h"
|
||||
#include "mozilla/SMILKeySpline.h"
|
||||
#include "mozilla/SMILRepeatCount.h"
|
||||
#include "mozilla/SMILTimeValue.h"
|
||||
#include "mozilla/SMILTimeValueSpecParams.h"
|
||||
#include "mozilla/SMILTypes.h"
|
||||
#include "mozilla/SMILValue.h"
|
||||
|
|
@ -128,6 +127,7 @@ inline bool ParseClockMetric(RangedPtr<const char16_t>& aIter,
|
|||
*/
|
||||
bool ParseClockValue(RangedPtr<const char16_t>& aIter,
|
||||
const RangedPtr<const char16_t>& aEnd,
|
||||
SMILTimeValue::Rounding aRounding,
|
||||
SMILTimeValue* aResult) {
|
||||
if (aIter == aEnd) {
|
||||
return false;
|
||||
|
|
@ -187,8 +187,9 @@ bool ParseClockValue(RangedPtr<const char16_t>& aIter,
|
|||
return false;
|
||||
}
|
||||
aResult->SetMillis(SMILTime(hours) * MSEC_PER_HOUR +
|
||||
minutes * MSEC_PER_MIN + seconds * MSEC_PER_SEC +
|
||||
NS_round(fraction * MSEC_PER_SEC));
|
||||
minutes * MSEC_PER_MIN +
|
||||
(seconds + fraction) * MSEC_PER_SEC,
|
||||
aRounding);
|
||||
aIter = iter;
|
||||
return true;
|
||||
case TIMECOUNT_VALUE:
|
||||
|
|
@ -203,8 +204,7 @@ bool ParseClockValue(RangedPtr<const char16_t>& aIter,
|
|||
if (!ParseClockMetric(iter, aEnd, multiplier)) {
|
||||
return false;
|
||||
}
|
||||
aResult->SetMillis(SMILTime(timecount) * multiplier +
|
||||
NS_round(fraction * multiplier));
|
||||
aResult->SetMillis((timecount + fraction) * multiplier, aRounding);
|
||||
aIter = iter;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -219,7 +219,8 @@ bool ParseOffsetValue(RangedPtr<const char16_t>& aIter,
|
|||
|
||||
int32_t sign;
|
||||
if (!SVGContentUtils::ParseOptionalSign(iter, aEnd, sign) ||
|
||||
!SkipWhitespace(iter, aEnd) || !ParseClockValue(iter, aEnd, aResult)) {
|
||||
!SkipWhitespace(iter, aEnd) ||
|
||||
!ParseClockValue(iter, aEnd, SMILTimeValue::Rounding::Nearest, aResult)) {
|
||||
return false;
|
||||
}
|
||||
if (sign == -1) {
|
||||
|
|
@ -240,7 +241,7 @@ bool ParseOptionalOffset(RangedPtr<const char16_t>& aIter,
|
|||
const RangedPtr<const char16_t>& aEnd,
|
||||
SMILTimeValue* aResult) {
|
||||
if (aIter == aEnd) {
|
||||
aResult->SetMillis(0L);
|
||||
*aResult = SMILTimeValue::Zero();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -597,11 +598,12 @@ bool SMILParserUtils::ParseTimeValueSpecParams(
|
|||
}
|
||||
|
||||
bool SMILParserUtils::ParseClockValue(const nsAString& aSpec,
|
||||
SMILTimeValue::Rounding aRounding,
|
||||
SMILTimeValue* aResult) {
|
||||
RangedPtr<const char16_t> iter(SVGContentUtils::GetStartRangedPtr(aSpec));
|
||||
RangedPtr<const char16_t> end(SVGContentUtils::GetEndRangedPtr(aSpec));
|
||||
|
||||
return ::ParseClockValue(iter, end, aResult) && iter == end;
|
||||
return ::ParseClockValue(iter, end, aRounding, aResult) && iter == end;
|
||||
}
|
||||
|
||||
int32_t SMILParserUtils::CheckForNegativeNumber(const nsAString& aStr) {
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@
|
|||
|
||||
#include "nsTArray.h"
|
||||
#include "nsStringFwd.h"
|
||||
#include "SMILTimeValue.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class SMILAttr;
|
||||
class SMILKeySpline;
|
||||
class SMILRepeatCount;
|
||||
class SMILTimeValue;
|
||||
class SMILTimeValueSpecParams;
|
||||
class SMILValue;
|
||||
|
||||
|
|
@ -72,7 +72,9 @@ class SMILParserUtils {
|
|||
* @param aResult The parsed result. [OUT]
|
||||
* @return true if parsing succeeded, otherwise false.
|
||||
*/
|
||||
static bool ParseClockValue(const nsAString& aSpec, SMILTimeValue* aResult);
|
||||
static bool ParseClockValue(const nsAString& aSpec,
|
||||
SMILTimeValue::Rounding aRounding,
|
||||
SMILTimeValue* aResult);
|
||||
|
||||
/*
|
||||
* This method checks whether the given string looks like a negative number.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "SMILTimeValue.h"
|
||||
#include "nsMathUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
@ -39,4 +40,13 @@ int8_t SMILTimeValue::CompareTo(const SMILTimeValue& aOther) const {
|
|||
return result;
|
||||
}
|
||||
|
||||
void SMILTimeValue::SetMillis(double aMillis, Rounding aRounding) {
|
||||
mState = STATE_DEFINITE;
|
||||
mMilliseconds = NS_round(aMillis);
|
||||
if (aRounding == Rounding::EnsureNonZero && !mMilliseconds && aMillis) {
|
||||
// Ensure we don't round small values to zero.
|
||||
mMilliseconds = std::copysign(1.0, aMillis);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ class SMILTimeValue {
|
|||
return value;
|
||||
}
|
||||
|
||||
static SMILTimeValue Zero() { return SMILTimeValue(SMILTime(0L)); }
|
||||
|
||||
bool IsIndefinite() const { return mState == STATE_INDEFINITE; }
|
||||
void SetIndefinite() {
|
||||
mState = STATE_INDEFINITE;
|
||||
|
|
@ -88,11 +90,23 @@ class SMILTimeValue {
|
|||
return mState == STATE_DEFINITE ? mMilliseconds : kUnresolvedMillis;
|
||||
}
|
||||
|
||||
bool IsZero() const {
|
||||
return mState == STATE_DEFINITE ? mMilliseconds == 0 : false;
|
||||
}
|
||||
|
||||
void SetMillis(SMILTime aMillis) {
|
||||
mState = STATE_DEFINITE;
|
||||
mMilliseconds = aMillis;
|
||||
}
|
||||
|
||||
/*
|
||||
* EnsureNonZero ensures values such as 0.0001s are not represented as 0
|
||||
* for values where 0 is invalid.
|
||||
*/
|
||||
enum class Rounding : uint8_t { EnsureNonZero, Nearest };
|
||||
|
||||
void SetMillis(double aMillis, Rounding aRounding);
|
||||
|
||||
int8_t CompareTo(const SMILTimeValue& aOther) const;
|
||||
|
||||
bool operator==(const SMILTimeValue& aOther) const {
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ SMILTimedElement::SMILTimedElement()
|
|||
mDeleteCount(0),
|
||||
mUpdateIntervalRecursionDepth(0) {
|
||||
mSimpleDur.SetIndefinite();
|
||||
mMin.SetMillis(0L);
|
||||
mMin = SMILTimeValue::Zero();
|
||||
mMax.SetIndefinite();
|
||||
}
|
||||
|
||||
|
|
@ -854,8 +854,9 @@ nsresult SMILTimedElement::SetSimpleDuration(const nsAString& aDurSpec) {
|
|||
if (dur.EqualsLiteral("media") || dur.EqualsLiteral("indefinite")) {
|
||||
duration.SetIndefinite();
|
||||
} else {
|
||||
if (!SMILParserUtils::ParseClockValue(dur, &duration) ||
|
||||
duration.GetMillis() == 0L) {
|
||||
if (!SMILParserUtils::ParseClockValue(
|
||||
dur, SMILTimeValue::Rounding::EnsureNonZero, &duration) ||
|
||||
duration.IsZero()) {
|
||||
mSimpleDur.SetIndefinite();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
@ -882,10 +883,11 @@ nsresult SMILTimedElement::SetMin(const nsAString& aMinSpec) {
|
|||
const nsAString& min = SMILParserUtils::TrimWhitespace(aMinSpec);
|
||||
|
||||
if (min.EqualsLiteral("media")) {
|
||||
duration.SetMillis(0L);
|
||||
duration = SMILTimeValue::Zero();
|
||||
} else {
|
||||
if (!SMILParserUtils::ParseClockValue(min, &duration)) {
|
||||
mMin.SetMillis(0L);
|
||||
if (!SMILParserUtils::ParseClockValue(min, SMILTimeValue::Rounding::Nearest,
|
||||
&duration)) {
|
||||
mMin = SMILTimeValue::Zero();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
|
@ -898,7 +900,7 @@ nsresult SMILTimedElement::SetMin(const nsAString& aMinSpec) {
|
|||
}
|
||||
|
||||
void SMILTimedElement::UnsetMin() {
|
||||
mMin.SetMillis(0L);
|
||||
mMin = SMILTimeValue::Zero();
|
||||
UpdateCurrentInterval();
|
||||
}
|
||||
|
||||
|
|
@ -912,8 +914,9 @@ nsresult SMILTimedElement::SetMax(const nsAString& aMaxSpec) {
|
|||
if (max.EqualsLiteral("media") || max.EqualsLiteral("indefinite")) {
|
||||
duration.SetIndefinite();
|
||||
} else {
|
||||
if (!SMILParserUtils::ParseClockValue(max, &duration) ||
|
||||
duration.GetMillis() == 0L) {
|
||||
if (!SMILParserUtils::ParseClockValue(
|
||||
max, SMILTimeValue::Rounding::EnsureNonZero, &duration) ||
|
||||
duration.IsZero()) {
|
||||
mMax.SetIndefinite();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
@ -974,7 +977,8 @@ nsresult SMILTimedElement::SetRepeatDur(const nsAString& aRepeatDurSpec) {
|
|||
if (repeatDur.EqualsLiteral("indefinite")) {
|
||||
duration.SetIndefinite();
|
||||
} else {
|
||||
if (!SMILParserUtils::ParseClockValue(repeatDur, &duration)) {
|
||||
if (!SMILParserUtils::ParseClockValue(
|
||||
repeatDur, SMILTimeValue::Rounding::EnsureNonZero, &duration)) {
|
||||
mRepeatDur.SetUnresolved();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
@ -1749,7 +1753,7 @@ SMILTime SMILTimedElement::ActiveTimeToSimpleTime(SMILTime aActiveTime,
|
|||
// Note that a negative aActiveTime will give us a negative value for
|
||||
// aRepeatIteration, which is bad because aRepeatIteration is unsigned
|
||||
|
||||
if (mSimpleDur.IsIndefinite() || mSimpleDur.GetMillis() == 0L) {
|
||||
if (mSimpleDur.IsIndefinite() || mSimpleDur.IsZero()) {
|
||||
aRepeatIteration = 0;
|
||||
result = aActiveTime;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
[short-simple-duration-and-fractional-repeatcount.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
||||
[Short simple duration and fractional repeatCount does not hang]
|
||||
expected: FAIL
|
||||
Loading…
Reference in a new issue