mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-26 01:35:08 +02:00
Previously, the LibWeb bindings generator would output multiple per interface files like Prototype/Constructor/Namespace/GlobalMixin depending on the contents of that IDL file. This complicates the build system as it means that it does not know what files will be generated without knowledge of the contents of that IDL file. Instead, for each IDL file only generate a single Bindings/<IDLFile>.h and Bindings/<IDLFile>.cpp.
143 lines
6.1 KiB
C++
143 lines
6.1 KiB
C++
/*
|
|
* Copyright (c) 2023-2024, Matthew Olsson <mattco@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Optional.h>
|
|
#include <AK/RedBlackTree.h>
|
|
#include <LibWeb/Animations/AnimationEffect.h>
|
|
#include <LibWeb/Bindings/KeyframeEffect.h>
|
|
#include <LibWeb/Bindings/PlatformObject.h>
|
|
#include <LibWeb/CSS/Selector.h>
|
|
#include <LibWeb/CSS/StyleValues/StyleValue.h>
|
|
|
|
namespace Web::Animations {
|
|
|
|
using EasingValue = Variant<String, CSS::EasingFunction>;
|
|
|
|
// https://www.w3.org/TR/web-animations-1/#the-keyframeeffectoptions-dictionary
|
|
struct KeyframeEffectOptions : public EffectTiming {
|
|
Bindings::CompositeOperation composite { Bindings::CompositeOperation::Replace };
|
|
Optional<String> pseudo_element {};
|
|
};
|
|
|
|
Bindings::CompositeOperation css_animation_composition_to_bindings_composite_operation(CSS::AnimationComposition composition);
|
|
Bindings::CompositeOperationOrAuto css_animation_composition_to_bindings_composite_operation_or_auto(CSS::AnimationComposition composition);
|
|
|
|
// https://www.w3.org/TR/web-animations-1/#dictdef-basepropertyindexedkeyframe
|
|
// Note: This is an intermediate structure used only when parsing Keyframes provided by the caller in a slightly
|
|
// different format. It is converted to BaseKeyframe, which is why it doesn't need to store the parsed properties
|
|
struct BasePropertyIndexedKeyframe {
|
|
Variant<Optional<double>, Vector<Optional<double>>> offset { Vector<Optional<double>> {} };
|
|
Variant<EasingValue, Vector<EasingValue>> easing { Vector<EasingValue> {} };
|
|
Variant<Bindings::CompositeOperationOrAuto, Vector<Bindings::CompositeOperationOrAuto>> composite { Vector<Bindings::CompositeOperationOrAuto> {} };
|
|
|
|
HashMap<String, Vector<String>> properties {};
|
|
};
|
|
|
|
// https://www.w3.org/TR/web-animations-1/#dictdef-basekeyframe
|
|
struct BaseKeyframe {
|
|
using UnparsedProperties = HashMap<String, String>;
|
|
using ParsedProperties = HashMap<CSS::PropertyID, NonnullRefPtr<CSS::StyleValue const>>;
|
|
|
|
Optional<double> offset {};
|
|
EasingValue easing { "linear"_string };
|
|
Bindings::CompositeOperationOrAuto composite { Bindings::CompositeOperationOrAuto::Auto };
|
|
|
|
Optional<double> computed_offset {};
|
|
|
|
Variant<UnparsedProperties, ParsedProperties> properties { UnparsedProperties {} };
|
|
|
|
UnparsedProperties& unparsed_properties() { return properties.get<UnparsedProperties>(); }
|
|
ParsedProperties& parsed_properties() { return properties.get<ParsedProperties>(); }
|
|
};
|
|
|
|
// https://www.w3.org/TR/web-animations-1/#the-keyframeeffect-interface
|
|
class KeyframeEffect final : public AnimationEffect {
|
|
WEB_PLATFORM_OBJECT(KeyframeEffect, AnimationEffect);
|
|
GC_DECLARE_ALLOCATOR(KeyframeEffect);
|
|
|
|
public:
|
|
constexpr static double AnimationKeyFrameKeyScaleFactor = 1000.0; // 0..100000
|
|
|
|
struct KeyFrameSet : public RefCounted<KeyFrameSet> {
|
|
struct UseInitial { };
|
|
struct ResolvedKeyFrame {
|
|
// These StyleValue properties can be unresolved, as they may be generated from a @keyframes rule, well
|
|
// before they are applied to an element
|
|
HashMap<CSS::PropertyID, Variant<UseInitial, NonnullRefPtr<CSS::StyleValue const>>> properties {};
|
|
Bindings::CompositeOperationOrAuto composite { Bindings::CompositeOperationOrAuto::Auto };
|
|
Variant<Empty, CSS::EasingFunction, NonnullRefPtr<CSS::StyleValue const>> easing {};
|
|
};
|
|
RedBlackTree<u64, ResolvedKeyFrame> keyframes_by_key;
|
|
};
|
|
static void generate_initial_and_final_frames(RefPtr<KeyFrameSet>, HashTable<CSS::PropertyID> const& animated_properties);
|
|
|
|
static int composite_order(GC::Ref<KeyframeEffect>, GC::Ref<KeyframeEffect>);
|
|
|
|
static GC::Ref<KeyframeEffect> create(JS::Realm&);
|
|
|
|
static WebIDL::ExceptionOr<GC::Ref<KeyframeEffect>> construct_impl(
|
|
JS::Realm&,
|
|
GC::Root<DOM::Element> const& target,
|
|
Optional<GC::Root<JS::Object>> const& keyframes,
|
|
Variant<double, KeyframeEffectOptions> options = KeyframeEffectOptions {});
|
|
|
|
static WebIDL::ExceptionOr<GC::Ref<KeyframeEffect>> construct_impl(JS::Realm&, GC::Ref<KeyframeEffect> source);
|
|
|
|
DOM::Element* target() const override { return m_target_element; }
|
|
void set_target(DOM::Element* target);
|
|
|
|
// JS bindings
|
|
Optional<String> pseudo_element() const;
|
|
WebIDL::ExceptionOr<void> set_pseudo_element(Optional<String>);
|
|
|
|
Optional<DOM::AbstractElement> target_abstract_element() const;
|
|
void set_target(DOM::AbstractElement);
|
|
|
|
Optional<CSS::PseudoElement> pseudo_element_type() const;
|
|
void set_pseudo_element(Optional<CSS::Selector::PseudoElementSelector> pseudo_element) { m_target_pseudo_selector = pseudo_element; }
|
|
|
|
Bindings::CompositeOperation composite() const { return m_composite; }
|
|
void set_composite(Bindings::CompositeOperation value) { m_composite = value; }
|
|
|
|
WebIDL::ExceptionOr<GC::RootVector<JS::Object*>> get_keyframes();
|
|
WebIDL::ExceptionOr<void> set_keyframes(Optional<GC::Root<JS::Object>> const&);
|
|
|
|
KeyFrameSet const* key_frame_set() { return m_key_frame_set; }
|
|
void set_key_frame_set(RefPtr<KeyFrameSet const> key_frame_set) { m_key_frame_set = key_frame_set; }
|
|
|
|
virtual bool is_keyframe_effect() const override { return true; }
|
|
|
|
virtual void update_computed_properties(AnimationUpdateContext&) override;
|
|
|
|
private:
|
|
KeyframeEffect(JS::Realm&);
|
|
virtual ~KeyframeEffect() override = default;
|
|
|
|
virtual void initialize(JS::Realm&) override;
|
|
virtual void visit_edges(Cell::Visitor&) override;
|
|
|
|
// https://www.w3.org/TR/web-animations-1/#effect-target-target-element
|
|
GC::Ptr<DOM::Element> m_target_element {};
|
|
|
|
// https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-pseudoelement
|
|
Optional<CSS::Selector::PseudoElementSelector> m_target_pseudo_selector {};
|
|
|
|
// https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-composite
|
|
Bindings::CompositeOperation m_composite { Bindings::CompositeOperation::Replace };
|
|
|
|
// https://www.w3.org/TR/web-animations-1/#keyframe
|
|
Vector<BaseKeyframe> m_keyframes {};
|
|
|
|
// A cached version of m_keyframes suitable for returning from get_keyframes()
|
|
Vector<GC::Ref<JS::Object>> m_keyframe_objects {};
|
|
|
|
RefPtr<KeyFrameSet const> m_key_frame_set {};
|
|
};
|
|
|
|
}
|