/* * Copyright (c) 2013, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "third_party/blink/renderer/core/animation/animation_effect.h" #include "third_party/blink/renderer/core/animation/timing_calculations.h" #include "testing/gtest/include/gtest/gtest.h" namespace blink { TEST(AnimationTimingCalculationsTest, ActiveTime) { Timing timing; // calculateActiveTime( // activeDuration, fillMode, localTime, parentPhase, phase, timing) // Before Phase timing.start_delay = 10; EXPECT_FALSE(CalculateActiveTime(20, Timing::FillMode::FORWARDS, 0, Timing::kPhaseBefore, timing)); EXPECT_FALSE(CalculateActiveTime(20, Timing::FillMode::NONE, 0, Timing::kPhaseBefore, timing)); EXPECT_EQ(AnimationTimeDelta(), CalculateActiveTime(20, Timing::FillMode::BACKWARDS, 0, Timing::kPhaseBefore, timing)); EXPECT_EQ(AnimationTimeDelta(), CalculateActiveTime(20, Timing::FillMode::BOTH, 0, Timing::kPhaseBefore, timing)); timing.start_delay = -10; EXPECT_EQ(AnimationTimeDelta::FromSecondsD(5), CalculateActiveTime(20, Timing::FillMode::BACKWARDS, -5, Timing::kPhaseBefore, timing)); // Active Phase timing.start_delay = 10; EXPECT_EQ(AnimationTimeDelta::FromSecondsD(5), CalculateActiveTime(20, Timing::FillMode::FORWARDS, 15, Timing::kPhaseActive, timing)); // After Phase timing.start_delay = 10; EXPECT_EQ(AnimationTimeDelta::FromSecondsD(21), CalculateActiveTime(21, Timing::FillMode::FORWARDS, 45, Timing::kPhaseAfter, timing)); EXPECT_EQ(AnimationTimeDelta::FromSecondsD(21), CalculateActiveTime(21, Timing::FillMode::BOTH, 45, Timing::kPhaseAfter, timing)); EXPECT_FALSE(CalculateActiveTime(21, Timing::FillMode::BACKWARDS, 45, Timing::kPhaseAfter, timing)); EXPECT_FALSE(CalculateActiveTime(21, Timing::FillMode::NONE, 45, Timing::kPhaseAfter, timing)); // None EXPECT_FALSE(CalculateActiveTime(32, Timing::FillMode::NONE, base::nullopt, Timing::kPhaseNone, timing)); } TEST(AnimationTimingCalculationsTest, OffsetActiveTime) { // if the active time is null EXPECT_FALSE(CalculateOffsetActiveTime(4, base::nullopt, 5)); // normal case EXPECT_EQ( AnimationTimeDelta::FromSecondsD(15), CalculateOffsetActiveTime(40, AnimationTimeDelta::FromSecondsD(10), 5)); // infinite activeTime EXPECT_TRUE(CalculateOffsetActiveTime(std::numeric_limits::infinity(), AnimationTimeDelta::Max(), 0) ->is_max()); // Edge case for active_time being within epsilon of active_duration. // https://crbug.com/962138 auto active_time = AnimationTimeDelta::FromSecondsD(1.3435713716800004); const double active_duration = 1.3435713716800002; EXPECT_EQ(active_time, CalculateOffsetActiveTime(active_duration, active_time, 0)); } TEST(AnimationTimingCalculationsTest, IterationTime) { Timing timing; // calculateIterationTime( // iterationDuration, activeDuration, scaledActiveTime, startOffset, // phase, timing) // if the scaled active time is null EXPECT_FALSE(CalculateIterationTime(1, 1, base::nullopt, 1, Timing::kPhaseActive, timing)); // if (complex-conditions)... EXPECT_EQ(AnimationTimeDelta::FromSecondsD(12), CalculateIterationTime(12, 12, AnimationTimeDelta::FromSecondsD(12), 0, Timing::kPhaseActive, timing)); // otherwise timing.iteration_count = 10; EXPECT_EQ( AnimationTimeDelta::FromSecondsD(5), CalculateIterationTime(10, 100, AnimationTimeDelta::FromSecondsD(25), 4, Timing::kPhaseActive, timing)); EXPECT_EQ( AnimationTimeDelta::FromSecondsD(7), CalculateIterationTime(11, 110, AnimationTimeDelta::FromSecondsD(29), 1, Timing::kPhaseActive, timing)); timing.iteration_start = 1.1; EXPECT_EQ( AnimationTimeDelta::FromSecondsD(8), CalculateIterationTime(12, 120, AnimationTimeDelta::FromSecondsD(20), 7, Timing::kPhaseActive, timing)); // Edge case for offset_active_time being within epsilon of (active_duration // + start_offset). https://crbug.com/962138 timing.iteration_count = 1; const double offset_active_time = 1.3435713716800004; const double iteration_duration = 1.3435713716800002; const double active_duration = 1.3435713716800002; EXPECT_NEAR(2.22045e-16, CalculateIterationTime( iteration_duration, active_duration, AnimationTimeDelta::FromSecondsD(offset_active_time), 0, Timing::kPhaseActive, timing) ->InSecondsF(), std::numeric_limits::epsilon()); } TEST(AnimationTimingCalculationsTest, OverallProgress) { // If the active time is null. EXPECT_FALSE(CalculateOverallProgress(Timing::kPhaseAfter, /*active_time=*/base::nullopt, /*iteration_duration=*/1.0, /*iteration_count=*/1.0, /*iteration_start=*/1.0)); // If iteration duration is zero, calculate progress based on iteration count. EXPECT_EQ(3, CalculateOverallProgress( Timing::kPhaseActive, /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0), /*iteration_duration=*/0.0, /*iteration_count=*/3.0, /*iteration_start=*/0.0)); // ...unless in before phase, in which case progress is zero. EXPECT_EQ(0, CalculateOverallProgress( Timing::kPhaseBefore, /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0), /*iteration_duration=*/0.0, /*iteration_count=*/3.0, /*iteration_start=*/0.0)); // Edge case for duration being within Epsilon of zero. // crbug.com/954558 EXPECT_EQ(1, CalculateOverallProgress( Timing::kPhaseActive, /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0), /*iteration_duration=*/1e-18, /*iteration_count=*/1.0, /*iteration_start=*/0.0)); // Otherwise. EXPECT_EQ(3.0, CalculateOverallProgress( Timing::kPhaseAfter, /*active_time=*/AnimationTimeDelta::FromSecondsD(2.5), /*iteration_duration=*/1.0, /*iteration_count=*/0.0, /*iteration_start=*/0.5)); } TEST(AnimationTimingCalculationsTest, CalculateSimpleIterationProgress) { // If the overall progress is null. EXPECT_FALSE( CalculateSimpleIterationProgress(Timing::kPhaseAfter, /*overall_progress=*/base::nullopt, /*iteration_start=*/1.0, /*active_time=*/base::nullopt, /*active_duration=*/1.0, /*iteration_count=*/1.0)); // If the overall progress is infinite. const double inf = std::numeric_limits::infinity(); EXPECT_EQ(0.5, CalculateSimpleIterationProgress( Timing::kPhaseAfter, /*overall_progress=*/inf, /*iteration_start=*/1.5, /*active_time=*/AnimationTimeDelta(), /*active_duration=*/0.0, /*iteration_count=*/inf)); // Precisely on an iteration boundary. EXPECT_EQ(1.0, CalculateSimpleIterationProgress( Timing::kPhaseAfter, /*overall_progress=*/3.0, /*iteration_start=*/0.0, /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0), /*active_duration=*/3.0, /*iteration_count=*/3.0)); // Otherwise. EXPECT_EQ(0.5, CalculateSimpleIterationProgress( Timing::kPhaseAfter, /*overall_progress=*/2.5, /*iteration_start=*/0.0, /*active_time=*/AnimationTimeDelta::FromSecondsD(2.5), /*active_duration=*/0.0, /*iteration_count=*/0.0)); } TEST(AnimationTimingCalculationsTest, CurrentIteration) { // If the active time is null. EXPECT_FALSE(CalculateCurrentIteration(Timing::kPhaseAfter, /*active_time=*/base::nullopt, /*iteration_count=*/1.0, /*overall_progress=*/base::nullopt, /*simple_iteration_progress=*/0)); // If the iteration count is infinite. const double inf = std::numeric_limits::infinity(); EXPECT_EQ(inf, CalculateCurrentIteration( Timing::kPhaseAfter, /*active_time=*/AnimationTimeDelta::FromSecondsD(1.0), /*iteration_count=*/inf, /*overall_progress=*/inf, /*simple_iteration_progress=*/0.0)); // Hold the endpoint of the final iteration of ending precisely on an // iteration boundary. EXPECT_EQ(2, CalculateCurrentIteration( Timing::kPhaseAfter, /*active_time=*/AnimationTimeDelta::FromSecondsD(3.0), /*iteration_count=*/3.0, /*overall_progress=*/3.0, /*simple_iteration_progress=*/1.0)); // Edge case for zero-duration animation. // crbug.com/954558 EXPECT_EQ(0, CalculateCurrentIteration(Timing::kPhaseAfter, /*active_time=*/AnimationTimeDelta(), /*iteration_count=*/1.0, /*overall_progress=*/0.0, /*simple_iteration_progress=*/1.0)); // Otherwise. EXPECT_EQ(2, CalculateCurrentIteration( Timing::kPhaseAfter, /*active_time=*/AnimationTimeDelta::FromSecondsD(2.5), /*iteration_count=*/0.0, /*overall_progress=*/2.5, /*simple_iteration_progress=*/0.5)); } TEST(AnimationTimingCalculationsTest, IsCurrentDirectionForwards) { // IsCurrentDirectionForwards(current_iteration, // direction); EXPECT_TRUE(IsCurrentDirectionForwards(0, Timing::PlaybackDirection::NORMAL)); EXPECT_TRUE(IsCurrentDirectionForwards(1, Timing::PlaybackDirection::NORMAL)); EXPECT_TRUE(IsCurrentDirectionForwards( 0, Timing::PlaybackDirection::ALTERNATE_NORMAL)); EXPECT_TRUE(IsCurrentDirectionForwards( 1, Timing::PlaybackDirection::ALTERNATE_REVERSE)); EXPECT_FALSE( IsCurrentDirectionForwards(0, Timing::PlaybackDirection::REVERSE)); EXPECT_FALSE( IsCurrentDirectionForwards(1, Timing::PlaybackDirection::REVERSE)); EXPECT_FALSE(IsCurrentDirectionForwards( 0, Timing::PlaybackDirection::ALTERNATE_REVERSE)); EXPECT_FALSE(IsCurrentDirectionForwards( 1, Timing::PlaybackDirection::ALTERNATE_NORMAL)); } TEST(AnimationTimingCalculationsTest, CalculateDirectedProgress) { // CalculateDirectedProgress(simple_iteration_progress, // current_iteration, // direction); // if the simple iteration progress is null EXPECT_FALSE(CalculateDirectedProgress(base::nullopt, base::nullopt, Timing::PlaybackDirection::NORMAL)); // forwards EXPECT_EQ(0, CalculateDirectedProgress(0, 8, Timing::PlaybackDirection::NORMAL)); EXPECT_EQ(1, CalculateDirectedProgress(1, 8, Timing::PlaybackDirection::NORMAL)); EXPECT_EQ(0, CalculateDirectedProgress(0, 9, Timing::PlaybackDirection::NORMAL)); EXPECT_EQ(1, CalculateDirectedProgress(1, 9, Timing::PlaybackDirection::NORMAL)); EXPECT_EQ(0, CalculateDirectedProgress( 0, 8, Timing::PlaybackDirection::ALTERNATE_NORMAL)); EXPECT_EQ(1, CalculateDirectedProgress( 1, 8, Timing::PlaybackDirection::ALTERNATE_NORMAL)); EXPECT_EQ(0, CalculateDirectedProgress( 0, 9, Timing::PlaybackDirection::ALTERNATE_REVERSE)); EXPECT_EQ(1, CalculateDirectedProgress( 1, 9, Timing::PlaybackDirection::ALTERNATE_REVERSE)); // reverse EXPECT_EQ( 1, CalculateDirectedProgress(0, 8, Timing::PlaybackDirection::REVERSE)); EXPECT_EQ( 0, CalculateDirectedProgress(1, 8, Timing::PlaybackDirection::REVERSE)); EXPECT_EQ( 1, CalculateDirectedProgress(0, 9, Timing::PlaybackDirection::REVERSE)); EXPECT_EQ( 0, CalculateDirectedProgress(1, 9, Timing::PlaybackDirection::REVERSE)); EXPECT_EQ(1, CalculateDirectedProgress( 0, 9, Timing::PlaybackDirection::ALTERNATE_NORMAL)); EXPECT_EQ(0, CalculateDirectedProgress( 1, 9, Timing::PlaybackDirection::ALTERNATE_NORMAL)); EXPECT_EQ(1, CalculateDirectedProgress( 0, 8, Timing::PlaybackDirection::ALTERNATE_REVERSE)); EXPECT_EQ(0, CalculateDirectedProgress( 1, 8, Timing::PlaybackDirection::ALTERNATE_REVERSE)); } TEST(AnimationTimingCalculationsTest, TransformedProgress) { // CalculateTransformedProgress( // phase, directed_progress, // is_current_direction_forward, timing_function) scoped_refptr timing_function = StepsTimingFunction::Create(4, StepsTimingFunction::StepPosition::END); // directed_progress is null. EXPECT_FALSE(CalculateTransformedProgress(Timing::kPhaseActive, base::nullopt, true, timing_function)); // At step boundaries. // Forward direction. EXPECT_EQ(0, CalculateTransformedProgress(Timing::kPhaseBefore, 0, true, timing_function)); EXPECT_EQ(0, CalculateTransformedProgress(Timing::kPhaseBefore, 0.25, true, timing_function)); EXPECT_EQ(0.25, CalculateTransformedProgress(Timing::kPhaseAfter, 0.25, true, timing_function)); EXPECT_EQ(0.25, CalculateTransformedProgress(Timing::kPhaseBefore, 0.5, true, timing_function)); EXPECT_EQ(0.5, CalculateTransformedProgress(Timing::kPhaseAfter, 0.5, true, timing_function)); EXPECT_EQ(0.5, CalculateTransformedProgress(Timing::kPhaseBefore, 0.75, true, timing_function)); EXPECT_EQ(0.75, CalculateTransformedProgress(Timing::kPhaseAfter, 0.75, true, timing_function)); EXPECT_EQ(0.75, CalculateTransformedProgress(Timing::kPhaseBefore, 1, true, timing_function)); EXPECT_EQ(1, CalculateTransformedProgress(Timing::kPhaseAfter, 1, true, timing_function)); // Reverse direction. EXPECT_EQ(1, CalculateTransformedProgress(Timing::kPhaseBefore, 1, false, timing_function)); EXPECT_EQ(0.75, CalculateTransformedProgress(Timing::kPhaseAfter, 1, false, timing_function)); EXPECT_EQ(0.75, CalculateTransformedProgress(Timing::kPhaseBefore, 0.75, false, timing_function)); EXPECT_EQ(0.5, CalculateTransformedProgress(Timing::kPhaseAfter, 0.75, false, timing_function)); EXPECT_EQ(0.5, CalculateTransformedProgress(Timing::kPhaseBefore, 0.5, false, timing_function)); EXPECT_EQ(0.25, CalculateTransformedProgress(Timing::kPhaseAfter, 0.5, false, timing_function)); EXPECT_EQ(0.25, CalculateTransformedProgress(Timing::kPhaseBefore, 0.25, false, timing_function)); EXPECT_EQ(0, CalculateTransformedProgress(Timing::kPhaseAfter, 0.25, false, timing_function)); // Edges cases EXPECT_EQ(1, CalculateTransformedProgress(Timing::kPhaseAfter, 1 - 1e-16, true, timing_function)); scoped_refptr step_start_timing_function = StepsTimingFunction::Create(4, StepsTimingFunction::StepPosition::START); EXPECT_EQ(0, CalculateTransformedProgress(Timing::kPhaseAfter, 1e-16, false, step_start_timing_function)); } } // namespace blink