diff --git a/Userland/Libraries/LibWeb/Animations/TimingFunction.cpp b/Userland/Libraries/LibWeb/Animations/TimingFunction.cpp index 8be42450fa..92e1b0b14d 100644 --- a/Userland/Libraries/LibWeb/Animations/TimingFunction.cpp +++ b/Userland/Libraries/LibWeb/Animations/TimingFunction.cpp @@ -7,6 +7,9 @@ #include #include +#include +#include +#include #include namespace Web::Animations { @@ -164,6 +167,80 @@ double StepsTimingFunction::operator()(double input_progress, bool before_flag) return current_step / jumps; } +TimingFunction TimingFunction::from_easing_style_value(CSS::EasingStyleValue const& easing_value) +{ + switch (easing_value.easing_function()) { + case CSS::EasingFunction::Linear: + return Animations::linear_timing_function; + case CSS::EasingFunction::Ease: + return Animations::ease_timing_function; + case CSS::EasingFunction::EaseIn: + return Animations::ease_in_timing_function; + case CSS::EasingFunction::EaseOut: + return Animations::ease_out_timing_function; + case CSS::EasingFunction::EaseInOut: + return Animations::ease_in_out_timing_function; + case CSS::EasingFunction::CubicBezier: { + auto values = easing_value.values(); + return { + Animations::CubicBezierTimingFunction { + values[0]->as_number().number(), + values[1]->as_number().number(), + values[2]->as_number().number(), + values[3]->as_number().number(), + }, + }; + } + case CSS::EasingFunction::Steps: { + auto values = easing_value.values(); + auto jump_at_start = false; + auto jump_at_end = true; + + if (values.size() > 1) { + auto identifier = values[1]->to_identifier(); + switch (identifier) { + case CSS::ValueID::JumpStart: + case CSS::ValueID::Start: + jump_at_start = true; + jump_at_end = false; + break; + case CSS::ValueID::JumpEnd: + case CSS::ValueID::End: + jump_at_start = false; + jump_at_end = true; + break; + case CSS::ValueID::JumpNone: + jump_at_start = false; + jump_at_end = false; + break; + default: + break; + } + } + + return Animations::TimingFunction { Animations::StepsTimingFunction { + .number_of_steps = static_cast(max(values[0]->as_integer().integer(), !(jump_at_end && jump_at_start) ? 1 : 0)), + .jump_at_start = jump_at_start, + .jump_at_end = jump_at_end, + } }; + } + case CSS::EasingFunction::StepEnd: + return Animations::TimingFunction { Animations::StepsTimingFunction { + .number_of_steps = 1, + .jump_at_start = false, + .jump_at_end = true, + } }; + case CSS::EasingFunction::StepStart: + return Animations::TimingFunction { Animations::StepsTimingFunction { + .number_of_steps = 1, + .jump_at_start = true, + .jump_at_end = false, + } }; + default: + return Animations::ease_timing_function; + } +} + double TimingFunction::operator()(double input_progress, bool before_flag) const { return function.visit([&](auto const& f) { return f(input_progress, before_flag); }); diff --git a/Userland/Libraries/LibWeb/Animations/TimingFunction.h b/Userland/Libraries/LibWeb/Animations/TimingFunction.h index 87a6a9e004..f2bd14d2a2 100644 --- a/Userland/Libraries/LibWeb/Animations/TimingFunction.h +++ b/Userland/Libraries/LibWeb/Animations/TimingFunction.h @@ -10,6 +10,10 @@ #include #include +namespace Web::CSS { +class EasingStyleValue; +} + namespace Web::Animations { // https://www.w3.org/TR/css-easing-1/#the-linear-easing-function @@ -45,6 +49,8 @@ struct StepsTimingFunction { }; struct TimingFunction { + static TimingFunction from_easing_style_value(CSS::EasingStyleValue const&); + Variant function; double operator()(double input_progress, bool before_flag) const; diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index ed87b96e09..d7ee606e56 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -1060,89 +1060,10 @@ ErrorOr StyleComputer::compute_cascaded_values(StyleProperties& style, DOM } Animations::TimingFunction timing_function = Animations::ease_timing_function; - if (auto timing_property = style.maybe_null_property(PropertyID::AnimationTimingFunction); timing_property && timing_property->is_easing()) { - auto& easing_value = timing_property->as_easing(); - switch (easing_value.easing_function()) { - case EasingFunction::Linear: - timing_function = Animations::linear_timing_function; - break; - case EasingFunction::Ease: - timing_function = Animations::ease_timing_function; - break; - case EasingFunction::EaseIn: - timing_function = Animations::ease_in_timing_function; - break; - case EasingFunction::EaseOut: - timing_function = Animations::ease_out_timing_function; - break; - case EasingFunction::EaseInOut: - timing_function = Animations::ease_in_out_timing_function; - break; - case EasingFunction::CubicBezier: { - auto values = easing_value.values(); - timing_function = { - Animations::CubicBezierTimingFunction { - values[0]->as_number().number(), - values[1]->as_number().number(), - values[2]->as_number().number(), - values[3]->as_number().number(), - }, - }; - break; - } - case EasingFunction::Steps: { - auto values = easing_value.values(); - auto jump_at_start = false; - auto jump_at_end = true; - - if (values.size() > 1) { - auto identifier = values[1]->to_identifier(); - switch (identifier) { - case ValueID::JumpStart: - case ValueID::Start: - jump_at_start = true; - jump_at_end = false; - break; - case ValueID::JumpEnd: - case ValueID::End: - jump_at_start = false; - jump_at_end = true; - break; - case ValueID::JumpNone: - jump_at_start = false; - jump_at_end = false; - break; - default: - break; - } - } - - timing_function = Animations::TimingFunction { Animations::StepsTimingFunction { - .number_of_steps = static_cast(max(values[0]->as_integer().integer(), !(jump_at_end && jump_at_start) ? 1 : 0)), - .jump_at_start = jump_at_start, - .jump_at_end = jump_at_end, - } }; - break; - } - case EasingFunction::StepEnd: - timing_function = Animations::TimingFunction { Animations::StepsTimingFunction { - .number_of_steps = 1, - .jump_at_start = false, - .jump_at_end = true, - } }; - break; - case EasingFunction::StepStart: - timing_function = Animations::TimingFunction { Animations::StepsTimingFunction { - .number_of_steps = 1, - .jump_at_start = true, - .jump_at_end = false, - } }; - break; - } - } + if (auto timing_property = style.maybe_null_property(PropertyID::AnimationTimingFunction); timing_property && timing_property->is_easing()) + timing_function = Animations::TimingFunction::from_easing_style_value(timing_property->as_easing()); auto& realm = element.realm(); - auto effect = Animations::KeyframeEffect::create(realm); auto iteration_duration = duration.has_value() ? Variant { duration.release_value().to_milliseconds() }