Bug 1248340 - Part 2: Implement Frames in ComputedTimingFunction. r=birtles
MozReview-Commit-ID: 92MAv3OD8Tu
--- a/dom/animation/ComputedTimingFunction.cpp
+++ b/dom/animation/ComputedTimingFunction.cpp
@@ -13,20 +13,17 @@ namespace mozilla {
void
ComputedTimingFunction::Init(const nsTimingFunction &aFunction)
{
mType = aFunction.mType;
if (nsTimingFunction::IsSplineType(mType)) {
mTimingFunction.Init(aFunction.mFunc.mX1, aFunction.mFunc.mY1,
aFunction.mFunc.mX2, aFunction.mFunc.mY2);
} else {
- // TODO: Support Frames
- MOZ_ASSERT(nsTimingFunction::Type::StepStart ||
- nsTimingFunction::Type::StepEnd);
- mSteps = aFunction.mStepsOrFrames;
+ mStepsOrFrames = aFunction.mStepsOrFrames;
}
}
static inline double
StepTiming(uint32_t aSteps,
double aPortion,
ComputedTimingFunction::BeforeFlag aBeforeFlag,
nsTimingFunction::Type aType)
@@ -56,17 +53,32 @@ StepTiming(uint32_t aSteps,
// input outside that range. This takes care of steps that would otherwise
// occur at boundaries.
if (result < 0.0 && aPortion >= 0.0) {
return 0.0;
}
if (result > 1.0 && aPortion <= 1.0) {
return 1.0;
}
+ return result;
+}
+static inline double
+FramesTiming(uint32_t aFrames, double aPortion)
+{
+ MOZ_ASSERT(aFrames > 1, "the number of frames must be greater than 1");
+ int32_t currentFrame = floor(aPortion * aFrames);
+ double result = double(currentFrame) / double(aFrames - 1);
+
+ // Don't overshoot the natural range of the animation (by producing an output
+ // progress greater than 1.0) when we are at the exact end of its interval
+ // (i.e. the input progress is 1.0).
+ if (result > 1.0 && aPortion <= 1.0) {
+ return 1.0;
+ }
return result;
}
double
ComputedTimingFunction::GetValue(
double aPortion,
ComputedTimingFunction::BeforeFlag aBeforeFlag) const
{
@@ -111,35 +123,38 @@ ComputedTimingFunction::GetValue(
}
// If we can't calculate a sensible tangent, don't extrapolate at all.
return 1.0;
}
return mTimingFunction.GetSplineValue(aPortion);
}
- return StepTiming(mSteps, aPortion, aBeforeFlag, mType);
+ return mType == nsTimingFunction::Type::Frames
+ ? FramesTiming(mStepsOrFrames, aPortion)
+ : StepTiming(mStepsOrFrames, aPortion, aBeforeFlag, mType);
}
int32_t
ComputedTimingFunction::Compare(const ComputedTimingFunction& aRhs) const
{
if (mType != aRhs.mType) {
return int32_t(mType) - int32_t(aRhs.mType);
}
if (mType == nsTimingFunction::Type::CubicBezier) {
int32_t order = mTimingFunction.Compare(aRhs.mTimingFunction);
if (order != 0) {
return order;
}
} else if (mType == nsTimingFunction::Type::StepStart ||
- mType == nsTimingFunction::Type::StepEnd) {
- if (mSteps != aRhs.mSteps) {
- return int32_t(mSteps) - int32_t(aRhs.mSteps);
+ mType == nsTimingFunction::Type::StepEnd ||
+ mType == nsTimingFunction::Type::Frames) {
+ if (mStepsOrFrames != aRhs.mStepsOrFrames) {
+ return int32_t(mStepsOrFrames) - int32_t(aRhs.mStepsOrFrames);
}
}
return 0;
}
void
ComputedTimingFunction::AppendToString(nsAString& aResult) const
@@ -149,17 +164,20 @@ ComputedTimingFunction::AppendToString(n
nsStyleUtil::AppendCubicBezierTimingFunction(mTimingFunction.X1(),
mTimingFunction.Y1(),
mTimingFunction.X2(),
mTimingFunction.Y2(),
aResult);
break;
case nsTimingFunction::Type::StepStart:
case nsTimingFunction::Type::StepEnd:
- nsStyleUtil::AppendStepsTimingFunction(mType, mSteps, aResult);
+ nsStyleUtil::AppendStepsTimingFunction(mType, mStepsOrFrames, aResult);
+ break;
+ case nsTimingFunction::Type::Frames:
+ // TODO: Serialize Frames timing function.
break;
default:
nsStyleUtil::AppendCubicBezierKeywordTimingFunction(mType, aResult);
break;
}
}
/* static */ int32_t
--- a/dom/animation/ComputedTimingFunction.h
+++ b/dom/animation/ComputedTimingFunction.h
@@ -25,23 +25,28 @@ public:
double GetValue(double aPortion, BeforeFlag aBeforeFlag) const;
const nsSMILKeySpline* GetFunction() const
{
NS_ASSERTION(HasSpline(), "Type mismatch");
return &mTimingFunction;
}
nsTimingFunction::Type GetType() const { return mType; }
bool HasSpline() const { return nsTimingFunction::IsSplineType(mType); }
- uint32_t GetSteps() const { return mSteps; }
+ uint32_t GetSteps() const
+ {
+ MOZ_ASSERT(mType == nsTimingFunction::Type::StepStart ||
+ mType == nsTimingFunction::Type::StepEnd);
+ return mStepsOrFrames;
+ }
bool operator==(const ComputedTimingFunction& aOther) const
{
return mType == aOther.mType &&
(HasSpline() ?
mTimingFunction == aOther.mTimingFunction :
- mSteps == aOther.mSteps);
+ mStepsOrFrames == aOther.mStepsOrFrames);
}
bool operator!=(const ComputedTimingFunction& aOther) const
{
return !(*this == aOther);
}
int32_t Compare(const ComputedTimingFunction& aRhs) const;
void AppendToString(nsAString& aResult) const;
@@ -52,14 +57,14 @@ public:
return aFunction ? aFunction->GetValue(aPortion, aBeforeFlag) : aPortion;
}
static int32_t Compare(const Maybe<ComputedTimingFunction>& aLhs,
const Maybe<ComputedTimingFunction>& aRhs);
private:
nsTimingFunction::Type mType;
nsSMILKeySpline mTimingFunction;
- uint32_t mSteps;
+ uint32_t mStepsOrFrames;
};
} // namespace mozilla
#endif // mozilla_ComputedTimingFunction_h