1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 02:27:43 +00:00

LibWeb: Correctly set timing function in AnimationEffect::update_timing

Also pulls out the parse_easing_string function out since it will be
needed elsewhere
This commit is contained in:
Matthew Olsson 2024-02-19 19:11:05 -07:00 committed by Andreas Kling
parent b33bb0997a
commit 62f62a0e52
3 changed files with 27 additions and 16 deletions

View file

@ -9,6 +9,7 @@
#include <LibWeb/Animations/AnimationEffect.h> #include <LibWeb/Animations/AnimationEffect.h>
#include <LibWeb/Animations/AnimationTimeline.h> #include <LibWeb/Animations/AnimationTimeline.h>
#include <LibWeb/Bindings/Intrinsics.h> #include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/CSS/Parser/Parser.h>
#include <LibWeb/DOM/Element.h> #include <LibWeb/DOM/Element.h>
#include <LibWeb/WebIDL/ExceptionOr.h> #include <LibWeb/WebIDL/ExceptionOr.h>
@ -181,8 +182,14 @@ WebIDL::ExceptionOr<void> AnimationEffect::update_timing(OptionalEffectTiming ti
m_playback_direction = timing.direction.value(); m_playback_direction = timing.direction.value();
// - easing → timing function // - easing → timing function
if (timing.easing.has_value()) if (timing.easing.has_value()) {
m_easing_function = timing.easing.value(); m_easing_function = timing.easing.value();
if (auto timing_function = parse_easing_string(realm(), m_easing_function)) {
m_timing_function = TimingFunction::from_easing_style_value(timing_function->as_easing());
} else {
m_timing_function = Animations::linear_timing_function;
}
}
if (auto animation = m_associated_animation) if (auto animation = m_associated_animation)
animation->effect_timing_changed({}); animation->effect_timing_changed({});
@ -580,6 +587,20 @@ Optional<double> AnimationEffect::transformed_progress() const
return m_timing_function(directed_progress.value(), before_flag); return m_timing_function(directed_progress.value(), before_flag);
} }
RefPtr<CSS::StyleValue const> AnimationEffect::parse_easing_string(JS::Realm& realm, StringView value)
{
auto maybe_parser = CSS::Parser::Parser::create(CSS::Parser::ParsingContext(realm), value);
if (maybe_parser.is_error())
return {};
if (auto style_value = maybe_parser.release_value().parse_as_css_value(CSS::PropertyID::AnimationTimingFunction)) {
if (style_value->is_easing())
return style_value;
}
return {};
}
AnimationEffect::AnimationEffect(JS::Realm& realm) AnimationEffect::AnimationEffect(JS::Realm& realm)
: Bindings::PlatformObject(realm) : Bindings::PlatformObject(realm)
{ {

View file

@ -65,6 +65,8 @@ class AnimationEffect : public Bindings::PlatformObject {
JS_DECLARE_ALLOCATOR(AnimationEffect); JS_DECLARE_ALLOCATOR(AnimationEffect);
public: public:
static RefPtr<CSS::StyleValue const> parse_easing_string(JS::Realm& realm, StringView value);
static JS::NonnullGCPtr<AnimationEffect> create(JS::Realm&); static JS::NonnullGCPtr<AnimationEffect> create(JS::Realm&);
EffectTiming get_timing() const; EffectTiming get_timing() const;

View file

@ -287,19 +287,6 @@ static WebIDL::ExceptionOr<Vector<BaseKeyframe>> process_a_keyframes_argument(JS
{ {
auto& vm = realm.vm(); auto& vm = realm.vm();
auto parse_easing_string = [&](auto& value) -> RefPtr<CSS::StyleValue const> {
auto maybe_parser = CSS::Parser::Parser::create(CSS::Parser::ParsingContext(realm), value);
if (maybe_parser.is_error())
return {};
if (auto style_value = maybe_parser.release_value().parse_as_css_value(CSS::PropertyID::AnimationTimingFunction)) {
if (style_value->is_easing())
return style_value;
}
return {};
};
// 1. If object is null, return an empty sequence of keyframes. // 1. If object is null, return an empty sequence of keyframes.
if (!object) if (!object)
return Vector<BaseKeyframe> {}; return Vector<BaseKeyframe> {};
@ -525,7 +512,7 @@ static WebIDL::ExceptionOr<Vector<BaseKeyframe>> process_a_keyframes_argument(JS
// //
// If parsing the "easing" property fails, throw a TypeError and abort this procedure. // If parsing the "easing" property fails, throw a TypeError and abort this procedure.
auto easing_string = keyframe.easing.get<String>(); auto easing_string = keyframe.easing.get<String>();
auto easing_value = parse_easing_string(easing_string); auto easing_value = AnimationEffect::parse_easing_string(realm, easing_string);
if (!easing_value) if (!easing_value)
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("Invalid animation easing value: \"{}\"", easing_string)) }; return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("Invalid animation easing value: \"{}\"", easing_string)) };
@ -537,7 +524,7 @@ static WebIDL::ExceptionOr<Vector<BaseKeyframe>> process_a_keyframes_argument(JS
// interface, and if any of the values fail to parse, throw a TypeError and abort this procedure. // interface, and if any of the values fail to parse, throw a TypeError and abort this procedure.
for (auto& unused_easing : unused_easings) { for (auto& unused_easing : unused_easings) {
auto easing_string = unused_easing.get<String>(); auto easing_string = unused_easing.get<String>();
auto easing_value = parse_easing_string(easing_string); auto easing_value = AnimationEffect::parse_easing_string(realm, easing_string);
if (!easing_value) if (!easing_value)
return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("Invalid animation easing value: \"{}\"", easing_string)) }; return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, MUST(String::formatted("Invalid animation easing value: \"{}\"", easing_string)) };
} }
@ -729,6 +716,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<KeyframeEffect>> KeyframeEffect::construct_
// - timing function. // - timing function.
effect->m_easing_function = source->m_easing_function; effect->m_easing_function = source->m_easing_function;
effect->m_timing_function = source->m_timing_function;
return effect; return effect;
} }