From 392510c631a4b01dd03f853389094cb54e6d3f0b Mon Sep 17 00:00:00 2001 From: Matthew Olsson Date: Wed, 3 Jul 2024 14:21:19 +0000 Subject: [PATCH] LibWeb: Store property transitions in Animatable Co-authored-by: Sam Atkins --- .../LibWeb/Animations/Animatable.cpp | 59 ++++++++++++++++++- .../Libraries/LibWeb/Animations/Animatable.h | 29 ++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibWeb/Animations/Animatable.cpp b/Userland/Libraries/LibWeb/Animations/Animatable.cpp index 5630637ed85..ab48f2c7dc7 100644 --- a/Userland/Libraries/LibWeb/Animations/Animatable.cpp +++ b/Userland/Libraries/LibWeb/Animations/Animatable.cpp @@ -1,5 +1,6 @@ /* - * Copyright (c) 2024, Matthew Olsson . + * Copyright (c) 2024, Matthew Olsson + * Copyright (c) 2024, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -8,6 +9,9 @@ #include #include #include +#include +#include +#include #include #include @@ -99,6 +103,57 @@ void Animatable::disassociate_with_animation(JS::NonnullGCPtr animati m_associated_animations.remove_first_matching([&](auto element) { return animation == element; }); } +void Animatable::add_transitioned_properties(Vector> properties, CSS::StyleValueVector delays, CSS::StyleValueVector durations, CSS::StyleValueVector timing_functions) +{ + VERIFY(properties.size() == delays.size()); + VERIFY(properties.size() == durations.size()); + VERIFY(properties.size() == timing_functions.size()); + + for (size_t i = 0; i < properties.size(); i++) { + size_t index_of_this_transition = m_transition_attributes.size(); + auto delay = delays[i]->is_time() ? delays[i]->as_time().time().to_milliseconds() : 0; + auto duration = durations[i]->is_time() ? durations[i]->as_time().time().to_milliseconds() : 0; + auto timing_function = timing_functions[i]->is_easing() ? timing_functions[i]->as_easing().function() : CSS::EasingStyleValue::CubicBezier::ease(); + VERIFY(timing_functions[i]->is_easing()); + m_transition_attributes.empend(delay, duration, timing_function); + + for (auto const& property : properties[i]) + m_transition_attribute_indices.set(property, index_of_this_transition); + } +} + +Optional Animatable::property_transition_attributes(CSS::PropertyID property) const +{ + if (auto maybe_index = m_transition_attribute_indices.get(property); maybe_index.has_value()) + return m_transition_attributes[maybe_index.value()]; + return {}; +} + +JS::GCPtr Animatable::property_transition(CSS::PropertyID property) const +{ + if (auto maybe_animation = m_associated_transitions.get(property); maybe_animation.has_value()) + return maybe_animation.value(); + return {}; +} + +void Animatable::set_transition(CSS::PropertyID property, JS::NonnullGCPtr animation) +{ + VERIFY(!m_associated_transitions.contains(property)); + m_associated_transitions.set(property, animation); +} + +void Animatable::remove_transition(CSS::PropertyID property_id) +{ + VERIFY(m_associated_transitions.contains(property_id)); + m_associated_transitions.remove(property_id); +} + +void Animatable::clear_transitions() +{ + m_transition_attribute_indices.clear(); + m_transition_attributes.clear(); +} + void Animatable::visit_edges(JS::Cell::Visitor& visitor) { visitor.visit(m_associated_animations); @@ -106,6 +161,8 @@ void Animatable::visit_edges(JS::Cell::Visitor& visitor) visitor.visit(cached_animation_source); for (auto const& cached_animation_name : m_cached_animation_name_animation) visitor.visit(cached_animation_name); + visitor.visit(m_cached_transition_property_source); + visitor.visit(m_associated_transitions); } JS::GCPtr Animatable::cached_animation_name_source(Optional pseudo_element) const diff --git a/Userland/Libraries/LibWeb/Animations/Animatable.h b/Userland/Libraries/LibWeb/Animations/Animatable.h index 9f4b374d76b..cbd419d645e 100644 --- a/Userland/Libraries/LibWeb/Animations/Animatable.h +++ b/Userland/Libraries/LibWeb/Animations/Animatable.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2024, Matthew Olsson . + * Copyright (c) 2024, Matthew Olsson + * Copyright (c) 2024, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,8 +8,13 @@ #pragma once #include +#include #include +namespace Web::CSS { +class CSSTransition; +} + namespace Web::Animations { // https://www.w3.org/TR/web-animations-1/#dictdef-keyframeanimationoptions @@ -25,6 +31,12 @@ struct GetAnimationsOptions { // https://www.w3.org/TR/web-animations-1/#animatable class Animatable { public: + struct TransitionAttributes { + double delay; + double duration; + CSS::EasingStyleValue::Function timing_function; + }; + virtual ~Animatable() = default; WebIDL::ExceptionOr> animate(Optional> keyframes, Variant options = {}); @@ -39,6 +51,16 @@ public: JS::GCPtr cached_animation_name_animation(Optional) const; void set_cached_animation_name_animation(JS::GCPtr value, Optional); + JS::GCPtr cached_transition_property_source() const { return m_cached_transition_property_source; } + void set_cached_transition_property_source(JS::GCPtr value) { m_cached_transition_property_source = value; } + + void add_transitioned_properties(Vector> properties, CSS::StyleValueVector delays, CSS::StyleValueVector durations, CSS::StyleValueVector timing_functions); + Optional property_transition_attributes(CSS::PropertyID) const; + void set_transition(CSS::PropertyID, JS::NonnullGCPtr); + void remove_transition(CSS::PropertyID); + JS::GCPtr property_transition(CSS::PropertyID) const; + void clear_transitions(); + protected: void visit_edges(JS::Cell::Visitor&); @@ -48,6 +70,11 @@ private: Array, to_underlying(CSS::Selector::PseudoElement::Type::KnownPseudoElementCount) + 1> m_cached_animation_name_source; Array, to_underlying(CSS::Selector::PseudoElement::Type::KnownPseudoElementCount) + 1> m_cached_animation_name_animation; + + HashMap m_transition_attribute_indices; + Vector m_transition_attributes; + JS::GCPtr m_cached_transition_property_source; + HashMap> m_associated_transitions; }; }