| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "core/animation/TimingInput.h" |
| |
| #include "bindings/core/v8/ExceptionState.h" |
| #include "core/animation/AnimationInputHelpers.h" |
| #include "core/animation/KeyframeEffectOptions.h" |
| |
| namespace blink { |
| |
| void TimingInput::setStartDelay(Timing& timing, double startDelay) { |
| if (std::isfinite(startDelay)) |
| timing.startDelay = startDelay / 1000; |
| else |
| timing.startDelay = Timing::defaults().startDelay; |
| } |
| |
| void TimingInput::setEndDelay(Timing& timing, double endDelay) { |
| if (std::isfinite(endDelay)) |
| timing.endDelay = endDelay / 1000; |
| else |
| timing.endDelay = Timing::defaults().endDelay; |
| } |
| |
| void TimingInput::setFillMode(Timing& timing, const String& fillMode) { |
| if (fillMode == "none") { |
| timing.fillMode = Timing::FillMode::NONE; |
| } else if (fillMode == "backwards") { |
| timing.fillMode = Timing::FillMode::BACKWARDS; |
| } else if (fillMode == "both") { |
| timing.fillMode = Timing::FillMode::BOTH; |
| } else if (fillMode == "forwards") { |
| timing.fillMode = Timing::FillMode::FORWARDS; |
| } else { |
| timing.fillMode = Timing::defaults().fillMode; |
| } |
| } |
| |
| bool TimingInput::setIterationStart(Timing& timing, |
| double iterationStart, |
| ExceptionState& exceptionState) { |
| DCHECK(std::isfinite(iterationStart)); |
| if (std::isnan(iterationStart) || iterationStart < 0) { |
| exceptionState.throwTypeError("iterationStart must be non-negative."); |
| return false; |
| } |
| timing.iterationStart = iterationStart; |
| return true; |
| } |
| |
| bool TimingInput::setIterationCount(Timing& timing, |
| double iterationCount, |
| ExceptionState& exceptionState) { |
| if (std::isnan(iterationCount) || iterationCount < 0) { |
| exceptionState.throwTypeError("iterationCount must be non-negative."); |
| return false; |
| } |
| timing.iterationCount = iterationCount; |
| return true; |
| } |
| |
| bool TimingInput::setIterationDuration( |
| Timing& timing, |
| const UnrestrictedDoubleOrString& iterationDuration, |
| ExceptionState& exceptionState) { |
| static const char* errorMessage = "duration must be non-negative or auto."; |
| |
| if (iterationDuration.isUnrestrictedDouble()) { |
| double durationNumber = iterationDuration.getAsUnrestrictedDouble(); |
| if (std::isnan(durationNumber) || durationNumber < 0) { |
| exceptionState.throwTypeError(errorMessage); |
| return false; |
| } |
| timing.iterationDuration = durationNumber / 1000; |
| return true; |
| } |
| |
| if (iterationDuration.getAsString() != "auto") { |
| exceptionState.throwTypeError(errorMessage); |
| return false; |
| } |
| |
| timing.iterationDuration = Timing::defaults().iterationDuration; |
| return true; |
| } |
| |
| void TimingInput::setPlaybackRate(Timing& timing, double playbackRate) { |
| if (std::isfinite(playbackRate)) |
| timing.playbackRate = playbackRate; |
| else |
| timing.playbackRate = Timing::defaults().playbackRate; |
| } |
| |
| void TimingInput::setPlaybackDirection(Timing& timing, |
| const String& direction) { |
| if (direction == "reverse") { |
| timing.direction = Timing::PlaybackDirection::REVERSE; |
| } else if (direction == "alternate") { |
| timing.direction = Timing::PlaybackDirection::ALTERNATE_NORMAL; |
| } else if (direction == "alternate-reverse") { |
| timing.direction = Timing::PlaybackDirection::ALTERNATE_REVERSE; |
| } else { |
| timing.direction = Timing::defaults().direction; |
| } |
| } |
| |
| bool TimingInput::setTimingFunction(Timing& timing, |
| const String& timingFunctionString, |
| Document* document, |
| ExceptionState& exceptionState) { |
| if (RefPtr<TimingFunction> timingFunction = |
| AnimationInputHelpers::parseTimingFunction( |
| timingFunctionString, document, exceptionState)) { |
| timing.timingFunction = timingFunction; |
| return true; |
| } |
| return false; |
| } |
| |
| bool TimingInput::convert(const KeyframeEffectOptions& timingInput, |
| Timing& timingOutput, |
| Document* document, |
| ExceptionState& exceptionState) { |
| setStartDelay(timingOutput, timingInput.delay()); |
| setEndDelay(timingOutput, timingInput.endDelay()); |
| setFillMode(timingOutput, timingInput.fill()); |
| |
| if (!setIterationStart(timingOutput, timingInput.iterationStart(), |
| exceptionState)) |
| return false; |
| |
| if (!setIterationCount(timingOutput, timingInput.iterations(), |
| exceptionState)) |
| return false; |
| |
| if (!setIterationDuration(timingOutput, timingInput.duration(), |
| exceptionState)) |
| return false; |
| |
| setPlaybackRate(timingOutput, 1.0); |
| setPlaybackDirection(timingOutput, timingInput.direction()); |
| |
| if (!setTimingFunction(timingOutput, timingInput.easing(), document, |
| exceptionState)) |
| return false; |
| |
| timingOutput.assertValid(); |
| |
| return true; |
| } |
| |
| bool TimingInput::convert(double duration, |
| Timing& timingOutput, |
| ExceptionState& exceptionState) { |
| DCHECK(timingOutput == Timing::defaults()); |
| return setIterationDuration( |
| timingOutput, |
| UnrestrictedDoubleOrString::fromUnrestrictedDouble(duration), |
| exceptionState); |
| } |
| |
| } // namespace blink |