namespace WebCore {
+static inline double multiplyZeroAlwaysGivesZero(double x, double y)
+{
+ ASSERT(!isNull(x));
+ ASSERT(!isNull(y));
+ return x && y ? x * y : 0;
+}
+
static inline TimedItem::Phase calculatePhase(double activeDuration, double localTime, const Timing& specified)
{
ASSERT(activeDuration >= 0);
}
}
-static inline double calculateActiveTime(double activeDuration, double localTime, TimedItem::Phase parentPhase, TimedItem::Phase phase, const Timing& specified)
+static inline double calculateActiveTime(double activeDuration, Timing::FillMode fillMode, double localTime, TimedItem::Phase parentPhase, TimedItem::Phase phase, const Timing& specified)
{
ASSERT(activeDuration >= 0);
ASSERT(phase == calculatePhase(activeDuration, localTime, specified));
switch (phase) {
case TimedItem::PhaseBefore:
- if (specified.fillMode == Timing::FillModeBackwards || specified.fillMode == Timing::FillModeBoth)
+ if (fillMode == Timing::FillModeBackwards || fillMode == Timing::FillModeBoth)
return 0;
return nullValue();
case TimedItem::PhaseActive:
- if (isActiveInParentPhase(parentPhase, specified.fillMode))
+ if (isActiveInParentPhase(parentPhase, fillMode))
return localTime - specified.startDelay;
return nullValue();
case TimedItem::PhaseAfter:
- if (specified.fillMode == Timing::FillModeForwards || specified.fillMode == Timing::FillModeBoth)
+ if (fillMode == Timing::FillModeForwards || fillMode == Timing::FillModeBoth)
return activeDuration;
return nullValue();
case TimedItem::PhaseNone:
if (isNull(activeTime))
return nullValue();
- ASSERT(activeTime >= 0);
-
- return (specified.playbackRate < 0 ? activeTime - activeDuration : activeTime) * specified.playbackRate + startOffset;
+ ASSERT(activeTime >= 0 && activeTime <= activeDuration);
+ return multiplyZeroAlwaysGivesZero(specified.playbackRate < 0 ? activeTime - activeDuration : activeTime, specified.playbackRate) + startOffset;
}
static inline bool endsOnIterationBoundary(double iterationCount, double iterationStart)
{
+ ASSERT(std::isfinite(iterationCount));
return !fmod(iterationCount + iterationStart, 1);
}
static inline double calculateIterationTime(double iterationDuration, double repeatedDuration, double scaledActiveTime, double startOffset, const Timing& specified)
{
- ASSERT(iterationDuration >= 0);
- ASSERT(repeatedDuration == iterationDuration * specified.iterationCount);
+ ASSERT(iterationDuration > 0);
+ ASSERT(repeatedDuration == multiplyZeroAlwaysGivesZero(iterationDuration, specified.iterationCount));
if (isNull(scaledActiveTime))
return nullValue();
ASSERT(scaledActiveTime >= 0);
ASSERT(scaledActiveTime <= repeatedDuration + startOffset);
- if (!iterationDuration)
- return 0;
-
- if (scaledActiveTime - startOffset == repeatedDuration && specified.iterationCount && endsOnIterationBoundary(specified.iterationCount, specified.iterationStart))
+ if (!std::isfinite(scaledActiveTime)
+ || (scaledActiveTime - startOffset == repeatedDuration && specified.iterationCount && endsOnIterationBoundary(specified.iterationCount, specified.iterationStart)))
return iterationDuration;
+ ASSERT(std::isfinite(scaledActiveTime));
return fmod(scaledActiveTime, iterationDuration);
}
static inline double calculateCurrentIteration(double iterationDuration, double iterationTime, double scaledActiveTime, const Timing& specified)
{
- ASSERT(iterationDuration >= 0);
+ ASSERT(iterationDuration > 0);
ASSERT(isNull(iterationTime) || iterationTime >= 0);
if (isNull(scaledActiveTime))
if (!scaledActiveTime)
return 0;
- if (!iterationDuration)
- return floor(specified.iterationStart + specified.iterationCount);
-
if (iterationTime == iterationDuration)
return specified.iterationStart + specified.iterationCount - 1;
double directedTime = calculateDirectedTime(currentIteration, iterationDuration, iterationTime, specified);
if (isNull(directedTime))
return nullValue();
- return specified.timingFunction ?
- iterationDuration * specified.timingFunction->evaluate(directedTime / iterationDuration, accuracyForDuration(iterationDuration)) :
- directedTime;
+ if (!std::isfinite(iterationDuration))
+ return directedTime;
+ double timeFraction = directedTime / iterationDuration;
+ ASSERT(timeFraction >= 0 && timeFraction <= 1);
+ return specified.timingFunction
+ ? multiplyZeroAlwaysGivesZero(iterationDuration, specified.timingFunction->evaluate(timeFraction, accuracyForDuration(iterationDuration)))
+ : directedTime;
}
} // namespace WebCore